Tutorial: How to make configurable mods

Post tutorials on how to use the Mod Maker here

Tutorial: How to make configurable mods

Joined: August 22nd, 2015, 3:29 pm

February 3rd, 2016, 5:43 am #1

This is a quick run down of the procedure for making configurable mods with Mod Maker v1.1.0.19 for Mod Manager 0.59. I've tried to keep it as simple as I can and assumed no previous knowledge of c#. Some knowledge of programming is required. I'm hoping it'll be most useful to anyone who has made a few hex edit mods and wants to try something a bit different. With a little effort, it actually makes the mod easier to expand and maintain. I find it's a lot less error prone than fiddling about with hex code.

Hopefully someone will find it useful anyway.

Feel free to crack open any of my configurable mods (notepad++ works) and reuse the scripts if you want. The one for Opulent Tints is tidier than some of the others.

Zip file contains pdf and odf versions.
Config_mods_tutorial.zip (542.55 KiB)
Quote
Like
Share

Joined: October 21st, 2017, 4:54 pm

November 30th, 2017, 9:35 am #2

[Edit: 13/01/18. I posted this a while ago as example of code, and have used parts of it to make my own scripts as you can see below. I recently discovered that the Daimod-Config-Script-Editor has a list of (I suppose unique) functions AND also more complex Examples on it's HELP menu]
Dheuster wrote: I noticed there were not a lot of Configuration Script examples here other than the basics outlined by Ehamloptiran in his 1.15 announcement post (dai-modding-tool-v1-15-alpha-has-been-released-t429.html). So I thought I would post my latest script (Pretty elaborate) and note some hurdles and tips. 

Basics: So why have a configure script?

To be honest, I found writing Configure scripts easier than editing EBX files with a Hex editor and importing the edits. Especially when dealing with Floats. It is bad enough that we have to convert everything to-from hex and reverse the bytes because of the "endian" ess of the data. When you deal with floats, you practically need a program to figure out what the hex value is. 

When you write a script, you just go to an offset (using the hex supplied by the XML) and write ints and floats from the script. No conversions necessary. And you can make it configurable, which most users appreciate. 

Aside from being easier and more user friendly, scripts allow you to swap in multiple EBX files. In my case, I have loot tables with additional items added to them. But some users may not want those items. So they have the option of swapping in my edited tables or using the originals. In the same way, a texture artist may want a single mod that offers different versions of the textures. For example, pale skin versus Tan. Or Blue versus Green versus red. Maybe different resolutions (if we are there yet, I dont know). Bottom line: 1 mod instead of making users download multiple versions. 

How does it work:

First you have to have "marked" some resources. The most common way is to open up an EBX, export it and then re-import it. You have to SAVE the mod with a name before the marked resources become official. Once saved, if you go to Edit -> Adv Mod Configuration, you will see a DATA tab that includes all the EBX files you have marked. I call these Data Streams. 

Data Streams that are associated with a resource are called BOUND. That is: The mod knows what it is going to replace that chunk of binary data with. The data tab also has an Add button. You can use this to point to pretty much anything. EBX files. Texture Files, etc... These data streams are called Unbound and are meant for use by your script, but if unused wont replace anything in the game. The script itself is in C# with 2 entry points. One for creating a GUI and another for executing when they hit [Merge]. (see link above). 

Now to some of my issues and tips:

1) Some helper methods offer access by name, but most work off of indexes. Bound_Data_0 is retrieved using the method:

Code: Select all

byte[] SomeData = Scripting.GetResourceData(0);
And if you had an Unbound_Data_1, you could retrieve it using:

Code: Select all

byte[] SomeData = Scripting.GetResourceData(1);
This is fine when you only have a handfull of data streams. But becomes unmanagable when you start getting into dozens or more. My MoreLoot mod currently has 312 Data streams, 265 of which are bound and 47 are unbound. But the real kicker is: If I decide to enhance my mod and mark more resources for inclusion, all the indexes will change. The only ordering guarantee you get is that the bound will precede the unbound. I dont know if a future version may enforce ordering, but named access solves that problem regardless.

So to fix this first issue (Not knowing where things are), I looked at the EBX reader source and figured out how to pull the name of the EBX out of the data stream. My script then has a pre-parse phase where it runs through all the data streams and builds name_to_index maps: One for the bound objects and another for the unbound objects.

2) The second issue I had was the lack of knowledge (script wise) as to where the bound/unbound boundary was. The simple fix for this was to make 2 class constants that track the number of bound versus total objects. The fact that I have to update these variables every time I mark new resources or add new unbound resources is a pain, but it is the only solution at the moment. Here is hopeing a future version offers some introspection methods to help. (totalResources(), totalBoundResources()). 

3) The third issue I had was actually swapping bound and unbound data. The 1.15 documentation talks about a ChangeResourceId(source_index, target_index) method for effectively swapping data. However my Unbound EBX files are larger than the original files because they have more items in the loot tables.  So when I would try to use those methods, I would get a task failed with the message "unable to write past end of stream".  I suspect ChangeResourceId might work if the two resources are identical in size (This might be the case for textures, I haven't work enough with textures to know). But it definitely doesnt work if the unbound object is larger. 

Luckily it appears SetResourceData(index, byte[]) still works, even if the byte [] is larger. There is a caveate. The [Test] button in the DAI Modding Tool will crash the tool if you attempt to write larger data than the original using the SetResourceData method. But strangely enough, the REAL ModManager (v0.48 alpha) works fine and doesn't crash. So it is a work around, but when you are testing your script in the Modding Tool, you have to make sure that line is commented out until you are ready to test for real using the Mod Manager. 

4) The GUI doesn't offer scroll bars.  So when you consider people with lower resolutions, that means you probably should keep your user input to less than 20 items. That may sound like a lot, but you would be surprised how quickly you can burn through 20 things. 

5) Config settings are not saved: The more your mod does, the more crucial of an issue this is. You dont want users to have to remember to hit Configure on your mod and tweak 20+ settings every time they want to install another mod.  The way I currently deal with it is that I offer several different "flavors" of my mod. Each flavor is in fact the exact same configurable mod. The only difference is the default configuration values set in the gui part of the script. So people can downlaod something close to what they want and not have to hit Configure or at least minimize the amount of tweaking they have to do.

Ok, so here is the script: (Note I removed all teir2+ items from the script as it made it too large (60000 character limit). I also had to remove the inner parenthesis on not conditions as the site barfs on the combination "left_parenthesis, exclamation, left_parenthesis", even in code brackets. 

Code: Select all


using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Threading;

namespace DAIMod {

  public enum Probability { Override_Disabled, Very_Low, Low, Medium, High, Very_High }
  public enum Quality     { Override_Disabled, Low_X, High_X, Low_XX, Med_XX, High_XX, Med_1XX, High_1XX, Med_2XX }
  public enum Stuff       { Disabled, Add_Weapons_and_Armor, Add_Schematics, Add_Everything }

  public enum IType       { Any, Material, Recipe, Armor, Weapon, Valuable, Upgrade, Jewelry, Gather_Cloth, Gather_Herb, Gather_Metal }

  public class LootTable {

    public long   offset;
    public bool   is_crafting;
    public int    numItems;
    public long   itemOffset;
    public IType  itype;

    public LootTable(long p_offset = 0, IType p_itype = IType.Any, int p_numItems = 0, long p_itemOffset = 0) {
      offset      = p_offset;
      itype       = p_itype; 
      is_crafting = ((itype == IType.Material) || (itype ==IType.Recipe));
      numItems    = p_numItems;
      itemOffset  = p_itemOffset;
    }

  }

  public class MoreLootFlexMod : ModScript {

    public const int totalBound = 265;
    public const int totalResources   = 313;
    public bool  logVerbose = false;


    public void ConstructUI(ModConfigElementsList ConfigElementsList) {


      ConfigElementsList.AddIntElement( "pIncrement",  "Increment Probabilities By (0-4)",    0, 0, 4);
      ConfigElementsList.AddEnumElement("gProb",       "Minimum Gold Probability",            typeof(Probability), 5);
      ConfigElementsList.AddEnumElement("gQual",       "Minimum Gold Quality",                typeof(Quality), 8);
      ConfigElementsList.AddEnumElement("dProb",       "Minimum Drop Probability",            typeof(Probability), 5);
      ConfigElementsList.AddEnumElement("aProb",       "Minimum Armor Probability",           typeof(Probability), 5);
      ConfigElementsList.AddEnumElement("wProb",       "Minimum Weapon Probability",          typeof(Probability), 5);
      ConfigElementsList.AddEnumElement("jProb",       "Minimum Jewelry Probability",         typeof(Probability), 5);
      ConfigElementsList.AddEnumElement("vProb",       "Minimum Valuable Probability",        typeof(Probability), 5);
      ConfigElementsList.AddEnumElement("uProb",       "Minimum Upgrade Probability",         typeof(Probability), 5);
      ConfigElementsList.AddEnumElement("mProb",       "Minimum Material Probability",        typeof(Probability), 5);
      ConfigElementsList.AddEnumElement("sProb",       "Minimum Schematic Probability",       typeof(Probability), 5);
      ConfigElementsList.AddIntElement( "mMin",        "Material Quantity Min",               3, 1, 255);
      ConfigElementsList.AddIntElement( "mMax",        "Material Quantity Max",               9, 1, 255);
      ConfigElementsList.AddBoolElement("mOverride",   "Use Above Material Quantities",       true);
      ConfigElementsList.AddIntElement( "gMin",        "Gather Quantity Min",                 3, 1, 255);
      ConfigElementsList.AddIntElement( "gMax",        "Gather Quantity Max",                 9, 1, 255);
      ConfigElementsList.AddBoolElement("gOverride",   "Use Above Gather Quantities",         true);
      ConfigElementsList.AddIntElement( "cgathermin",  "Min Gather Cloth Prob (0-100)",    0, 0, 100);
      ConfigElementsList.AddIntElement( "hgathermin",  "Min Gather Herb  Prob (0-100)",    0, 0, 100);
      ConfigElementsList.AddIntElement( "mgathermin",  "Min Gather Metal Prob (0-100)",    0, 0, 100);
      ConfigElementsList.AddEnumElement("addStuff",    "Add Extra Stuff",                     typeof(Stuff), 3);
      ConfigElementsList.AddBoolElement("wBoost",      "Boost Override Weights",              true);
      ConfigElementsList.AddBoolElement("logVerbose",  "Log Verbose",                         false);

    }

    public void Log(string s) {
      if (logVerbose) {
        Scripting.LogLn(s);
      }
    }

    public static string ReadNullString(Stream s) {
      string res = "";
      byte b;
      while ((b = (byte)s.ReadByte()) > 0) res += (char)b;
      return res;
    }

    public static float ReadFloat(Stream s) {
      byte[] buff = new byte[4];
      s.Read(buff, 0, 4);
      return BitConverter.ToSingle(buff, 0);
    }

    public void RunScript() {

      logVerbose             = (bool)Scripting.GetConfigParam("logVerbose");
      Probability dProb      = (Probability)Scripting.GetConfigParam("dProb");
      Probability gProb      = (Probability)Scripting.GetConfigParam("gProb");
      Quality     gQual      = (Quality)Scripting.GetConfigParam("gQual");
      int         pIncrement = (int)Scripting.GetConfigParam("pIncrement");

      Probability aProb      = (Probability)Scripting.GetConfigParam("aProb");
      Probability wProb      = (Probability)Scripting.GetConfigParam("wProb");
      Probability jProb      = (Probability)Scripting.GetConfigParam("jProb");
      Probability vProb      = (Probability)Scripting.GetConfigParam("vProb");
      Probability uProb      = (Probability)Scripting.GetConfigParam("uProb");
      Probability mProb      = (Probability)Scripting.GetConfigParam("mProb");
      Probability sProb      = (Probability)Scripting.GetConfigParam("sProb");

      bool        mOverride  = (bool)Scripting.GetConfigParam("mOverride");
      int         mMin       = (int)Scripting.GetConfigParam("mMin");
      int         mMax       = (int)Scripting.GetConfigParam("mMax");

      bool        gOverride  = (bool)Scripting.GetConfigParam("gOverride");
      int         gMin       = (int)Scripting.GetConfigParam("gMin");
      int         gMax       = (int)Scripting.GetConfigParam("gMax");

      int         cgathermin = (int)Scripting.GetConfigParam("cgathermin");
      int         hgathermin = (int)Scripting.GetConfigParam("hgathermin");
      int         mgathermin = (int)Scripting.GetConfigParam("mgathermin");

      Stuff       addStuff   = (Stuff)Scripting.GetConfigParam("addStuff");
      bool        wBoost     = (bool)Scripting.GetConfigParam("wBoost");

      if (mMin > mMax) {
        mMax = mMin;
      }

      if (gMin > gMax) {
        gMax = gMin;
      }

      int dpb = ((int)dProb);
      int apb = ((int)aProb);
      int wpb = ((int)wProb);
      int jpb = ((int)jProb);
      int vpb = ((int)vProb);
      int upb = ((int)uProb);
      int mpb = ((int)mProb);
      int spb = ((int)sProb);
      int gpb = ((int)gProb);
      int gq  = ((int)gQual);

      bool gAlways = ((gq != 0) && (gpb != 0));

      if (gq > 2) { gq = gq + 2; }

      Scripting.LogLn("Applying Loot Settings: ");
      Scripting.LogLn("  Drop Probability              : " + dProb.ToString() + " (" + dpb.ToString() + ")");
      Scripting.LogLn("  Gold Probability              : " + gProb.ToString() + " (" + gpb.ToString() + ")");
      Scripting.LogLn("  Gold Quality                  : " + gQual.ToString() + " (" + gq.ToString() + ")");
      Scripting.LogLn("  Increment Probabilities By    : " + pIncrement.ToString());
      Scripting.LogLn("  Minimum Armor Probability     : " + aProb.ToString() + " (" + apb.ToString() + ")");
      Scripting.LogLn("  Minimum Weapon Probability    : " + wProb.ToString() + " (" + wpb.ToString() + ")");
      Scripting.LogLn("  Minimum Jewelry Probability   : " + jProb.ToString() + " (" + jpb.ToString() + ")");
      Scripting.LogLn("  Minimum Valuable Probability  : " + vProb.ToString() + " (" + vpb.ToString() + ")");
      Scripting.LogLn("  Minimum Upgrade Probability   : " + uProb.ToString() + " (" + upb.ToString() + ")");
      Scripting.LogLn("  Minimum Material Probability  : " + mProb.ToString() + " (" + mpb.ToString() + ")");
      Scripting.LogLn("  Minimum Schematic Probability : " + sProb.ToString() + " (" + spb.ToString() + ")");
      Scripting.LogLn("  Use Material Quantities       : " + mOverride.ToString());
      if (mOverride) {
        Scripting.LogLn("  Material Quantity Min         : " + mMin.ToString());
        Scripting.LogLn("  Material Quantity Max         : " + mMax.ToString());
      } else {
        Scripting.LogLn("  Material Quantity Min         : " + mMin.ToString() + " (ignored)");
        Scripting.LogLn("  Material Quantity Max         : " + mMax.ToString() + " (ignored)");
      }
      Scripting.LogLn("  Use Gather Quantities         : " + gOverride.ToString());
      if (gOverride) {
        Scripting.LogLn("  Gather Quantity Min           : " + gMin.ToString());
        Scripting.LogLn("  Gather Quantity Max           : " + gMax.ToString());
      } else {
        Scripting.LogLn("  Gather Quantity Min           : " + gMin.ToString() + " (ignored)");
        Scripting.LogLn("  Gather Quantity Max           : " + gMax.ToString() + " (ignored)");
      }

      Scripting.LogLn("  Minimum Gather Cloth Probability  : " + cgathermin.ToString());
      Scripting.LogLn("  Minimum Gather Herb Probability   : " + hgathermin.ToString());
      Scripting.LogLn("  Minimum Gather Metal Probability  : " + mgathermin.ToString());

      Scripting.LogLn("  Add Extra Stuff                   : " + addStuff.ToString());
      Scripting.LogLn("  Override Boost Prob Weights       : " + wBoost.ToString());
      Scripting.LogLn("  logVerbose                        : " + logVerbose.ToString());

      Dictionary<int, string>      data_lookup  = new Dictionary<int, string>();
      Dictionary<string,LootTable> ltbl_lookup  = new Dictionary<string, LootTable>();

      ltbl_lookup.Add("ltbl_acc_container_1",                              new LootTable(0x0AF8, IType.Jewelry, 34, 0x0B24));
      ltbl_lookup.Add("ltbl_adamant_fortress_main",                        new LootTable(0x0688));
      ltbl_lookup.Add("ltbl_crafting_cloth_tier1",                         new LootTable(0x0778, IType.Material,  6,  0x07A4));
      ltbl_lookup.Add("ltbl_crafting_herbs_tier1",                         new LootTable(0x07D8, IType.Material,  9,  0x0804));
      ltbl_lookup.Add("ltbl_crafting_leather_tier1",                       new LootTable(0x0798, IType.Material,  7,  0x07C4));
      ltbl_lookup.Add("ltbl_crafting_metal_rift_tier1",                    new LootTable(0x0778, IType.Material,  6,  0x07A4));
      ltbl_lookup.Add("ltbl_crafting_metal_tier1",                         new LootTable(0x0778, IType.Material,  6,  0x07A4));
      ltbl_lookup.Add("ltbl_container_cache_tier_a_4_7",                   new LootTable(0x0688));
      ltbl_lookup.Add("ltbl_container_demons_general_1",                   new LootTable(0x0738));
      ltbl_lookup.Add("ltbl_container_demons_materials_1",                 new LootTable(0x0748, IType.Material,  4,  0x0774));
      ltbl_lookup.Add("ltbl_container_tier_a_4_7",                         new LootTable(0x0848));
      ltbl_lookup.Add("ltbl_creature_demon_1",                             new LootTable(0x05C8));
      ltbl_lookup.Add("ltbl_creature_demon_cold_8_11",                     new LootTable(0x06E8, IType.Material, 1, 0x0714));
      ltbl_lookup.Add("ltbl_creature_demon_fire_8_11",                     new LootTable(0x06E8, IType.Material, 1, 0x0714));
      ltbl_lookup.Add("ltbl_creature_demon_lightning_12_15",               new LootTable(0x0708, IType.Material, 2, 0x0734));
      ltbl_lookup.Add("ltbl_creature_demon_spirit_4_7",                    new LootTable(0x06E8, IType.Material, 1, 0x0714));
      ltbl_lookup.Add("ltbl_creature_dragon_16_19",                        new LootTable(0x06D8, IType.Material, 1, 0x0704));
      ltbl_lookup.Add("ltbl_creature_giant_8_11",                          new LootTable(0x0748));
      ltbl_lookup.Add("ltbl_creature_mag_tier_a_4_7",                      new LootTable(0x0708));
      ltbl_lookup.Add("ltbl_creature_rog_tier_a_4_7",                      new LootTable(0x0718));
      ltbl_lookup.Add("ltbl_creature_undead_8_11",                         new LootTable(0x06C8));
      ltbl_lookup.Add("ltbl_creature_war_tier_a_4_7",                      new LootTable(0x0718));
      ltbl_lookup.Add("ltbl_dgn_s_140",                                    new LootTable(0x0678));
      ltbl_lookup.Add("ltbl_ferelden_lakeside",                            new LootTable(0x0678));
      ltbl_lookup.Add("ltbl_frostback_mountains",                          new LootTable(0x0688));
      ltbl_lookup.Add("ltbl_ham_winter_palace",                            new LootTable(0x05B8));
      ltbl_lookup.Add("ltbl_mag_armor_upgrades_arms_a_4_7",                new LootTable(0x0728, IType.Upgrade, 3,  0x0754));
      ltbl_lookup.Add("ltbl_mag_armor_upgrades_legs_a_4_7",                new LootTable(0x0728, IType.Upgrade, 3,  0x0754));
      ltbl_lookup.Add("ltbl_mag_ring_upgrade_1",                           new LootTable(0x0898, IType.Upgrade, 15, 0x08C4));
      ltbl_lookup.Add("ltbl_mag_weapons_tier_a_4_7",                       new LootTable(0x0788, IType.Weapon, 6,   0x07B4));
      ltbl_lookup.Add("ltbl_mag_weapons_upgrades_staff_blade_a_4_7",       new LootTable(0x0718, IType.Upgrade, 2,  0x0744));
      ltbl_lookup.Add("ltbl_mag_weapons_upgrades_staff_grip_a_4_7",        new LootTable(0x0718, IType.Upgrade, 2,  0x0744));
      ltbl_lookup.Add("ltbl_rog_armor_upgrades_arms_a_4_7",                new LootTable(0x0728, IType.Upgrade, 3,  0x0754));
      ltbl_lookup.Add("ltbl_rog_armor_upgrades_legs_a_4_7",                new LootTable(0x0728, IType.Upgrade, 3,  0x0754));
      ltbl_lookup.Add("ltbl_rog_ring_upgrade_1",                           new LootTable(0x08B8, IType.Upgrade, 16, 0x08E4));
      ltbl_lookup.Add("ltbl_rog_weapons_tier_a_4_7",                       new LootTable(0x0908, IType.Weapon, 18,  0x0934));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_bow_grip_a_4_7",          new LootTable(0x0718, IType.Upgrade, 2,  0x0744));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_dagger_grip_a_4_7",       new LootTable(0x0718, IType.Upgrade, 2,  0x0744));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_dualdagger_grip_b_8_15",  new LootTable(0x06F8, IType.Upgrade, 1,  0x0724));
      ltbl_lookup.Add("ltbl_sack_tier_a_4_7",                              new LootTable(0x0708));
      ltbl_lookup.Add("ltbl_valuables_1",                                  new LootTable(0x0978, IType.Valuable, 22, 0x09A4));
      ltbl_lookup.Add("ltbl_valuables_creatures_tier_a_4_7",               new LootTable(0x06B8, IType.Valuable));
      ltbl_lookup.Add("ltbl_war_armor_upgrades_arms_a_4_7",                new LootTable(0x0728, IType.Upgrade, 3,  0x0754));
      ltbl_lookup.Add("ltbl_war_armor_upgrades_legs_a_4_7",                new LootTable(0x0728, IType.Upgrade, 3,  0x0754));
      ltbl_lookup.Add("ltbl_war_ring_upgrade_1",                           new LootTable(0x08D8, IType.Upgrade, 17, 0x0904));
      ltbl_lookup.Add("ltbl_war_weapons_tier_a_4_7",                       new LootTable(0x08C8, IType.Weapon, 16,  0x08F4));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_1handed_grip_a_4_7",      new LootTable(0x0718, IType.Upgrade, 2,  0x0744));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_2handed_grip_a_4_7",      new LootTable(0x0718, IType.Upgrade, 2,  0x0744));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_2handed_pommel_a_4_7",    new LootTable(0x0718, IType.Upgrade, 2,  0x0744));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_gsword_grip_a_4_7",       new LootTable(0x0718, IType.Upgrade, 2,  0x0744));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_lsword_grip_a_4_7",       new LootTable(0x0718, IType.Upgrade, 2,  0x0744));
      ltbl_lookup.Add("ltbl_western_approach_main",                        new LootTable(0x05C8));


      ltbl_lookup.Add("ltdp_creature_crafting_cloth_bandit_rogue",         new LootTable(0x0708, IType.Gather_Cloth, 5,  0x0724));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_bandit_warrior",       new LootTable(0x0728, IType.Gather_Cloth, 6,  0x0744));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_cotton",               new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_dales_loden_wool",     new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_darkened_samite",      new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_everknit_wool",        new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_highever_weave",       new LootTable(0x06A8, IType.Gather_Cloth, 2,  0x06C4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_lambswool",            new LootTable(0x06C8, IType.Gather_Cloth, 2,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_lastrous_cotton",      new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_plaideweave",          new LootTable(0x06A8, IType.Gather_Cloth, 2,  0x06C4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_ring_velvet",          new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_royal_sea_silk",       new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_samite",               new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_silk",                 new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_silk_brocade",         new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_velveteen",            new LootTable(0x06C8, IType.Gather_Cloth, 3,  0x06E4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_imperial_vestment_cotton", new LootTable(0x06D8, IType.Gather_Cloth, 3,  0x06F4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_infused_vyrantium_samite", new LootTable(0x06D8, IType.Gather_Cloth, 3,  0x06F4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_kings_willow_weave",       new LootTable(0x06B8, IType.Gather_Cloth, 2,  0x06D4));
      ltbl_lookup.Add("ltdp_creature_crafting_cloth_plush_fustian_velvet",     new LootTable(0x06D8, IType.Gather_Cloth, 3,  0x06F4));


      ltbl_lookup.Add("ltdp_gather_herb_elfroot",                          new LootTable(0x0678, IType.Gather_Herb, 4,  0x0694));
      ltbl_lookup.Add("ltdp_gather_herb_ameritavein",                      new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_arborblessing",                    new LootTable(0x06A8, IType.Gather_Herb, 4,  0x06C4));
      ltbl_lookup.Add("ltdp_gather_herb_blacklotus",                       new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_bloodlotus",                       new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_crystalgrace",                     new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_dawnlotus",                        new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_deathroot",                        new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_deepmushroom",                     new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_dragonthorn",                      new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_embrium",                          new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_felandris",                        new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_goulsbeard",                       new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_prohpetslaurel",                   new LootTable(0x06A8, IType.Gather_Herb, 4,  0x06C4));
      ltbl_lookup.Add("ltdp_gather_herb_rashvine",                         new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_rashvinenettle",                   new LootTable(0x06A8, IType.Gather_Herb, 4,  0x06C4));
      ltbl_lookup.Add("ltdp_gather_herb_royalelfroot",                     new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_spindleweed",                      new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_vandalaria",                       new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));
      ltbl_lookup.Add("ltdp_gather_herb_witherstalk",                      new LootTable(0x0698, IType.Gather_Herb, 4,  0x06B4));


      ltbl_lookup.Add("ltdp_gather_metal_iron",                            new LootTable(0x06B8, IType.Gather_Metal, 4,  0x06D4));
      ltbl_lookup.Add("ltdp_gather_metal_bloodstone",                      new LootTable(0x06B8, IType.Gather_Metal, 4,  0x06D4));
      ltbl_lookup.Add("ltdp_gather_metal_bluevitroil",                     new LootTable(0x06C8, IType.Gather_Metal, 4,  0x06E4));
      ltbl_lookup.Add("ltdp_gather_metal_dawnstone",                       new LootTable(0x06D8, IType.Gather_Metal, 4,  0x06F4));
      ltbl_lookup.Add("ltdp_gather_metal_drakestone",                      new LootTable(0x06B8, IType.Gather_Metal, 4,  0x06D4));
      ltbl_lookup.Add("ltdp_gather_metal_everite",                         new LootTable(0x06D8, IType.Gather_Metal, 4,  0x06F4));
      ltbl_lookup.Add("ltdp_gather_metal_lazurite",                        new LootTable(0x06B8, IType.Gather_Metal, 4,  0x06D4));
      ltbl_lookup.Add("ltdp_gather_metal_nevarrite",                       new LootTable(0x06B8, IType.Gather_Metal, 4,  0x06D4));
      ltbl_lookup.Add("ltdp_gather_metal_obsidian",                        new LootTable(0x06D8, IType.Gather_Metal, 4,  0x06F4));
      ltbl_lookup.Add("ltdp_gather_metal_onyx",                            new LootTable(0x06D8, IType.Gather_Metal, 4,  0x06F4));
      ltbl_lookup.Add("ltdp_gather_metal_paragonsluster",                  new LootTable(0x06E8, IType.Gather_Metal, 4,  0x0704));
      ltbl_lookup.Add("ltdp_gather_metal_pyrophite",                       new LootTable(0x06D8, IType.Gather_Metal, 4,  0x06F4));
      ltbl_lookup.Add("ltdp_gather_metal_serpentstone",                    new LootTable(0x06E8, IType.Gather_Metal, 4,  0x0704));
      ltbl_lookup.Add("ltdp_gather_metal_silverite",                       new LootTable(0x06D8, IType.Gather_Metal, 4,  0x06F4));
      ltbl_lookup.Add("ltdp_gather_metal_stormheart",                      new LootTable(0x06D8, IType.Gather_Metal, 4,  0x06F4));
      ltbl_lookup.Add("ltdp_gather_metal_summerstone",                     new LootTable(0x06E8, IType.Gather_Metal, 4,  0x0704));
      ltbl_lookup.Add("ltdp_gather_metal_veridium",                        new LootTable(0x06D8, IType.Gather_Metal, 4,  0x06F4));
      ltbl_lookup.Add("ltdp_gather_metal_volcanicaurum",                   new LootTable(0x06E8, IType.Gather_Metal, 4,  0x0704));

      Dictionary<string,bool> add_lookup  = new Dictionary<string, bool>();

      if ((addStuff == Stuff.Add_Weapons_and_Armor) || (addStuff == Stuff.Add_Everything)) {

        ltbl_lookup.Add("ltbl_mag_generic_armors_4_7",                     new LootTable(0x0AC8, IType.Armor,  8, 0x0AF4));
        ltbl_lookup.Add("ltbl_qunari_headgear_t1",                         new LootTable(0x0B58, IType.Armor,  9, 0x0B84));
        ltbl_lookup.Add("ltbl_rog_generic_armors_4_7",                     new LootTable(0x0AC8, IType.Armor,  8, 0x0AF4));
        ltbl_lookup.Add("ltbl_war_generic_armors_4_7",                     new LootTable(0x0A38, IType.Armor,  7, 0x0A64));

        add_lookup.Add("ltbl_mag_generic_armors_4_7",   true);
        add_lookup.Add("ltbl_qunari_headgear_t1",       true);
        add_lookup.Add("ltbl_rog_generic_armors_4_7",   true);
        add_lookup.Add("ltbl_war_generic_armors_4_7",   true);

      } else {

        ltbl_lookup.Add("ltbl_mag_generic_armors_4_7",                     new LootTable(0x0778, IType.Armor,  7, 0x07A4));
        ltbl_lookup.Add("ltbl_qunari_headgear_t1",                         new LootTable(0x07D8, IType.Armor,  9, 0x0804));
        ltbl_lookup.Add("ltbl_rog_generic_armors_4_7",                     new LootTable(0x0798, IType.Armor,  7,  0x07C4));
        ltbl_lookup.Add("ltbl_war_generic_armors_4_7",                     new LootTable(0x0778, IType.Armor,  6, 0x07A4));
      }

      if ((addStuff == Stuff.Add_Schematics) || (addStuff == Stuff.Add_Everything)) {

        ltbl_lookup.Add("ltbl_mag_armor_recipes_a_4_7",                    new LootTable(0x0D18, IType.Recipe, 12, 0x0D44));
        ltbl_lookup.Add("ltbl_rog_armor_recipes_a_4_7",                    new LootTable(0x0BF8, IType.Recipe, 10, 0x0C24));
        ltbl_lookup.Add("ltbl_war_armor_recipes_a_4_7",                    new LootTable(0x0BF8, IType.Recipe, 10, 0x0C24));
        ltbl_lookup.Add("ltbl_mag_weapon_recipes_tier_a_4_7",              new LootTable(0x0BF8, IType.Recipe, 10, 0x0C24));
        ltbl_lookup.Add("ltbl_rog_weapon_recipes_tier_a_4_7",              new LootTable(0x0DA8, IType.Recipe, 13, 0x0DD4));
        ltbl_lookup.Add("ltbl_war_weapon_recipes_tier_a_4_7",              new LootTable(0x13E8, IType.Recipe, 24, 0x1414));

        add_lookup.Add("ltbl_mag_armor_recipes_a_4_7",         true);
        add_lookup.Add("ltbl_rog_armor_recipes_a_4_7",         true);
        add_lookup.Add("ltbl_war_armor_recipes_a_4_7",         true);
        add_lookup.Add("ltbl_mag_weapon_recipes_tier_a_4_7",   true);
        add_lookup.Add("ltbl_rog_weapon_recipes_tier_a_4_7",   true);
        add_lookup.Add("ltbl_war_weapon_recipes_tier_a_4_7",   true);

      } else {

        ltbl_lookup.Add("ltbl_mag_armor_recipes_a_4_7",                    new LootTable(0x07C8, IType.Recipe,  8, 0x07F4));
        ltbl_lookup.Add("ltbl_rog_armor_recipes_a_4_7",                    new LootTable(0x07C8, IType.Recipe,  8, 0x07F4));
        ltbl_lookup.Add("ltbl_war_armor_recipes_a_4_7",                    new LootTable(0x07C8, IType.Recipe,  8, 0x07F4));
        ltbl_lookup.Add("ltbl_mag_weapon_recipes_tier_a_4_7",              new LootTable(0x07C8, IType.Recipe,  8, 0x07F4));
        ltbl_lookup.Add("ltbl_rog_weapon_recipes_tier_a_4_7",              new LootTable(0x07C8, IType.Recipe,  8, 0x07F4));
        ltbl_lookup.Add("ltbl_war_weapon_recipes_tier_a_4_7",              new LootTable(0x0918, IType.Recipe, 18, 0x0944));
      }


      Char[] split_seperator = new Char[] {'/'};

      Dictionary<int, string> index_to_name  = new Dictionary<int, string>();
      Dictionary<string, int> name_to_index  = new Dictionary<string, int>();

      for (int iblob = 0; iblob < totalBound; iblob++) {
        MemoryStream ms = new MemoryStream(Scripting.GetResourceData(iblob));
        BinaryReader Reader = new BinaryReader(ms);
        Reader.BaseStream.Seek(4, SeekOrigin.Begin);
        uint nameOffset = Reader.ReadUInt32();
        Reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);

        string fullname = ReadNullString(Reader.BaseStream);
        string[] parts  = fullname.Split(split_seperator);
        if (parts.Length < 1) {
          Reader.Close();
          continue;
        }

        string res_name = parts[(parts.Length - 1)];
        index_to_name.Add(iblob, res_name);
        name_to_index.Add(res_name, iblob);
        Reader.Close();
      }

      if (addStuff != Stuff.Disabled) {
        for (int iblob = totalBound; iblob < totalResources; iblob++) {
          MemoryStream ms = new MemoryStream(Scripting.GetResourceData(iblob));
          BinaryReader Reader = new BinaryReader(ms);
          Reader.BaseStream.Seek(4, SeekOrigin.Begin);
          uint nameOffset = Reader.ReadUInt32();
          Reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
          
          string fullname = ReadNullString(Reader.BaseStream);
          string[] parts  = fullname.Split(split_seperator);
          if (parts.Length < 1) {
            Reader.Close();
            continue;
          }
          
          string res_name = parts[(parts.Length - 1)];
          bool replace = false;
          add_lookup.TryGetValue(res_name, out replace);
        
          if (replace) {
            int replace_index;
            if (name_to_index.TryGetValue(res_name, out replace_index)) {
              Log("  Adding Items to [" + res_name + "]");
              Scripting.SetResourceData(replace_index, ms.ToArray());
            }
          }
          Reader.Close();
        }
      }

      /* Pre-Scan to compute the final minimum probability */
      int bmin = 5;
      string bmin_res_name = "";

      for (int iblob = 0; iblob < totalBound; iblob++) {
        MemoryStream ms = new MemoryStream(Scripting.GetResourceData(iblob));
        BinaryReader Reader = new BinaryReader(ms);        
        Reader.BaseStream.Seek(4, SeekOrigin.Begin);
        uint nameOffset = Reader.ReadUInt32();
        Reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
        string res_name;
        if (!index_to_name.TryGetValue(iblob, out res_name)) {
          Reader.Close();
          continue;
        }
        LootTable ltbl;
        if (!ltbl_lookup.TryGetValue(res_name, out ltbl)) {
          Reader.Close();
          continue;
        }
        if (ltbl.itype == IType.Gather_Cloth || ltbl.itype == IType.Gather_Herb || ltbl.itype == IType.Gather_Metal) {
          Reader.Close();
          continue;
        }
        long iProbOffset = ltbl.offset;
        Reader.BaseStream.Seek(iProbOffset, SeekOrigin.Begin);

        int iProbCurr = Reader.ReadInt32();

        if (iProbCurr > 0 && iProbCurr < 6) {
          int new_pb = iProbCurr + pIncrement;
          if (new_pb > 4) {
            new_pb = 5;
          } else {
            if (ltbl.itype == IType.Material && mpb > new_pb) { new_pb = mpb; }
            if (ltbl.itype == IType.Recipe   && spb > new_pb) { new_pb = spb; }
            if (ltbl.itype == IType.Armor    && apb > new_pb) { new_pb = apb; }
            if (ltbl.itype == IType.Weapon   && wpb > new_pb) { new_pb = wpb; }
            if (ltbl.itype == IType.Valuable && vpb > new_pb) { new_pb = vpb; }
            if (ltbl.itype == IType.Upgrade  && upb > new_pb) { new_pb = upb; }
            if (ltbl.itype == IType.Jewelry  && jpb > new_pb) { new_pb = jpb; }
            if (ltbl.itype == IType.Any      && dpb > new_pb) { new_pb = dpb; }
          }         
          if (new_pb < bmin) {
            bmin_res_name = res_name;
            bmin = new_pb; 
          }
        }        
        Reader.Close();
      }

      Log("  Minimum Probability = [" + bmin.ToString() + "] Resource [" + bmin_res_name + "]");

      float badjust = (float)bmin - 1;
      if (badjust < 0F) {
        badjust = 0F;
      }

      for (int iblob = 0; iblob < totalBound; iblob++) {
        MemoryStream ms = new MemoryStream(Scripting.GetResourceData(iblob));
        BinaryReader Reader = new BinaryReader(ms);        
        Reader.BaseStream.Seek(4, SeekOrigin.Begin);
        uint nameOffset = Reader.ReadUInt32();
        Reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);
        string res_name;
        if (!index_to_name.TryGetValue(iblob, out res_name)) {
          Scripting.LogLn("  Skipping Resource [" + iblob.ToString() + "]. Not a valid EBX");
          Reader.Close();
          continue;
        }
        LootTable ltbl;
        if (!ltbl_lookup.TryGetValue(res_name, out ltbl)) {
          Scripting.LogLn("  Skipping Resource [" + res_name + "]. No offset data.");
          Reader.Close();
          continue;
        }

        Log("  " + res_name + ":");
        BinaryWriter Writer = new BinaryWriter(ms);

        if (ltbl.itype == IType.Gather_Cloth || ltbl.itype == IType.Gather_Herb || ltbl.itype == IType.Gather_Metal) {

          float gather_prob = 0F;
          if (ltbl.itype == IType.Gather_Cloth)      { gather_prob = cgathermin;  }
          else if (ltbl.itype == IType.Gather_Herb)  { gather_prob = hgathermin; }
          else if (ltbl.itype == IType.Gather_Metal) { gather_prob = mgathermin; }

          if ((gOverride) || (gather_prob != 0F)) {
            for (int j = 0; j < ltbl.numItems; j++) {

              long gatherOffset      = ltbl.itemOffset + (j * 68);
              long gatherminOffset   = gatherOffset + 4;
              long gathermaxOffset   = gatherOffset + 8;
              long gmaxPerAreaOffset = gatherOffset + 12;
              long probabilityOffset = gatherOffset + 44;

              Reader.BaseStream.Seek(gatherOffset, SeekOrigin.Begin);
              long res_id  = Reader.ReadUInt32();
              int minimum  = Reader.ReadInt32();
              int maximum  = Reader.ReadInt32();
              int maxarea  = Reader.ReadInt32();
              Reader.BaseStream.Seek(probabilityOffset, SeekOrigin.Begin);
              float probability = ReadFloat(Reader.BaseStream);
              Log("    item [" + j.ToString() + "]:");

              /* Dont mess with amounts unless the user checked the box */
              if (gOverride) {
                if (gMin > minimum) {
                  Writer.BaseStream.Seek(gatherminOffset, SeekOrigin.Begin);
                  Writer.Write(gMin);
                  Log("      GatherMin: " + minimum.ToString() + " => " + gMin.ToString());
                }
                if (gMax > maximum) {
                  Writer.BaseStream.Seek(gathermaxOffset, SeekOrigin.Begin);
                  Writer.Write(gMax);
                  Log("      GatherMax: " + maximum.ToString() + " => " + gMax.ToString());
                }
                if (maxarea > 0) {
                  Writer.BaseStream.Seek(gmaxPerAreaOffset, SeekOrigin.Begin);
                  Writer.Write(0); /* No Max Per Area */
                  Log("      GatherMaxPerArea: " + maxarea.ToString() + " => Unlimited");
                }
              }

              /* Dont mess with probability unless user specified a Minimum Gather Prob Override */
              if (gather_prob != 0F && probability != 0F) {
                if (probability < gather_prob) {
                  Writer.BaseStream.Seek(probabilityOffset, SeekOrigin.Begin);
                  Writer.Write(gather_prob);
                  Log("      GatherProbability: " + probability.ToString() + " => " + gather_prob.ToString()) ;
                }
              }
            } /* for */

            Scripting.SetResourceData(iblob, ms.ToArray());
          } /* (gOverride || (gather_prob != 0F)) */
          Writer.Close();
          Reader.Close();
          continue;
        }

        long iProbOffset = ltbl.offset;
        long gProbOffset = ltbl.offset + 8;
        long gQualOffset = ltbl.offset + 12;

        Reader.BaseStream.Seek(iProbOffset, SeekOrigin.Begin);

        int iProbCurr = Reader.ReadInt32();
        int gProbCurr = Reader.ReadInt32();
        int gQualCurr = Reader.ReadInt32();

        /* Gold Qualities: */
        /* 0 = 0, 1 = ~4, 2 = ~8, 3 = ~12, 4 = ~16, 5 = ~20, 6 = ~48, 7 = ~96, 8 = ~144, 9 = ~ 196, 10 = ~240 */

        if (gQualCurr > 1 && gQualCurr < 5) { gQualCurr = 2; }

        /* DAI Probability values: */
        /* 0 = None, 1 = Very_Low, 2 = Low, 3 = Medium, 4 = High, 5 = Very_High, 6 = Always     */

        /* update boost value when we calculate the probability (or leave at 1 if prob is out of consideration range) */
        float boostvalue = 1F;

        /* We dont mess with values that are None or Always. And if it is already Very_High, there is nothing we can do to it. */
        if (iProbCurr > 0 && iProbCurr < 6) {
          int new_pb = iProbCurr + pIncrement;
          if (new_pb > 4) {
            new_pb = 5;
          } else {
            /* Does it meet the minimum? */
            if (ltbl.itype == IType.Material && mpb > new_pb) { new_pb = mpb; }
            if (ltbl.itype == IType.Recipe   && spb > new_pb) { new_pb = spb; }
            if (ltbl.itype == IType.Armor    && apb > new_pb) { new_pb = apb; }
            if (ltbl.itype == IType.Weapon   && wpb > new_pb) { new_pb = wpb; }
            if (ltbl.itype == IType.Valuable && vpb > new_pb) { new_pb = vpb; }
            if (ltbl.itype == IType.Upgrade  && upb > new_pb) { new_pb = upb; }
            if (ltbl.itype == IType.Jewelry  && jpb > new_pb) { new_pb = jpb; }
            if (ltbl.itype == IType.Any      && dpb > new_pb) { new_pb = dpb; }
          }
         
          boostvalue = (float)new_pb - badjust;
          if (new_pb > iProbCurr) {
            if (new_pb < bmin) { bmin = new_pb; } 
            Writer.BaseStream.Seek(iProbOffset, SeekOrigin.Begin);
            Writer.Write(new_pb);
            Log("    iProb: " + iProbCurr.ToString() + " => " + new_pb.ToString());
          }
        }
        
        /* If something has gold quality -1, dont touch */
        if (gQualCurr > -1 && (gProbCurr > 0 || gAlways)) {
          if (gProbCurr < 5) {
            int new_gpb = gProbCurr + pIncrement;
            if (new_gpb > 4) {
              new_gpb = 5;
            } else if (gpb > new_gpb) {
              new_gpb = gpb;
            }
            if (new_gpb > gProbCurr) {
              Writer.BaseStream.Seek(gProbOffset, SeekOrigin.Begin);
              Writer.Write(new_gpb);
              Log("    gProb: " + gProbCurr.ToString() + " => " + new_gpb.ToString());
            }
          }

          if (gq > gQualCurr) {
            Writer.BaseStream.Seek(gQualOffset, SeekOrigin.Begin);
            Writer.Write(gq);
            Log("    gQual: " + gQualCurr.ToString() + " => " + gq.ToString());
          }
        }

        if (ltbl.numItems > 0 && ltbl.itemOffset != 0) {
          for (int j = 0; j < ltbl.numItems; j++) {
            long itemOffset        = ltbl.itemOffset + (j * 36);
            long minQuantityOffset = itemOffset + 4;
            long maxQuantityOffset = itemOffset + 8;
            long maxPerAreaOffset  = itemOffset + 12;
            long weightOffset      = itemOffset + 16;

            Reader.BaseStream.Seek(itemOffset, SeekOrigin.Begin);

            long res_id  = Reader.ReadUInt32();
            int minimum  = Reader.ReadInt32();
            int maximum  = Reader.ReadInt32();
            int maxarea  = Reader.ReadInt32();
            float weight = ReadFloat(Reader.BaseStream);

            Log("    item [" + j.ToString() + "]:");
            
            /* Dont mess with amounts unless it is a material and the user checked the box */

            if (mOverride && ltbl.itype == IType.Material) {
              if (mMin > minimum) {
                Writer.BaseStream.Seek(minQuantityOffset, SeekOrigin.Begin);
                Writer.Write(mMin);
                Log("      MinQuantity: " + minimum.ToString() + " => " + mMin.ToString());
              }
              if (mMax > maximum) {
                Writer.BaseStream.Seek(maxQuantityOffset, SeekOrigin.Begin);
                Writer.Write(mMax);
                Log("      MaxQuantity: " + maximum.ToString() + " => " + mMax.ToString());
              }
              if (maxarea > 0) {
                Writer.BaseStream.Seek(maxPerAreaOffset, SeekOrigin.Begin);
                Writer.Write(0); /* No Max Per Area */
                Log("      MaxPerArea: " + maxarea.ToString() + " => Unlimited");
              }
            }
            
            /* do we boost? */
            if (wBoost) {
              Writer.BaseStream.Seek(weightOffset, SeekOrigin.Begin);
              Writer.Write(boostvalue);
              Log("      ProbWeightBoost: " + weight.ToString() + " => " + boostvalue.ToString());
            } else if (weight != 1.0) {
              Writer.BaseStream.Seek(weightOffset, SeekOrigin.Begin);
              Writer.Write(1.0);
              Log("      ProbWeight: " + weight.ToString() + " => 1.0");
            }    
          }
        }

        Scripting.SetResourceData(iblob, ms.ToArray());
        Reader.Close();
        Writer.Close();

      }

      Scripting.LogLn("Loot Settings Applied");

    }
  }
}

I found this on another thread here: config-coding-example-and-tips-t648.html and thought it would be useful for someone to pick up scripting tips from. 

Bear in mind that this entire script may not be useful per se, as Tirnoney had to remake it afterwards because of a patch (this quote is from Moreloot Remade mod page on Nexus):
The original More Loot mod was built with a different game patch and a completely different set of modding tools. Rebuilding it meant exporting and importing every single loot table from scratch (207 of them to be exact). Unfortunately until recently, there hasn't been a way to restore configuration scripts so any attempt to rebuild the mod wouldn't have worked. I've tried to reuse as much of the original configuration script as I could, but some of it had to be culled and rebuilt. The current modding tools don't support the addition of unbound data, so the Add Extra Stuff option had to go. There is a way around that, but it involves a lot of extra work I'm not quite ready to embark upon at the moment. Every single loot table offset has also changed, including the way each variable is addressed within the asset, so that too had to be altered.

Hopefully, there wont be any more patches that will break it horribly in the near future.
.
.
The Config Script Editor Tirnoney mentions is here: daimod-config-script-editor-t1346.html

I've always found C to be completely impenetrable, so I'm going to learn more via some tutorial videos. This playlist looks like a good starting point to me.
https://www.youtube.com/watch?v=3Ti_n6d ... 96&index=2
Last edited by Svarty on January 12th, 2018, 8:31 pm, edited 3 times in total.
Quote
Like
Share

Joined: October 21st, 2017, 4:54 pm

December 4th, 2017, 9:37 pm #3

HOLY SHIZZLE! I did it! I wrote something in C! It's messy, but it's amazing! I'm amazing! WOOHOO!

So here is my crappy code. It takes data from the NewData array and puts it in the corresponding position in the Offset array. In this specific instance, it fixes elf ear clipping on helmets by telling the game to use the alternate head morph "NoEars" - and in the case of Elven cowl, it turns ears on (that's the 00 value in the NewData array).

Code: Select all

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Threading;
namespace DAIMod {
    public class EarClipFixScript : ModScript 
    {
        public void ConstructUI(ModConfigElementsList ConfigElementsList) 
        {
        }
        public void RunScript() {
            int TotalEBXResourceNumber = 8;
            int[] NewData = new int[8]; 
            // We will put 1 new datum in each Offset
            NewData[0] = 01;
            NewData[1] = 00;
            NewData[2] = 01;
            NewData[3] = 01;
            NewData[4] = 01;
            NewData[5] = 01;
            NewData[6] = 01;
            NewData[7] = 01;
            long[] Offset = new long[8]; 
            // We will change 1 Offset Per hat (that's why we only need 1 loop)
            Offset[0] = 0x1390;
            Offset[1] = 0x1390;
            Offset[2] = 0x1390;
            Offset[3] = 0x13a0;
            Offset[4] = 0x13a0;
            Offset[5] = 0x13a0;
            Offset[6] = 0x13a0;
            Offset[7] = 0x13a0;
            // We know there are 6 Different Hats to change
            // Loop through the Hats
            for (int EBXCounter = 0; EBXCounter < TotalEBXResourceNumber; EBXCounter++) {
                //ASSIGN WHICH RESOURCE HERE
                MemoryStream memSt = new MemoryStream(Scripting.GetResourceData(EBXCounter));
                BinaryWriter Writer = new BinaryWriter(memSt);
                // Write the Data
                Writer.BaseStream.Seek(Offset[EBXCounter], SeekOrigin.Begin);
                Writer.Write(NewData[EBXCounter]);
                Scripting.SetResourceData(EBXCounter, memSt.ToArray());
                Writer.Close();
                }
        }
    }    
}        
Thanks Tirnoney and Dheuster, you guys are fantastic!
Quote
Like
Share

Joined: October 21st, 2017, 4:54 pm

December 9th, 2017, 2:59 pm #4

This is my Better Hats script. It just replaces the Primary slots with 5 and the secondary slots with 12 (note that it is 12 in decimal in the code and not the hex version, 0c). As you can see there are 27 vanilla hats.
Each hat recipe is imported as a Bound Resource.

This same code can be used to modify things instead of using hex editors. That big list of Add statements should be replaced with your own, but all you do is;
  • put the Bound Resource number as the Resource (in Tirnoney's example above it's just 0),
  • the Offset in the format of the ones below and,
  • the Value you want in that Offset. 
I'm still learning and have yet to work out how to send a code like 3e to the Offsets (I would guess you work out what it is in decimal (i.e. 62) and send that [Confirmed in the script in the post below this one, also see that code for (byte)Convert.ToInt32( variable_name , 16 ); ]).

Code: Select all

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Threading;
namespace DAIMod {
    public class BetterHatsScript : ModScript 
    {
        public void ConstructUI(ModConfigElementsList ConfigElementsList) 
        {
        }
        class Item
        {
            public int Resource{ get;set; }
            public long Offset{ get;set; }
            public int Value{ get;set; }
        }
        public void RunScript() {
            List<Item> Items = new List<Item>();
            //
            Items.Add(new Item{Resource = 0, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 1, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 2, Offset = 0xa1c, Value = 05});
            Items.Add(new Item{Resource = 3, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 4, Offset = 0xa20, Value = 05});
            Items.Add(new Item{Resource = 5, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 6, Offset = 0xa20, Value = 05});
            Items.Add(new Item{Resource = 7, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 8, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 9, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 10, Offset = 0xa50, Value = 05});
            Items.Add(new Item{Resource = 11, Offset = 0xa68, Value = 05});            
            Items.Add(new Item{Resource = 12, Offset = 0xa20, Value = 05});
            Items.Add(new Item{Resource = 13, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 14, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 15, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 16, Offset = 0xa50, Value = 05});
            Items.Add(new Item{Resource = 17, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 18, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 19, Offset = 0xa78, Value = 05});
            Items.Add(new Item{Resource = 20, Offset = 0xa48, Value = 05});
            Items.Add(new Item{Resource = 21, Offset = 0xa50, Value = 05});
            Items.Add(new Item{Resource = 22, Offset = 0xa20, Value = 05});
            Items.Add(new Item{Resource = 23, Offset = 0xa48, Value = 05});
            Items.Add(new Item{Resource = 24, Offset = 0xa60, Value = 05});
            Items.Add(new Item{Resource = 25, Offset = 0xa38, Value = 05});            
            Items.Add(new Item{Resource = 26, Offset = 0xa50, Value = 05});
            Items.Add(new Item{Resource = 0, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 1, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 2, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 3, Offset = 0xa20, Value = 12});
            Items.Add(new Item{Resource = 4, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 5, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 6, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 7, Offset = 0xa20, Value = 12});
            Items.Add(new Item{Resource = 8, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 9, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 10, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 11, Offset = 0xa50, Value = 12});            
            Items.Add(new Item{Resource = 12, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 13, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 14, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 15, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 16, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 17, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 18, Offset = 0xa20, Value = 12});
            Items.Add(new Item{Resource = 19, Offset = 0xa48, Value = 12});
            Items.Add(new Item{Resource = 20, Offset = 0xa78, Value = 12});
            Items.Add(new Item{Resource = 21, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 22, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 23, Offset = 0xa60, Value = 12});
            Items.Add(new Item{Resource = 24, Offset = 0xa78, Value = 12});
            Items.Add(new Item{Resource = 25, Offset = 0xa20, Value = 12});            
            Items.Add(new Item{Resource = 26, Offset = 0xa38, Value = 12});
            //
            //
            //
            foreach (var Thing in Items)
                {
                // 
                MemoryStream memSt = new MemoryStream(Scripting.GetResourceData(Thing.Resource));
                // 
                BinaryWriter Writer = new BinaryWriter(memSt);
                // 
                Writer.BaseStream.Seek(Thing.Offset, SeekOrigin.Begin);
                // 
                Writer.Write(Thing.Value);
                // 
                Scripting.SetResourceData(Thing.Resource, memSt.ToArray());
                Writer.Close();
                }
        }
    }    
}        
Here is the spreadsheet I made to make inputting the data easier. I just pasted the Bound (Resources) column three times to make it easy to refer to (I know it's not 100% correct):

As Dheuster mentions above, you don't get to choose which number is allocated to the Bound Resources, that's why I had to make note of it.
Last edited by Svarty on December 19th, 2017, 9:55 am, edited 2 times in total.
Quote
Like
Share

Joined: October 21st, 2017, 4:54 pm

December 14th, 2017, 5:41 pm #5

As a non-programmer who doesn't know C, I found it extremely difficult to write script with barely any examples. This is why I'm posting all my scripts on this thread - to help people with working examples.

To this end I give you my Better Hats and The One Hat mod. This contains the mod above, but also adds a LOT of configurable functionality to a single hat - I wanted to put both together to avoid people having to mess about with a Load Order. 

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace DAIMod
{
    // This section sets up elements for the UI dropdown menus
    public enum Material   { Cloth, Leather, Metal }
    public enum Slottype   { Defense, Utility }    
    public enum Appearance { Templar_Helmet, Dwarven_Helmet, Warden_Helmet, Helm_of_the_Inquisitor, Venatori_Helmet, 
                             Orlesian_Helmet, Templar_Scribe_Cowl, Battlemage_Cowl, Elven_Cowl, Overseer_Cowl, Inquisitor_Hat, 
                             Orlesian_Mage_Hat, Seer_Cowl, Scout_Hat, Fereldan_Scout_Hat, Adventurer_Hat, 
                             Inquisition_Scout_Hat, Carta_Hat, Skirmisher_Hat, Overlord_Helm, Mask_of_the_Empress,
                             Mask_of_the_Baron, Ambassador_Mask, Mask_of_the_Grand_Duchess, Gladiator_Helmet}
                             
    public class scriptname : ModScript 
    {
        // This section sets up the list items that will get sent to the writer
        class Item 
        {
            public int Resource{ get;set; }
            public long Offset{  get;set; }
            public byte Value{   get;set; }
        } 
        
        //    This section is the UI 
        public void ConstructUI(ModConfigElementsList ConfigElementsList) 
        {
            ConfigElementsList.AddEnumElement( "SOM", "Slot 1 Material",   typeof(Material), 1); // Defaults to 1
            ConfigElementsList.AddIntElement(  "SOS", "Slot 1 Size",       5, 1, 99); //Defaults to 5, min 1 max 99
            ConfigElementsList.AddEnumElement( "STM", "Slot 2 Material ",  typeof(Material), 1);
            ConfigElementsList.AddIntElement(  "STS", "Slot 2 Size",       12, 1, 99);
            ConfigElementsList.AddEnumElement( "STT", "Slot 2 Type ",      typeof(Slottype), 1);
            ConfigElementsList.AddEnumElement( "APP", "Appearance ",       typeof(Appearance), 7);
        }    
        
        public void RunScript() 
        {
            List<Item> Items = new List<Item>();
            
            int schmtc = 1; //Bound resource number of the schematic for the hat we are changing
            int qptmplt= 0; //Bound resource number of the equiptemplate for the hat we are changing
            
            //This section gets data from the UI
            Material SOM = (Material)Scripting.GetConfigParam("SOM");
            Material STM = (Material)Scripting.GetConfigParam("STM");
            int STS = (int)Scripting.GetConfigParam("STS");                
            int SOS = (int)Scripting.GetConfigParam("SOS");             
            Slottype STT = (Slottype)Scripting.GetConfigParam("STT");
            Appearance APP = (Appearance)Scripting.GetConfigParam("APP");
            
            //This section converts UI data to ints
            byte Slot_One_Mat =  (byte)((int)SOM);
            byte Slot_Two_Mat =  (byte)((int)STM);
            byte Slot_One_Siz =  (byte)((int)SOS);
            byte Slot_Two_Siz =  (byte)((int)STS);
            byte Slot_Two_Typ =  (byte)((int)STT);
            byte Skin_num =      (byte)((int)APP);

            //REPORT Section. This section outputs settings to the Modmanager window
            Scripting.LogLn("THE ONE HAT choices chosen ****************************");             
            Scripting.LogLn("  Slot one material          : " + SOM.ToString() + " (" + Slot_One_Mat.ToString() + ")");
            Scripting.LogLn("  Slot two material          : " + STM.ToString() + " (" + Slot_Two_Mat.ToString() + ")");
            Scripting.LogLn("  Slot one size              : " + SOS.ToString() + " (" + Slot_One_Siz.ToString() + ")");
            Scripting.LogLn("  Slot two size              : " + STS.ToString() + " (" + Slot_Two_Siz.ToString() + ")");
            Scripting.LogLn("  Slot two type              : " + STT.ToString() + " (" + Slot_Two_Typ.ToString() + ")");
            Scripting.LogLn("  Skin                       : " + APP.ToString() + " (" + Skin_num.ToString() + ")");
            Scripting.LogLn("THE ONE HAT choices ends here ************************");
            
            //STATS Section. This section puts values in the list that overwrite the RECIPE for heavy helm 5 rare
            Slot_Two_Typ++;         // This line adds 1 to the number, making it 2 for Utility and 1 for Defense slot
            Items.Add(new Item{Resource = schmtc, Offset = 0xa2c, Value = Slot_Two_Typ}); 
            if (Slot_Two_Typ == 1)  // You need to change 2 values to change a slot type, this one is stringID for it
            {
                Items.Add(new Item{Resource = schmtc, Offset = 0xa28, Value = 61}); // 61 = 3D
            }
            else
            {
                Items.Add(new Item{Resource = schmtc, Offset = 0xa28, Value = 62}); // 62 = 3E
            }
    
            Items.Add(new Item{Resource = schmtc, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = schmtc, Offset = 0xa38, Value = Slot_Two_Siz});
            Items.Add(new Item{Resource = schmtc, Offset = 0xa64, Value = Slot_One_Mat});
            Items.Add(new Item{Resource = schmtc, Offset = 0xa34, Value = Slot_Two_Mat});
            
            Items.Add(new Item{Resource = schmtc, Offset = 0xa04, Value = 27}); // This sets the Level of the item
            //STATS End of section
                    
            
            //APPEARANCE Section. This replaces appearance on the resource 1 equiptemplate for heavy helmet 2        
            int Num_Of_Skins = 25; //Number of skins -1 because they start at 0
            string[] GUID_Array = new string[(Num_Of_Skins*2)]; 
            int[] HeadAppCode = new int[Num_Of_Skins];
            // "Templar Helmet"
            GUID_Array[0] = "c3b4a62d00f7e843989c3d33b22af36d";
            GUID_Array[0+Num_Of_Skins] = "77c15f4398f8b448a7f1b8eeadeec1fe";
            HeadAppCode [0] = 3;
            // "Dwarven Helmet"
            GUID_Array[1] = "fd3879a71c273545bc50ce069d94946b";
            GUID_Array[1+Num_Of_Skins] = "a39a9fbdb2043c49978a66b9132048af";
            HeadAppCode [1] = 7;
            // "Warden Helmet"
            GUID_Array[2] = "d38742761fab7946b6ee4c4e5de5f575";
            GUID_Array[2+Num_Of_Skins] = "9d3d6c735b3f0b4e920a89f4b8ec3b03";
            HeadAppCode [2] = 3;
            // "Helm of the Inquisitor"
            GUID_Array[3] = "c3a33a33d6f2644980a29451c22f41e9";
            GUID_Array[3+Num_Of_Skins] = "23bb645915f5994788bfb271f16b8678";
            HeadAppCode [3] = 1;
            // "Venatori Helmet"
            GUID_Array[4] = "59afff6a84ad4b4bb280b695bd137741";
            GUID_Array[4+Num_Of_Skins] = "e960c5aa57a58f4b8c7204470d6f092a";
            HeadAppCode [4] = 3;
            // "Orlesian Helmet"
            GUID_Array[5] = "bfd2f974899b0a41affe049ea7c6e092";
            GUID_Array[5+Num_Of_Skins] = "90bfcb300fd0ed44835e915a788c6d6d";
            HeadAppCode [5] = 3;
            // "Templar Scribe Cowl"
            GUID_Array[6] = "dc1b4b7c88bc3549977d1a73bc3cc633";
            GUID_Array[6+Num_Of_Skins] = "ce4a79dbbd7aa542abea14de04682819";
            HeadAppCode [6] = 1;
            // "Battlemage Cowl"            
            GUID_Array[7] = "9c827aba86c0534f9616fb5ad8de4fe1";
            GUID_Array[7+Num_Of_Skins] = "10f3a980fc3d0543879247301fc5e669";
            HeadAppCode [7] = 1;
            // "Elven Cowl"
            GUID_Array[8] = "25670455ce8c5448b79de995c05cb110";
            GUID_Array[8+Num_Of_Skins] = "5a49ce62c036e844a94039e05c8b6b57";
            HeadAppCode [8] = 0;
            // "Overseer Cowl"
            GUID_Array[9] = "658aa815dfb19a48b9b15935b88283ed";
            GUID_Array[9+Num_Of_Skins] = "60e4b971e1f42447af94321ca552db5c";
            HeadAppCode [9] = 0;
            // "Inquisitor Hat"
            GUID_Array[10] = "f3e26e2a6d427a449ea3edb356b3b005";
            GUID_Array[10+Num_Of_Skins] = "40c6779486a5be4cb6b99a26a692b47b";
            HeadAppCode [10] = 0;
            // "Orlesian Mage Hat"
            GUID_Array[11] = "415b04341f080549ae92221467d740d5";
            GUID_Array[11+Num_Of_Skins] = "332b05473ee9de4496b32123d554d28e";
            HeadAppCode [11] = 0;
            // "Seer Cowl"
            GUID_Array[12] = "7f3e61caf7389849aab8733738bf6790";
            GUID_Array[12+Num_Of_Skins] = "f1ca9bd4b062a346bb849ec267394dc9";
            HeadAppCode [12] = 1;
            // "Scout Hat"
            GUID_Array[13] = "981ef3f13ab0e145adc9a28c2c87ca58";
            GUID_Array[13+Num_Of_Skins] = "ca9a2e34eb12eb4f9d568030e0ead4e3";
            HeadAppCode [13] = 1;
            // "Fereldan Scout Hat"
            GUID_Array[14] = "10007181f808cc418bd14ab3bc8d294b";
            GUID_Array[14+Num_Of_Skins] = "e639bbc396bdb44db35411f9417b7c0c";
            HeadAppCode [14] = 1;
            // "Adventurer Hat"
            GUID_Array[15] = "ad9063844e3db64895eb0da7db61dce5";
            GUID_Array[15+Num_Of_Skins] = "f225c6aae37c3b4eaccc87369b5778a0";
            HeadAppCode [15] = 1;
            // "Inquisition Scout Hat"
            GUID_Array[16] = "02e343e3b640974b87a7f7b358fdbdf2";
            GUID_Array[16+Num_Of_Skins] = "4fb5b1e35335da40875496c63c478caa";
            HeadAppCode [16] = 0;
            // "Carta Hat"
            GUID_Array[17] = "d477188ec951724e9a0fd941b7016490";
            GUID_Array[17+Num_Of_Skins] = "fe3ba72e2a717847aade478ff7208b00";
            HeadAppCode [17] = 1;
            // "Skirmisher Hat"
            GUID_Array[18] = "9fa94cb58b7cb24fac8a978987bab3fc";
            GUID_Array[18+Num_Of_Skins] = "4955e5f707c8de48a59255597fc412e4";
            HeadAppCode [18] = 3;
            // "Overlord Helm"
            GUID_Array[19] = "c493053226948346b04ed2a41b1cf446";
            GUID_Array[19+Num_Of_Skins] = "49ce7c87620aca48b38be49e09a762d4";
            HeadAppCode [19] = 0;
            // "Mask Empress"
            GUID_Array[20] = "78a345450ed9e94ab7247f2e946d77fd";
            GUID_Array[20+Num_Of_Skins] = "bf7dabead684ef4085cb428614772ee4";
            HeadAppCode [20] = 1;
            // "Mask Baron"
            GUID_Array[21] = "b58ad694e9c2f44ea377ba9ea98efb9e";
            GUID_Array[21+Num_Of_Skins] = "67ffa84fcf99fe499166c7cbb94020bc";
            HeadAppCode [21] = 1;
            // Mask Ambassador
            GUID_Array[22] = "a5714f14d9576d478fa8789f879621b1"; 
            GUID_Array[22+Num_Of_Skins] = "7e11274d35b03f4fbe6bdfab0ce743ab";
            HeadAppCode [22] = 1;
            // Mask Grand Duchess
            GUID_Array[23] = "a44d2a393cd1b842867a367bf2220e4c"; 
            GUID_Array[23+Num_Of_Skins] = "f0ef2dd88d88be47b91ac01c690cb5d5";
            HeadAppCode [23] = 1;
            // Gladiator Helmet
            GUID_Array[24] = "6cb48fd001425d4f9230daef4322b97b"; 
            GUID_Array[24+Num_Of_Skins] = "698bcd243cde9f42949dd8a09df91bb2";
            HeadAppCode [24] = 7;
            
            // This subsection decodes HeadAppCode into 3: so game can turn off Ears, Beard, Face as appropriate
            // Code is turn off 1 Ears + 2 Beard + 4 Face : so 5 would be ears and face but not beard for example
            int the_reducer = HeadAppCode[Skin_num];
            // FACE    
            if ((the_reducer -4) > 0)
            {
                the_reducer -= 4;
                Items.Add(new Item{Resource = qptmplt, Offset = 0x139c, Value = 01}); // sends 1 to turn off face
            }
            else
            {
                Items.Add(new Item{Resource = qptmplt, Offset = 0x139c, Value = 00}); // sends a 0 to keep face
            }
            //BEARD
            if ((the_reducer -2) > 0)
            {
                the_reducer -= 2;
                Items.Add(new Item{Resource = qptmplt, Offset = 0x139b, Value = 01}); // sends 1 to turn off beard
            }
            else
            {
                Items.Add(new Item{Resource = qptmplt, Offset = 0x139b, Value = 00}); // sends a 0 to keep beard
            }
            //EARS
            if (the_reducer > 0)
            {
                Items.Add(new Item{Resource = qptmplt, Offset = 0x1390, Value = 01}); // sends a 1 to turn off ears
            }
            else
            {
                Items.Add(new Item{Resource = qptmplt, Offset = 0x1390, Value = 00}); // sends a 0 to turn keep ears
            }
            // end of subsection
            
            // This subsection writes the GUIDs of the selected skin  
            string[] GUID = new string[2] {GUID_Array[Skin_num],GUID_Array[Skin_num + Num_Of_Skins]};
            long[] Origin = new long[2] {0x0100,0x0110};
            
            for (int counter = 0 ; counter <= 1 ; counter++ )
            {
                long Offski = Origin[counter];
                for ( int i = 0; i < 16; i++ )
                {
                    Offski = Origin[counter] + i;                                     //move the pointer to the next 2 characters in the destination offset
                    string Vaski = (string)GUID[counter].Substring( i * 2 , 2 );     //Vaski is the value of the guid in the position (i*2) and is 2 characters long.
                    byte Vaskibyte = (byte)Convert.ToInt32( Vaski , 16 );             //convert the 2 string characters of decimal value Vaski to a byte value in hex (the 16)
                    Items.Add(new Item{Resource = qptmplt, Offset = Offski, Value = Vaskibyte}); 
                }
            }
            //APPEARANCE: End of section 
            
            //BETTER OTHER HATS This section replaces MaterialUsedCount on 27 hats to 05 for Primary slot and 12 for Secondary slot 
            /*
            0. is equiptemplate 
            1. is the schematic, it is written above instead
            */  
            //Items.Add(new Item{Resource = 0, Offset = 0xa68, Value = 05});
            //Items.Add(new Item{Resource = 1, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 2, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 3, Offset = 0xa1c, Value = 05});
            Items.Add(new Item{Resource = 4, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 5, Offset = 0xa20, Value = 05});
            Items.Add(new Item{Resource = 6, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 7, Offset = 0xa20, Value = 05});
            Items.Add(new Item{Resource = 8, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 9, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 10, Offset = 0xa68, Value = 05});            
            Items.Add(new Item{Resource = 11, Offset = 0xa50, Value = 05});
            Items.Add(new Item{Resource = 12, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 13, Offset = 0xa20, Value = 05});
            Items.Add(new Item{Resource = 14, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 15, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 16, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 17, Offset = 0xa50, Value = 05});
            Items.Add(new Item{Resource = 18, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 19, Offset = 0xa68, Value = 05});
            Items.Add(new Item{Resource = 20, Offset = 0xa78, Value = 05});
            Items.Add(new Item{Resource = 21, Offset = 0xa48, Value = 05});
            Items.Add(new Item{Resource = 22, Offset = 0xa50, Value = 05});
            Items.Add(new Item{Resource = 23, Offset = 0xa20, Value = 05});
            Items.Add(new Item{Resource = 24, Offset = 0xa48, Value = 05});
            Items.Add(new Item{Resource = 25, Offset = 0xa60, Value = 05});            
            Items.Add(new Item{Resource = 26, Offset = 0xa38, Value = 05});
            Items.Add(new Item{Resource = 27, Offset = 0xa50, Value = 05});
            //Items.Add(new Item{Resource = 0, Offset = 0xa38, Value = 12});
            //Items.Add(new Item{Resource = 1, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 2, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 3, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 4, Offset = 0xa20, Value = 12});
            Items.Add(new Item{Resource = 5, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 6, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 7, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 8, Offset = 0xa20, Value = 12});
            Items.Add(new Item{Resource = 9, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 10, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 12, Offset = 0xa50, Value = 12});            
            Items.Add(new Item{Resource = 13, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 14, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 15, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 16, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 17, Offset = 0xa68, Value = 12});
            Items.Add(new Item{Resource = 18, Offset = 0xa50, Value = 12});
            Items.Add(new Item{Resource = 19, Offset = 0xa20, Value = 12});
            Items.Add(new Item{Resource = 20, Offset = 0xa48, Value = 12});
            Items.Add(new Item{Resource = 21, Offset = 0xa78, Value = 12});
            Items.Add(new Item{Resource = 22, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 23, Offset = 0xa38, Value = 12});
            Items.Add(new Item{Resource = 24, Offset = 0xa60, Value = 12});
            Items.Add(new Item{Resource = 25, Offset = 0xa78, Value = 12});            
            Items.Add(new Item{Resource = 26, Offset = 0xa20, Value = 12});
            Items.Add(new Item{Resource = 27, Offset = 0xa38, Value = 12});
            //SECTION ENDS
            
            //This section does all the voodoo mojo magic stuff I don't understand
            foreach (var Thing in Items) 
            {
                MemoryStream memSt = new MemoryStream(Scripting.GetResourceData(Thing.Resource));
                BinaryWriter Writer = new BinaryWriter(memSt);
                Writer.BaseStream.Seek(Thing.Offset, SeekOrigin.Begin);
                Writer.Write(Thing.Value);
                Scripting.SetResourceData(Thing.Resource, memSt.ToArray());
                Writer.Close();
            }
            
        }    
    }
}
After struggling my way through all this, I finally found a Documentation section on the Config Script Editor. I urge all new script writers to look at it, it has a LOT of good info.

Things to do if you want to add new hats to the mod (you don't need to add bound resources):
  • Add the hat name(s) to the big list at the top that has names of hats in it,
  • Search the program for "Num_Of_Skins" (without quotes) and add however many new hats you are adding to the number,
  • Add a new entry to the GUID list with the two GUID numbers of the APPEARANCE of the hat(s) - remember to increase the number in square brackets by 1 for that entry
  •             GUID_Array[20] = "78a345450ed9e94ab7247f2e946d77fd";
  •             GUID_Array[20+Num_Of_Skins] = "bf7dabead684ef4085cb428614772ee4";
  • Add an entry for HeadAppCode like this (again remember to increase the number in square brackets.
  • The code is this, if the hat should turn off the head, add 4 to the number, if it is to turn off beards, add 2, if it is to turn off ears, add 1 - if it looks fine without anything turned off (i.e. you don't get graphics clipping) put 0.
  •             HeadAppCode [20] = 0;
That's it! 

Here is what the spreadsheet looked like in the end: 
Last edited by Svarty on December 22nd, 2017, 7:06 am, edited 5 times in total.
Quote
Like
Share

Joined: October 21st, 2017, 4:54 pm

December 18th, 2017, 2:51 pm #6

Here is the script for Choose Your Own Avenger. 

You need to make the EQUIP TEMPLATE for Avenger ("longsword t3_5 Unique") into a bound asset (Export it then Import it again in ModMaker - no changes necessary). Save that Daimod and then combine with this script in the DAIMod Config Script Editor.

As you can see, this is a stripped-down version of my hats mod (above).

Now that I've done this basic code structure, it can be manipulated for much easy modding :D WOohoo! Enjoy!

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace DAIMod
{
    // This section sets up elements for the UI dropdown menus
    public enum Appearance { Blade_of_the_Champion, Emperor_Guard_Blade, Keen_Machete, Longsword_of_the_Dragon,
                            Nevarran_Noble_Sword, Sword_of_Charris_Allied, Templars_First, The_Bone }
                             
    public class scriptname : ModScript 
    {
        // This section sets up the list items that will get sent to the writer
        class Item 
        {
            public int Resource{ get;set; }
            public long Offset{  get;set; }
            public byte Value{   get;set; }
        } 
        
        //    This section is the UI 
        public void ConstructUI(ModConfigElementsList ConfigElementsList) 
        {
                ConfigElementsList.AddEnumElement( "APP", "Appearance  ",       typeof(Appearance), 0);
        }    
        
        public void RunScript() 
        {
            List<Item> Items = new List<Item>();
            
            int qptmplt= 0; //Bound resource number of the equiptemplate for the swd we are changing
            
            //This section gets data from the UI
            Appearance APP = (Appearance)Scripting.GetConfigParam("APP");
            
            //This section converts UI data to ints
            byte Skin_num =      (byte)((int)APP);

            //REPORT Section. This section outputs settings to the Modmanager window
            
            //APPEARANCE Section. This replaces appearance on the resource 1 equiptemplate for heavy helmet 2        
            int Num_Of_Skins = 8; //Number of skins -1 because they start at 0
            string[] GUID_Array = new string[(Num_Of_Skins*2)]; 
            
            //Blade_of_the_Champion,  
            GUID_Array[0] = "bf0843742ea2124ebf1c67265b5f4860";
            GUID_Array[0+Num_Of_Skins] = "cf99df30db1f344db43a8234f318f5b5";
            //Emperor_Guard Blade,
            GUID_Array[1] = "c6746dfa1a5d814f8bc76dc8ea1adf60";
            GUID_Array[1+Num_Of_Skins] = "7cf0f0e5de6c8e41954fa11aa0d972ef";
            //Keen_Machete, 
            GUID_Array[2] = "b7ee7c05bc717a42bde6ab1cc7dfaf51";
            GUID_Array[2+Num_Of_Skins] = "a60dbfdba1682d429032187d0ac4c2cd";
            //Longsword_of_the_Dragon
            GUID_Array[3] = "ce0fd719c783464f87b016c7fb1a0710";
            GUID_Array[3+Num_Of_Skins] = "37e87b28b254974da01f2dde118bb108";
            //Nevarran_Noble_Sword,
            GUID_Array[4] = "3c1dd0b94f50eb4d814f17a4934c60de";
            GUID_Array[4+Num_Of_Skins] = "20074c6da0e79d45b490b4af8df1d2df";
            //Sword_of_Charris_Allied,
            GUID_Array[5] = "1ef151050380764c8bb7cf8e1d26f2f9";
            GUID_Array[5+Num_Of_Skins] = "3da2055bd9c1814caf0ae144f87d7700";
            //Templar's_First, 
            GUID_Array[6] = "6b8e352a68692044991e0896f9f6fcee";
            GUID_Array[6+Num_Of_Skins] = "cf0348780c28104a9435638bdc9c8bbc";
            //The_Bone
            GUID_Array[7] = "afecb3de49a1784eadfd96d1be500fcc";
            GUID_Array[7+Num_Of_Skins] = "1e7160575b00eb41a6d7b669d67725f5";
            
            // This subsection writes the GUIDs of the selected skin  
            string[] GUID = new string[2] {GUID_Array[Skin_num],GUID_Array[Skin_num + Num_Of_Skins]};
            long[] Origin = new long[2] {0x0100,0x0110};
            
            for (int counter = 0 ; counter <= 1 ; counter++ )
            {
                long Offski = Origin[counter];
                for ( int i = 0; i < 16; i++ )
                {
                    Offski = Origin[counter] + i;                                     //move the pointer to the next 2 characters in the destination offset
                    string Vaski = (string)GUID[counter].Substring( i * 2 , 2 );     //Vaski is the value of the guid in the position (i*2) and is 2 characters long.
                    byte Vaskibyte = (byte)Convert.ToInt32( Vaski , 16 );             //convert the 2 string characters of decimal value Vaski to a byte value in hex (the 16)
                    Items.Add(new Item{Resource = qptmplt, Offset = Offski, Value = Vaskibyte}); 
                    Scripting.LogLn("Writing offset: " + Offski + " with " + Vaskibyte);        
                }
            }
            //APPEARANCE: End of section 
            
            
            //This section does all the voodoo mojo magic stuff I don't understand
            foreach (var Thing in Items) 
            {
                MemoryStream memSt = new MemoryStream(Scripting.GetResourceData(Thing.Resource));
                BinaryWriter Writer = new BinaryWriter(memSt);
                Writer.BaseStream.Seek(Thing.Offset, SeekOrigin.Begin);
                Writer.Write(Thing.Value);
                Scripting.SetResourceData(Thing.Resource, memSt.ToArray());
                Writer.Close();
            }
            
        }    
    }
}
The hard part was finding all the appearance codes. As you can see, some of the swords below didn't make it into the final mod, but could easily be added using the technique described in the post above this one for adding new hats:
 
Quote
Like
Share

Joined: October 21st, 2017, 4:54 pm

December 19th, 2017, 2:13 pm #7

I'm currently testing to see if it's possible to make a file that I can use to save the config settings in. If it works, it would allow users who merge a lot to keep their settings each time. 

Early indications are.... NO.


If this is going to be possible, I suspect it will have to be someone who actually understands C# that does it. Sorry.
Quote
Like
Share

Joined: October 21st, 2017, 4:54 pm

December 22nd, 2017, 6:46 am #8

It turns out that .daimod files include the entirety of the script that authors put in them. I cut this out of Tirnoney's updated MoreFlexLoot. This should be compared with Dheuster's original (above).

FURTHER EXAMPLES can be found in this mod: https://rd.nexusmods.com/dragonageinqui ... escription (Simply open the DAImod files with Notepad++ and scroll down to the code).

Code: Select all

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Threading;

namespace DAIMod {

  public enum Probability { Override_Disabled, Very_Low, Low, Medium, High, Very_High }
  public enum Quality     { Override_Disabled, Low_X, High_X, Low_XX, Med_XX, High_XX, Med_1XX, High_1XX, Med_2XX }

  public enum IType       { Any, Material, Recipe, Armor, Weapon, Valuable, Upgrade, Jewelry }

  public class LootTable {

    public long   offset;
    public bool   is_crafting;
    public int    numItems;
    public long   itemOffset;
    public IType  itype;

    public LootTable(long p_offset = 0, IType p_itype = IType.Any, int p_numItems = 0, long p_itemOffset = 0) {
      offset      = p_offset;
      itype       = p_itype; 
      is_crafting = ((itype == IType.Material) || (itype ==IType.Recipe));
      numItems    = p_numItems;
      itemOffset  = p_itemOffset;
    }

  }

  public class MoreLootFlexMod : ModScript {

    public const int totalBound = 207;
    public bool  logVerbose = false;


    public void ConstructUI(ModConfigElementsList ConfigElementsList) {


      ConfigElementsList.AddEnumElement("dProb",       "Override Drop Probability",           typeof(Probability), 0);
      ConfigElementsList.AddIntElement( "pIncrement",  "Increment Probabilities By (0-4)",    2, 0, 4);

      ConfigElementsList.AddEnumElement("gProb",       "Gold Probability",                    typeof(Probability), 0);
      ConfigElementsList.AddEnumElement("gQual",       "Gold Quality",                        typeof(Quality), 0);
      ConfigElementsList.AddEnumElement("aProb",       "Override Armor Probability",          typeof(Probability), 0);
      ConfigElementsList.AddEnumElement("wProb",       "Override Weapon Probability",         typeof(Probability), 0);
      ConfigElementsList.AddEnumElement("jProb",       "Override Jewelry Probability",        typeof(Probability), 0);
      ConfigElementsList.AddEnumElement("vProb",       "Override Valuable Probability",       typeof(Probability), 0);
      ConfigElementsList.AddEnumElement("uProb",       "Override Upgrade Probability",        typeof(Probability), 0);
      ConfigElementsList.AddEnumElement("mProb",       "Override Material Probability",       typeof(Probability), 4);
      ConfigElementsList.AddEnumElement("sProb",       "Override Schematic Probability",      typeof(Probability), 5);
      ConfigElementsList.AddBoolElement("mOverride",   "Use Material Quantity Overrides ",    true);
      ConfigElementsList.AddIntElement( "mMin",        "Override Material Min Quantity",      6, 1, 255);
      ConfigElementsList.AddIntElement( "mMax",        "Override Material Max Quantity",      12, 1, 255);
      ConfigElementsList.AddBoolElement("wBoost",      "Boost Override Weights",              true);
      ConfigElementsList.AddBoolElement("logVerbose",  "Log Verbose",                         false);

    }

    public void Log(string s) {
      if (logVerbose) {
        Scripting.LogLn(s);
      }
    }

    public static string ReadNullString(Stream s) {
      string res = "";
      byte b;
      while ((b = (byte)s.ReadByte()) > 0) res += (char)b;
      return res;
    }

    public static float ReadFloat(Stream s) {
      byte[] buff = new byte[4];
      s.Read(buff, 0, 4);
      return BitConverter.ToSingle(buff, 0);
    }

    public void RunScript() {

      logVerbose             = (bool)Scripting.GetConfigParam("logVerbose");
      Probability dProb      = (Probability)Scripting.GetConfigParam("dProb");
      Probability gProb      = (Probability)Scripting.GetConfigParam("gProb");
      Quality     gQual      = (Quality)Scripting.GetConfigParam("gQual");
      int         pIncrement = (int)Scripting.GetConfigParam("pIncrement");

      Probability aProb      = (Probability)Scripting.GetConfigParam("aProb");
      Probability wProb      = (Probability)Scripting.GetConfigParam("wProb");
      Probability jProb      = (Probability)Scripting.GetConfigParam("jProb");
      Probability vProb      = (Probability)Scripting.GetConfigParam("vProb");
      Probability uProb      = (Probability)Scripting.GetConfigParam("uProb");
      Probability mProb      = (Probability)Scripting.GetConfigParam("mProb");
      Probability sProb      = (Probability)Scripting.GetConfigParam("sProb");

      bool        mOverride  = (bool)Scripting.GetConfigParam("mOverride");

      int         mMin       = (int)Scripting.GetConfigParam("mMin");
      int         mMax       = (int)Scripting.GetConfigParam("mMax");
      bool        wBoost     = (bool)Scripting.GetConfigParam("wBoost");

      if (mMin > mMax) {
        mMax = mMin;
      }

      int dpb = ((int)dProb);
      int apb = ((int)aProb);
      int wpb = ((int)wProb);
      int jpb = ((int)jProb);
      int vpb = ((int)vProb);
      int upb = ((int)uProb);
      int mpb = ((int)mProb);
      int spb = ((int)sProb);
      int gpb = ((int)gProb);
      int gq  = ((int)gQual);

      bool gAlways = ((gq != 0) && (gpb != 0));

      if (gq > 2) { gq = gq + 2; }

      float badjust = 0F;
      if (wBoost) {
        float bmin = 6F;
        if ((apb != 0) && (apb < bmin)) { bmin = (float)apb; }
        if ((wpb != 0) && (wpb < bmin)) { bmin = (float)wpb; }
        if ((jpb != 0) && (jpb < bmin)) { bmin = (float)jpb; }
        if ((vpb != 0) && (vpb < bmin)) { bmin = (float)vpb; }
        if ((upb != 0) && (upb < bmin)) { bmin = (float)upb; }
        if ((mpb != 0) && (mpb < bmin)) { bmin = (float)mpb; }
        if ((spb != 0) && (spb < bmin)) { bmin = (float)spb; }
        if (bmin != 6F) {
          badjust = bmin - 1F;
        }
      }

      Scripting.LogLn("Applying Loot Settings: ");
      Scripting.LogLn("  Drop Probability                : " + dProb.ToString() + " (" + dpb.ToString() + ")");
      Scripting.LogLn("  Gold Probability                : " + gProb.ToString() + " (" + gpb.ToString() + ")");
      Scripting.LogLn("  Gold Quality                    : " + gQual.ToString() + " (" + gq.ToString() + ")");
      Scripting.LogLn("  Increment Probabilities By      : " + pIncrement.ToString());
      Scripting.LogLn("  Override Armor Probability      : " + aProb.ToString() + " (" + apb.ToString() + ")");
      Scripting.LogLn("  Override Weapon Probability     : " + wProb.ToString() + " (" + wpb.ToString() + ")");
      Scripting.LogLn("  Override Jewelry Probability    : " + jProb.ToString() + " (" + jpb.ToString() + ")");
      Scripting.LogLn("  Override Valuable Probability   : " + vProb.ToString() + " (" + vpb.ToString() + ")");
      Scripting.LogLn("  Override Upgrade Probability    : " + uProb.ToString() + " (" + upb.ToString() + ")");
      Scripting.LogLn("  Override Material Probability   : " + mProb.ToString() + " (" + mpb.ToString() + ")");
      Scripting.LogLn("  Override Schematic Probability  : " + sProb.ToString() + " (" + spb.ToString() + ")");
      Scripting.LogLn("  Use Material Quantity Overrides : " + mOverride.ToString());
      if (mOverride) {
        Scripting.LogLn("  Override Material Min Quantity  : " + mMin.ToString());
        Scripting.LogLn("  Override Material Max Quantity  : " + mMax.ToString());
      } else {
        Scripting.LogLn("  Override Material Min Quantity  : " + mMin.ToString() + " (ignored)");
        Scripting.LogLn("  Override Material Max Quantity  : " + mMax.ToString() + " (ignored)");
      }
      Scripting.LogLn("  Override Boost Prob Weights     : " + wBoost.ToString());
      Scripting.LogLn("  logVerbose                      : " + logVerbose.ToString());

      Dictionary<string,LootTable> ltbl_lookup  = new Dictionary<string, LootTable>();

      ltbl_lookup.Add("ltbl_acc_container_1",                              new LootTable(0x0B18, IType.Jewelry, 34, 0x0B44));
      ltbl_lookup.Add("ltbl_acc_container_2",                              new LootTable(0x0F78, IType.Jewelry, 69, 0x0FA4));
      ltbl_lookup.Add("ltbl_acc_container_3",                              new LootTable(0x06F8, IType.Jewelry, 1,  0x0724));
      ltbl_lookup.Add("ltbl_adamant_fortress_main",                        new LootTable(0x0698));
      ltbl_lookup.Add("ltbl_crafting_cloth_tier1",                         new LootTable(0x0798, IType.Material,  6,  0x07C4));
      ltbl_lookup.Add("ltbl_crafting_cloth_tier2",                         new LootTable(0x0798, IType.Material,  6,  0x07C4));
      ltbl_lookup.Add("ltbl_crafting_cloth_tier3",                         new LootTable(0x0798, IType.Material,  6,  0x07C4));
      ltbl_lookup.Add("ltbl_crafting_herbs_tier1",                         new LootTable(0x07F8, IType.Material,  9,  0x0824));
      ltbl_lookup.Add("ltbl_crafting_herbs_tier2",                         new LootTable(0x07B8, IType.Material,  7,  0x07E4));
      ltbl_lookup.Add("ltbl_crafting_herbs_tier3",                         new LootTable(0x0758, IType.Material,  4,  0x0784));
      ltbl_lookup.Add("ltbl_crafting_leather_tier1",                       new LootTable(0x07B8, IType.Material,  7,  0x07E4));
      ltbl_lookup.Add("ltbl_crafting_leather_tier2",                       new LootTable(0x07D8, IType.Material,  8,  0x0804));
      ltbl_lookup.Add("ltbl_crafting_leather_tier3",                       new LootTable(0x0778, IType.Material,  5,  0x07A4));
      ltbl_lookup.Add("ltbl_crafting_metal_rift_tier1",                    new LootTable(0x0798, IType.Material,  6,  0x07C4));
      ltbl_lookup.Add("ltbl_crafting_metal_rift_tier2",                    new LootTable(0x0798, IType.Material,  6,  0x07C4));
      ltbl_lookup.Add("ltbl_crafting_metal_rift_tier3",                    new LootTable(0x0798, IType.Material,  6,  0x07C4));
      ltbl_lookup.Add("ltbl_crafting_metal_tier1",                         new LootTable(0x0798, IType.Material,  6,  0x07C4));
      ltbl_lookup.Add("ltbl_crafting_metal_tier2",                         new LootTable(0x0798, IType.Material,  6,  0x07C4));
      ltbl_lookup.Add("ltbl_crafting_metal_tier3",                         new LootTable(0x0798, IType.Material,  6,  0x07C4));
      ltbl_lookup.Add("ltbl_container_cache_tier_a_4_7",                   new LootTable(0x0698));
      ltbl_lookup.Add("ltbl_container_cache_tier_b_8_11",                  new LootTable(0x0698));
      ltbl_lookup.Add("ltbl_container_cache_tier_c_12_15",                 new LootTable(0x0698));
      ltbl_lookup.Add("ltbl_container_cache_tier_d_16_19",                 new LootTable(0x0698));
      ltbl_lookup.Add("ltbl_container_demons_general_1",                   new LootTable(0x0748));
      ltbl_lookup.Add("ltbl_container_demons_general_2",                   new LootTable(0x0748));
      ltbl_lookup.Add("ltbl_container_demons_general_3",                   new LootTable(0x0748));
      ltbl_lookup.Add("ltbl_container_demons_materials_1",                 new LootTable(0x0768, IType.Material,  4,  0x0794));
      ltbl_lookup.Add("ltbl_container_demons_materials_2",                 new LootTable(0x0768, IType.Material,  4,  0x0794));
      ltbl_lookup.Add("ltbl_container_demons_materials_3",                 new LootTable(0x0768, IType.Material,  4,  0x0794));
      ltbl_lookup.Add("ltbl_container_tier_a_4_7",                         new LootTable(0x0878));
      ltbl_lookup.Add("ltbl_container_tier_b_8_11",                        new LootTable(0x0878));
      ltbl_lookup.Add("ltbl_container_tier_c_12_15",                       new LootTable(0x0878));
      ltbl_lookup.Add("ltbl_container_tier_d_16_19",                       new LootTable(0x0878));
      ltbl_lookup.Add("ltbl_container_tier_e_20_23",                       new LootTable(0x0858));
      ltbl_lookup.Add("ltbl_creature_demon_1",                             new LootTable(0x05E8));
      ltbl_lookup.Add("ltbl_creature_demon_cold_12_15",                    new LootTable(0x0728, IType.Material, 2, 0x0754));
      ltbl_lookup.Add("ltbl_creature_demon_cold_16_19",                    new LootTable(0x0708, IType.Material, 1, 0x0734));
      ltbl_lookup.Add("ltbl_creature_demon_cold_8_11",                     new LootTable(0x0708, IType.Material, 1, 0x0734));
      ltbl_lookup.Add("ltbl_creature_demon_fire_12_15",                    new LootTable(0x0728, IType.Material, 2, 0x0754));
      ltbl_lookup.Add("ltbl_creature_demon_fire_16_19",                    new LootTable(0x0708, IType.Material, 1, 0x0734));
      ltbl_lookup.Add("ltbl_creature_demon_fire_8_11",                     new LootTable(0x0708, IType.Material, 1, 0x0734));
      ltbl_lookup.Add("ltbl_creature_demon_lightning_12_15",               new LootTable(0x0728, IType.Material, 2, 0x0754));
      ltbl_lookup.Add("ltbl_creature_demon_lightning_16_19",               new LootTable(0x0708, IType.Material, 1, 0x0734));
      ltbl_lookup.Add("ltbl_creature_demon_lightning_20_23",               new LootTable(0x0708, IType.Material, 1, 0x0734));
      ltbl_lookup.Add("ltbl_creature_demon_spirit_12_15",                  new LootTable(0x0728, IType.Material, 2, 0x0754));
      ltbl_lookup.Add("ltbl_creature_demon_spirit_16_19",                  new LootTable(0x0708, IType.Material, 1, 0x0734));
      ltbl_lookup.Add("ltbl_creature_demon_spirit_4_7",                    new LootTable(0x0708, IType.Material, 1, 0x0734));
      ltbl_lookup.Add("ltbl_creature_demon_spirit_8_11",                   new LootTable(0x0708, IType.Material, 1, 0x0734));
      ltbl_lookup.Add("ltbl_creature_dragon_16_19",                        new LootTable(0x06F8, IType.Material, 1, 0x0724));
      ltbl_lookup.Add("ltbl_creature_giant_12_15",                         new LootTable(0x0758));
      ltbl_lookup.Add("ltbl_creature_giant_16_19",                         new LootTable(0x0758));
      ltbl_lookup.Add("ltbl_creature_giant_8_11",                          new LootTable(0x0758));
      ltbl_lookup.Add("ltbl_creature_mag_tier_a_4_7",                      new LootTable(0x0718));
      ltbl_lookup.Add("ltbl_creature_mag_tier_b_8_11",                     new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_mag_tier_c_12_15",                    new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_mag_tier_d_16_19",                    new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_mag_tier_e_20_23",                    new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_rog_tier_a_4_7",                      new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_rog_tier_b_8_11",                     new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_rog_tier_c_12_15",                    new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_rog_tier_d_16_19",                    new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_rog_tier_e_20_23",                    new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_undead_8_11",                         new LootTable(0x06D8));
      ltbl_lookup.Add("ltbl_creature_war_tier_a_4_7",                      new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_war_tier_b_8_11",                     new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_war_tier_c_12_15",                    new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_war_tier_d_16_19",                    new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_creature_war_tier_e_20_23",                    new LootTable(0x0728));
      ltbl_lookup.Add("ltbl_dgn_s_140",                                    new LootTable(0x0688));
      ltbl_lookup.Add("ltbl_ferelden_lakeside",                            new LootTable(0x0688));
      ltbl_lookup.Add("ltbl_frostback_mountains",                          new LootTable(0x0698));
      ltbl_lookup.Add("ltbl_ham_winter_palace",                            new LootTable(0x05D8));
      ltbl_lookup.Add("ltbl_mag_armor_upgrades_arms_a_4_7",                new LootTable(0x0748, IType.Upgrade, 3,  0x0774));
      ltbl_lookup.Add("ltbl_mag_armor_upgrades_arms_b_8_15",               new LootTable(0x07A8, IType.Upgrade, 6,  0x07D4));
      ltbl_lookup.Add("ltbl_mag_armor_upgrades_arms_c_16_23",              new LootTable(0x07A8, IType.Upgrade, 6,  0x07D4));
      ltbl_lookup.Add("ltbl_mag_armor_upgrades_legs_a_4_7",                new LootTable(0x0748, IType.Upgrade, 3,  0x0774));
      ltbl_lookup.Add("ltbl_mag_armor_upgrades_legs_b_8_15",               new LootTable(0x07A8, IType.Upgrade, 6,  0x07D4));
      ltbl_lookup.Add("ltbl_mag_armor_upgrades_legs_c_16_23",              new LootTable(0x07A8, IType.Upgrade, 6,  0x07D4));
      ltbl_lookup.Add("ltbl_mag_ring_upgrade_1",                           new LootTable(0x08B8, IType.Upgrade, 15, 0x08E4));
      ltbl_lookup.Add("ltbl_mag_ring_upgrade_2",                           new LootTable(0x08B8, IType.Upgrade, 15, 0x08E4));
      ltbl_lookup.Add("ltbl_mag_ring_upgrade_3",                           new LootTable(0x08B8, IType.Upgrade, 15, 0x08E4));
      ltbl_lookup.Add("ltbl_mag_weapons_tier_a_4_7",                       new LootTable(0x07A8, IType.Weapon, 6,   0x07D4));
      ltbl_lookup.Add("ltbl_mag_weapons_tier_b_8_11",                      new LootTable(0x07C8, IType.Weapon, 7,   0x07F4));
      ltbl_lookup.Add("ltbl_mag_weapons_tier_c_12_15",                     new LootTable(0x0808, IType.Weapon, 9,   0x0834));
      ltbl_lookup.Add("ltbl_mag_weapons_tier_d_16_19",                     new LootTable(0x07C8, IType.Weapon, 7,   0x07F4));
      ltbl_lookup.Add("ltbl_mag_weapons_tier_e_20_23",                     new LootTable(0x0788, IType.Weapon, 5,   0x07B4));
      ltbl_lookup.Add("ltbl_mag_weapons_upgrades_staff_blade_a_4_7",       new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_mag_weapons_upgrades_staff_blade_b_8_15",      new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_mag_weapons_upgrades_staff_blade_c_16_23",     new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_mag_weapons_upgrades_staff_grip_a_4_7",        new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_mag_weapons_upgrades_staff_grip_b_8_15",       new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_mag_weapons_upgrades_staff_grip_c_16_23",      new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_rog_armor_upgrades_arms_a_4_7",                new LootTable(0x0748, IType.Upgrade, 3,  0x0774));
      ltbl_lookup.Add("ltbl_rog_armor_upgrades_arms_b_8_15",               new LootTable(0x07A8, IType.Upgrade, 6,  0x07D4));
      ltbl_lookup.Add("ltbl_rog_armor_upgrades_arms_c_16_23",              new LootTable(0x07A8, IType.Upgrade, 6,  0x07D4));
      ltbl_lookup.Add("ltbl_rog_armor_upgrades_legs_a_4_7",                new LootTable(0x0748, IType.Upgrade, 3,  0x0774));
      ltbl_lookup.Add("ltbl_rog_armor_upgrades_legs_b_8_15",               new LootTable(0x07A8, IType.Upgrade, 6,  0x07D4));
      ltbl_lookup.Add("ltbl_rog_armor_upgrades_legs_c_16_23",              new LootTable(0x07A8, IType.Upgrade, 6,  0x07D4));
      ltbl_lookup.Add("ltbl_rog_ring_upgrade_1",                           new LootTable(0x08D8, IType.Upgrade, 16, 0x0904));
      ltbl_lookup.Add("ltbl_rog_ring_upgrade_2",                           new LootTable(0x08D8, IType.Upgrade, 16, 0x0904));
      ltbl_lookup.Add("ltbl_rog_ring_upgrade_3",                           new LootTable(0x08D8, IType.Upgrade, 16, 0x0904));
      ltbl_lookup.Add("ltbl_rog_weapons_tier_a_4_7",                       new LootTable(0x0928, IType.Weapon, 18,  0x0954));
      ltbl_lookup.Add("ltbl_rog_weapons_tier_b_8_11",                      new LootTable(0x08A8, IType.Weapon, 14,  0x08D4));
      ltbl_lookup.Add("ltbl_rog_weapons_tier_c_12_15",                     new LootTable(0x0968, IType.Weapon, 20,  0x0994));
      ltbl_lookup.Add("ltbl_rog_weapons_tier_d_16_19",                     new LootTable(0x0948, IType.Weapon, 19,  0x0974));
      ltbl_lookup.Add("ltbl_rog_weapons_tier_e_20_23",                     new LootTable(0x0808, IType.Weapon, 9,   0x0834));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_bow_grip_a_4_7",          new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_bow_grip_b_8_15",         new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_bow_grip_c_16_23",        new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_dagger_grip_a_4_7",       new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_dagger_grip_b_8_15",      new LootTable(0x0778, IType.Upgrade, 5,  0x07A4));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_dagger_grip_c_16_23",     new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_dualdagger_grip_b_8_15",  new LootTable(0x0718, IType.Upgrade, 1,  0x0744));
      ltbl_lookup.Add("ltbl_rog_weapons_upgrades_dualdagger_grip_c_16_23", new LootTable(0x0778, IType.Upgrade, 4,  0x07A4));
      ltbl_lookup.Add("ltbl_sack_tier_a_4_7",                              new LootTable(0x0718));
      ltbl_lookup.Add("ltbl_sack_tier_b_8_11",                             new LootTable(0x0738));
      ltbl_lookup.Add("ltbl_sack_tier_c_12_15",                            new LootTable(0x0738));
      ltbl_lookup.Add("ltbl_sack_tier_d_16_19",                            new LootTable(0x0738));
      ltbl_lookup.Add("ltbl_sack_tier_e_20_23",                            new LootTable(0x0738));
      ltbl_lookup.Add("ltbl_valuables_1",                                  new LootTable(0x0998, IType.Valuable, 22, 0x09C4));
      ltbl_lookup.Add("ltbl_valuables_2",                                  new LootTable(0x09D8, IType.Valuable, 24, 0x0A04));
      ltbl_lookup.Add("ltbl_valuables_3",                                  new LootTable(0x0A18, IType.Valuable, 26, 0x0A44));
      ltbl_lookup.Add("ltbl_valuables_4",                                  new LootTable(0x0A38, IType.Valuable, 28, 0x0A64));
      ltbl_lookup.Add("ltbl_valuables_5",                                  new LootTable(0x0A78, IType.Valuable, 29, 0x0AA4));
      ltbl_lookup.Add("ltbl_valuables_creatures_tier_a_4_7",               new LootTable(0x06C8, IType.Valuable));
      ltbl_lookup.Add("ltbl_valuables_creatures_tier_b_8_11",              new LootTable(0x06E8, IType.Valuable));
      ltbl_lookup.Add("ltbl_valuables_creatures_tier_c_12_15",             new LootTable(0x06E8, IType.Valuable));
      ltbl_lookup.Add("ltbl_valuables_creatures_tier_d_16_19",             new LootTable(0x06E8, IType.Valuable));
      ltbl_lookup.Add("ltbl_valuables_creatures_tier_e_20_23",             new LootTable(0x06C8, IType.Valuable));
      ltbl_lookup.Add("ltbl_war_armor_upgrades_arms_a_4_7",                new LootTable(0x0748, IType.Upgrade, 3,  0x0774));
      ltbl_lookup.Add("ltbl_war_armor_upgrades_arms_b_8_15",               new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_war_armor_upgrades_arms_c_16_23",              new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_war_armor_upgrades_legs_a_4_7",                new LootTable(0x0748, IType.Upgrade, 3,  0x0774));
      ltbl_lookup.Add("ltbl_war_armor_upgrades_legs_b_8_15",               new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_war_armor_upgrades_legs_c_16_23",              new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_war_ring_upgrade_1",                           new LootTable(0x08F8, IType.Upgrade, 17, 0x0924));
      ltbl_lookup.Add("ltbl_war_ring_upgrade_2",                           new LootTable(0x08F8, IType.Upgrade, 17, 0x0924));
      ltbl_lookup.Add("ltbl_war_ring_upgrade_3",                           new LootTable(0x08F8, IType.Upgrade, 17, 0x0924));
      ltbl_lookup.Add("ltbl_war_weapons_tier_a_4_7",                       new LootTable(0x08E8, IType.Weapon, 16,  0x0914));
      ltbl_lookup.Add("ltbl_war_weapons_tier_b_8_11",                      new LootTable(0x09C8, IType.Weapon, 23,  0x09F4));
      ltbl_lookup.Add("ltbl_war_weapons_tier_c_12_15",                     new LootTable(0x0BC8, IType.Weapon, 39,  0x0BF4));
      ltbl_lookup.Add("ltbl_war_weapons_tier_d_16_19",                     new LootTable(0x0B88, IType.Weapon, 37,  0x0BB4));
      ltbl_lookup.Add("ltbl_war_weapons_tier_e_20_23",                     new LootTable(0x09C8, IType.Weapon, 23,  0x09F4));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_1handed_grip_a_4_7",      new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_1handed_grip_b_8_15",     new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_1handed_grip_c_16_23",    new LootTable(0x07F8, IType.Upgrade, 8,  0x0824));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_2handed_grip_a_4_7",      new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_2handed_grip_b_8_15",     new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_2handed_grip_c_16_23",    new LootTable(0x07F8, IType.Upgrade, 8,  0x0824));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_2handed_pommel_a_4_7",    new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_2handed_pommel_b_8_15",   new LootTable(0x07F8, IType.Upgrade, 8,  0x0824));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_2handed_pommel_c_16_23",  new LootTable(0x0858, IType.Upgrade, 11, 0x0884));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_gsword_grip_a_4_7",       new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_gsword_grip_b_8_15",      new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_gsword_grip_c_16_23",     new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_lsword_grip_a_4_7",       new LootTable(0x0738, IType.Upgrade, 2,  0x0764));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_lsword_grip_b_8_15",      new LootTable(0x07D8, IType.Upgrade, 7,  0x0804));
      ltbl_lookup.Add("ltbl_war_weapons_upgrades_lsword_grip_c_16_23",     new LootTable(0x07B8, IType.Upgrade, 6,  0x07E4));
      ltbl_lookup.Add("ltbl_western_approach_main",                        new LootTable(0x05E8));
      ltbl_lookup.Add("ltbl_mag_generic_armor_12_15",                    new LootTable(0x07D8, IType.Armor, 9, 0x0804));
      ltbl_lookup.Add("ltbl_mag_generic_armor_16_19",                    new LootTable(0x07F8, IType.Armor, 9, 0x0824));
      ltbl_lookup.Add("ltbl_mag_generic_armor_20_23",                    new LootTable(0x0718, IType.Armor, 2, 0x0744));
      ltbl_lookup.Add("ltbl_mag_generic_armors_4_7",                     new LootTable(0x0798, IType.Armor,  7, 0x07C4));
      ltbl_lookup.Add("ltbl_mag_generic_armors_8_11",                    new LootTable(0x07D8, IType.Armor, 8, 0x0804));
      ltbl_lookup.Add("ltbl_qunari_headgear_t1",                         new LootTable(0x07F8, IType.Armor,  9, 0x0824));
      ltbl_lookup.Add("ltbl_qunari_headgear_t2",                         new LootTable(0x07F8, IType.Armor,  9, 0x0824));
      ltbl_lookup.Add("ltbl_qunari_headgear_t3",                         new LootTable(0x07F8, IType.Armor,  9, 0x0824));
      ltbl_lookup.Add("ltbl_rog_generic_armor_20_23",                    new LootTable(0x0718, IType.Armor, 2, 0x0744));
      ltbl_lookup.Add("ltbl_rog_generic_armors_12_15",                   new LootTable(0x0818, IType.Armor, 10, 0x0844));
      ltbl_lookup.Add("ltbl_rog_generic_armors_16_19",                   new LootTable(0x0838, IType.Armor, 11, 0x0864));
      ltbl_lookup.Add("ltbl_rog_generic_armors_4_7",                     new LootTable(0x07B8, IType.Armor,  7, 0x07E4));
      ltbl_lookup.Add("ltbl_rog_generic_armors_8_11",                    new LootTable(0x07F8, IType.Armor, 9, 0x0824));
      ltbl_lookup.Add("ltbl_war_generic_armor_20_23",                    new LootTable(0x0718, IType.Armor, 2, 0x0744));
      ltbl_lookup.Add("ltbl_war_generic_armors_12_15",                   new LootTable(0x07B8, IType.Armor, 7, 0x07E4));
      ltbl_lookup.Add("ltbl_war_generic_armors_16_19",                   new LootTable(0x07F8, IType.Armor, 9, 0x0824));
      ltbl_lookup.Add("ltbl_war_generic_armors_4_7",                     new LootTable(0x0798, IType.Armor,  6, 0x07C4));
      ltbl_lookup.Add("ltbl_war_generic_armors_8_11",                    new LootTable(0x07F8, IType.Armor, 9, 0x0824));
      ltbl_lookup.Add("ltbl_mag_armor_recipes_a_4_7",                    new LootTable(0x07E8, IType.Recipe, 8, 0x0814));
      ltbl_lookup.Add("ltbl_mag_armor_recipes_b_8_11",                   new LootTable(0x0828, IType.Recipe, 10, 0x0854));
      ltbl_lookup.Add("ltbl_mag_armor_recipes_c_12_15",                  new LootTable(0x0848, IType.Recipe, 11, 0x0874));
      ltbl_lookup.Add("ltbl_mag_armor_recipes_d_16_19",                  new LootTable(0x0808, IType.Recipe, 9, 0x0834));
      ltbl_lookup.Add("ltbl_mag_armor_recipes_e_20_23",                  new LootTable(0x0848, IType.Recipe, 11, 0x0874));
      ltbl_lookup.Add("ltbl_rog_armor_recipes_a_4_7",                    new LootTable(0x07E8, IType.Recipe, 8, 0x0814));
      ltbl_lookup.Add("ltbl_rog_armor_recipes_b_8_11",                   new LootTable(0x0828, IType.Recipe, 10, 0x0854));
      ltbl_lookup.Add("ltbl_rog_armor_recipes_c_12_15",                  new LootTable(0x0868, IType.Recipe, 12, 0x0894));
      ltbl_lookup.Add("ltbl_rog_armor_recipes_d_16_19",                  new LootTable(0x0808, IType.Recipe,  9, 0x0834));
      ltbl_lookup.Add("ltbl_rog_armor_recipes_e_20_23",                  new LootTable(0x0848, IType.Recipe, 11, 0x0874));
      ltbl_lookup.Add("ltbl_war_armor_recipes_a_4_7",                    new LootTable(0x07E8, IType.Recipe,  8, 0x0814));
      ltbl_lookup.Add("ltbl_war_armor_recipes_b_8_11",                   new LootTable(0x0828, IType.Recipe, 10, 0x0854));
      ltbl_lookup.Add("ltbl_war_armor_recipes_c_12_15",                  new LootTable(0x08C8, IType.Recipe, 15, 0x08F4));
      ltbl_lookup.Add("ltbl_war_armor_recipes_d_16_19",                  new LootTable(0x0888, IType.Recipe, 13, 0x08B4));
      ltbl_lookup.Add("ltbl_war_armor_recipes_e_20_23",                  new LootTable(0x0888, IType.Recipe, 13, 0x08B4));
      ltbl_lookup.Add("ltbl_mag_weapon_recipes_tier_a_4_7",              new LootTable(0x07E8, IType.Recipe,  8, 0x0814));
      ltbl_lookup.Add("ltbl_mag_weapon_recipes_tier_b_8_11",             new LootTable(0x0748, IType.Recipe, 3,  0x0774));
      ltbl_lookup.Add("ltbl_mag_weapon_recipes_tier_c_12_15",            new LootTable(0x0758, IType.Recipe,  3, 0x0784));
      ltbl_lookup.Add("ltbl_mag_weapon_recipes_tier_d_16_19",            new LootTable(0x0898, IType.Recipe, 13, 0x08C4));
      ltbl_lookup.Add("ltbl_mag_weapon_recipes_tier_e_20_23",            new LootTable(0x08B8, IType.Recipe, 14, 0x08E4));
      ltbl_lookup.Add("ltbl_rog_weapon_recipes_tier_a_4_7",              new LootTable(0x07E8, IType.Recipe,  8, 0x0814));
      ltbl_lookup.Add("ltbl_rog_weapon_recipes_tier_b_8_11",             new LootTable(0x0798, IType.Recipe,  5, 0x07C4));
      ltbl_lookup.Add("ltbl_rog_weapon_recipes_tier_c_12_15",            new LootTable(0x07D8, IType.Recipe,  7, 0x0804));
      ltbl_lookup.Add("ltbl_rog_weapon_recipes_tier_d_16_19",            new LootTable(0x0898, IType.Recipe, 13, 0x08C4));
      ltbl_lookup.Add("ltbl_rog_weapon_recipes_tier_e_20_23",            new LootTable(0x0878, IType.Recipe, 12, 0x08A4));
      ltbl_lookup.Add("ltbl_war_weapon_recipes_tier_a_4_7",              new LootTable(0x0938, IType.Recipe, 18, 0x0964));
      ltbl_lookup.Add("ltbl_war_weapon_recipes_tier_b_8_11",             new LootTable(0x08F8, IType.Recipe, 16, 0x0924));
      ltbl_lookup.Add("ltbl_war_weapon_recipes_tier_c_12_15",            new LootTable(0x08D8, IType.Recipe, 15, 0x0904));
      ltbl_lookup.Add("ltbl_war_weapon_recipes_tier_d_16_19",            new LootTable(0x0BD8, IType.Recipe, 39, 0x0C04));
      ltbl_lookup.Add("ltbl_war_weapon_recipes_tier_e_20_23",            new LootTable(0x0BB8, IType.Recipe, 38, 0x0BE4));

      Char[] split_seperator = new Char[] {'/'};

      Dictionary<int, string> index_to_name  = new Dictionary<int, string>();
      Dictionary<string, int> name_to_index  = new Dictionary<string, int>();

      for (int iblob = 0; iblob < totalBound; iblob++) {
        MemoryStream ms = new MemoryStream(Scripting.GetResourceData(iblob));
        BinaryReader Reader = new BinaryReader(ms);
        Reader.BaseStream.Seek(4, SeekOrigin.Begin);
        uint nameOffset = Reader.ReadUInt32();
        Reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);

        string fullname = ReadNullString(Reader.BaseStream);
        string[] parts  = fullname.Split(split_seperator);
        if (parts.Length < 1) {
          Reader.Close();
          continue;
        }

        string res_name = parts[(parts.Length - 1)];
        index_to_name.Add(iblob, res_name);
        name_to_index.Add(res_name, iblob);
        Reader.Close();
      }

    for (int iblob = 0; iblob < totalBound; iblob++) {
        MemoryStream ms = new MemoryStream(Scripting.GetResourceData(iblob));
        BinaryReader Reader = new BinaryReader(ms);
        
        Reader.BaseStream.Seek(4, SeekOrigin.Begin);
        uint nameOffset = Reader.ReadUInt32();
        Reader.BaseStream.Seek(nameOffset, SeekOrigin.Begin);

        string res_name;
        if (!(index_to_name.TryGetValue(iblob, out res_name))) {
          Scripting.LogLn("  Skipping Resource [" + iblob.ToString() + "]. Not a valid EBX");
          Reader.Close();
          continue;
        }

        LootTable ltbl;
        if (!(ltbl_lookup.TryGetValue(res_name, out ltbl))) {
          Scripting.LogLn("  Skipping Resource [" + res_name + "]. No offset data.");
          Reader.Close();
          continue;
        }
/* ItemProbability , GoldProbability and GoldQuantity */
        long iProbOffset = ltbl.offset + 20;
        long gProbOffset = iProbOffset + 4;
        long gQualOffset = gProbOffset + 4;

        Reader.BaseStream.Seek(iProbOffset, SeekOrigin.Begin);
        int iProbCurr = Reader.ReadInt32();
        int gProbCurr = Reader.ReadInt32();
        int gQualCurr = Reader.ReadInt32();

        /* Gold Qualities: */
        /* 0 = 0, 1 = ~4, 2 = ~8, 3 = ~12, 4 = ~16, 5 = ~20, 6 = ~48, 7 = ~96, 8 = ~144, 9 = ~ 196, 10 = ~240 */

        if (gQualCurr > 1 && gQualCurr < 5) {
          gQualCurr = 2;
        }

        Log("  " + res_name + ":");

        BinaryWriter Writer = new BinaryWriter(ms);

        /* DAI Probability values: */
        /* 0 = None, 1 = Very_Low, 2 = Low, 3 = Medium, 4 = High, 5 = Very_High, 6 = Always     */

        /* We dont mess with values that are None or Always. And if it is already Very_High, there is nothing we can do to it. */
        if (iProbCurr > 0 && iProbCurr < 5) {
          /* When Override specified, only change if value is greater than original (decreasing can cause bugs) */
          bool use_increment = false;
          Writer.BaseStream.Seek(iProbOffset, SeekOrigin.Begin);
          if (ltbl.itype == IType.Material) {
            if (mpb == 0) {
              use_increment = true; 
            } else if (mpb > iProbCurr) {
              Writer.Write(mpb);
              Log("    iProb: " + iProbCurr.ToString() + " => " + mpb.ToString());
            }
          } else if (ltbl.itype == IType.Recipe) {
            if (spb == 0) { 
              use_increment = true; 
            } else if (spb > iProbCurr) {
              Writer.Write(spb);
              Log("    iProb: " + iProbCurr.ToString() + " => " + spb.ToString());
            }
          } else if (ltbl.itype == IType.Armor) {
            if (apb == 0) { 
              use_increment = true; 
            } else if (apb > iProbCurr) {
              Writer.Write(apb);
              Log("    iProb: " + iProbCurr.ToString() + " => " + apb.ToString());
            }
          } else if (ltbl.itype == IType.Weapon) {
            if (wpb == 0) { 
              use_increment = true; 
            } else if (wpb > iProbCurr) {
              Writer.Write(wpb);
              Log("    iProb: " + iProbCurr.ToString() + " => " + wpb.ToString());
            }
          } else if (ltbl.itype == IType.Valuable) {
            if (vpb == 0) { 
              use_increment = true; 
            } else if (vpb > iProbCurr) {
              Writer.Write(wpb);
              Log("    iProb: " + iProbCurr.ToString() + " => " + wpb.ToString());
            }
          } else if (ltbl.itype == IType.Upgrade) {
            if (upb == 0) { 
              use_increment = true; 
            } else if (upb > iProbCurr) {
              Writer.Write(upb);
              Log("    iProb: " + iProbCurr.ToString() + " => " + upb.ToString());
            }
          } else if (ltbl.itype == IType.Jewelry) {
            if (jpb == 0) { 
              use_increment = true; 
            } else if (jpb > iProbCurr) {
              Writer.Write(jpb);
              Log("    iProb: " + iProbCurr.ToString() + " => " + jpb.ToString());
            }
          } else {
            /* Containers and anything else... */
            if (dpb == 0) { 
              use_increment = true; 
            } else if (dpb > iProbCurr) {
              Writer.Write(dpb);
              Log("    iProb: " + iProbCurr.ToString() + " => " + dpb.ToString());
            }
          }
          if (use_increment) {
            int ivalue = pIncrement + iProbCurr;
            if (ivalue > 5) {
              ivalue = 5;
            }
            Writer.Write(ivalue);
            Log("    iProb: " + iProbCurr.ToString() + " => " + ivalue.ToString());
          }
        }
        
        /* If something has gold quality -1, ignore */

        if (gQualCurr > -1) {
          if (gpb > gProbCurr) {
            if (gProbCurr > 0 || gAlways) {
              Writer.BaseStream.Seek(gProbOffset, SeekOrigin.Begin);
              Writer.Write(gpb);
              Log("    gProb: " + gProbCurr.ToString() + " => " + gpb.ToString());
            }
          }
          if (gq > gQualCurr) {
            if (gProbCurr > 0 || gAlways) {
              Writer.BaseStream.Seek(gQualOffset, SeekOrigin.Begin);
              Writer.Write(gq);
              Log("    gQual: " + gQualCurr.ToString() + " => " + gq.ToString());
            }
          }
        }

        if (ltbl.numItems > 0 && ltbl.itemOffset != 0) {
/* +12 gives baselootitem, +20 gives 1st ItemAsset offset */
long startOffset = ltbl.itemOffset + 20;
          for (int j = 0; j < ltbl.numItems; j++) {
            long itemOffset        = startOffset + (j * 36);
            long minQuantityOffset = itemOffset + 4;
            long maxQuantityOffset = itemOffset + 8;
            long maxPerAreaOffset  = itemOffset + 12;
            long weightOffset      = itemOffset + 16;

            Reader.BaseStream.Seek(itemOffset, SeekOrigin.Begin);
            long res_id  = Reader.ReadUInt32();
            int minimum  = Reader.ReadInt32();
            int maximum  = Reader.ReadInt32();
            int maxarea  = Reader.ReadInt32();
            float weight = ReadFloat(Reader.BaseStream);
            
            Log("    item [" + j.ToString() + "]:");
            
            /* Dont mess with amounts unless it is a material and the user checked the box */

            if (mOverride && ltbl.itype == IType.Material) {
              if (mMin > minimum) {
                Writer.BaseStream.Seek(minQuantityOffset, SeekOrigin.Begin);
                Writer.Write(mMin);
                Log("      MinQuantity: " + minimum.ToString() + " => " + mMin.ToString());
              }
              if (mMax > maximum) {
                Writer.BaseStream.Seek(maxQuantityOffset, SeekOrigin.Begin);
                Writer.Write(mMax);
                Log("      MaxQuantity: " + maximum.ToString() + " => " + mMax.ToString());
              }
              if (maxarea > 0) {
                Writer.BaseStream.Seek(maxPerAreaOffset, SeekOrigin.Begin);
                Writer.Write(0); /* No Max Per Area */
                Log("      MaxPerArea: " + maxarea.ToString() + " => Unlimited");
              }
            }
            
            /* do we boost? */
            float boostvalue = -1F;
            if (wBoost) {
              /* dpb (drop probability definitions) do not have any loot to adjust... */
              if (ltbl.itype == IType.Material && mpb != 0) { boostvalue = (float)mpb - badjust; }
              if (ltbl.itype == IType.Recipe   && spb != 0) { boostvalue = (float)spb - badjust; }
              if (ltbl.itype == IType.Armor    && apb != 0) { boostvalue = (float)apb - badjust; }
              if (ltbl.itype == IType.Weapon   && wpb != 0) { boostvalue = (float)wpb - badjust; }
              if (ltbl.itype == IType.Valuable && vpb != 0) { boostvalue = (float)vpb - badjust; }
              if (ltbl.itype == IType.Upgrade  && upb != 0) { boostvalue = (float)upb - badjust; }
              if (ltbl.itype == IType.Jewelry  && jpb != 0) { boostvalue = (float)jpb - badjust; }
            }
 
            if (boostvalue != -1F) {
              Writer.BaseStream.Seek(weightOffset, SeekOrigin.Begin);
              Writer.Write(boostvalue);
              Log("      ProbWeightBoost: " + weight.ToString() + " => " + boostvalue.ToString());
            } else if (weight != 1.0) {
              Writer.BaseStream.Seek(weightOffset, SeekOrigin.Begin);
              Writer.Write(1.0);
              Log("      ProbWeight: " + weight.ToString() + " => 1.0");
            }
              
          }
        }

        Scripting.SetResourceData(iblob, ms.ToArray());
        Reader.Close();
        Writer.Close();

      }
      Scripting.LogLn("Loot Settings Applied");

    }
  }
}
Last edited by Svarty on December 29th, 2017, 9:49 am, edited 1 time in total.
Quote
Like
Share

Joined: October 21st, 2017, 4:54 pm

December 23rd, 2017, 9:41 pm #9

Here is the code for Better Weapon Upgrades Warrior Two-Handed. I'll be replacing the current version because players have reported problems (crashes) with old saves &/or the nug (I can't promise it will fix them all, though).

I don't understand why it's not always putting the slot type name on the crafting page, but it seems to be working anyway, so I'll ignore this issue for now.

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace DAIMod
{
    // This section sets up elements for the UI dropdown menus
    public class scriptname : ModScript 
    {
        // This section sets up what a field of the LIST looks like. This will get sent to the writer in the loop at the bottom
        class Item 
        {
            public int Resource{ get;set; }
            public long Offset{  get;set; }
            public byte Value{   get;set; }
        } 
        
        //    This section is the UI 
        public void ConstructUI(ModConfigElementsList ConfigElementsList) 
        {
            ConfigElementsList.AddIntElement(  "SOS", "Slot 1 Size (1-99)",       8, 1, 99); //Defaults to 8, min 1 max 99
            ConfigElementsList.AddIntElement(  "STS", "Slot 2 Size (1-99)",       3, 1, 99);
        }    
        
        public void RunScript() 
        {
            // The list is a list of fields we set up above, ie.e Resource, Offset, Value
            List<Item> Items = new List<Item>();
            
            //This section gets data from the UI
            int SOS = (int)Scripting.GetConfigParam("SOS"); 
            int STS = (int)Scripting.GetConfigParam("STS");                
            
            //This converts them to bytes so they can go in the LIST
            byte Slot_One_Siz =  (byte)((int)SOS);
            byte Slot_Two_Siz =  (byte)((int)STS);
            
            //STATS Section. This section puts values in the LIST to overwrite the RECIPE values
            // By setting these up as variables here, we can change them on every upgrade easily
            byte Util  = 62;
            byte Util2 = 02; 
            byte Offe  = 40;
            byte Offe1 = 01; 
            byte Cloth = 00;
            byte Leath = 01;
            byte Metal = 02;
                        
            // decorative    Metal    Utility    grip_t3_1
            Items.Add(new Item{Resource = 0, Offset = 0xa38, Value = Util});
            Items.Add(new Item{Resource = 0, Offset = 0xa3c, Value = Util2});
            Items.Add(new Item{Resource = 0, Offset = 0xa44, Value = Metal});
            Items.Add(new Item{Resource = 0, Offset = 0xa48, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 0, Offset = 0xa20, Value = Util});
            Items.Add(new Item{Resource = 0, Offset = 0xa24, Value = Util2});
            Items.Add(new Item{Resource = 0, Offset = 0xa2c, Value = Metal});
            Items.Add(new Item{Resource = 0, Offset = 0xa30, Value = Slot_Two_Siz});
            // inscribed    cloth     Utility    two_handed_grip_t3_2
            Items.Add(new Item{Resource = 1, Offset = 0xa68, Value = Util});
            Items.Add(new Item{Resource = 1, Offset = 0xa6c, Value = Util2});
            Items.Add(new Item{Resource = 1, Offset = 0xa74, Value = Cloth});
            Items.Add(new Item{Resource = 1, Offset = 0xa78, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 1, Offset = 0xa38, Value = Util});
            Items.Add(new Item{Resource = 1, Offset = 0xa3c, Value = Util2});
            Items.Add(new Item{Resource = 1, Offset = 0xa44, Value = Cloth});
            Items.Add(new Item{Resource = 1, Offset = 0xa48, Value = Slot_Two_Siz});
            // mw engraved    Metal    offense    grip_t3_3_rare            
            Items.Add(new Item{Resource = 2, Offset = 0xa68, Value = Offe});
            Items.Add(new Item{Resource = 2, Offset = 0xa6c, Value = Offe1});
            Items.Add(new Item{Resource = 2, Offset = 0xa74, Value = Metal});
            Items.Add(new Item{Resource = 2, Offset = 0xa78, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 2, Offset = 0xa20, Value = Offe});
            Items.Add(new Item{Resource = 2, Offset = 0xa24, Value = Offe1});
            Items.Add(new Item{Resource = 2, Offset = 0xa2c, Value = Metal});
            Items.Add(new Item{Resource = 2, Offset = 0xa30, Value = Slot_Two_Siz});
            // Wide    cloth     utility    grip_t2_3 
            Items.Add(new Item{Resource = 3, Offset = 0xa20, Value = Util});
            Items.Add(new Item{Resource = 3, Offset = 0xa24, Value = Util2});
            Items.Add(new Item{Resource = 3, Offset = 0xa2c, Value = Cloth});
            Items.Add(new Item{Resource = 3, Offset = 0xa30, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 3, Offset = 0xa38, Value = Util});
            Items.Add(new Item{Resource = 3, Offset = 0xa3c, Value = Util2});
            Items.Add(new Item{Resource = 3, Offset = 0xa44, Value = Cloth});
            Items.Add(new Item{Resource = 3, Offset = 0xa48, Value = Slot_Two_Siz});
            // butterfly    cloth     offense    grip_t3_4
            Items.Add(new Item{Resource = 4, Offset = 0xa20, Value = Offe});
            Items.Add(new Item{Resource = 4, Offset = 0xa24, Value = Offe1});
            Items.Add(new Item{Resource = 4, Offset = 0xa2c, Value = Cloth});
            Items.Add(new Item{Resource = 4, Offset = 0xa30, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 4, Offset = 0xa38, Value = Offe});
            Items.Add(new Item{Resource = 4, Offset = 0xa3c, Value = Offe1});
            Items.Add(new Item{Resource = 4, Offset = 0xa44, Value = Cloth});
            Items.Add(new Item{Resource = 4, Offset = 0xa48, Value = Slot_Two_Siz});
            // Curved    Metal    utility    grip_t3_5
            Items.Add(new Item{Resource = 5, Offset = 0xa20, Value = Util});
            Items.Add(new Item{Resource = 5, Offset = 0xa24, Value = Util2});
            Items.Add(new Item{Resource = 5, Offset = 0xa2c, Value = Metal});
            Items.Add(new Item{Resource = 5, Offset = 0xa30, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 5, Offset = 0xa68, Value = Util});
            Items.Add(new Item{Resource = 5, Offset = 0xa6c, Value = Util2});
            Items.Add(new Item{Resource = 5, Offset = 0xa74, Value = Metal});
            Items.Add(new Item{Resource = 5, Offset = 0xa78, Value = Slot_Two_Siz});
            // mw etched    Metal    offense    grip_t3_6_rare
            Items.Add(new Item{Resource = 6, Offset = 0xa38, Value = Offe});
            Items.Add(new Item{Resource = 6, Offset = 0xa3c, Value = Offe1});
            Items.Add(new Item{Resource = 6, Offset = 0xa44, Value = Metal});
            Items.Add(new Item{Resource = 6, Offset = 0xa48, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 6, Offset = 0xa68, Value = Offe});
            Items.Add(new Item{Resource = 6, Offset = 0xa6c, Value = Offe1});
            Items.Add(new Item{Resource = 6, Offset = 0xa74, Value = Metal});
            Items.Add(new Item{Resource = 6, Offset = 0xa78, Value = Slot_Two_Siz});
            // Firm    Leather    Utility    pommel_t2_6
            Items.Add(new Item{Resource = 7, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 7, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 7, Offset = 0xa34, Value = Leath});
            Items.Add(new Item{Resource = 7, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 7, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 7, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 7, Offset = 0xa64, Value = Leath});
            Items.Add(new Item{Resource = 7, Offset = 0xa68, Value = Slot_Two_Siz});
            // decorative    Leather    offense    pommel_t3_5
            Items.Add(new Item{Resource = 8, Offset = 0xa28, Value = Offe});
            Items.Add(new Item{Resource = 8, Offset = 0xa2c, Value = Offe1});
            Items.Add(new Item{Resource = 8, Offset = 0xa34, Value = Leath});
            Items.Add(new Item{Resource = 8, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 8, Offset = 0xa10, Value = Offe});
            Items.Add(new Item{Resource = 8, Offset = 0xa14, Value = Offe1});
            Items.Add(new Item{Resource = 8, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 8, Offset = 0xa20, Value = Slot_Two_Siz});
            // Notched    cloth     offense    grip_t2_2
            Items.Add(new Item{Resource = 9, Offset = 0xa58, Value = Offe});
            Items.Add(new Item{Resource = 9, Offset = 0xa5c, Value = Offe1});
            Items.Add(new Item{Resource = 9, Offset = 0xa64, Value = Cloth});
            Items.Add(new Item{Resource = 9, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 9, Offset = 0xa10, Value = Offe});
            Items.Add(new Item{Resource = 9, Offset = 0xa14, Value = Offe1});
            Items.Add(new Item{Resource = 9, Offset = 0xa1c, Value = Cloth});
            Items.Add(new Item{Resource = 9, Offset = 0xa20, Value = Slot_Two_Siz});
            // bound    Leather    offense    grip_t3_5
            Items.Add(new Item{Resource = 10, Offset = 0xa58, Value = Offe});
            Items.Add(new Item{Resource = 10, Offset = 0xa5c, Value = Offe1});
            Items.Add(new Item{Resource = 10, Offset = 0xa64, Value = Leath});
            Items.Add(new Item{Resource = 10, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 10, Offset = 0xa40, Value = Offe});
            Items.Add(new Item{Resource = 10, Offset = 0xa44, Value = Offe1});
            Items.Add(new Item{Resource = 10, Offset = 0xa4c, Value = Leath});
            Items.Add(new Item{Resource = 10, Offset = 0xa50, Value = Slot_Two_Siz});
            // condensed    Leather    Utility    grip_t3_6
            Items.Add(new Item{Resource = 11, Offset = 0xa10, Value = Util});
            Items.Add(new Item{Resource = 11, Offset = 0xa14, Value = Util2});
            Items.Add(new Item{Resource = 11, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 11, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 11, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 11, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 11, Offset = 0xa64, Value = Leath});
            Items.Add(new Item{Resource = 11, Offset = 0xa68, Value = Slot_Two_Siz});
            // MW Firm    Metal     Utility    t2_3_rare
            Items.Add(new Item{Resource = 12, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 12, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 12, Offset = 0xa64, Value = Metal});
            Items.Add(new Item{Resource = 12, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 12, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 12, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 12, Offset = 0xa34, Value = Metal});
            Items.Add(new Item{Resource = 12, Offset = 0xa38, Value = Slot_Two_Siz});
            // Wrapped    Leather    offense    _t3_9
            Items.Add(new Item{Resource = 13, Offset = 0xa28, Value = Offe});
            Items.Add(new Item{Resource = 13, Offset = 0xa2c, Value = Offe1});
            Items.Add(new Item{Resource = 13, Offset = 0xa34, Value = Leath});
            Items.Add(new Item{Resource = 13, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 13, Offset = 0xa40, Value = Offe});
            Items.Add(new Item{Resource = 13, Offset = 0xa44, Value = Offe1});
            Items.Add(new Item{Resource = 13, Offset = 0xa4c, Value = Leath});
            Items.Add(new Item{Resource = 13, Offset = 0xa50, Value = Slot_Two_Siz});
            // MW Jeweled GS    Leather    utility    grip_t2_2_rare
            Items.Add(new Item{Resource = 14, Offset = 0xa38, Value = Offe});
            Items.Add(new Item{Resource = 14, Offset = 0xa3c, Value = Offe1});
            Items.Add(new Item{Resource = 14, Offset = 0xa44, Value = Leath});
            Items.Add(new Item{Resource = 14, Offset = 0xa48, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 14, Offset = 0xa68, Value = Offe});
            Items.Add(new Item{Resource = 14, Offset = 0xa6c, Value = Offe1});
            Items.Add(new Item{Resource = 14, Offset = 0xa74, Value = Leath});
            Items.Add(new Item{Resource = 14, Offset = 0xa78, Value = Slot_Two_Siz});
            // ornate     Metal    offense    grip_t3_1
            Items.Add(new Item{Resource = 15, Offset = 0xa20, Value = Offe});
            Items.Add(new Item{Resource = 15, Offset = 0xa24, Value = Offe1});
            Items.Add(new Item{Resource = 15, Offset = 0xa2c, Value = Metal});
            Items.Add(new Item{Resource = 15, Offset = 0xa30, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 15, Offset = 0xa68, Value = Offe});
            Items.Add(new Item{Resource = 15, Offset = 0xa6c, Value = Offe1});
            Items.Add(new Item{Resource = 15, Offset = 0xa74, Value = Metal});
            Items.Add(new Item{Resource = 15, Offset = 0xa78, Value = Slot_Two_Siz});
            // mw ornate     Leather    utility    grip_t3_3_rare
            Items.Add(new Item{Resource = 16, Offset = 0xa50, Value = Util});
            Items.Add(new Item{Resource = 16, Offset = 0xa54, Value = Util2});
            Items.Add(new Item{Resource = 16, Offset = 0xa5c, Value = Leath});
            Items.Add(new Item{Resource = 16, Offset = 0xa60, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 16, Offset = 0xa68, Value = Util});
            Items.Add(new Item{Resource = 16, Offset = 0xa6c, Value = Util2});
            Items.Add(new Item{Resource = 16, Offset = 0xa74, Value = Leath});
            Items.Add(new Item{Resource = 16, Offset = 0xa78, Value = Slot_Two_Siz});
            // Engraved    Metal    offense    pommel_t2_1
            Items.Add(new Item{Resource = 17, Offset = 0xa28, Value = Offe});
            Items.Add(new Item{Resource = 17, Offset = 0xa2c, Value = Offe1});
            Items.Add(new Item{Resource = 17, Offset = 0xa34, Value = Metal});
            Items.Add(new Item{Resource = 17, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 17, Offset = 0xa10, Value = Offe});
            Items.Add(new Item{Resource = 17, Offset = 0xa14, Value = Offe1});
            Items.Add(new Item{Resource = 17, Offset = 0xa1c, Value = Metal});
            Items.Add(new Item{Resource = 17, Offset = 0xa20, Value = Slot_Two_Siz});
            // mw balanced    cloth     Utility    pommel_t2_2_rare
            Items.Add(new Item{Resource = 18, Offset = 0xa50, Value = Util});
            Items.Add(new Item{Resource = 18, Offset = 0xa54, Value = Util2});
            Items.Add(new Item{Resource = 18, Offset = 0xa5c, Value = Cloth});
            Items.Add(new Item{Resource = 18, Offset = 0xa60, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 18, Offset = 0xa20, Value = Util});
            Items.Add(new Item{Resource = 18, Offset = 0xa24, Value = Util2});
            Items.Add(new Item{Resource = 18, Offset = 0xa2c, Value = Cloth});
            Items.Add(new Item{Resource = 18, Offset = 0xa30, Value = Slot_Two_Siz});
            // Spiked    cloth     offense    pommel_t3_1
            Items.Add(new Item{Resource = 19, Offset = 0xa28, Value = Offe});
            Items.Add(new Item{Resource = 19, Offset = 0xa2c, Value = Offe1});
            Items.Add(new Item{Resource = 19, Offset = 0xa34, Value = Cloth});
            Items.Add(new Item{Resource = 19, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 19, Offset = 0xa40, Value = Offe});
            Items.Add(new Item{Resource = 19, Offset = 0xa44, Value = Offe1});
            Items.Add(new Item{Resource = 19, Offset = 0xa4c, Value = Cloth});
            Items.Add(new Item{Resource = 19, Offset = 0xa50, Value = Slot_Two_Siz});
                                     
            //SECTION ENDS
            
            //This section does all the voodoo mojo magic stuff I don't understand
            foreach (var Thing in Items) 
            {
                MemoryStream memSt = new MemoryStream(Scripting.GetResourceData(Thing.Resource));
                BinaryWriter Writer = new BinaryWriter(memSt);
                Writer.BaseStream.Seek(Thing.Offset, SeekOrigin.Begin);
                Writer.Write(Thing.Value);
                Scripting.SetResourceData(Thing.Resource, memSt.ToArray());
                Writer.Close();
            }
            
        }    
    }
}
Here is the spreadsheet for it - errors on here include resource 15 has the wrong numbers for slot 1 and assets 18 and 19 should be 17 and 18 respectively.: 
Quote
Like
Share

Joined: October 21st, 2017, 4:54 pm

January 6th, 2018, 10:57 am #10

Better Armour Upgrade Recipes Alternative Configurable Version All-In-One (breathe!):

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace DAIMod
{
    // This section sets up elements for the UI dropdown menus
    public class scriptname : ModScript 
    {
        // This section sets up what a field of the LIST looks like. This will get sent to the writer in the loop at the bottom
        class Item 
        {
            public int Resource{ get;set; }
            public long Offset{  get;set; }
            public byte Value{   get;set; }
        } 
        
        //    This section is the UI 
        public void ConstructUI(ModConfigElementsList ConfigElementsList) 
        {
            ConfigElementsList.AddIntElement(  "SOS", "Slot 1 Size (1-99)",       8, 1, 99); //Defaults to 8, min 1 max 99
            ConfigElementsList.AddIntElement(  "STS", "Slot 2 Size (1-99)",       3, 1, 99);
        }    
        
        public void RunScript() 
        {
            // The list is a list of fields we set up above, ie.e Resource, Offset, Value
            List<Item> Items = new List<Item>();
            
            //This section gets data from the UI
            int SOS = (int)Scripting.GetConfigParam("SOS"); 
            int STS = (int)Scripting.GetConfigParam("STS");                
            
            //This converts them to bytes so they can go in the LIST
            byte Slot_One_Siz =  (byte)((int)SOS);
            byte Slot_Two_Siz =  (byte)((int)STS);
            
            //STATS Section. This section puts values in the LIST to overwrite the RECIPE values
            // By setting these up as variables here, we can change them on every upgrade easily
            byte Util  = 62;
            byte Util2 = 02; 
            byte Defe  = 61;
            byte Defe1 = 01; 
            byte Cloth = 00;
            byte Leath = 01;
            byte Metal = 02;
                        
            // Vanguard    Coat    Legs    Cloth    Defense    recipe_heavy_var2_0002b
            Items.Add(new Item{Resource = 0, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 0, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 0, Offset = 0xa1c, Value = Cloth});
            Items.Add(new Item{Resource = 0, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 0, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 0, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 0, Offset = 0xa34, Value = Cloth});
            Items.Add(new Item{Resource = 0, Offset = 0xa38, Value = Slot_Two_Siz});
            // Battlemaster    Coat    Legs    Leather    Utility    recipe_heavy_var2_0002c
            Items.Add(new Item{Resource = 1, Offset = 0xa10, Value = Util});
            Items.Add(new Item{Resource = 1, Offset = 0xa14, Value = Util2});
            Items.Add(new Item{Resource = 1, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 1, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 1, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 1, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 1, Offset = 0xa64, Value = Leath});
            Items.Add(new Item{Resource = 1, Offset = 0xa68, Value = Slot_Two_Siz});
            // Vanguard    Mail    Legs    Cloth    Utility    recipe_heavy_var2_0003b
            Items.Add(new Item{Resource = 2, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 2, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 2, Offset = 0xa64, Value = Cloth});
            Items.Add(new Item{Resource = 2, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 2, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 2, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 2, Offset = 0xa34, Value = Cloth});
            Items.Add(new Item{Resource = 2, Offset = 0xa38, Value = Slot_Two_Siz});
            // Battlemaster    Mail    Legs    Metal    Defense    recipe_heavy_var2_0003c
            Items.Add(new Item{Resource = 3, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 3, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 3, Offset = 0xa34, Value = Metal});
            Items.Add(new Item{Resource = 3, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 3, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 3, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 3, Offset = 0xa1c, Value = Metal});
            Items.Add(new Item{Resource = 3, Offset = 0xa20, Value = Slot_Two_Siz});
            // Vanguard    Armor    Legs    Leather    Defense    recipe_heavy_var2_0004b
            Items.Add(new Item{Resource = 4, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 4, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 4, Offset = 0xa34, Value = Leath});
            Items.Add(new Item{Resource = 4, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 4, Offset = 0xa58, Value = Defe});
            Items.Add(new Item{Resource = 4, Offset = 0xa5c, Value = Defe1});
            Items.Add(new Item{Resource = 4, Offset = 0xa64, Value = Leath});
            Items.Add(new Item{Resource = 4, Offset = 0xa68, Value = Slot_Two_Siz});
            // Battlemaster    Armor    Legs    Metal    Utility    recipe_heavy_var2_0004c
            Items.Add(new Item{Resource = 5, Offset = 0xa10, Value = Util});
            Items.Add(new Item{Resource = 5, Offset = 0xa14, Value = Util2});
            Items.Add(new Item{Resource = 5, Offset = 0xa1c, Value = Metal});
            Items.Add(new Item{Resource = 5, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 5, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 5, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 5, Offset = 0xa4c, Value = Metal});
            Items.Add(new Item{Resource = 5, Offset = 0xa50, Value = Slot_Two_Siz});
            // Vanguard    Coat    Arms    Cloth    Defense    recipe_heavy_var2_0020b
            Items.Add(new Item{Resource = 6, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 6, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 6, Offset = 0xa1c, Value = Cloth});
            Items.Add(new Item{Resource = 6, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 6, Offset = 0xa58, Value = Defe});
            Items.Add(new Item{Resource = 6, Offset = 0xa5c, Value = Defe1});
            Items.Add(new Item{Resource = 6, Offset = 0xa64, Value = Cloth});
            Items.Add(new Item{Resource = 6, Offset = 0xa68, Value = Slot_Two_Siz});
            // Battlemaster    Coat    Arms    Leather    Utility    recipe_heavy_var2_0020c
            Items.Add(new Item{Resource = 7, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 7, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 7, Offset = 0xa64, Value = Leath});
            Items.Add(new Item{Resource = 7, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 7, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 7, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 7, Offset = 0xa4c, Value = Leath});
            Items.Add(new Item{Resource = 7, Offset = 0xa50, Value = Slot_Two_Siz});
            // Vanguard    Mail    Arms    Cloth    Utility    recipe_heavy_var2_0030b
            Items.Add(new Item{Resource = 8, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 8, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 8, Offset = 0xa4c, Value = Cloth});
            Items.Add(new Item{Resource = 8, Offset = 0xa50, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 8, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 8, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 8, Offset = 0xa64, Value = Cloth});
            Items.Add(new Item{Resource = 8, Offset = 0xa68, Value = Slot_Two_Siz});
            // Battlemaster    Mail    Arms    Metal    Defense    recipe_heavy_var2_0030c
            Items.Add(new Item{Resource = 9, Offset = 0xa58, Value = Defe});
            Items.Add(new Item{Resource = 9, Offset = 0xa5c, Value = Defe1});
            Items.Add(new Item{Resource = 9, Offset = 0xa64, Value = Metal});
            Items.Add(new Item{Resource = 9, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 9, Offset = 0xa40, Value = Defe});
            Items.Add(new Item{Resource = 9, Offset = 0xa44, Value = Defe1});
            Items.Add(new Item{Resource = 9, Offset = 0xa4c, Value = Metal});
            Items.Add(new Item{Resource = 9, Offset = 0xa50, Value = Slot_Two_Siz});
            // Vanguard    Armor    Arms    Leather    Defense    recipe_heavy_var2_0040b
            Items.Add(new Item{Resource = 10, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 10, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 10, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 10, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 10, Offset = 0xa40, Value = Defe});
            Items.Add(new Item{Resource = 10, Offset = 0xa44, Value = Defe1});
            Items.Add(new Item{Resource = 10, Offset = 0xa4c, Value = Leath});
            Items.Add(new Item{Resource = 10, Offset = 0xa50, Value = Slot_Two_Siz});
            // Battlemaster    Armor    Arms    Metal    Utility    recipe_heavy_var2_0040c            
            Items.Add(new Item{Resource = 11, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 11, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 11, Offset = 0xa4c, Value = Metal});
            Items.Add(new Item{Resource = 11, Offset = 0xa50, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 11, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 11, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 11, Offset = 0xa34, Value = Metal});
            Items.Add(new Item{Resource = 11, Offset = 0xa38, Value = Slot_Two_Siz});
            // Enchanter     Coat    Arms    Leather    Defense    recipe_light_var2_0020b
            Items.Add(new Item{Resource = 12, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 12, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 12, Offset = 0xa34, Value = Leath});
            Items.Add(new Item{Resource = 12, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 12, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 12, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 12, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 12, Offset = 0xa20, Value = Slot_Two_Siz});
            // Battlemage     Coat    Arms    Leather    Utility    recipe_light_var2_0020c
            Items.Add(new Item{Resource = 13, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 13, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 13, Offset = 0xa34, Value = Leath});
            Items.Add(new Item{Resource = 13, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 13, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 13, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 13, Offset = 0xa4c, Value = Leath});
            Items.Add(new Item{Resource = 13, Offset = 0xa50, Value = Slot_Two_Siz});
            // Enchanter    Mail    Arms    Cloth    Defense    recipe_light_var2_0030b
            Items.Add(new Item{Resource = 14, Offset = 0xa58, Value = Defe});
            Items.Add(new Item{Resource = 14, Offset = 0xa5c, Value = Defe1});
            Items.Add(new Item{Resource = 14, Offset = 0xa64, Value = Cloth});
            Items.Add(new Item{Resource = 14, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 14, Offset = 0xa40, Value = Defe});
            Items.Add(new Item{Resource = 14, Offset = 0xa44, Value = Defe1});
            Items.Add(new Item{Resource = 14, Offset = 0xa4c, Value = Cloth});
            Items.Add(new Item{Resource = 14, Offset = 0xa50, Value = Slot_Two_Siz});
            // Battlemage    Mail    Arms    Cloth    Utility    recipe_light_var2_0030c
            Items.Add(new Item{Resource = 15, Offset = 0xa10, Value = Util});
            Items.Add(new Item{Resource = 15, Offset = 0xa14, Value = Util2});
            Items.Add(new Item{Resource = 15, Offset = 0xa1c, Value = Cloth});
            Items.Add(new Item{Resource = 15, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 15, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 15, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 15, Offset = 0xa64, Value = Cloth});
            Items.Add(new Item{Resource = 15, Offset = 0xa68, Value = Slot_Two_Siz});
            // Enchanter     Armor    Arms    Metal    Defense    recipe_light_var2_0040b
            Items.Add(new Item{Resource = 16, Offset = 0xa40, Value = Defe});
            Items.Add(new Item{Resource = 16, Offset = 0xa44, Value = Defe1});
            Items.Add(new Item{Resource = 16, Offset = 0xa4c, Value = Metal});
            Items.Add(new Item{Resource = 16, Offset = 0xa50, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 16, Offset = 0xa58, Value = Defe});
            Items.Add(new Item{Resource = 16, Offset = 0xa5c, Value = Defe1});
            Items.Add(new Item{Resource = 16, Offset = 0xa64, Value = Metal});
            Items.Add(new Item{Resource = 16, Offset = 0xa68, Value = Slot_Two_Siz});
            // Battlemage     Armor    Arms    Metal    Utility    recipe_light_var2_0040c
            Items.Add(new Item{Resource = 17, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 17, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 17, Offset = 0xa34, Value = Metal});
            Items.Add(new Item{Resource = 17, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 17, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 17, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 17, Offset = 0xa4c, Value = Metal});
            Items.Add(new Item{Resource = 17, Offset = 0xa50, Value = Slot_Two_Siz});
            // Enchanter     Mail    Legs    Cloth    Defense    recipe_light_var2_0002b
            Items.Add(new Item{Resource = 18, Offset = 0xa58, Value = Defe});
            Items.Add(new Item{Resource = 18, Offset = 0xa5c, Value = Defe1});
            Items.Add(new Item{Resource = 18, Offset = 0xa64, Value = Cloth});
            Items.Add(new Item{Resource = 18, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 18, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 18, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 18, Offset = 0xa34, Value = Cloth});
            Items.Add(new Item{Resource = 18, Offset = 0xa38, Value = Slot_Two_Siz});
            // Battlemage    Coat    Legs    Leather    Utility    recipe_light_var2_0002c
            Items.Add(new Item{Resource = 19, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 19, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 19, Offset = 0xa64, Value = Leath});
            Items.Add(new Item{Resource = 19, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 19, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 19, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 19, Offset = 0xa34, Value = Leath});
            Items.Add(new Item{Resource = 19, Offset = 0xa38, Value = Slot_Two_Siz});
            // Enchanter     Coat    Legs    Leather    Defense    recipe_light_var2_0003b
            Items.Add(new Item{Resource = 20, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 20, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 20, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 20, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 20, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 20, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 20, Offset = 0xa34, Value = Leath});
            Items.Add(new Item{Resource = 20, Offset = 0xa38, Value = Slot_Two_Siz});            
            // Battlemage     Mail    Legs    Cloth    Utility    recipe_light_var2_0003c
            Items.Add(new Item{Resource = 21, Offset = 0xa10, Value = Util});
            Items.Add(new Item{Resource = 21, Offset = 0xa14, Value = Util2});
            Items.Add(new Item{Resource = 21, Offset = 0xa1c, Value = Cloth});
            Items.Add(new Item{Resource = 21, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 21, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 21, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 21, Offset = 0xa64, Value = Cloth});
            Items.Add(new Item{Resource = 21, Offset = 0xa68, Value = Slot_Two_Siz});            
            // Enchanter    Armor    Legs    Metal    Defense    recipe_light_var2_0004b
            Items.Add(new Item{Resource = 22, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 22, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 22, Offset = 0xa34, Value = Metal});
            Items.Add(new Item{Resource = 22, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 22, Offset = 0xa58, Value = Defe});
            Items.Add(new Item{Resource = 22, Offset = 0xa5c, Value = Defe1});
            Items.Add(new Item{Resource = 22, Offset = 0xa64, Value = Metal});
            Items.Add(new Item{Resource = 22, Offset = 0xa68, Value = Slot_Two_Siz});            
            // Battlemage     Armor    Legs    Metal    Utility    recipe_light_var2_0004c
            Items.Add(new Item{Resource = 23, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 23, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 23, Offset = 0xa64, Value = Metal});
            Items.Add(new Item{Resource = 23, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 23, Offset = 0xa10, Value = Util});
            Items.Add(new Item{Resource = 23, Offset = 0xa14, Value = Util2});
            Items.Add(new Item{Resource = 23, Offset = 0xa1c, Value = Metal});
            Items.Add(new Item{Resource = 23, Offset = 0xa20, Value = Slot_Two_Siz});            
            // Hunter    Coat    Arms    Leather    Defense    recipe_medium_var2_0020b
            Items.Add(new Item{Resource = 24, Offset = 0xa58, Value = Defe});
            Items.Add(new Item{Resource = 24, Offset = 0xa5c, Value = Defe1});
            Items.Add(new Item{Resource = 24, Offset = 0xa64, Value = Leath});
            Items.Add(new Item{Resource = 24, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 24, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 24, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 24, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 24, Offset = 0xa20, Value = Slot_Two_Siz});            
            // Prowler    Coat    Arms    Leather    Utility    recipe_medium_var2_0020c
            Items.Add(new Item{Resource = 25, Offset = 0xa10, Value = Util});
            Items.Add(new Item{Resource = 25, Offset = 0xa14, Value = Util2});
            Items.Add(new Item{Resource = 25, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 25, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 25, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 25, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 25, Offset = 0xa4c, Value = Leath});
            Items.Add(new Item{Resource = 25, Offset = 0xa50, Value = Slot_Two_Siz});            
            // Hunter    Mail    Arms    Metal    Defense    recipe_medium_var2_0030b
            Items.Add(new Item{Resource = 26, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 26, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 26, Offset = 0xa34, Value = Metal});
            Items.Add(new Item{Resource = 26, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 26, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 26, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 26, Offset = 0xa1c, Value = Metal});
            Items.Add(new Item{Resource = 26, Offset = 0xa20, Value = Slot_Two_Siz});            
            // Prowler    Mail    Arms    Metal    Utility    recipe_medium_var2_0030c
            Items.Add(new Item{Resource = 27, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 27, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 27, Offset = 0xa64, Value = Metal});
            Items.Add(new Item{Resource = 27, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 27, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 27, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 27, Offset = 0xa4c, Value = Metal});
            Items.Add(new Item{Resource = 27, Offset = 0xa50, Value = Slot_Two_Siz});            
            // Hunter    Armor    Arms    Cloth    Defense    recipe_medium_var2_0040b
            Items.Add(new Item{Resource = 28, Offset = 0xa40, Value = Defe});
            Items.Add(new Item{Resource = 28, Offset = 0xa44, Value = Defe1});
            Items.Add(new Item{Resource = 28, Offset = 0xa4c, Value = Cloth});
            Items.Add(new Item{Resource = 28, Offset = 0xa50, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 28, Offset = 0xa58, Value = Defe});
            Items.Add(new Item{Resource = 28, Offset = 0xa5c, Value = Defe1});
            Items.Add(new Item{Resource = 28, Offset = 0xa64, Value = Cloth});
            Items.Add(new Item{Resource = 28, Offset = 0xa68, Value = Slot_Two_Siz});            
            // Prowler    Armor    Arms    Cloth    Utility    recipe_medium_var2_0040c
            Items.Add(new Item{Resource = 29, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 29, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 29, Offset = 0xa34, Value = Cloth});
            Items.Add(new Item{Resource = 29, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 29, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 29, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 29, Offset = 0xa4c, Value = Cloth});
            Items.Add(new Item{Resource = 29, Offset = 0xa50, Value = Slot_Two_Siz});            
            // Hunter    Mail    Legs    Metal    Defense    recipe_medium_var2_0002b
            Items.Add(new Item{Resource = 30, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 30, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 30, Offset = 0xa34, Value = Metal});
            Items.Add(new Item{Resource = 30, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 30, Offset = 0xa40, Value = Defe});
            Items.Add(new Item{Resource = 30, Offset = 0xa44, Value = Defe1});
            Items.Add(new Item{Resource = 30, Offset = 0xa4c, Value = Metal});
            Items.Add(new Item{Resource = 30, Offset = 0xa50, Value = Slot_Two_Siz});            
            // Prowler    Coat    Legs    Leather    Utility    recipe_medium_var2_0002c
            Items.Add(new Item{Resource = 31, Offset = 0xa58, Value = Util});
            Items.Add(new Item{Resource = 31, Offset = 0xa5c, Value = Util2});
            Items.Add(new Item{Resource = 31, Offset = 0xa64, Value = Leath});
            Items.Add(new Item{Resource = 31, Offset = 0xa68, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 31, Offset = 0xa10, Value = Util});
            Items.Add(new Item{Resource = 31, Offset = 0xa14, Value = Util2});
            Items.Add(new Item{Resource = 31, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 31, Offset = 0xa20, Value = Slot_Two_Siz});            
            //Hunter    Coat    Legs    Leather    Defense    recipe_medium_var2_0003b
            Items.Add(new Item{Resource = 32, Offset = 0xa28, Value = Defe});
            Items.Add(new Item{Resource = 32, Offset = 0xa2c, Value = Defe1});
            Items.Add(new Item{Resource = 32, Offset = 0xa34, Value = Leath});
            Items.Add(new Item{Resource = 32, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 32, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 32, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 32, Offset = 0xa1c, Value = Leath});
            Items.Add(new Item{Resource = 32, Offset = 0xa20, Value = Slot_Two_Siz});            
            // Prowler    Mail    Legs    Metal    Utility    recipe_medium_var2_0003c
            Items.Add(new Item{Resource = 33, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 33, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 33, Offset = 0xa4c, Value = Metal});
            Items.Add(new Item{Resource = 33, Offset = 0xa50, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 33, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 33, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 33, Offset = 0xa34, Value = Metal});
            Items.Add(new Item{Resource = 33, Offset = 0xa38, Value = Slot_Two_Siz});            
            //Hunter    Armor    Legs    Cloth    Defense    recipe_medium_var2_0004b
            Items.Add(new Item{Resource = 34, Offset = 0xa10, Value = Defe});
            Items.Add(new Item{Resource = 34, Offset = 0xa14, Value = Defe1});
            Items.Add(new Item{Resource = 34, Offset = 0xa1c, Value = Cloth});
            Items.Add(new Item{Resource = 34, Offset = 0xa20, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 34, Offset = 0xa40, Value = Defe});
            Items.Add(new Item{Resource = 34, Offset = 0xa44, Value = Defe1});
            Items.Add(new Item{Resource = 34, Offset = 0xa4c, Value = Cloth});
            Items.Add(new Item{Resource = 34, Offset = 0xa50, Value = Slot_Two_Siz});            
            //Prowler    Armor    Legs    Cloth    Utility    recipe_medium_var2_0004c
            Items.Add(new Item{Resource = 35, Offset = 0xa28, Value = Util});
            Items.Add(new Item{Resource = 35, Offset = 0xa2c, Value = Util2});
            Items.Add(new Item{Resource = 35, Offset = 0xa34, Value = Cloth});
            Items.Add(new Item{Resource = 35, Offset = 0xa38, Value = Slot_One_Siz});
            Items.Add(new Item{Resource = 35, Offset = 0xa40, Value = Util});
            Items.Add(new Item{Resource = 35, Offset = 0xa44, Value = Util2});
            Items.Add(new Item{Resource = 35, Offset = 0xa4c, Value = Cloth});
            Items.Add(new Item{Resource = 35, Offset = 0xa50, Value = Slot_Two_Siz});            
            
            
            
            
            
                                     
            //SECTION ENDS
            
            //This section does all the voodoo mojo magic stuff
            foreach (var Thing in Items) 
            {
                MemoryStream memSt = new MemoryStream(Scripting.GetResourceData(Thing.Resource));
                BinaryWriter Writer = new BinaryWriter(memSt);
                Writer.BaseStream.Seek(Thing.Offset, SeekOrigin.Begin);
                Writer.Write(Thing.Value);
                Scripting.SetResourceData(Thing.Resource, memSt.ToArray());
                Writer.Close();
            }
            
        }    
    }
}
Quote
Like
Share