diff --git a/docs/equipment-icon-quality-audit.md b/docs/equipment-icon-quality-audit.md index 718c7fc..dcf2bd5 100644 --- a/docs/equipment-icon-quality-audit.md +++ b/docs/equipment-icon-quality-audit.md @@ -30,22 +30,24 @@ Generated by `scripts/audit-equipment-icon-quality.mjs`. - The previous shared armor and robe silhouettes now use item-specific helper shapes with stronger outer contours and material cues. - accessory charms and tokens: `bravery-token`, `mountain-guide-scroll`, `peach-charm`, `war-manual`, `wind-quiver`, `grain-pouch`, `yellow-scarf-charm` - Accessory icons now use distinct badge, scroll, charm, pouch, manual, and quiver silhouettes at small camp UI sizes. +- remaining low-detail weapon icons: `leader-axe`, `training-sword`, `yellow-turban-saber` + - The final low-detail common weapons now use dedicated axe, training sword, and Yellow Turban saber silhouettes. ## Next Improvement Target -- Target: remaining low-detail equipment icons -- Item ids: `leader-axe`, `training-sword`, `yellow-turban-saber` -- Reason: All named batches are complete; remaining work should be selected from the low-detail inventory rows. +- Target: no flagged equipment icon batch +- Item ids: none currently flagged +- Reason: No generated equipment icon currently has a low-detail or shared-helper audit concern; choose the next visual asset pass from in-game QA. ## Highest-Risk Shared Silhouette Groups | score | signature | slots | ranks | items | | ---: | --- | --- | --- | --- | -| 6 | `drawAxeIcon` | weapon | common | `leader-axe` | -| 6 | `drawSaberIcon` | weapon | common | `yellow-turban-saber` | -| 6 | `drawSwordIcon` | weapon | common | `training-sword` | | 5 | `drawFanIcon` | weapon | treasure | `white-feather-fan` | | 5 | `drawGreenDragonGlaiveIcon` | weapon | treasure | `green-dragon-glaive` | +| 5 | `drawSerpentSpearIcon` | weapon | treasure | `serpent-spear` | +| 5 | `drawSkyPiercerHalberdIcon` | weapon | treasure | `sky-piercer-halberd` | +| 5 | `drawSwordIcon+drawSwordIcon` | weapon | treasure | `twin-oath-blades` | ## Full Item Inventory @@ -57,11 +59,11 @@ Generated by `scripts/audit-equipment-icon-quality.mjs`. | `twin-oath-blades` | weapon | treasure | `drawSwordIcon`
`drawSwordIcon` | 2 | 32 | 4 | none | | `white-feather-fan` | weapon | treasure | `drawFanIcon` | 1 | 19 | 3 | none | | `iron-spear` | weapon | common | `drawIronSpearIcon` | 1 | 26 | 7 | none | -| `leader-axe` | weapon | common | `drawAxeIcon` | 1 | 7 | 2 | low primitive detail | +| `leader-axe` | weapon | common | `drawLeaderAxeIcon` | 1 | 26 | 8 | none | | `short-bow` | weapon | common | `drawBowIcon` | 1 | 18 | 3 | none | -| `training-sword` | weapon | common | `drawSwordIcon` | 1 | 16 | 4 | low primitive detail | +| `training-sword` | weapon | common | `drawTrainingSwordIcon` | 1 | 31 | 7 | none | | `western-cavalry-spear` | weapon | common | `drawWesternCavalrySpearIcon` | 1 | 27 | 7 | none | -| `yellow-turban-saber` | weapon | common | `drawSaberIcon` | 1 | 12 | 2 | low primitive detail | +| `yellow-turban-saber` | weapon | common | `drawYellowTurbanSaberIcon` | 1 | 35 | 4 | none | | `oath-robe` | armor | treasure | `drawOathRobeIcon` | 1 | 25 | 6 | none | | `reinforced-lamellar` | armor | treasure | `drawReinforcedLamellarIcon` | 1 | 24 | 5 | none | | `cloth-armor` | armor | common | `drawClothArmorIcon` | 1 | 24 | 6 | none | @@ -77,8 +79,7 @@ Generated by `scripts/audit-equipment-icon-quality.mjs`. ## Recommended Next Batch Definition -- Scope: improve remaining low-detail equipment icons while keeping `item-${itemId}` texture keys stable. -- Item ids: `leader-axe`, `training-sword`, `yellow-turban-saber` -- Success criteria: Clear remaining low-detail concerns without changing stable texture keys. -- Keep the existing 64px texture size unless a UI-wide equipment icon pass is planned. -- Add before/after contact sheets and verify the sortie equipment list and equipment swap panel in a desktop browser. +- Scope: no generated equipment icon is currently below the audit threshold. +- Item ids: none currently flagged +- Success criteria: Keep the generated equipment icon audit green while selecting the next art target from runtime screenshots. +- Suggested next area: map/background or unit sprite assets that still look low-resolution in gameplay. diff --git a/docs/equipment-icon-remaining-weapons-pass.md b/docs/equipment-icon-remaining-weapons-pass.md new file mode 100644 index 0000000..85edab6 --- /dev/null +++ b/docs/equipment-icon-remaining-weapons-pass.md @@ -0,0 +1,26 @@ +# Remaining Weapon Equipment Icon Pass + +Generated after the final low-detail weapon icon rework in `src/game/scenes/BootScene.ts`. + +## Scope + +- `leader-axe` +- `training-sword` +- `yellow-turban-saber` + +## Before and After + +| item id | previous helper | current helper | previous primitives | current primitives | audit concerns | +| --- | --- | --- | ---: | ---: | --- | +| `leader-axe` | `drawAxeIcon` | `drawLeaderAxeIcon` | 7 | 26 | none | +| `training-sword` | `drawSwordIcon` | `drawTrainingSwordIcon` | 16 | 31 | none | +| `yellow-turban-saber` | `drawSaberIcon` | `drawYellowTurbanSaberIcon` | 12 | 35 | none | + +## Browser QA + +![Sortie prep remaining weapon icon QA](./equipment-icon-remaining-weapons-sortie-prep.png) + +- URL checked: `http://127.0.0.1:4201/heros_web/?debug&debugSortiePrep&renderer=canvas` +- Result: sortie prep opened on a desktop 1280x720 canvas and rendered the generated weapon textures in roster, slot, and detail surfaces. +- Browser console warnings/errors: none observed. +- Follow-up target from the updated audit: no generated equipment icon batch is currently flagged; select the next art pass from runtime screenshots. diff --git a/docs/equipment-icon-remaining-weapons-sortie-prep.png b/docs/equipment-icon-remaining-weapons-sortie-prep.png new file mode 100644 index 0000000..e1bec97 Binary files /dev/null and b/docs/equipment-icon-remaining-weapons-sortie-prep.png differ diff --git a/scripts/audit-equipment-icon-quality.mjs b/scripts/audit-equipment-icon-quality.mjs index eecb3ac..a45d6e1 100644 --- a/scripts/audit-equipment-icon-quality.mjs +++ b/scripts/audit-equipment-icon-quality.mjs @@ -315,6 +315,7 @@ function buildRecommendations(itemRows, groupedRows) { ]; const armorTargetIds = ['oath-robe', 'reinforced-lamellar', 'cloth-armor', 'lamellar-armor', 'rebel-vest']; const accessoryIds = itemRows.filter((row) => row.slot === 'accessory').map((row) => row.itemId); + const lowDetailWeaponTargetIds = ['leader-axe', 'training-sword', 'yellow-turban-saber']; const targets = [ { title: 'weapon spear/polearm family', @@ -344,6 +345,15 @@ function buildRecommendations(itemRows, groupedRows) { openReason: 'Accessories are the smallest UI read and several use compact badge-like shapes.', successCriteria: 'Each accessory should keep a compact footprint while gaining a distinct readable prop shape at 20px and 30px.' + }, + { + title: 'remaining low-detail weapon icons', + itemIds: lowDetailWeaponTargetIds, + completeReason: + 'The final low-detail common weapons now use dedicated axe, training sword, and Yellow Turban saber silhouettes.', + openReason: + 'These are the last generated equipment icons still below the primitive-detail threshold after the larger weapon, armor, and accessory passes.', + successCriteria: 'Clear the low primitive detail concerns without changing stable item texture keys.' } ].map((target) => ({ ...target, @@ -356,12 +366,17 @@ function buildRecommendations(itemRows, groupedRows) { itemIds: target.rows.map((row) => row.itemId), reason: target.completeReason })); + const remainingConcernRows = itemRows.filter((row) => row.concerns.length > 0); const nextTarget = targets.find((target) => !improvementTargetComplete(target)) ?? { - title: 'remaining low-detail equipment icons', - rows: itemRows.filter((row) => row.concerns.length > 0), - openReason: 'All named batches are complete; remaining work should be selected from the low-detail inventory rows.', - successCriteria: 'Clear remaining low-detail concerns without changing stable texture keys.' + title: remainingConcernRows.length ? 'remaining low-detail equipment icons' : 'no flagged equipment icon batch', + rows: remainingConcernRows, + openReason: remainingConcernRows.length + ? 'All named batches are complete; remaining work should be selected from the low-detail inventory rows.' + : 'No generated equipment icon currently has a low-detail or shared-helper audit concern; choose the next visual asset pass from in-game QA.', + successCriteria: remainingConcernRows.length + ? 'Clear remaining low-detail concerns without changing stable texture keys.' + : 'Keep the generated equipment icon audit green while selecting the next art target from runtime screenshots.' }; const nextTargetIndex = targets.findIndex((target) => target.title === nextTarget.title); const followUps = targets @@ -426,7 +441,7 @@ function renderReport({ iconSourceSize, iconTextureSize, itemRows, groupedRows, '## Next Improvement Target', '', `- Target: ${recommendations.firstTargetTitle}`, - `- Item ids: ${recommendations.firstTargetIds.map((itemId) => `\`${itemId}\``).join(', ')}`, + `- Item ids: ${formatItemIds(recommendations.firstTargetIds)}`, `- Reason: ${recommendations.firstTargetReason}`, '', ...renderFollowUpTargets(recommendations.followUps), @@ -456,15 +471,37 @@ function renderReport({ iconSourceSize, iconTextureSize, itemRows, groupedRows, ].join(' | ') ).map((line) => `| ${line} |`), '', + ...renderRecommendedNextBatch(recommendations) + ].join('\n')}`; +} + +function formatItemIds(itemIds) { + return itemIds.length ? itemIds.map((itemId) => `\`${itemId}\``).join(', ') : 'none currently flagged'; +} + +function renderRecommendedNextBatch(recommendations) { + if (!recommendations.firstTargetIds.length) { + return [ + '## Recommended Next Batch Definition', + '', + '- Scope: no generated equipment icon is currently below the audit threshold.', + '- Item ids: none currently flagged', + `- Success criteria: ${recommendations.firstTargetSuccessCriteria}`, + '- Suggested next area: map/background or unit sprite assets that still look low-resolution in gameplay.', + '' + ]; + } + + return [ '## Recommended Next Batch Definition', '', `- Scope: improve ${recommendations.firstTargetTitle} while keeping \`item-\${itemId}\` texture keys stable.`, - `- Item ids: ${recommendations.firstTargetIds.map((itemId) => `\`${itemId}\``).join(', ')}`, + `- Item ids: ${formatItemIds(recommendations.firstTargetIds)}`, `- Success criteria: ${recommendations.firstTargetSuccessCriteria}`, '- Keep the existing 64px texture size unless a UI-wide equipment icon pass is planned.', '- Add before/after contact sheets and verify the sortie equipment list and equipment swap panel in a desktop browser.', '' - ].join('\n')}`; + ]; } function renderCompletedTargets(completedTargets) { diff --git a/src/game/scenes/BootScene.ts b/src/game/scenes/BootScene.ts index 00c6a0c..24d8f53 100644 --- a/src/game/scenes/BootScene.ts +++ b/src/game/scenes/BootScene.ts @@ -30,7 +30,7 @@ export class BootScene extends Phaser.Scene { } private createEquipmentIconTextures() { - this.createItemIcon('item-training-sword', (graphics) => this.drawSwordIcon(graphics, 0xbfd6e6, 0x6b4a2c)); + this.createItemIcon('item-training-sword', (graphics) => this.drawTrainingSwordIcon(graphics)); this.createItemIcon('item-twin-oath-blades', (graphics) => { this.drawSwordIcon(graphics, 0xe8edf7, 0x8a5a32, -4); this.drawSwordIcon(graphics, 0xd8b15f, 0x8a5a32, 4); @@ -41,9 +41,9 @@ export class BootScene extends Phaser.Scene { this.createItemIcon('item-sky-piercer-halberd', (graphics) => this.drawSkyPiercerHalberdIcon(graphics)); this.createItemIcon('item-western-cavalry-spear', (graphics) => this.drawWesternCavalrySpearIcon(graphics)); this.createItemIcon('item-white-feather-fan', (graphics) => this.drawFanIcon(graphics, 0xf3f0df, 0x6e8eb8)); - this.createItemIcon('item-yellow-turban-saber', (graphics) => this.drawSaberIcon(graphics, 0xd8b15f, 0x9c6b2f)); + this.createItemIcon('item-yellow-turban-saber', (graphics) => this.drawYellowTurbanSaberIcon(graphics)); this.createItemIcon('item-short-bow', (graphics) => this.drawBowIcon(graphics, 0xc58a4c, 0xe8dfca)); - this.createItemIcon('item-leader-axe', (graphics) => this.drawAxeIcon(graphics, 0xd8dfe6, 0x8d5a3a)); + this.createItemIcon('item-leader-axe', (graphics) => this.drawLeaderAxeIcon(graphics)); this.createItemIcon('item-cloth-armor', (graphics) => this.drawClothArmorIcon(graphics)); this.createItemIcon('item-lamellar-armor', (graphics) => this.drawLamellarArmorIcon(graphics)); @@ -95,6 +95,43 @@ export class BootScene extends Phaser.Scene { graphics.fillCircle(8 + offsetX, 23, 2); } + private drawTrainingSwordIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.lineStyle(5, 0x50606a, 1); + graphics.beginPath(); + graphics.moveTo(7, 23); + graphics.lineTo(20, 5); + graphics.strokePath(); + graphics.lineStyle(3, 0xbfd6e6, 1); + graphics.beginPath(); + graphics.moveTo(8, 22); + graphics.lineTo(20, 6); + graphics.strokePath(); + graphics.lineStyle(1, 0xeff7ff, 0.9); + graphics.beginPath(); + graphics.moveTo(11, 18); + graphics.lineTo(18, 8); + graphics.strokePath(); + graphics.fillStyle(0xd8dfe6, 1); + graphics.fillTriangle(18, 4, 23, 5, 19, 10); + graphics.lineStyle(3, 0xd8b15f, 1); + graphics.beginPath(); + graphics.moveTo(5, 18); + graphics.lineTo(13, 23); + graphics.moveTo(8, 16); + graphics.lineTo(15, 20); + graphics.strokePath(); + graphics.lineStyle(2, 0x6b4a2c, 1); + graphics.beginPath(); + graphics.moveTo(6, 22); + graphics.lineTo(10, 25); + graphics.strokePath(); + graphics.fillStyle(0x6b4a2c, 1); + graphics.fillCircle(7, 24, 2); + graphics.fillStyle(0x9b4c3a, 1); + graphics.fillTriangle(10, 22, 15, 24, 12, 27); + graphics.fillCircle(13, 23, 1); + } + private drawGreenDragonGlaiveIcon(graphics: Phaser.GameObjects.Graphics) { graphics.lineStyle(4, 0x704728, 1); graphics.beginPath(); @@ -254,19 +291,45 @@ export class BootScene extends Phaser.Scene { graphics.strokePath(); } - private drawSaberIcon(graphics: Phaser.GameObjects.Graphics, bladeColor: number, gripColor: number) { - graphics.lineStyle(4, bladeColor, 1); + private drawYellowTurbanSaberIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.lineStyle(5, 0x6b4a2c, 1); + graphics.beginPath(); + graphics.moveTo(7, 22); + graphics.lineTo(12, 15); + graphics.lineTo(19, 8); + graphics.lineTo(24, 5); + graphics.strokePath(); + graphics.lineStyle(4, 0xd8b15f, 1); graphics.beginPath(); graphics.moveTo(8, 22); graphics.lineTo(13, 15); graphics.lineTo(19, 8); graphics.lineTo(23, 6); graphics.strokePath(); - graphics.lineStyle(3, gripColor, 1); + graphics.lineStyle(2, 0xf2d68b, 0.9); + graphics.beginPath(); + graphics.moveTo(12, 17); + graphics.lineTo(19, 9); + graphics.lineTo(22, 7); + graphics.strokePath(); + graphics.fillStyle(0xf2d68b, 1); + graphics.fillTriangle(21, 4, 26, 5, 22, 9); + graphics.fillStyle(0x9c6b2f, 1); + graphics.fillTriangle(10, 17, 17, 18, 12, 22); + graphics.lineStyle(3, 0x9c6b2f, 1); graphics.beginPath(); graphics.moveTo(6, 21); graphics.lineTo(12, 23); graphics.strokePath(); + graphics.lineStyle(2, 0xd8b15f, 1); + graphics.beginPath(); + graphics.moveTo(8, 20); + graphics.lineTo(5, 25); + graphics.moveTo(10, 21); + graphics.lineTo(11, 26); + graphics.strokePath(); + graphics.fillStyle(0xd8b15f, 1); + graphics.fillCircle(7, 22, 2); } private drawBowIcon(graphics: Phaser.GameObjects.Graphics, bowColor: number, stringColor: number) { @@ -290,15 +353,38 @@ export class BootScene extends Phaser.Scene { graphics.strokePath(); } - private drawAxeIcon(graphics: Phaser.GameObjects.Graphics, bladeColor: number, gripColor: number) { - graphics.lineStyle(3, gripColor, 1); + private drawLeaderAxeIcon(graphics: Phaser.GameObjects.Graphics) { + graphics.lineStyle(4, 0x6b4a2c, 1); graphics.beginPath(); graphics.moveTo(9, 24); graphics.lineTo(18, 5); graphics.strokePath(); - graphics.fillStyle(bladeColor, 1); - graphics.fillTriangle(16, 5, 25, 8, 16, 15); - graphics.fillTriangle(16, 5, 9, 9, 15, 14); + graphics.lineStyle(1, 0xc99755, 0.9); + graphics.beginPath(); + graphics.moveTo(11, 22); + graphics.lineTo(18, 7); + graphics.strokePath(); + graphics.fillStyle(0xd8dfe6, 1); + graphics.fillEllipse(20, 10, 12, 12); + graphics.fillTriangle(16, 4, 26, 8, 17, 15); + graphics.fillTriangle(16, 5, 8, 9, 15, 15); + graphics.fillStyle(0xeff7ff, 0.85); + graphics.fillTriangle(18, 6, 24, 8, 18, 11); + graphics.fillTriangle(15, 7, 10, 9, 15, 12); + graphics.fillStyle(0x50606a, 1); + graphics.fillTriangle(17, 11, 22, 14, 15, 16); + graphics.lineStyle(2, 0x8d5a3a, 1); + graphics.beginPath(); + graphics.moveTo(14, 7); + graphics.lineTo(20, 13); + graphics.moveTo(12, 14); + graphics.lineTo(18, 16); + graphics.strokePath(); + graphics.fillStyle(0xd8b15f, 1); + graphics.fillCircle(17, 10, 2); + graphics.fillCircle(9, 24, 2); + graphics.fillStyle(0x9b4c3a, 1); + graphics.fillTriangle(13, 15, 18, 17, 14, 22); } private drawFanIcon(graphics: Phaser.GameObjects.Graphics, featherColor: number, ribColor: number) {