Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4.  
  5. namespace D2MonsterAuxParser
  6. {
  7.     public class Program
  8.     {
  9.  
  10.         public static string[] SplitAggregateData(string data)
  11.         {
  12.  
  13.             data = data.Replace(" ", ""); // Remove spaces
  14.             data = data.Replace(",", ""); // Remove Commas (they exist for some pages and not others)
  15.             data = data.Trim(); // This may not be needed.
  16.             data = data.Replace("--", "0"); // Evidently this should just be ran on everything.
  17.             return data.Split('/');
  18.         }
  19.  
  20.         public static string[] SplitTreasureClassData(string data)
  21.         {
  22.             data = data.Replace(" ", ""); // Remove spaces
  23.             data = data.Trim(); // This may not be needed.
  24.             data = data.Replace("--", "0"); // Evidently this should just be ran on everything.
  25.             string[] split = data.Split(',');
  26.             return new string[] {
  27.                 split[0].Split('/')[0].Trim(),
  28.                 split[1].Split('/')[0].Trim(),
  29.                 split[2].Split('/')[0].Trim(),
  30.             };
  31.         }
  32.  
  33.         public static string[] ParseBlockData(string data)
  34.         {
  35.             // D2 Blocking data is basically a cluster fuck.
  36.             data = data.Trim();
  37.             data = data.Replace("%", "");
  38.             data = data.Replace("--", "0"); // Evidently this should just be ran on everything.
  39.             if (data.Equals("0"))
  40.             {
  41.                 return new string[] { "0", "0", "0" };
  42.             }
  43.             int count = 0;
  44.             foreach (char character in data)
  45.             {
  46.                 if (character == '/')
  47.                 {
  48.                     count++;
  49.                 }
  50.             }
  51.             if (count == 0)
  52.             {
  53.                 // Blocking is universal for all difficulties
  54.                 return new string[] { data, data, data };
  55.             }
  56.             if (count == 2)
  57.             {
  58.                 // There are three separate blocking values; one for each difficulty
  59.                 string[] split = data.Split("/");
  60.                 return new string[] {
  61.                     split[0],
  62.                     split[1],
  63.                     split[2] };
  64.             }
  65.             // Throw an error, because there is an edge case we're not prepared for!
  66.             throw new Exception("Blocking edge case detected!");
  67.         }
  68.  
  69.         public static void Main(string[] args)
  70.         {
  71.             bool isDebugging = false;
  72.             bool filterNullData = false;
  73.             int resistanceTableLayoutCulture = 0;
  74.             Dictionary<string, string> auxData = new Dictionary<string, string>();
  75.             StringBuilder builder = new StringBuilder();
  76.  
  77.             /**
  78.              * Get the monster base type from the user; this can be null
  79.              */
  80.             Console.WriteLine("Enter the monster base type:");
  81.             Console.WriteLine("NOTE: For Unique Monsters, this should be left NULL");
  82.             Console.WriteLine("(Enter 'null' to skip)");
  83.             string input = Console.ReadLine();
  84.             if (!input.Equals("null"))
  85.             {
  86.                 auxData.Add("ibasename", input.Trim());
  87.             }
  88.             else
  89.             {
  90.                 auxData.Add("ibasename", "0");
  91.             }
  92.  
  93.             /**
  94.              * Parse Statistics:  Name, Level Experience, Hit Points, Speed, and Max TC
  95.              */
  96.             Console.WriteLine("Input First Row 'Statistics' Data: ");
  97.             input = Console.ReadLine();
  98.             string[] firstRowSegments = input.Split('_');
  99.             // Name
  100.             auxData.Add("imvariant_name", firstRowSegments[0].Trim());
  101.             // Level
  102.             string[] splitCache = SplitAggregateData(firstRowSegments[1]);
  103.             auxData.Add("imlvl_norm", splitCache[0]);
  104.             auxData.Add("imlvl_night", splitCache[1]);
  105.             auxData.Add("imlvl_hell", splitCache[2]);
  106.             // Max TC
  107.             splitCache = SplitTreasureClassData(firstRowSegments[5]);
  108.             auxData.Add("imtrclass_norm", splitCache[0]);
  109.             auxData.Add("imtrclass_night", splitCache[1]);
  110.             auxData.Add("imtrclass_hell", splitCache[2]);
  111.             // Experience
  112.             splitCache = SplitAggregateData(firstRowSegments[2]);
  113.             auxData.Add("imxp_norm", splitCache[0]);
  114.             auxData.Add("imxp_night", splitCache[1]);
  115.             auxData.Add("imxp_hell", splitCache[2]);
  116.             // Hitpoints
  117.             splitCache = SplitAggregateData(firstRowSegments[3]);
  118.             auxData.Add("imhp_norm", splitCache[0]);
  119.             auxData.Add("imhp_night", splitCache[1]);
  120.             auxData.Add("imhp_hell", splitCache[2]);
  121.             // Speed (Unused for Diablo2.io
  122.             // We won't parse it because we don't need to
  123.  
  124.             /**
  125.              * Parse Defenses: Defense, Blocking, Regen Rate, Drain Effectiveness, Chill Effectiveness
  126.              */
  127.             Console.WriteLine("Input Second Row 'Defense' Data:");
  128.             input = Console.ReadLine();
  129.             string[] secondRowSegments = input.Split('_');
  130.  
  131.             // Defense
  132.             splitCache = SplitAggregateData(secondRowSegments[0]);
  133.             auxData.Add("imdefense_norm", splitCache[0]);
  134.             auxData.Add("imdefense_night", splitCache[1]);
  135.             auxData.Add("imdefense_hell", splitCache[2]);
  136.             // Blocking
  137.             splitCache = ParseBlockData(secondRowSegments[1]);
  138.             auxData.Add("imblock_norm", splitCache[0]);
  139.             auxData.Add("imblock_night", splitCache[1]);
  140.             auxData.Add("imblock_hell", splitCache[2]);
  141.             // Regen Rate
  142.             // We won't parse it because we don't need to
  143.             // Drain Effectiveness
  144.             splitCache = SplitAggregateData(secondRowSegments[3]);
  145.             auxData.Add("imdrain_norm", splitCache[0]);
  146.             auxData.Add("imdrain_night", splitCache[1]);
  147.             auxData.Add("imdrain_hell", splitCache[2]);
  148.             // Chill Effectiveness
  149.             splitCache = SplitAggregateData(secondRowSegments[4]);
  150.             auxData.Add("imchill_norm", splitCache[0]);
  151.             auxData.Add("imchill_night", splitCache[1]);
  152.             auxData.Add("imchill_hell", splitCache[2]);
  153.  
  154.             /**
  155.              * Parse Resistances: Physical, Fire, Cold, Lightning, Poison, Magic
  156.              */
  157.             Console.WriteLine("Define the Resistance Table Layout:");
  158.             Console.WriteLine("Enter '1' for a layout of: 'Physical, Fire, Cold, Lightning, Poison, Magic'");
  159.             Console.WriteLine("Enter '2' for a layout of: 'Physical, Magic, Fire, Cold, Lightning, Poison'");
  160.  
  161.             // Ask the user for the table layout culture of the monster
  162.             input = Console.ReadLine();
  163.             if (Int32.TryParse(input, out int tlcInput))
  164.             {
  165.                 resistanceTableLayoutCulture = tlcInput;
  166.             }
  167.             else
  168.             {
  169.                 throw new Exception("Table Layout must an integer between 1 and 2!");
  170.             }
  171.  
  172.             // Configure Resistance Table Layout
  173.             int resPhysicalTableIndex = 0;
  174.             int resMagicTableIndex = 0;
  175.             int resFireTableIndex = 0;
  176.             int resColdTableIndex = 0;
  177.             int resLightTableIndex = 0;
  178.             int resPoisonTableIndex = 0;
  179.             switch (resistanceTableLayoutCulture)
  180.             {
  181.                 case 1: // Layout: Physical, Fire, Cold, Lightning, Poison, Magic
  182.                     resPhysicalTableIndex = 0;
  183.                     resMagicTableIndex = 5;
  184.                     resFireTableIndex = 1;
  185.                     resColdTableIndex = 2;
  186.                     resLightTableIndex = 3;
  187.                     resPoisonTableIndex = 4;
  188.                     break;
  189.                 case 2: // Layout: Physical, Magic, Fire, Cold, Lightning, Poison
  190.                     resPhysicalTableIndex = 0;
  191.                     resMagicTableIndex = 1;
  192.                     resFireTableIndex = 2;
  193.                     resColdTableIndex = 3;
  194.                     resLightTableIndex = 4;
  195.                     resPoisonTableIndex = 5;
  196.                     break;
  197.                 default:
  198.                     break;
  199.             }
  200.  
  201.             Console.WriteLine("Input Third Row 'Resistances' Data:");
  202.             input = Console.ReadLine();
  203.             string[] thirdRowSegments = input.Split('_');
  204.             // Physical
  205.             splitCache = SplitAggregateData(thirdRowSegments[resPhysicalTableIndex]);
  206.             auxData.Add("imdmgres_norm", splitCache[0].Replace("%", ""));
  207.             auxData.Add("imdmgres_night", splitCache[1].Replace("%", ""));
  208.             auxData.Add("imdmgres_hell", splitCache[2].Replace("%", ""));
  209.             // Fire
  210.             splitCache = SplitAggregateData(thirdRowSegments[resFireTableIndex]);
  211.             auxData.Add("imfireres_norm", splitCache[0].Replace("%", ""));
  212.             auxData.Add("imfireres_night", splitCache[1].Replace("%", ""));
  213.             auxData.Add("imfireres_hell", splitCache[2].Replace("%", ""));
  214.             // Cold
  215.             splitCache = SplitAggregateData(thirdRowSegments[resColdTableIndex]);
  216.             auxData.Add("imcoldres_norm", splitCache[0].Replace("%", ""));
  217.             auxData.Add("imcoldres_night", splitCache[1].Replace("%", ""));
  218.             auxData.Add("imcoldres_hell", splitCache[2].Replace("%", ""));
  219.             // Lightning
  220.             splitCache = SplitAggregateData(thirdRowSegments[resLightTableIndex]);
  221.             auxData.Add("imlightres_norm", splitCache[0].Replace("%", ""));
  222.             auxData.Add("imlightres_night", splitCache[1].Replace("%", ""));
  223.             auxData.Add("imlightres_hell", splitCache[2].Replace("%", ""));
  224.             // Poison
  225.             splitCache = SplitAggregateData(thirdRowSegments[resPoisonTableIndex]);
  226.             auxData.Add("impoisres_norm", splitCache[0].Replace("%", ""));
  227.             auxData.Add("impoisres_night", splitCache[1].Replace("%", ""));
  228.             auxData.Add("impoisres_hell", splitCache[2].Replace("%", ""));
  229.             // Magic
  230.             splitCache = SplitAggregateData(thirdRowSegments[resMagicTableIndex]);
  231.             auxData.Add("immagicres_norm", splitCache[0].Replace("%", ""));
  232.             auxData.Add("immagicres_night", splitCache[1].Replace("%", ""));
  233.             auxData.Add("immagicres_hell", splitCache[2].Replace("%", ""));
  234.  
  235.             /**
  236.              * We need to manually input attack1 and attack2 as well as attackrating1 and attackrating2
  237.              * because there are far too many ways of inputing this data, and it's nearly
  238.              * impossible, if not literally impossible to parse.
  239.              */
  240.             Console.WriteLine("Input Attack1 Damage and Attack Rating (Enter 'null' to skip)");
  241.             Console.WriteLine("Format Hint: 'DamageNormal/DamageNightmare/DamageHell_ARNormal/ARNightmare/ARHell'");
  242.             Console.WriteLine("Format Example: '1-4/1-4/1-4_20/20/20'");
  243.             input = Console.ReadLine();
  244.             if (!input.Equals("null"))
  245.             {
  246.                 string[] attack1DamAndARSegments = input.Split("_");
  247.                 // Attack1 Damage
  248.                 splitCache = SplitAggregateData(attack1DamAndARSegments[0]);
  249.                 auxData.Add("imattack1_norm", splitCache[0].Replace(",", "").Trim());
  250.                 auxData.Add("imattack1_night", splitCache[1].Replace(",", "").Trim());
  251.                 auxData.Add("imattack1_hell", splitCache[2].Replace(",", "").Trim());
  252.                 // Attack1 Attack Rating
  253.                 splitCache = SplitAggregateData(attack1DamAndARSegments[1]);
  254.                 auxData.Add("imrating1_norm", splitCache[0].Replace(",", "").Trim());
  255.                 auxData.Add("imrating1_night", splitCache[1].Replace(",", "").Trim());
  256.                 auxData.Add("imrating1_hell", splitCache[2].Replace(",", "").Trim());
  257.             }
  258.             else
  259.             {
  260.                 // Fill in null data
  261.                 auxData.Add("imattack1_norm", "0");
  262.                 auxData.Add("imattack1_night", "0");
  263.                 auxData.Add("imattack1_hell", "0");
  264.                 auxData.Add("imrating1_norm", "0");
  265.                 auxData.Add("imrating1_night", "0");
  266.                 auxData.Add("imrating1_hell", "0");
  267.             }
  268.  
  269.             Console.WriteLine("Input Attack2 Damage and Attack Rating (Enter 'null' to skip)");
  270.             Console.WriteLine("Format Hint: 'DamageNormal/DamageNightmare/DamageHell_ARNormal/ARNightmare/ARHell'");
  271.             Console.WriteLine("Format Example: '1-4/1-4/1-4_20/20/20'");
  272.             input = Console.ReadLine();
  273.             if (!input.Equals("null"))
  274.             {
  275.                 string[] attack2DamAndARSegments = input.Split("_");
  276.                 // Attack2 Damage
  277.                 splitCache = SplitAggregateData(attack2DamAndARSegments[0]);
  278.                 auxData.Add("imattack2_norm", splitCache[0].Replace(",", "").Trim());
  279.                 auxData.Add("imattack2_night", splitCache[1].Replace(",", "").Trim());
  280.                 auxData.Add("imattack2_hell", splitCache[2].Replace(",", "").Trim());
  281.                 // Attack2 Attack Rating
  282.                 splitCache = SplitAggregateData(attack2DamAndARSegments[1]);
  283.                 auxData.Add("imrating2_norm", splitCache[0].Replace(",", "").Trim());
  284.                 auxData.Add("imrating2_night", splitCache[1].Replace(",", "").Trim());
  285.                 auxData.Add("imrating2_hell", splitCache[2].Replace(",", "").Trim());
  286.             }
  287.             else
  288.             {
  289.                 // Fill in null data
  290.                 auxData.Add("imattack2_norm", "0");
  291.                 auxData.Add("imattack2_night", "0");
  292.                 auxData.Add("imattack2_hell", "0");
  293.                 auxData.Add("imrating2_norm", "0");
  294.                 auxData.Add("imrating2_night", "0");
  295.                 auxData.Add("imrating2_hell", "0");
  296.             }
  297.  
  298.             /**
  299.              * Next, we need to parse for immunities using the data we already gained.
  300.              * If any resistance is greater than or equal to 100, we treat it as an immunity.
  301.              * This seems to be standard in all the tables I looked at.
  302.              */
  303.             #region Automagically Detect Immunity Shenanigans
  304.             string normalImmunity = "0";
  305.             string nightmareImmunity = "0";
  306.             string hellImmunity1 = "0";
  307.             string hellImmunity2 = "0";
  308.  
  309.             foreach (KeyValuePair<string, string> pair in auxData)
  310.             {
  311.                 switch (pair.Key)
  312.                 {
  313.  
  314.                     case "imdmgres_norm":
  315.                     case "immagicres_norm":
  316.                     case "imfireres_norm":
  317.                     case "imcoldres_norm":
  318.                     case "imlightres_norm":
  319.                     case "impoisres_norm":
  320.                         if (normalImmunity.Equals("0"))
  321.                         {
  322.                             if (pair.Value.StartsWith("-"))
  323.                             {
  324.                                 // The resistance is negative
  325.                                 continue;
  326.                             }
  327.                             else
  328.                             {
  329.                                 if (Int32.TryParse(pair.Value, out int normalResistance))
  330.                                 {
  331.                                     if (normalResistance >= 100)
  332.                                     {
  333.                                         switch (pair.Key)
  334.                                         {
  335.                                             case "imdmgres_norm":
  336.                                                 normalImmunity = "Physical";
  337.                                                 break;
  338.                                             case "immagicres_norm":
  339.                                                 normalImmunity = "Magic";
  340.                                                 break;
  341.                                             case "imfireres_norm":
  342.                                                 normalImmunity = "Fire";
  343.                                                 break;
  344.                                             case "imcoldres_norm":
  345.                                                 normalImmunity = "Cold";
  346.                                                 break;
  347.                                             case "imlightres_norm":
  348.                                                 normalImmunity = "Lightning";
  349.                                                 break;
  350.                                             case "impoisres_norm":
  351.                                                 normalImmunity = "Poison";
  352.                                                 break;
  353.                                             default:
  354.                                                 break; // Should never happen.
  355.                                         }
  356.                                     }
  357.                                 }
  358.                             }
  359.                         }
  360.                         break;
  361.                     case "imdmgres_night":
  362.                     case "immagicres_night":
  363.                     case "imfireres_night":
  364.                     case "imcoldres_night":
  365.                     case "imlightres_night":
  366.                     case "impoisres_night":
  367.                         if (nightmareImmunity.Equals("0"))
  368.                         {
  369.                             if (pair.Value.StartsWith("-"))
  370.                             {
  371.                                 // The resistance is negative
  372.                                 continue;
  373.                             }
  374.                             else
  375.                             {
  376.                                 if (Int32.TryParse(pair.Value, out int nightmareResistance))
  377.                                 {
  378.                                     if (nightmareResistance >= 100)
  379.                                     {
  380.                                         switch (pair.Key)
  381.                                         {
  382.                                             case "imdmgres_night":
  383.                                                 nightmareImmunity = "Physical";
  384.                                                 break;
  385.                                             case "immagicres_night":
  386.                                                 nightmareImmunity = "Magic";
  387.                                                 break;
  388.                                             case "imfireres_night":
  389.                                                 nightmareImmunity = "Fire";
  390.                                                 break;
  391.                                             case "imcoldres_night":
  392.                                                 nightmareImmunity = "Cold";
  393.                                                 break;
  394.                                             case "imlightres_night":
  395.                                                 nightmareImmunity = "Lightning";
  396.                                                 break;
  397.                                             case "impoisres_night":
  398.                                                 nightmareImmunity = "Poison";
  399.                                                 break;
  400.                                             default:
  401.                                                 break; // Should never happen.
  402.                                         }
  403.                                     }
  404.                                 }
  405.                             }
  406.                         }
  407.                         break;
  408.                     case "imdmgres_hell":
  409.                     case "immagicres_hell":
  410.                     case "imfireres_hell":
  411.                     case "imcoldres_hell":
  412.                     case "imlightres_hell":
  413.                     case "impoisres_hell":
  414.                         /**
  415.                          * An inherent edge case exists here, because Hell difficulty
  416.                          * is listed as having two possible immunities.
  417.                          */
  418.                         if (pair.Value.StartsWith("-"))
  419.                         {
  420.                             // The resistance is negative
  421.                             continue;
  422.                         }
  423.                         else
  424.                         {
  425.                             if (Int32.TryParse(pair.Value, out int hellResistance))
  426.                             {
  427.                                 if (hellResistance >= 100)
  428.                                 {
  429.                                     switch (pair.Key)
  430.                                     {
  431.                                         case "imdmgres_hell":
  432.                                             if (hellImmunity1.Equals("0"))
  433.                                             {
  434.                                                 hellImmunity1 = "Physical";
  435.                                             }
  436.                                             else
  437.                                             {
  438.                                                 hellImmunity2 = "Physical";
  439.                                             }
  440.                                             break;
  441.                                         case "immagicres_hell":
  442.                                             if (hellImmunity1.Equals("0"))
  443.                                             {
  444.                                                 hellImmunity1 = "Magic";
  445.                                             }
  446.                                             else
  447.                                             {
  448.                                                 hellImmunity2 = "Magic";
  449.                                             }
  450.                                             break;
  451.                                         case "imfireres_hell":
  452.                                             if (hellImmunity1.Equals("0"))
  453.                                             {
  454.                                                 hellImmunity1 = "Fire";
  455.                                             }
  456.                                             else
  457.                                             {
  458.                                                 hellImmunity2 = "Fire";
  459.                                             }
  460.                                             break;
  461.                                         case "imcoldres_hell":
  462.                                             if (hellImmunity1.Equals("0"))
  463.                                             {
  464.                                                 hellImmunity1 = "Cold";
  465.                                             }
  466.                                             else
  467.                                             {
  468.                                                 hellImmunity2 = "Cold";
  469.                                             }
  470.                                             break;
  471.                                         case "imlightres_hell":
  472.                                             if (hellImmunity1.Equals("0"))
  473.                                             {
  474.                                                 hellImmunity1 = "Lightning";
  475.                                             }
  476.                                             else
  477.                                             {
  478.                                                 hellImmunity2 = "Lightning";
  479.                                             }
  480.                                             break;
  481.                                         case "impoisres_hell":
  482.                                             if (hellImmunity1.Equals("0"))
  483.                                             {
  484.                                                 hellImmunity1 = "Poison";
  485.                                             }
  486.                                             else
  487.                                             {
  488.                                                 hellImmunity2 = "Poison";
  489.                                             }
  490.                                             break;
  491.                                         default:
  492.                                             break; // Should never happen.
  493.                                     }
  494.                                 }
  495.                             }
  496.                         }
  497.                         break;
  498.                     default:
  499.                         break;
  500.                 }
  501.             }
  502.  
  503.  
  504.             // Add the new immunity data to the auxdata
  505.             auxData.Add("imimm_norm", normalImmunity);
  506.             auxData.Add("imimm_night", nightmareImmunity);
  507.             auxData.Add("imimm_hell", hellImmunity1);
  508.             auxData.Add("imimm_hell2", hellImmunity2);
  509.             #endregion
  510.  
  511.             /**
  512.              * Continue to debugging and then finally generating
  513.              * and printing data out.
  514.              */
  515.             if (isDebugging)
  516.             {
  517.                 Console.WriteLine();
  518.                 Console.WriteLine("Printing Debug Log...");
  519.                 foreach (KeyValuePair<string, string> pair in auxData)
  520.                 {
  521.                     Console.WriteLine(pair.Key + " " + pair.Value);
  522.                 }
  523.                 Console.WriteLine("Debug Log Finished.");
  524.  
  525.             }
  526.  
  527.             /**
  528.              * Generate Diablo2.io Markup
  529.              */
  530.             Console.WriteLine();
  531.             Console.WriteLine("Generating Diablo2.io Markup...");
  532.  
  533.             builder.AppendLine("[zform][form][b]irarity[/b][/form][fbox]Monster (Auxiliary)[/fbox][/zform]");
  534.             builder.AppendLine("[zform][form][b]igraphic[/b][/form][att][attachment=0][/attachment][/att][/zform]");
  535.             foreach (KeyValuePair<string, string> pair in auxData)
  536.             {
  537.                 if (filterNullData)
  538.                 {
  539.                     if (pair.Value.Equals("0"))
  540.                     {
  541.                         continue;
  542.                     }
  543.                 }
  544.                 builder.AppendLine("[zform][form][b]" + pair.Key + "[/b][/form][fbox]" + pair.Value + "[/fbox][/zform]");
  545.             }
  546.  
  547.             Console.WriteLine("Finished generating markup!");
  548.             Console.WriteLine("Printing Diablo2.io Aux Markup!");
  549.             Console.WriteLine(builder.ToString());
  550.         }
  551.     }
  552. }
  553.