
/* FFXI Skill Cap Calculator - JavaScript      */
/* Copyright (c) Nathan Mercuri 2007-2011      */
/* All rights reserved.                        */
/* http://www.nateworld.com/                   */
/* Author: Nathan Mercuri (aka "Divinius")     */
/* Email: divinius@gmail.com                   */
/* Version 5.5.99                              */
/* Last Update: 14 Dec 2011                    */

/* Original Source file location:                       */
/* http://www.nateworld.com/ffxi/scfiles/skillcalc.js   */


// *****  Constant Definitions for Lookup Tables  *****

const LvlCap = 99;  // Defined the highest job level currently attainable in the game
const SklTtl = 31;  // Defines the total number of skills that the game has
const BrkPnt = 19;  // Defines the breakpoint between Combat and Magic Skills
   // This value must be equal to the number of Combat Skills (which is also the array index of the first Magic Skill)

const MaxCombatMrts = 32;  // Defines the Maximum allowed number of Merits you can have in Combat Skills
const MaxMagicMrts = 24;   // Defines the Maximum allowed number of Merits you can have in Magic Skills

var grades = new Array(SklTtl);  // Holds the arrays of Job Skill Grades for each Skill
//      each element: (  Skill Name   , WAR , MNK , WHM , BLM , RDM , THF , PLD , DRK , BST , BRD , RNG , SAM , NIN , DRG , SMN , BLU , COR , PUP , DNC , SCH  );

grades[ 0] = new Array( "Hand-to-Hand", "D ", "A+", "  ", "  ", "  ", "E ", "  ", "  ", "  ", "  ", "  ", "  ", "E ", "  ", "  ", "  ", "  ", "B+", "D ", "  " );
grades[ 1] = new Array( "Dagger"      , "B-", "  ", "  ", "D ", "B ", "A-", "C-", "C ", "C+", "B-", "B-", "E ", "C+", "E ", "E ", "  ", "B+", "C-", "B+", "D " );
grades[ 2] = new Array( "Sword"       , "B ", "  ", "  ", "  ", "B ", "D ", "A+", "B-", "E ", "C-", "D ", "C+", "C ", "C-", "  ", "A-", "B-", "  ", "D ", "  " );
grades[ 3] = new Array( "Great Sword" , "B+", "  ", "  ", "  ", "  ", "  ", "B ", "A-", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[ 4] = new Array( "Axe"         , "A-", "  ", "  ", "  ", "  ", "  ", "  ", "B-", "A-", "  ", "B-", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[ 5] = new Array( "Great Axe"   , "A+", "  ", "  ", "  ", "  ", "  ", "  ", "B-", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[ 6] = new Array( "Scythe"      , "B+", "  ", "  ", "E ", "  ", "  ", "  ", "A+", "B-", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[ 7] = new Array( "Polearm"     , "B-", "  ", "  ", "  ", "  ", "  ", "E ", "  ", "  ", "  ", "  ", "B-", "  ", "A+", "  ", "  ", "  ", "  ", "  ", "  " );
grades[ 8] = new Array( "Katana"      , "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "A-", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[ 9] = new Array( "Great Katana", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "A+", "C-", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[10] = new Array( "Club"        , "B-", "C+", "B+", "C+", "D ", "E ", "A-", "C-", "D ", "D ", "E ", "E ", "E ", "E ", "C+", "B-", "  ", "D ", "  ", "C+" );
grades[11] = new Array( "Staff"       , "B ", "B ", "C+", "B-", "  ", "  ", "A-", "  ", "  ", "C+", "  ", "  ", "  ", "B-", "B ", "  ", "  ", "  ", "  ", "C+" );

grades[12] = new Array( "Archery"     , "D ", "  ", "  ", "  ", "D ", "C-", "  ", "  ", "  ", "  ", "A-", "C+", "E ", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[13] = new Array( "Marksmanship", "D ", "  ", "  ", "  ", "  ", "C+", "  ", "E ", "  ", "  ", "A-", "  ", "C ", "  ", "  ", "  ", "B ", "  ", "  ", "  " );
grades[14] = new Array( "Throwing"    , "D ", "E ", "E ", "D ", "F ", "D ", "  ", "  ", "  ", "E ", "C-", "C ", "A-", "  ", "  ", "  ", "C+", "C+", "C+", "D " );

grades[15] = new Array( "Guarding"    , "  ", "A-", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "B-", "  ", "  " );
grades[16] = new Array( "Evasion"     , "C ", "B+", "E ", "E ", "D ", "A+", "C ", "C ", "C ", "D ", "E ", "B+", "A-", "C-", "E ", "C-", "D ", "B ", "B+", "E " );
grades[17] = new Array( "Shield"      , "C+", "  ", "D ", "  ", "F ", "F ", "A+", "  ", "E ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[18] = new Array( "Parrying"    , "C-", "E ", "  ", "  ", "E ", "A-", "C ", "E ", "C ", "E ", "  ", "A-", "A-", "C ", "  ", "D ", "A-", "D ", "B ", "E " );

grades[19] = new Array( "Divine"      , "  ", "  ", "A-", "  ", "E ", "  ", "B+", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "D " );
grades[20] = new Array( "Healing"     , "  ", "  ", "A+", "  ", "C-", "  ", "C ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "D " );
grades[21] = new Array( "Enhancing"   , "  ", "  ", "C+", "E ", "B+", "  ", "D ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "D " );
grades[22] = new Array( "Enfeebling"  , "  ", "  ", "C ", "C+", "A+", "  ", "  ", "C ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "D " );
grades[23] = new Array( "Elemental"   , "  ", "  ", "  ", "A+", "C+", "  ", "  ", "B+", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "D " );
grades[24] = new Array( "Dark"        , "  ", "  ", "  ", "A-", "E ", "  ", "  ", "A-", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "D " );
grades[25] = new Array( "Summoning"   , "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "A-", "  ", "  ", "  ", "  ", "  " );
grades[26] = new Array( "Ninjutsu"    , "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "A-", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[27] = new Array( "Singing"     , "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "C ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[28] = new Array( "String"      , "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "C ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[29] = new Array( "Wind"        , "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "C ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  " );
grades[30] = new Array( "Blue Magic"  , "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "  ", "A+", "  ", "  ", "  ", "  " );

var gradeNums = new Array(SklTtl);  // Holds the arrays of THE NUMERICAL EQUIVALENTS of Job Skill Grades for each Skill

var levels = new Array(LvlCap + 1);  // Holds the arrays of Skill Caps for each Job Level
//      each element: ( X,  A+,  A-,  B+,  B ,  B-,  C+,  C ,  C-,  D ,  E ,  F  );
levels[ 0] = new Array( 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 );
levels[ 1] = new Array( 0,   6,   6,   5,   5,   5,   5,   5,   5,   4,   4,   4 );
levels[ 2] = new Array( 0,   9,   9,   7,   7,   7,   7,   7,   7,   6,   6,   6 );
levels[ 3] = new Array( 0,  12,  12,  10,  10,  10,  10,  10,  10,   9,   9,   8 );
levels[ 4] = new Array( 0,  15,  15,  13,  13,  13,  13,  13,  13,  12,  11,  10 );
levels[ 5] = new Array( 0,  18,  18,  16,  16,  16,  16,  16,  16,  14,  14,  13 );
levels[ 6] = new Array( 0,  21,  21,  19,  19,  19,  19,  19,  19,  17,  16,  15 );
levels[ 7] = new Array( 0,  24,  24,  22,  22,  22,  21,  21,  21,  20,  19,  17 );
levels[ 8] = new Array( 0,  27,  27,  25,  25,  25,  24,  24,  24,  22,  21,  20 );
levels[ 9] = new Array( 0,  30,  30,  28,  28,  28,  27,  27,  27,  25,  24,  22 );
levels[10] = new Array( 0,  33,  33,  31,  31,  31,  30,  30,  30,  28,  26,  24 );
levels[11] = new Array( 0,  36,  36,  34,  34,  34,  33,  33,  33,  31,  29,  27 );
levels[12] = new Array( 0,  39,  39,  36,  36,  36,  35,  35,  35,  33,  31,  29 );
levels[13] = new Array( 0,  42,  42,  39,  39,  39,  38,  38,  38,  36,  34,  31 );
levels[14] = new Array( 0,  45,  45,  42,  42,  42,  41,  41,  41,  39,  36,  33 );
levels[15] = new Array( 0,  48,  48,  45,  45,  45,  44,  44,  44,  41,  39,  36 );
levels[16] = new Array( 0,  51,  51,  48,  48,  48,  47,  47,  47,  44,  41,  38 );
levels[17] = new Array( 0,  54,  54,  51,  51,  51,  49,  49,  49,  47,  44,  40 );
levels[18] = new Array( 0,  57,  57,  54,  54,  54,  52,  52,  52,  49,  46,  43 );
levels[19] = new Array( 0,  60,  60,  57,  57,  57,  55,  55,  55,  52,  49,  45 );
levels[20] = new Array( 0,  63,  63,  60,  60,  60,  58,  58,  58,  55,  51,  47 );
levels[21] = new Array( 0,  66,  66,  63,  63,  63,  61,  61,  61,  58,  54,  50 );
levels[22] = new Array( 0,  69,  69,  65,  65,  65,  63,  63,  63,  60,  56,  52 );
levels[23] = new Array( 0,  72,  72,  68,  68,  68,  66,  66,  66,  63,  59,  54 );
levels[24] = new Array( 0,  75,  75,  71,  71,  71,  69,  69,  69,  66,  61,  56 );
levels[25] = new Array( 0,  78,  78,  74,  74,  74,  72,  72,  72,  68,  64,  59 );
levels[26] = new Array( 0,  81,  81,  77,  77,  77,  75,  75,  75,  71,  66,  61 );
levels[27] = new Array( 0,  84,  84,  80,  80,  80,  77,  77,  77,  74,  69,  63 );
levels[28] = new Array( 0,  87,  87,  83,  83,  83,  80,  80,  80,  76,  71,  66 );
levels[29] = new Array( 0,  90,  90,  86,  86,  86,  83,  83,  83,  79,  74,  68 );
levels[30] = new Array( 0,  93,  93,  89,  89,  89,  86,  86,  86,  82,  76,  70 );
levels[31] = new Array( 0,  96,  96,  92,  92,  92,  89,  89,  89,  85,  79,  73 );
levels[32] = new Array( 0,  99,  99,  94,  94,  94,  91,  91,  91,  87,  81,  75 );
levels[33] = new Array( 0, 102, 102,  97,  97,  97,  94,  94,  94,  90,  84,  77 );
levels[34] = new Array( 0, 105, 105, 100, 100, 100,  97,  97,  97,  93,  86,  79 );
levels[35] = new Array( 0, 108, 108, 103, 103, 103, 100, 100, 100,  95,  89,  82 );
levels[36] = new Array( 0, 111, 111, 106, 106, 106, 103, 103, 103,  98,  91,  84 );
levels[37] = new Array( 0, 114, 114, 109, 109, 109, 105, 105, 105, 101,  94,  86 );
levels[38] = new Array( 0, 117, 117, 112, 112, 112, 108, 108, 108, 103,  96,  89 );
levels[39] = new Array( 0, 120, 120, 115, 115, 115, 111, 111, 111, 106,  99,  91 );
levels[40] = new Array( 0, 123, 123, 118, 118, 118, 114, 114, 114, 109, 101,  93 );
levels[41] = new Array( 0, 126, 126, 121, 121, 121, 117, 117, 117, 112, 104,  96 );
levels[42] = new Array( 0, 129, 129, 123, 123, 123, 119, 119, 119, 114, 106,  98 );
levels[43] = new Array( 0, 132, 132, 126, 126, 126, 122, 122, 122, 117, 109, 100 );
levels[44] = new Array( 0, 135, 135, 129, 129, 129, 125, 125, 125, 120, 111, 102 );
levels[45] = new Array( 0, 138, 138, 132, 132, 132, 128, 128, 128, 122, 114, 105 );
levels[46] = new Array( 0, 141, 141, 135, 135, 135, 131, 131, 131, 125, 116, 107 );
levels[47] = new Array( 0, 144, 144, 138, 138, 138, 133, 133, 133, 128, 119, 109 );
levels[48] = new Array( 0, 147, 147, 141, 141, 141, 136, 136, 136, 130, 121, 112 );
levels[49] = new Array( 0, 150, 150, 144, 144, 144, 139, 139, 139, 133, 124, 114 );
levels[50] = new Array( 0, 153, 153, 147, 147, 147, 142, 142, 142, 136, 126, 116 );

levels[51] = new Array( 0, 158, 158, 151, 151, 151, 146, 146, 146, 140, 130, 120 );
levels[52] = new Array( 0, 163, 163, 156, 156, 156, 151, 151, 151, 145, 135, 124 );
levels[53] = new Array( 0, 168, 168, 161, 161, 161, 156, 156, 156, 150, 139, 128 );
levels[54] = new Array( 0, 173, 173, 166, 166, 166, 161, 161, 161, 154, 144, 133 );
levels[55] = new Array( 0, 178, 178, 171, 171, 171, 166, 166, 166, 159, 148, 137 );
levels[56] = new Array( 0, 183, 183, 176, 176, 176, 170, 170, 170, 164, 153, 141 );
levels[57] = new Array( 0, 188, 188, 181, 181, 181, 175, 175, 175, 168, 157, 146 );
levels[58] = new Array( 0, 193, 193, 186, 186, 186, 180, 180, 180, 173, 162, 150 );
levels[59] = new Array( 0, 198, 198, 191, 191, 191, 185, 185, 185, 178, 166, 154 );
levels[60] = new Array( 0, 203, 203, 196, 196, 196, 190, 190, 190, 183, 171, 159 );

levels[61] = new Array( 0, 207, 207, 199, 199, 198, 192, 192, 192, 184, 172, 161 );
levels[62] = new Array( 0, 212, 211, 203, 202, 201, 195, 194, 194, 186, 174, 163 );
levels[63] = new Array( 0, 217, 215, 207, 205, 204, 197, 196, 196, 188, 176, 165 );
levels[64] = new Array( 0, 222, 219, 210, 208, 206, 200, 199, 198, 190, 178, 167 );
levels[65] = new Array( 0, 227, 223, 214, 212, 209, 202, 201, 200, 192, 180, 169 );
levels[66] = new Array( 0, 232, 227, 218, 215, 212, 205, 203, 202, 194, 182, 171 );
levels[67] = new Array( 0, 236, 231, 221, 218, 214, 207, 205, 204, 195, 184, 173 );
levels[68] = new Array( 0, 241, 235, 225, 221, 217, 210, 208, 206, 197, 186, 175 );
levels[69] = new Array( 0, 246, 239, 229, 225, 220, 212, 210, 208, 199, 188, 177 );
levels[70] = new Array( 0, 251, 244, 233, 228, 223, 215, 212, 210, 201, 190, 179 );

levels[71] = new Array( 0, 256, 249, 237, 232, 226, 218, 214, 212, 203, 192, 181 );
levels[72] = new Array( 0, 261, 254, 241, 236, 229, 221, 217, 214, 205, 194, 183 );
levels[73] = new Array( 0, 266, 259, 246, 240, 232, 224, 219, 216, 207, 196, 185 );
levels[74] = new Array( 0, 271, 264, 251, 245, 236, 227, 222, 218, 208, 198, 187 );
levels[75] = new Array( 0, 276, 269, 256, 250, 240, 230, 225, 220, 210, 200, 189 );

//      each element: ( X,  A+,  A-,  B+,  B ,  B-,  C+,  C ,  C-,  D ,  E ,  F  );
levels[76] = new Array( 0, 281, 274, 261, 255, 245, 235, 230, 225, 214, 203, 191 );
levels[77] = new Array( 0, 286, 279, 266, 260, 250, 240, 235, 230, 218, 206, 193 );
levels[78] = new Array( 0, 291, 284, 271, 265, 255, 245, 240, 235, 222, 209, 195 );
levels[79] = new Array( 0, 296, 289, 276, 270, 260, 250, 245, 240, 226, 212, 197 );
levels[80] = new Array( 0, 301, 294, 281, 275, 265, 255, 250, 245, 230, 215, 199 );

levels[81] = new Array( 0, 307, 300, 287, 281, 271, 261, 256, 251, 235, 219, 202 );
levels[82] = new Array( 0, 313, 306, 293, 287, 277, 267, 262, 257, 240, 223, 205 );
levels[83] = new Array( 0, 319, 312, 299, 293, 283, 273, 268, 263, 245, 227, 208 );
levels[84] = new Array( 0, 325, 318, 305, 299, 289, 279, 274, 269, 250, 231, 211 );
levels[85] = new Array( 0, 331, 324, 311, 305, 295, 285, 280, 275, 255, 235, 214 );

levels[86] = new Array( 0, 337, 330, 317, 311, 301, 291, 286, 281, 260, 239, 217 );
levels[87] = new Array( 0, 343, 336, 323, 317, 307, 297, 292, 287, 265, 243, 220 );
levels[88] = new Array( 0, 349, 342, 329, 323, 313, 303, 298, 293, 270, 247, 223 );
levels[89] = new Array( 0, 355, 348, 335, 329, 319, 309, 304, 299, 275, 251, 226 );
levels[90] = new Array( 0, 361, 354, 341, 335, 325, 315, 310, 305, 280, 255, 229 );

levels[91] = new Array( 0, 368, 361, 348, 342, 332, 322, 317, 312, 286, 260, 233 );
levels[92] = new Array( 0, 375, 368, 355, 349, 339, 329, 324, 319, 292, 265, 237 );
levels[93] = new Array( 0, 382, 375, 362, 356, 346, 336, 331, 326, 298, 270, 241 );
levels[94] = new Array( 0, 389, 382, 369, 363, 353, 343, 338, 333, 304, 275, 245 );
levels[95] = new Array( 0, 396, 389, 376, 370, 360, 350, 345, 340, 310, 280, 249 );

levels[96] = new Array( 0, 403, 396, 383, 377, 367, 357, 352, 347, 316, 285, 253 );
levels[97] = new Array( 0, 410, 403, 390, 384, 374, 364, 359, 354, 322, 290, 257 );
levels[98] = new Array( 0, 417, 410, 397, 391, 381, 371, 366, 361, 328, 295, 261 );
levels[99] = new Array( 0, 424, 417, 404, 398, 388, 378, 373, 368, 334, 300, 265 );

// Holds the max number of active skill Merits available for each job level
// size = LvlCap + 1  -- (currently set to 100 for a level cap of 99)
var merits = new Array( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                        2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
                        3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
                        4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
                        5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
                        7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
                        8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
                        8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
                        8, 8, 8, 8, 8, 8, 8, 8, 8, 8 );

// Define the arrays of Weaponskill info for each weapon type
var weapons = new Array(14);  // 3-dimensional array
   // 1st dim = 14 Weapon types
   // 2nd dim = 7 to 11 weaponskills for each type (not all the same length)
   // 3rd dim = 22 data points for each weaponskill (skill level, name, and availability code for all 20 jobs)

const WsH2H =  0;  // Hand-to-Hand
const WsDgr =  1;  // Dagger
const WsSwd =  2;  // Sword
const WsGSw =  3;  // Great Sword
const WsAxe =  4;  // Axe
const WsGAx =  5;  // Great Axe
const WsScy =  6;  // Scythe
const WsPol =  7;  // Polearm
const WsKat =  8;  // Katana
const WsGKt =  9;  // Great Katana
const WsClb = 10;  // Club
const WsStf = 11;  // Staff
const WsArc = 12;  // Archery
const WsMrk = 13;  // Marksmanship

// Hand-to-Hand
weapons[WsH2H] = new Array(10);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsH2H][ 0] = new Array(   5, "Combo"            , 3 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 3 , 3 , 0 );
weapons[WsH2H][ 1] = new Array(  40, "Shoulder Tackle"  , 3 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 3 , 3 , 0 );
weapons[WsH2H][ 2] = new Array(  75, "One Inch Punch"   , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 );
weapons[WsH2H][ 3] = new Array( 100, "Backhand Blow"    , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 );
weapons[WsH2H][ 4] = new Array( 125, "Raging Fists"     , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 );
weapons[WsH2H][ 5] = new Array( 150, "Spinning Attack"  , 2 , 2 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 2 , 2 , 0 );
weapons[WsH2H][ 6] = new Array( 200, "Howling Fist"     , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 );
weapons[WsH2H][ 7] = new Array( 225, "Dragon Kick"      , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 );
weapons[WsH2H][ 8] = new Array( 300, "Tornado Kick"     , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 );
weapons[WsH2H][ 9] = new Array( 250, "Asuran Fists"     , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );  // Quested WS

// Dagger
weapons[WsDgr] = new Array(11);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsDgr][ 0] = new Array(   5, "Wasp Sting"       , 3 , 0 , 0 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 3 , 3 , 3 );
weapons[WsDgr][ 1] = new Array(  40, "Gust Slash"       , 3 , 0 , 0 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 3 , 3 , 3 );
weapons[WsDgr][ 2] = new Array(  70, "Shadowstitch"     , 3 , 0 , 0 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 3 , 3 , 3 );
weapons[WsDgr][ 3] = new Array( 100, "Viper Bite"       , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 );
weapons[WsDgr][ 4] = new Array( 125, "Cyclone"          , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 );
weapons[WsDgr][ 5] = new Array( 150, "Energy Steal"     , 2 , 0 , 0 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 2 , 2 , 2 );
weapons[WsDgr][ 6] = new Array( 175, "Energy Drain"     , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 );
weapons[WsDgr][ 7] = new Array( 200, "Dancing Edge"     , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 );
weapons[WsDgr][ 8] = new Array( 225, "Shark Bite"       , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 );
weapons[WsDgr][ 9] = new Array( 290, "Aeolian Edge"     , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 );
weapons[WsDgr][10] = new Array( 230, "Evisceration"     , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 0 );  // Quested WS

// Sword
weapons[WsSwd] = new Array(12);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsSwd][ 0] = new Array(   5, "Fast Blade"       , 3 , 0 , 0 , 0 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 3 , 0 , 3 , 0 );
weapons[WsSwd][ 1] = new Array(  30, "Burning Blade"    , 3 , 0 , 0 , 0 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 3 , 0 , 3 , 0 );
weapons[WsSwd][ 2] = new Array(  50, "Red Lotus Blade"  , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 );
weapons[WsSwd][ 3] = new Array(  75, "Flat Blade"       , 3 , 0 , 0 , 0 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 3 , 0 , 3 , 0 );
weapons[WsSwd][ 4] = new Array( 100, "Shining Blade"    , 3 , 0 , 0 , 0 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 3 , 0 , 3 , 0 );
weapons[WsSwd][ 5] = new Array( 125, "Seraph Blade"     , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 );
weapons[WsSwd][ 6] = new Array( 150, "Circle Blade"     , 2 , 0 , 0 , 0 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 2 , 0 , 2 , 0 );
weapons[WsSwd][ 7] = new Array( 175, "Spirits Within"   , 2 , 0 , 0 , 0 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 2 , 0 , 2 , 0 );
weapons[WsSwd][ 8] = new Array( 200, "Vorpal Blade"     , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 );
weapons[WsSwd][ 9] = new Array( 225, "Swift Blade"      , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsSwd][10] = new Array( 300, "Sanguine Blade"   , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 );
weapons[WsSwd][11] = new Array( 240, "Savage Blade"     , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 );  // Quested WS

// Great Sword
weapons[WsGSw] = new Array(10);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsGSw][ 0] = new Array(   5, "Hard Slash"       , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGSw][ 1] = new Array(  30, "Power Slash"      , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGSw][ 2] = new Array(  70, "Frostbite"        , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGSw][ 3] = new Array( 100, "Freezebite"       , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGSw][ 4] = new Array( 150, "Shockwave"        , 2 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGSw][ 5] = new Array( 175, "Crescent Moon"    , 2 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGSw][ 6] = new Array( 200, "Sickle Moon"      , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGSw][ 7] = new Array( 225, "Spinning Slash"   , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGSw][ 8] = new Array( 290, "Herculean Slash"  , 2 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGSw][ 9] = new Array( 250, "Ground Strike"    , 2 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );  // Quested WS

// Axe
weapons[WsAxe] = new Array(10);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsAxe][ 0] = new Array(   5, "Raging Axe"       , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsAxe][ 1] = new Array(  40, "Smash Axe"        , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsAxe][ 2] = new Array(  70, "Gale Axe"         , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsAxe][ 3] = new Array( 100, "Avalanche Axe"    , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsAxe][ 4] = new Array( 150, "Spinning Axe"     , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsAxe][ 5] = new Array( 175, "Rampage"          , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsAxe][ 6] = new Array( 200, "Calamity"         , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsAxe][ 7] = new Array( 225, "Mistral Axe"      , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsAxe][ 8] = new Array( 290, "Bora Axe"         , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsAxe][ 9] = new Array( 240, "Decimation"       , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );  // Quested WS

// Great Axe
weapons[WsGAx] = new Array(10);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsGAx][ 0] = new Array(   5, "Shield Break"     , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGAx][ 1] = new Array(  40, "Iron Tempest"     , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGAx][ 2] = new Array(  70, "Sturmwind"        , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGAx][ 3] = new Array( 100, "Armor Break"      , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGAx][ 4] = new Array( 150, "Keen Edge"        , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGAx][ 5] = new Array( 175, "Weapon Break"     , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGAx][ 6] = new Array( 200, "Raging Rush"      , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGAx][ 7] = new Array( 225, "Full Break"       , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGAx][ 8] = new Array( 300, "Fell Cleave"      , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGAx][ 9] = new Array( 240, "Steel Cyclone"    , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );  // Quested WS

// Scythe
weapons[WsScy] = new Array(10);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsScy][ 0] = new Array(   5, "Slice"            , 3 , 0 , 0 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsScy][ 1] = new Array(  30, "Dark Harvest"     , 3 , 0 , 0 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsScy][ 2] = new Array(  70, "Shadow of Death"  , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsScy][ 3] = new Array( 100, "Nightmare Scythe" , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsScy][ 4] = new Array( 125, "Spinning Scythe"  , 2 , 0 , 0 , 2 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsScy][ 5] = new Array( 150, "Vorpal Scythe"    , 2 , 0 , 0 , 2 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsScy][ 6] = new Array( 200, "Guillotine"       , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsScy][ 7] = new Array( 225, "Cross Reaper"     , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsScy][ 8] = new Array( 300, "Infernal Scythe"  , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsScy][ 9] = new Array( 240, "Spiral Hell"      , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );  // Quested WS

// Polearm
weapons[WsPol] = new Array(10);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsPol][ 0] = new Array(   5, "Double Thrust"    , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsPol][ 1] = new Array(  30, "Thunder Thrust"   , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsPol][ 2] = new Array(  70, "Raiden Thrust"    , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsPol][ 3] = new Array( 100, "Leg Sweep"        , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsPol][ 4] = new Array( 150, "Penta Thrust"     , 2 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 2 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsPol][ 5] = new Array( 175, "Vorpal Thrust"    , 2 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 2 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsPol][ 6] = new Array( 200, "Skewer"           , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsPol][ 7] = new Array( 225, "Wheeling Thrust"  , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsPol][ 8] = new Array( 300, "Sonic Thrust"     , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsPol][ 9] = new Array( 240, "Impulse Drive"    , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 );  // Quested WS

// Katana
weapons[WsKat] = new Array(10);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsKat][ 0] = new Array(   5, "Blade: Rin"       , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsKat][ 1] = new Array(  30, "Blade: Retsu"     , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsKat][ 2] = new Array(  70, "Blade: Teki"      , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsKat][ 3] = new Array( 100, "Blade: To"        , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsKat][ 4] = new Array( 150, "Blade: Chi"       , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsKat][ 5] = new Array( 175, "Blade: Ei"        , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsKat][ 6] = new Array( 200, "Blade: Jin"       , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsKat][ 7] = new Array( 225, "Blade: Ten"       , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsKat][ 8] = new Array( 290, "Blade: Yu"        , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsKat][ 9] = new Array( 250, "Blade: Ku"        , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );  // Quested WS

// Great Katana
weapons[WsGKt] = new Array(10);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsGKt][ 0] = new Array(   5, "Tachi: Enpi"      , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGKt][ 1] = new Array(  30, "Tachi: Hobaku"    , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGKt][ 2] = new Array(  70, "Tachi: Goten"     , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGKt][ 3] = new Array( 100, "Tachi: Kagero"    , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGKt][ 4] = new Array( 150, "Tachi: Jinpu"     , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGKt][ 5] = new Array( 175, "Tachi: Koki"      , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGKt][ 6] = new Array( 200, "Tachi: Yukikaze"  , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGKt][ 7] = new Array( 225, "Tachi: Gekko"     , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGKt][ 8] = new Array( 300, "Tachi: Ageha"     , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsGKt][ 9] = new Array( 250, "Tachi: Kasha"     , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );  // Quested WS

// Club
weapons[WsClb] = new Array(11);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsClb][ 0] = new Array(   5, "Shining Strike"   , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 0 , 3 );
weapons[WsClb][ 1] = new Array(  40, "Seraph Strike"    , 3 , 0 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 );
weapons[WsClb][ 2] = new Array(  70, "Brainshaker"      , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 0 , 3 );
weapons[WsClb][ 3] = new Array( 100, "Starlight"        , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 3 , 0 , 3 );
weapons[WsClb][ 4] = new Array( 125, "Moonlight"        , 3 , 0 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 );
weapons[WsClb][ 5] = new Array( 150, "Skullbreaker"     , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 0 , 2 );
weapons[WsClb][ 6] = new Array( 175, "True Strike"      , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 0 , 2 );
weapons[WsClb][ 7] = new Array( 200, "Judgment"         , 3 , 0 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 );
weapons[WsClb][ 8] = new Array( 220, "Hexa Strike"      , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsClb][ 9] = new Array( 290, "Flash Nova"       , 3 , 0 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 );
weapons[WsClb][10] = new Array( 230, "Black Halo"       , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 );  // Quested WS

// Staff
weapons[WsStf] = new Array(10);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsStf][ 0] = new Array(   5, "Heavy Swing"      , 3 , 3 , 3 , 3 , 0 , 0 , 3 , 0 , 0 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 3 );
weapons[WsStf][ 1] = new Array(  40, "Rock Crusher"     , 3 , 3 , 3 , 3 , 0 , 0 , 3 , 0 , 0 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 3 );
weapons[WsStf][ 2] = new Array(  70, "Earth Crusher"    , 3 , 3 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsStf][ 3] = new Array( 100, "Starburst"        , 3 , 3 , 3 , 3 , 0 , 0 , 3 , 0 , 0 , 3 , 0 , 0 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 3 );
weapons[WsStf][ 4] = new Array( 150, "Sunburst"         , 3 , 3 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsStf][ 5] = new Array( 175, "Shell Crusher"    , 2 , 2 , 2 , 2 , 0 , 0 , 2 , 0 , 0 , 2 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 2 );
weapons[WsStf][ 6] = new Array( 200, "Full Swing"       , 2 , 2 , 2 , 2 , 0 , 0 , 2 , 0 , 0 , 2 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 2 );
weapons[WsStf][ 7] = new Array( 215, "Spirit Taker"     , 2 , 2 , 2 , 2 , 0 , 0 , 2 , 0 , 0 , 2 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 2 );
weapons[WsStf][ 8] = new Array( 290, "Cataclysm"        , 3 , 3 , 3 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsStf][ 9] = new Array( 230, "Retribution"      , 2 , 2 , 2 , 2 , 0 , 0 , 2 , 0 , 0 , 2 , 0 , 0 , 0 , 2 , 2 , 0 , 0 , 0 , 0 , 2 );  // Quested WS

// Archery
weapons[WsArc] = new Array(8);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsArc][ 0] = new Array(   5, "Flaming Arrow"    , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsArc][ 1] = new Array(  40, "Piercing Arrow"   , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsArc][ 2] = new Array(  80, "Dulling Arrow"    , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsArc][ 3] = new Array( 175, "Sidewinder"       , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsArc][ 4] = new Array( 200, "Blast Arrow"      , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsArc][ 5] = new Array( 225, "Arching Arrow"    , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsArc][ 6] = new Array( 290, "Refulgent Arrow"  , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsArc][ 7] = new Array( 250, "Empyreal Arrow"   , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );  // Quested WS

// Marksmanship
weapons[WsMrk] = new Array(8);
//              each element: ( Lvl, Weaponskill Name   ,WAR,MNK,WHM,BLM,RDM,THF,PLD,DRK,BST,BRD,RNG,SAM,NIN,DRG,SMN,BLU,COR,PUP,DNC,SCH);
weapons[WsMrk][ 0] = new Array(   5, "Hot Shot"         , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 );
weapons[WsMrk][ 1] = new Array(  40, "Split Shot"       , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 );
weapons[WsMrk][ 2] = new Array(  80, "Sniper Shot"      , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 );
weapons[WsMrk][ 3] = new Array( 175, "Slug Shot"        , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 );
weapons[WsMrk][ 4] = new Array( 200, "Blast Shot"       , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsMrk][ 5] = new Array( 225, "Heavy Shot"       , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
weapons[WsMrk][ 6] = new Array( 290, "Numbing Shot"     , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 );
weapons[WsMrk][ 7] = new Array( 250, "Detonator"        , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 );  // Quested WS


// *****  Global Varible Definitions  *****

var currentCaps = new Array(SklTtl);  // Holds the final Skill Cap values for all the skills for the selected Main/Sub Jobs


// *****  Function Definitions  *****

function InitSkillValues() {
   var i = 0;
   var j = 0;

   // Upon load, we create the "gradeNums" 2-D array
   for( i = 0; i < SklTtl; i++ ) {

      gradeNums[i] = new Array(grades[i].length);

      for( j = 0; j < grades[i].length; j++ ) {
         switch( grades[i][j] ) {
            case "A+":
               gradeNums[i][j] = 1;
               break;
            case "A-":
               gradeNums[i][j] = 2;
               break;
            case "B+":
               gradeNums[i][j] = 3;
               break;
            case "B ":
               gradeNums[i][j] = 4;
               break;
            case "B-":
               gradeNums[i][j] = 5;
               break;
            case "C+":
               gradeNums[i][j] = 6;
               break;
            case "C ":
               gradeNums[i][j] = 7;
               break;
            case "C-":
               gradeNums[i][j] = 8;
               break;
            case "D ":
               gradeNums[i][j] = 9;
               break;
            case "E ":
               gradeNums[i][j] = 10;
               break;
            case "F ":
               gradeNums[i][j] = 11;
               break;
            default:
               gradeNums[i][j] = 0;
         }
      }
   }

   GetSkillCaps();  // refresh the screen
}


function UpdateMainLevel() {

   // if the MainJob's level is changed to "--",
   //    clear all of the other selections
   if( document.f.MainJobLevel.value == 0 ) {
      document.f.MainJobClass.selectedIndex = 0;
      document.f.SubJobLevel.selectedIndex = 0;
      document.f.SubJobClass.selectedIndex = 0;
   }
   // otherwise:
   else {
      // if there is no SubJob class selected,
      //    clear the SubJob's level
      if( document.f.SubJobClass.value == 0 ) {
         document.f.SubJobLevel.selectedIndex = 0;
      }
      // but if there is a SubJob selected,
      //    default the SubJob's level to half of the MainJob's level.
      else {
         if( document.f.MainJobLevel.value == 1 ) {
            document.f.SubJobLevel.selectedIndex = 1;
         }
         else {
            document.f.SubJobLevel.selectedIndex = Math.floor( document.f.MainJobLevel.value / 2 );
         }
      }
   }

   GetSkillCaps();  // refresh the screen
}

function UpdateMainClass() {

   // if the MainJob's class is changed to "--none--",
   //    clear all of the other selections
   if( document.f.MainJobClass.value == 0 ) {
      document.f.MainJobLevel.selectedIndex = 0;
      document.f.SubJobLevel.selectedIndex = 0;
      document.f.SubJobClass.selectedIndex = 0;
   }
   // otherwise:
   else {
      // if the MainJob's level is still set to "--",
      //    then default the MainJob's level to the current level cap
      if( document.f.MainJobLevel.value == 0 ) {
         document.f.MainJobLevel.selectedIndex = LvlCap;
      }
      // also, if the MainJob's class is changed to the same job as the SubJob,
      //    then set the SubJob to "--none--", and clear it's level
      if( document.f.MainJobClass.value == document.f.SubJobClass.value ) {
         document.f.SubJobLevel.selectedIndex = 0;
         document.f.SubJobClass.selectedIndex = 0;
      }
   }

   GetSkillCaps();  // refresh the screen
}

function UpdateSubLevel() {

   // if the SubJob's level is changed to "--",
   //    clear the SubJob's class selection
   if( document.f.SubJobLevel.value == 0 ) {
      document.f.SubJobClass.selectedIndex = 0;
   }
   // otherwise:
   else {
      // if the SubJob's level is changed to something higher than half of the MainJob's level
      //    then revert the Subjob's level to half of the MainJob's level
      if( document.f.MainJobLevel.value == 1 ) {
         document.f.SubJobLevel.selectedIndex = 1;
      }
      else if( document.f.SubJobLevel.value > Math.floor( document.f.MainJobLevel.value / 2 ) ) {
         document.f.SubJobLevel.selectedIndex = Math.floor( document.f.MainJobLevel.value / 2 );
      }
   }

   GetSkillCaps();  // refresh the screen
}

function UpdateSubClass() {

   // if the SubJob's class is changed to "--none--",
   // or, if there is no MainJob chosen yet,
   // or, if the SubJob's class is changed to the same job as the MainJob,
   //    then reset the SubJob to "--none--", and clear it's level
   if( (document.f.SubJobClass.value == 0) ||
       (document.f.MainJobClass.value == 0) ||
       (document.f.SubJobClass.value == document.f.MainJobClass.value) ) {
      document.f.SubJobLevel.selectedIndex = 0;
      document.f.SubJobClass.selectedIndex = 0;
   }
   // otherwise:
   else {
      // if the SubJob's level is still set to "--",
      //    then default the Subjob's level to half of the MainJob's level
      if( document.f.SubJobLevel.value == 0 ) {
         if( document.f.MainJobLevel.value == 1 ) {
            document.f.SubJobLevel.selectedIndex = 1;
         }
         else {
            document.f.SubJobLevel.selectedIndex = Math.floor( document.f.MainJobLevel.value / 2 );
         }
      }
   }

   GetSkillCaps();  // refresh the screen
}

function UpdateMerits(sklnum) {
// Error checking function for number of merit points allocated

   var i = 0;
   var curtot = 0;  // holds the current total number of merits

   // if the updated Merit was a Combat Merit
   if( sklnum < BrkPnt ) {
      // Add up all the Combat Merits
      for( i = 0; i < BrkPnt; i++ ) {
         curtot = curtot + (document.f.SkillMerit[i].value*1);
         // (We need the "*1" to convert the value from a string to a real number)
      }
      // ... and make sure we don't have too many
      // if we do, set the last updated Merit to the maximum it can be
      if( curtot > MaxCombatMrts ) {
         document.f.SkillMerit[sklnum].selectedIndex = MaxCombatMrts - ( curtot - document.f.SkillMerit[sklnum].value );
      }
   }
   // otherwise, the updated Merit was a Magic Merit
   else {
      // So add up all the Magic Merits
      for( i = BrkPnt; i < SklTtl; i++ ) {
         curtot = curtot + (document.f.SkillMerit[i].value*1);
            // (We need the "*1" to convert the value from a string to a real number)
      }
      // ... and make sure we don't have too many
      // if we do, set the last updated Merit to the maximum it can be
      if( curtot > MaxMagicMrts ) {
         document.f.SkillMerit[sklnum].selectedIndex = MaxMagicMrts - ( curtot - document.f.SkillMerit[sklnum].value );
      }
   }

   GetSkillCaps();  // refresh the screen
}


function GetSkillCaps() {
// This function refreshes the screen, and displays all the necessary skill cap values

   var i = 0;

   // Show or Hide the Merit Selection section of the interface
   if( document.f.ShowMerits.checked == true ) {
      document.getElementById("MeritTable1").className = 'TableOn';
      document.getElementById("MeritTable2").className = 'TableOn';
   }
   else {
      document.getElementById("MeritTable1").className = 'TableOff';
      document.getElementById("MeritTable2").className = 'TableOff';
   }

   // Show or Hide the Weaponskills section of the interface
   if( document.f.ShowWeapon.checked == true ) {
      document.getElementById("WSTable").className = 'TableOn';
   }
   else {
      document.getElementById("WSTable").className = 'TableOff';
   }


   // If there are no jobs selected:
   if( document.f.MainJobClass.value == 0 ) {
      // Put the Skill name only in all the Skill boxes by default
      for( i = 0; i < SklTtl; i++ ) {
         document.f.Skl[i].className = 'SklSub';
         document.f.Skl[i].value = grades[i][0];
         document.f.Cap[i].className = 'CapOff';
         document.f.Cap[i].value = "";
         document.f.Grd[i].className = 'GrdOff';
         document.f.Grd[i].value = "";

         currentCaps[i] = 0;  // and clear the Current Skill Caps array
      }
   }
   // otherwise:
   else {
      // Fill in boxes in order with the used skills only,
      //    and clear the remaining boxes for both sections

      var MJcap = 0;   // Holds the Skill Cap value for the current skill for the selected Main Job
      var SJcap = 0;   // Holds the Skill Cap value for the current skill for the selected Sub Job
      var inpIdx = 0;  // pointer for current skill box set

      for( i = 0; i < SklTtl; i++ ) {

         // Calculate the skill caps for this skill for the selected jobs and levels
         MJcap = levels[document.f.MainJobLevel.value][ gradeNums[i][document.f.MainJobClass.value] ];
         SJcap = levels[document.f.SubJobLevel.value][ gradeNums[i][document.f.SubJobClass.value] ];

         // Check if this is a MainJob skill
         if( MJcap > 0 ) {

            // Step 1)  Show and set Skill Name
            document.f.Skl[inpIdx].className = 'SklMan';
            document.f.Skl[inpIdx].value = grades[i][0];

            // Step 2a)  Calculate Skill Cap value
            // Check for merit points if desired, and if we have some in this skill
            if( (document.f.ShowMerits.checked == true) && (document.f.SkillMerit[i].value > 0) ) {
               // If we have more merits than our MainJob level will allow
               if( document.f.SkillMerit[i].value > merits[document.f.MainJobLevel.value] ) {
                  // then use the max merits allowed for this level
                  currentCaps[i] = MJcap + (merits[document.f.MainJobLevel.value] * 2);
               }
               else {  // otherwise use the number of merits selected
                  currentCaps[i] = MJcap + (document.f.SkillMerit[i].value * 2);
               }
            }
            else {  // if no merits, just use the base main job skill level
               currentCaps[i] = MJcap;
            }

            // Step 2b)  Show and set Skill Cap Value
            document.f.Cap[inpIdx].className = 'CapMan';
            document.f.Cap[inpIdx].value = currentCaps[i];

            // Step 3)  Show and set Skill Grade (if selected)
            if( document.f.ShowGrades.checked == true ) {
               document.f.Grd[inpIdx].className = 'GrdMan';
               document.f.Grd[inpIdx].value = grades[i][document.f.MainJobClass.value];
            }
            else {
               document.f.Grd[inpIdx].className = 'GrdOff';
               document.f.Grd[inpIdx].value = "";
            }

            // Step 4)  Increment box pointer to next box
            inpIdx++;
         }

         // If not, check if this is a SubJob skill
         else if( SJcap > 0 ) {

            // Step 1)  Show and set Skill Name
            document.f.Skl[inpIdx].className = 'SklSub';
            document.f.Skl[inpIdx].value = grades[i][0];

            // Step 2a)  Calculate Skill Cap value
            // Check for merit points if desired, and if we have some in this skill
            if( (document.f.ShowMerits.checked == true) && (document.f.SkillMerit[i].value > 0) ) {
               // If we have more merits than our MainJob level will allow
               if( document.f.SkillMerit[i].value > merits[document.f.MainJobLevel.value] ) {
                  // then use the max merits allowed for this level
                  currentCaps[i] = SJcap + (merits[document.f.MainJobLevel.value] * 2);
               }
               else {  // otherwise use the number of merits selected
                  currentCaps[i] = SJcap + (document.f.SkillMerit[i].value * 2);
               }
            }
            else {  // if no merits, just use the base subjob skill level
               currentCaps[i] = SJcap;
            }

            // Step 2b)  Show and set Skill Cap Value
            document.f.Cap[inpIdx].className = 'CapSub';
            document.f.Cap[inpIdx].value = currentCaps[i];

            // Step 3)  Show and set Skill Grade (if selected)
            if( document.f.ShowGrades.checked == true ) {
               document.f.Grd[inpIdx].className = 'GrdSub';
               document.f.Grd[inpIdx].value = grades[i][document.f.SubJobClass.value];
            }
            else {
               document.f.Grd[inpIdx].className = 'GrdOff';
               document.f.Grd[inpIdx].value = "";
            }

            // Step 4)  Increment box pointer to next box
            inpIdx++;
         }

         // Even if not a MainJob or SubJob skill, check if skill is available from Merits
         else if( (document.f.ShowMerits.checked == true) &&       // if merit bonus calculation is turned on
                  (document.f.SkillMerit[i].value > 0) &&          // and this skill has some merits put into it
                  (merits[document.f.MainJobLevel.value] > 0) ) {  // and the main job level is high enough to enable them

            // Step 1)  Show and set Skill Name
            document.f.Skl[inpIdx].className = 'SklSub';
            document.f.Skl[inpIdx].value = grades[i][0];

            // Step 2a)  Calculate Skill Cap value
            // If we have more merits than our MainJob level will allow
            if( document.f.SkillMerit[i].value > merits[document.f.MainJobLevel.value] ) {
               // then use the max merits allowed for this level
               currentCaps[i] = merits[document.f.MainJobLevel.value] * 2;
            }
            else { // otherwise use the number of merits selected
               currentCaps[i] = document.f.SkillMerit[i].value * 2;
            }

            // Step 2b)  Show and set Skill Cap Value
            document.f.Cap[inpIdx].className = 'CapSub';
            document.f.Cap[inpIdx].value = currentCaps[i];

            // Step 3)  Hide Skill Grade for Merit-Only skills
            document.f.Grd[inpIdx].className = 'GrdOff';
            document.f.Grd[inpIdx].value = "";

            // Step 4)  Increment box pointer to next box
            inpIdx++;
         }

         // If not a MainJob or SubJob skill, and no merits available
         else {
            currentCaps[i] = 0;  // set the Current Skill Caps array element to zero
         }

         // Break between Combat and Magic skills...
         // clear out and hide all remaining boxes before Magic skills
         if( i == BrkPnt - 1 ) {
            while( inpIdx < BrkPnt ) {
               document.f.Skl[inpIdx].className = 'SklOff';
               document.f.Skl[inpIdx].value = "";
               document.f.Cap[inpIdx].className = 'CapOff';
               document.f.Cap[inpIdx].value = "";
               document.f.Grd[inpIdx].className = 'GrdOff';
               document.f.Grd[inpIdx].value = "";
               inpIdx++;
            }
         }
      }

      // Clear out and hide all remaining boxes
      while( inpIdx < SklTtl ) {
         document.f.Skl[inpIdx].className = 'SklOff';
         document.f.Skl[inpIdx].value = "";
         document.f.Cap[inpIdx].className = 'CapOff';
         document.f.Cap[inpIdx].value = "";
         document.f.Grd[inpIdx].className = 'GrdOff';
         document.f.Grd[inpIdx].value = "";
         inpIdx++;
      }
   }

   if( document.f.ShowWeapon.checked == true ) {
      UpdateWeapons();  // and update Weaponskill info if selected
   }
}


function UpdateWeapons() {
// This function refreshes the Weaponskill section

   if( document.f.WeaponType.value > 0 ) {  // check if a weapon is selected

      // set weapon type
      var wpn = document.f.WeaponType.value - 1;

      // store skill grades for current weapon
      var wsMJgrd = gradeNums[wpn][document.f.MainJobClass.value];
      var wsSJgrd = gradeNums[wpn][document.f.SubJobClass.value];

      var wsIndex = 0;  // pointer for current weaponskill box set
      var lvltemp = 0;  // used when determining the main job levels at which weaponskills become available
      var i = 0;

      // Holds the list of Skill Caps for each Job Level for the chosen weapon type
      var wslevels = new Array(LvlCap+1);

      // Calculate level caps for all job levels (from 0 to the max job level) for the skill of the selected weapon
      for( i = 0; i < LvlCap+1; i++ ) {

         if( wsMJgrd > 0 ) {  // check for main job skill
            // and if available, set the skill level to the cap for this job level
            wslevels[i] = levels[i][wsMJgrd];
         }
         else if( wsSJgrd > 0 ) {  // check for sub job skill
            // and if available, set the skill level to the cap for half of this job level
            wslevels[i] = levels[Math.floor( i / 2 )][wsSJgrd];

            // make an exception if the main and sub jobs are both at level 1
            if( i == 1 ) {
               wslevels[i] = levels[i][wsSJgrd];
            }
         }
         else {  // otherwise assume no skill
            wslevels[i] = 0;
         }

         // Add in skill points from merits, if necessary
         if( (document.f.ShowMerits.checked == true) && (document.f.SkillMerit[wpn].value > 0) ) {
            // If we have more merits than our MainJob level will allow
            if( document.f.SkillMerit[wpn].value > merits[i] ) {
               // then use the max merits allowed for this level
               wslevels[i] = wslevels[i] + (merits[i] * 2);
            }
            else { // otherwise use the number of merits selected
               wslevels[i] = wslevels[i] + (document.f.SkillMerit[wpn].value * 2);
            }
         }
      }

      // Display Weaponskill list
      for( i = 0; i < weapons[wpn].length; i++ ) {

         // check if this is the last weaponskill in the set
         if( i == weapons[wpn].length - 1 ) {
            // and if it is, clear out any extra boxes and advance the pointer
            //    to the final box for the "Quested Weaponskill"
            while( wsIndex < document.f.WsNm.length - 1 ) {
               document.f.WsJl[wsIndex].className = 'WsJlOff';
               document.f.WsJl[wsIndex].value = "";
               document.f.WsNm[wsIndex].className = 'WsNmOff';
               document.f.WsNm[wsIndex].value = "";
               wsIndex++;
            }
         }

         // print the weaponskill name and skill level in the name box
         document.f.WsNm[wsIndex].value = weapons[wpn][i][0] + " - " + weapons[wpn][i][1];

         // if no main job is selected, only show the weaponskill name box (with gray background)
         if( document.f.MainJobClass.value == 0 ) {
            document.f.WsJl[wsIndex].value = "";
            document.f.WsJl[wsIndex].className = 'WsJlOff';
            document.f.WsNm[wsIndex].className = 'WsNmNo';
         }
         // otherwise determine availability and level caps
         else {
            // if the main job is not allowed to use the weaponskill...
            if( (weapons[wpn][i][(document.f.MainJobClass.value*1) + 1] == 0) &&
                // and the subjob can't use it either, or there is NO subjob...
                ( (weapons[wpn][i][(document.f.SubJobClass.value*1) + 1] < 2) ||
                  (document.f.SubJobClass.value == 0) ) ) {
               // then gray out the job level and weaponskill name boxes
               document.f.WsJl[wsIndex].value = "- -";
               document.f.WsJl[wsIndex].className = 'WsJlNA';
               document.f.WsNm[wsIndex].className = 'WsNmNA';
            }
            else {
               // find the job levels at which the weaponskill will be available
               for( lvltemp = 0; lvltemp < LvlCap+1; lvltemp++ ) {
                  if( wslevels[lvltemp] >= weapons[wpn][i][0] ) {
                     break;
                  }
               }

               if( lvltemp < LvlCap+1 ) {  // and if it's at the max job level or lower, put it into the job level box
                  document.f.WsJl[wsIndex].value = lvltemp;
               }
               else {  // otherwise don't enter a level
                  document.f.WsJl[wsIndex].value = "- -";
               }

               // now set the box styles
               if( currentCaps[wpn] < weapons[wpn][i][0] ) {  // if the current skill level is too low
                  // give it the gray background
                  document.f.WsJl[wsIndex].className = 'WsJlNo';
                  document.f.WsNm[wsIndex].className = 'WsNmNo';
               }
               else {  // otherwise
                  // give it the normal white background
                  document.f.WsJl[wsIndex].className = 'WsJlYes';
                  document.f.WsNm[wsIndex].className = 'WsNmYes';
               }
            }
         }

         // Increment box pointer to next box
         wsIndex++;
      }

      // turn on the "Quested Weaponskill" label
      document.getElementById("QWSlabel").className = 'TableOn';
   }

   // if no weapon type is selected, clear and remove all boxes
   else {
      for( i = 0; i < document.f.WsNm.length; i++ ) {
         document.f.WsJl[i].className = 'WsJlOff';
         document.f.WsJl[i].value = "";
         document.f.WsNm[i].className = 'WsNmOff';
         document.f.WsNm[i].value = "";
      }
      // turn off the "Quested Weaponskill" label
      document.getElementById("QWSlabel").className = 'TableOff';
   }
}


// Save, Load, and Clear Merits

function SaveMerits() {
   var cookieName = "FFXImerits";

   if( confirm("Overwrite any previously saved merits?") ) {
      var cookieString = "";
      for( i = 0; i < SklTtl; i++ ) {
         cookieString = cookieString + document.f.SkillMerit[i].value + ";";
      }

      if( cookieString.length < 4096 ) {
         setCookie( cookieName, cookieString, 4383, "/" );  // set cookie to expire in 12 years
         alert( "Merits successfully saved!" );
      }
      else {
         alert( "Error: Cookie too large!  Merits could not be saved." );
      }
   }
   else {
      alert( "Merits NOT saved!" );
   }
}

function LoadMerits() {
   var cookieName = "FFXImerits";

   if( confirm( "Loading saved merits will overwrite the currently entered merits.  Continue?") ) {
      var cookieString = getCookie( cookieName );
      if( !cookieString ) {
         alert( "Error:  No saved merits!" );
         return false;
      }

      var spl = cookieString.split(";");
      if( spl.length < SklTtl ) {
         alert( "Error: The saved merits cookie is corrupted!" );
         return false;
      }

      for( i = 0; i < SklTtl; i++ ) {
         document.f.SkillMerit[i].value = spl[i];
         UpdateMerits(i);
      }

      GetSkillCaps();  // refresh the screen
   }
}

function ClearMerits() {
   if( confirm( "This will clear all currently entered merits.  Continue?") ) {
      for( i = 0; i < SklTtl; i++ ) {
         document.f.SkillMerit[i].value = 0;
         UpdateMerits(i);
      }

      GetSkillCaps();  // refresh the screen
   }
}

