diff --git a/create-card.js b/create-card.js index 0dc24f4..69e30d8 100644 --- a/create-card.js +++ b/create-card.js @@ -21,7 +21,7 @@ const med = '30px "Source Sans Pro"'; const smed = '25px "Source Sans Pro"'; const large = '45px "Source Sans Pro SemiBold"'; -const jobsRowTextStartX = 495; +const jobsRowTextStartX = 485; const jobsRowTextSize = 30; const jobsRowTextSpacer = jobsRowTextSize * 2; @@ -166,9 +166,9 @@ class CardCreator { 'alchemist', 'armorer', 'blacksmith', 'carpenter', 'culinarian', 'goldsmith', 'leatherworker', 'weaver', 'botanist', 'fisher', 'miner', 'gladiator', 'paladin', 'marauder', 'warrior', 'darkknight', 'gunbreaker', - 'conjurer', 'whitemage', 'scholar', 'astrologian', + 'conjurer', 'whitemage', 'scholar', 'astrologian', 'sage', 'archer', 'bard', 'machinist', 'dancer', - 'lancer', 'dragoon', 'pugilist', 'monk', 'rogue', 'ninja', 'samurai', + 'lancer', 'dragoon', 'pugilist', 'monk', 'rogue', 'ninja', 'samurai', 'reaper', 'thaumaturge', 'blackmage', 'arcanist', 'summoner', 'redmage', 'bluemage', ]; @@ -313,7 +313,7 @@ class CardCreator { 'Character.ActiveClassJob.UnlockedState.ID', 'Character.ClassJobs.*.Level', 'Character.ClassJobs.*.UnlockedState.ID', 'Character.ClassJobsBozjan.Level', 'Character.ClassJobsElemental.Level', 'Character.DC', 'Character.FreeCompanyName', 'Character.GearSet.Gear', 'Character.GrandCompany.Company.Name', 'Character.GrandCompany.Rank.Icon', 'Character.GuardianDeity.Name', 'Character.GuardianDeity.Icon', 'Character.Name', 'Character.Portrait', 'Character.Race.Name', 'Character.Tribe.Name', 'Character.Server', 'Character.Title.Name', - 'FreeCompany.Crest', 'FreeCompany.Tag', 'Minions.*.dummy', 'Mounts.*.dummy', + 'FreeCompany.Crest', 'FreeCompany.Tag', 'Minions', 'Mounts', ]; const characterInfoUrl = new URL(`https://xivapi.com/character/${encodeURIComponent(characterId)}`) @@ -381,28 +381,30 @@ class CardCreator { // Draw non data dependent job icons { - ctx.drawImage(this.cjIcons.darkknight, 540, jobsRowIcon1Y, 30, 30); // Darkknight - ctx.drawImage(this.cjIcons.gunbreaker, 570, jobsRowIcon1Y, 30, 30); // Gunbreaker - ctx.drawImage(this.cjIcons.scholar, 660, jobsRowIcon1Y, 30, 30); // Scholar - ctx.drawImage(this.cjIcons.astrologian, 690, jobsRowIcon1Y, 30, 30); // Astrologian + ctx.drawImage(this.cjIcons.darkknight, 530, jobsRowIcon1Y, 30, 30); // Darkknight + ctx.drawImage(this.cjIcons.gunbreaker, 560, jobsRowIcon1Y, 30, 30); // Gunbreaker + ctx.drawImage(this.cjIcons.scholar, 650, jobsRowIcon1Y, 30, 30); // Scholar + ctx.drawImage(this.cjIcons.astrologian, 680, jobsRowIcon1Y, 30, 30); // Astrologian + ctx.drawImage(this.cjIcons.sage, 710, jobsRowIcon1Y, 30, 30); // Sage - ctx.drawImage(this.cjIcons.machinist, 780, jobsRowIcon1Y, 30, 30); // Machinist - ctx.drawImage(this.cjIcons.dancer, 810, jobsRowIcon1Y, 30, 30); // Dancer - ctx.drawImage(this.cjIcons.samurai, 570, jobsRowIcon2Y, 30, 30); // Samurai - ctx.drawImage(this.cjIcons.redmage, 690, jobsRowIcon2Y, 30, 30); // Redmage - ctx.drawImage(this.cjIcons.bluemage, 780, jobsRowIcon2Y, 33, 33); // Bluemage + ctx.drawImage(this.cjIcons.machinist, 800, jobsRowIcon1Y, 30, 30); // Machinist + ctx.drawImage(this.cjIcons.dancer, 830, jobsRowIcon1Y, 30, 30); // Dancer + ctx.drawImage(this.cjIcons.samurai, 560, jobsRowIcon2Y, 30, 30); // Samurai + ctx.drawImage(this.cjIcons.reaper, 590, jobsRowIcon2Y, 30, 30); // Reaper + ctx.drawImage(this.cjIcons.redmage, 710, jobsRowIcon2Y, 30, 30); // Redmage + ctx.drawImage(this.cjIcons.bluemage, 800, jobsRowIcon2Y, 33, 33); // Bluemage - ctx.drawImage(this.cjIcons.carpenter, 480, jobsRowIcon3Y, 30, 30); // Carpenter - ctx.drawImage(this.cjIcons.blacksmith, 510, jobsRowIcon3Y, 30, 30); // Blacksmith - ctx.drawImage(this.cjIcons.armorer, 540, jobsRowIcon3Y, 30, 30); // Armorer - ctx.drawImage(this.cjIcons.goldsmith, 570, jobsRowIcon3Y, 30, 30); // Goldsmith - ctx.drawImage(this.cjIcons.leatherworker, 600, jobsRowIcon3Y, 30, 30); // Leatherworker - ctx.drawImage(this.cjIcons.weaver, 630, jobsRowIcon3Y, 30, 30); // Weaver - ctx.drawImage(this.cjIcons.alchemist, 660, jobsRowIcon3Y, 30, 30); // Alchemist - ctx.drawImage(this.cjIcons.culinarian, 690, jobsRowIcon3Y, 30, 30); // Culinarian - ctx.drawImage(this.cjIcons.miner, 750, jobsRowIcon3Y, 30, 30); // Miner - ctx.drawImage(this.cjIcons.botanist, 780, jobsRowIcon3Y, 30, 30); // Botanist - ctx.drawImage(this.cjIcons.fisher, 810, jobsRowIcon3Y, 30, 30); // Fisher + ctx.drawImage(this.cjIcons.carpenter, 470, jobsRowIcon3Y, 30, 30); // Carpenter + ctx.drawImage(this.cjIcons.blacksmith, 500, jobsRowIcon3Y, 30, 30); // Blacksmith + ctx.drawImage(this.cjIcons.armorer, 530, jobsRowIcon3Y, 30, 30); // Armorer + ctx.drawImage(this.cjIcons.goldsmith, 560, jobsRowIcon3Y, 30, 30); // Goldsmith + ctx.drawImage(this.cjIcons.leatherworker, 590, jobsRowIcon3Y, 30, 30); // Leatherworker + ctx.drawImage(this.cjIcons.weaver, 620, jobsRowIcon3Y, 30, 30); // Weaver + ctx.drawImage(this.cjIcons.alchemist, 650, jobsRowIcon3Y, 30, 30); // Alchemist + ctx.drawImage(this.cjIcons.culinarian, 680, jobsRowIcon3Y, 30, 30); // Culinarian + ctx.drawImage(this.cjIcons.miner, 770, jobsRowIcon3Y, 30, 30); // Miner + ctx.drawImage(this.cjIcons.botanist, 800, jobsRowIcon3Y, 30, 30); // Botanist + ctx.drawImage(this.cjIcons.fisher, 830, jobsRowIcon3Y, 30, 30); // Fisher } // Draw info from character data @@ -437,8 +439,14 @@ class CardCreator { // Mounts & Minions { - const mountsPercentage = Math.ceil(((Mounts.length ?? 0) / this.mountCount) * 100); - const minionsPercentage = Math.ceil(((Minions.length ?? 0) / this.minionCount) * 100); + let minionsPercentage = "N/A" + let mountsPercentage = "N/A" + if (Minions != null) { + const minionsPercentage = Math.ceil(((Minions.length ?? 0) / this.minionCount) * 100); + } + if (Mounts != null) { + const mountsPercentage = Math.ceil(((Mounts.length ?? 0) / this.mountCount) * 100); + } ctx.font = smed; ctx.fillStyle = white; @@ -500,15 +508,15 @@ class CardCreator { // Classes & Jobs - data dependant job or class icons { const { ClassJobs } = Character; - ctx.drawImage(this.classOrJobIcon(ClassJobs[0], 19, 'gladiator', 'paladin'), 480, jobsRowIcon1Y, 30, 30); // Gladiator/Paladin - ctx.drawImage(this.classOrJobIcon(ClassJobs[1], 21, 'marauder', 'warrior'), 510, jobsRowIcon1Y, 30, 30); // Marauder/Warrior - ctx.drawImage(this.classOrJobIcon(ClassJobs[8], 24, 'conjurer', 'whitemage'), 630, jobsRowIcon1Y, 30, 30); // Conjurer/Whitemage - ctx.drawImage(this.classOrJobIcon(ClassJobs[11], 23, 'archer', 'bard'), 750, jobsRowIcon1Y, 30, 30); // Archer/Bard - ctx.drawImage(this.classOrJobIcon(ClassJobs[5], 22, 'lancer', 'dragoon'), 480, jobsRowIcon2Y, 30, 30); // Lancer/Dragoon - ctx.drawImage(this.classOrJobIcon(ClassJobs[4], 20, 'pugilist', 'monk'), 510, jobsRowIcon2Y, 30, 30); // Monk/Pugilist - ctx.drawImage(this.classOrJobIcon(ClassJobs[6], 30, 'rogue', 'ninja'), 540, jobsRowIcon2Y, 30, 30); // Ninja/Rogue - ctx.drawImage(this.classOrJobIcon(ClassJobs[14], 25, 'thaumaturge', 'blackmage'), 630, jobsRowIcon2Y, 30, 30); // Thaumaturge/Blackmage - ctx.drawImage(this.classOrJobIcon(ClassJobs[15], 27, 'arcanist', 'summoner'), 660, jobsRowIcon2Y, 30, 30); // Summoner/Arcanist + ctx.drawImage(this.classOrJobIcon(ClassJobs[0], 19, 'gladiator', 'paladin'), 470, jobsRowIcon1Y, 30, 30); // Gladiator/Paladin + ctx.drawImage(this.classOrJobIcon(ClassJobs[1], 21, 'marauder', 'warrior'), 500, jobsRowIcon1Y, 30, 30); // Marauder/Warrior + ctx.drawImage(this.classOrJobIcon(ClassJobs[4], 24, 'conjurer', 'whitemage'), 620, jobsRowIcon1Y, 30, 30); // Conjurer/Whitemage + ctx.drawImage(this.classOrJobIcon(ClassJobs[13], 23, 'archer', 'bard'), 770, jobsRowIcon1Y, 30, 30); // Archer/Bard + ctx.drawImage(this.classOrJobIcon(ClassJobs[9], 22, 'lancer', 'dragoon'), 470, jobsRowIcon2Y, 30, 30); // Lancer/Dragoon + ctx.drawImage(this.classOrJobIcon(ClassJobs[8], 20, 'pugilist', 'monk'), 500, jobsRowIcon2Y, 30, 30); // Monk/Pugilist + ctx.drawImage(this.classOrJobIcon(ClassJobs[10], 30, 'rogue', 'ninja'), 530, jobsRowIcon2Y, 30, 30); // Ninja/Rogue + ctx.drawImage(this.classOrJobIcon(ClassJobs[16], 25, 'thaumaturge', 'blackmage'), 650, jobsRowIcon2Y, 30, 30); // Thaumaturge/Blackmage + ctx.drawImage(this.classOrJobIcon(ClassJobs[17], 27, 'arcanist', 'summoner'), 680, jobsRowIcon2Y, 30, 30); // Summoner/Arcanist } // Classes & Jobs - levels @@ -529,59 +537,63 @@ class CardCreator { rowTextX += jobsRowTextSize; ctx.fillText(ClassJobs[3].Level, rowTextX, jobsRowText1Y); // Gunbreaker rowTextX += jobsRowTextSpacer; - ctx.fillText(ClassJobs[8].Level, rowTextX, jobsRowText1Y); // Conjurer/Whitemage + ctx.fillText(ClassJobs[4].Level, rowTextX, jobsRowText1Y); // Conjurer/Whitemage rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[9].Level >= 30 ? ClassJobs[9].Level : '0', rowTextX, jobsRowText1Y); // Scholar + ctx.fillText(ClassJobs[5].Level >= 30 ? ClassJobs[9].Level : '0', rowTextX, jobsRowText1Y); // Scholar rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[10].Level, rowTextX, jobsRowText1Y); // Astrologian + ctx.fillText(ClassJobs[6].Level, rowTextX, jobsRowText1Y); // Astrologian + rowTextX += jobsRowTextSize; + ctx.fillText(ClassJobs[7].Level, rowTextX, jobsRowText1Y); // Sage rowTextX += jobsRowTextSpacer; - ctx.fillText(ClassJobs[11].Level, rowTextX, jobsRowText1Y); // Archer/Bard + ctx.fillText(ClassJobs[13].Level, rowTextX, jobsRowText1Y); // Archer/Bard rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[12].Level, rowTextX, jobsRowText1Y); // Machinist + ctx.fillText(ClassJobs[14].Level, rowTextX, jobsRowText1Y); // Machinist rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[13].Level, rowTextX, jobsRowText1Y); // Dancer + ctx.fillText(ClassJobs[15].Level, rowTextX, jobsRowText1Y); // Dancer // Second row rowTextX = jobsRowTextStartX; - ctx.fillText(ClassJobs[5].Level, rowTextX, jobsRowText2Y); // Lancer/Dragoon + ctx.fillText(ClassJobs[9].Level, rowTextX, jobsRowText2Y); // Lancer/Dragoon rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[4].Level, rowTextX, jobsRowText2Y); // Monk/Pugilist + ctx.fillText(ClassJobs[8].Level, rowTextX, jobsRowText2Y); // Monk/Pugilist rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[6].Level, rowTextX, jobsRowText2Y); // Ninja/Rogue + ctx.fillText(ClassJobs[10].Level, rowTextX, jobsRowText2Y); // Ninja/Rogue rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[7].Level, rowTextX, jobsRowText2Y); // Samurai + ctx.fillText(ClassJobs[11].Level, rowTextX, jobsRowText2Y); // Samurai + rowTextX += jobsRowTextSize; + ctx.fillText(ClassJobs[12].Level, rowTextX, jobsRowText2Y); // Reaper rowTextX += jobsRowTextSpacer; - ctx.fillText(ClassJobs[14].Level, rowTextX, jobsRowText2Y); // Thaumaturge/Blackmage + ctx.fillText(ClassJobs[16].Level, rowTextX, jobsRowText2Y); // Thaumaturge/Blackmage rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[15].Level, rowTextX, jobsRowText2Y); // Summoner/Arcanist + ctx.fillText(ClassJobs[17].Level, rowTextX, jobsRowText2Y); // Summoner/Arcanist rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[16].Level, rowTextX, jobsRowText2Y); // Redmage + ctx.fillText(ClassJobs[18].Level, rowTextX, jobsRowText2Y); // Redmage rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[17].Level, 796, jobsRowText2Y); // Bluemage + ctx.fillText(ClassJobs[19].Level, 815, jobsRowText2Y); // Bluemage // Third row rowTextX = jobsRowTextStartX; - ctx.fillText(ClassJobs[18].Level, rowTextX, jobsRowText3Y); // Carpenter + ctx.fillText(ClassJobs[20].Level, rowTextX, jobsRowText3Y); // Carpenter rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[19].Level, rowTextX, jobsRowText3Y); // Blacksmith + ctx.fillText(ClassJobs[21].Level, rowTextX, jobsRowText3Y); // Blacksmith rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[20].Level, rowTextX, jobsRowText3Y); // Armorer + ctx.fillText(ClassJobs[22].Level, rowTextX, jobsRowText3Y); // Armorer rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[21].Level, rowTextX, jobsRowText3Y); // Goldsmith + ctx.fillText(ClassJobs[23].Level, rowTextX, jobsRowText3Y); // Goldsmith rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[22].Level, rowTextX, jobsRowText3Y); // Leatherworker + ctx.fillText(ClassJobs[24].Level, rowTextX, jobsRowText3Y); // Leatherworker rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[23].Level, rowTextX, jobsRowText3Y); // Weaver + ctx.fillText(ClassJobs[25].Level, rowTextX, jobsRowText3Y); // Weaver rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[24].Level, rowTextX, jobsRowText3Y); // Alchemist + ctx.fillText(ClassJobs[26].Level, rowTextX, jobsRowText3Y); // Alchemist rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[25].Level, rowTextX, jobsRowText3Y); // Culinarian - rowTextX += jobsRowTextSpacer; - ctx.fillText(ClassJobs[26].Level, rowTextX, jobsRowText3Y); // Miner + ctx.fillText(ClassJobs[27].Level, rowTextX, jobsRowText3Y); // Culinarian + rowTextX += jobsRowTextSpacer * 1.5; + ctx.fillText(ClassJobs[28].Level, rowTextX, jobsRowText3Y); // Miner rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[27].Level, rowTextX, jobsRowText3Y); // Botanist + ctx.fillText(ClassJobs[29].Level, rowTextX, jobsRowText3Y); // Botanist rowTextX += jobsRowTextSize; - ctx.fillText(ClassJobs[28].Level, rowTextX, jobsRowText3Y); // Fisher + ctx.fillText(ClassJobs[30].Level, rowTextX, jobsRowText3Y); // Fisher } // Remaining asynchronous drawing diff --git a/resources/class-jobs-icons/reaper.png b/resources/class-jobs-icons/reaper.png new file mode 100644 index 0000000..b43c222 Binary files /dev/null and b/resources/class-jobs-icons/reaper.png differ diff --git a/resources/class-jobs-icons/sage.png b/resources/class-jobs-icons/sage.png new file mode 100644 index 0000000..53fae00 Binary files /dev/null and b/resources/class-jobs-icons/sage.png differ