diff --git a/docs/equipment-icon-accessory-pass.md b/docs/equipment-icon-accessory-pass.md
new file mode 100644
index 0000000..3b3c15d
--- /dev/null
+++ b/docs/equipment-icon-accessory-pass.md
@@ -0,0 +1,34 @@
+# Accessory Equipment Icon Pass
+
+Generated after the accessory icon rework in `src/game/scenes/BootScene.ts`.
+
+## Scope
+
+- `peach-charm`
+- `war-manual`
+- `mountain-guide-scroll`
+- `bravery-token`
+- `grain-pouch`
+- `yellow-scarf-charm`
+- `wind-quiver`
+
+## Before and After
+
+| item id | previous helper | current helper | previous primitives | current primitives | audit concerns |
+| --- | --- | --- | ---: | ---: | --- |
+| `bravery-token` | `drawTokenIcon` | `drawBraveryTokenIcon` | 4 | 19 | none |
+| `mountain-guide-scroll` | `drawMapScrollIcon` | `drawMountainGuideScrollIcon` | 13 | 23 | none |
+| `peach-charm` | `drawCharmIcon` | `drawPeachCharmIcon` | 4 | 22 | none |
+| `war-manual` | `drawBookIcon` | `drawWarManualIcon` | 7 | 20 | none |
+| `wind-quiver` | `drawQuiverIcon` | `drawWindQuiverIcon` | 8 | 24 | none |
+| `grain-pouch` | `drawPouchIcon` | `drawGrainPouchIcon` | 7 | 22 | none |
+| `yellow-scarf-charm` | `drawCharmIcon` | `drawYellowScarfCharmIcon` | 4 | 25 | none |
+
+## Browser QA
+
+
+
+- URL checked: `http://127.0.0.1:4200/heros_web/?debug&debugSortiePrep&renderer=canvas`
+- Result: sortie prep opened on a desktop 1280x720 canvas and rendered the generated accessory textures in roster, slot, and detail surfaces.
+- Browser console warnings/errors: none observed.
+- Follow-up target from the updated audit: remaining low-detail equipment icons.
diff --git a/docs/equipment-icon-accessory-sortie-prep.png b/docs/equipment-icon-accessory-sortie-prep.png
new file mode 100644
index 0000000..e1bec97
Binary files /dev/null and b/docs/equipment-icon-accessory-sortie-prep.png differ
diff --git a/docs/equipment-icon-quality-audit.md b/docs/equipment-icon-quality-audit.md
index 4519ba8..718c7fc 100644
--- a/docs/equipment-icon-quality-audit.md
+++ b/docs/equipment-icon-quality-audit.md
@@ -28,22 +28,24 @@ Generated by `scripts/audit-equipment-icon-quality.mjs`.
- The previous shared spear/polearm silhouettes now use item-specific helper shapes with enough primitive detail for 20px and 30px equipment UI reads.
- armor silhouettes: `oath-robe`, `reinforced-lamellar`, `cloth-armor`, `lamellar-armor`, `rebel-vest`
- 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.
## Next Improvement Target
-- Target: accessory charms and tokens
-- Item ids: `bravery-token`, `mountain-guide-scroll`, `peach-charm`, `war-manual`, `wind-quiver`, `grain-pouch`, `yellow-scarf-charm`
-- Reason: Accessories are the smallest UI read and several use compact badge-like shapes.
+- 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.
## Highest-Risk Shared Silhouette Groups
| score | signature | slots | ranks | items |
| ---: | --- | --- | --- | --- |
-| 8 | `drawCharmIcon` | accessory | common, treasure | `peach-charm`, `yellow-scarf-charm` |
| 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` |
## Full Item Inventory
@@ -65,18 +67,18 @@ Generated by `scripts/audit-equipment-icon-quality.mjs`.
| `cloth-armor` | armor | common | `drawClothArmorIcon` | 1 | 24 | 6 | none |
| `lamellar-armor` | armor | common | `drawLamellarArmorIcon` | 1 | 23 | 4 | none |
| `rebel-vest` | armor | common | `drawRebelVestIcon` | 1 | 24 | 7 | none |
-| `bravery-token` | accessory | treasure | `drawTokenIcon` | 1 | 4 | 2 | low primitive detail |
-| `mountain-guide-scroll` | accessory | treasure | `drawMapScrollIcon` | 1 | 13 | 5 | low primitive detail |
-| `peach-charm` | accessory | treasure | `drawCharmIcon` | 1 | 4 | 2 | shared helper silhouette
low primitive detail |
-| `war-manual` | accessory | treasure | `drawBookIcon` | 1 | 7 | 3 | low primitive detail |
-| `wind-quiver` | accessory | treasure | `drawQuiverIcon` | 1 | 8 | 2 | low primitive detail |
-| `grain-pouch` | accessory | common | `drawPouchIcon` | 1 | 7 | 2 | low primitive detail |
-| `yellow-scarf-charm` | accessory | common | `drawCharmIcon` | 1 | 4 | 2 | shared helper silhouette
low primitive detail |
+| `bravery-token` | accessory | treasure | `drawBraveryTokenIcon` | 1 | 19 | 5 | none |
+| `mountain-guide-scroll` | accessory | treasure | `drawMountainGuideScrollIcon` | 1 | 23 | 7 | none |
+| `peach-charm` | accessory | treasure | `drawPeachCharmIcon` | 1 | 22 | 5 | none |
+| `war-manual` | accessory | treasure | `drawWarManualIcon` | 1 | 20 | 7 | none |
+| `wind-quiver` | accessory | treasure | `drawWindQuiverIcon` | 1 | 24 | 6 | none |
+| `grain-pouch` | accessory | common | `drawGrainPouchIcon` | 1 | 22 | 5 | none |
+| `yellow-scarf-charm` | accessory | common | `drawYellowScarfCharmIcon` | 1 | 25 | 5 | none |
## Recommended Next Batch Definition
-- Scope: improve accessory charms and tokens while keeping `item-${itemId}` texture keys stable.
-- Item ids: `bravery-token`, `mountain-guide-scroll`, `peach-charm`, `war-manual`, `wind-quiver`, `grain-pouch`, `yellow-scarf-charm`
-- Success criteria: Each accessory should keep a compact footprint while gaining a distinct readable prop shape at 20px and 30px.
+- 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.
diff --git a/src/game/scenes/BootScene.ts b/src/game/scenes/BootScene.ts
index 6998156..00c6a0c 100644
--- a/src/game/scenes/BootScene.ts
+++ b/src/game/scenes/BootScene.ts
@@ -51,13 +51,13 @@ export class BootScene extends Phaser.Scene {
this.createItemIcon('item-reinforced-lamellar', (graphics) => this.drawReinforcedLamellarIcon(graphics));
this.createItemIcon('item-rebel-vest', (graphics) => this.drawRebelVestIcon(graphics));
- this.createItemIcon('item-peach-charm', (graphics) => this.drawCharmIcon(graphics, 0xf0a6a4, 0xd8b15f));
- this.createItemIcon('item-war-manual', (graphics) => this.drawBookIcon(graphics, 0x5b78a0, 0xe8dfca));
- this.createItemIcon('item-mountain-guide-scroll', (graphics) => this.drawMapScrollIcon(graphics, 0xcfae72, 0x5f8f65));
- this.createItemIcon('item-bravery-token', (graphics) => this.drawTokenIcon(graphics, 0xd8b15f, 0x9b4c3a));
- this.createItemIcon('item-grain-pouch', (graphics) => this.drawPouchIcon(graphics, 0xa7794a, 0xe8dfca));
- this.createItemIcon('item-yellow-scarf-charm', (graphics) => this.drawCharmIcon(graphics, 0xd8b15f, 0x8b6f2a));
- this.createItemIcon('item-wind-quiver', (graphics) => this.drawQuiverIcon(graphics, 0x8bb3c7, 0xe8dfca));
+ this.createItemIcon('item-peach-charm', (graphics) => this.drawPeachCharmIcon(graphics));
+ this.createItemIcon('item-war-manual', (graphics) => this.drawWarManualIcon(graphics));
+ this.createItemIcon('item-mountain-guide-scroll', (graphics) => this.drawMountainGuideScrollIcon(graphics));
+ this.createItemIcon('item-bravery-token', (graphics) => this.drawBraveryTokenIcon(graphics));
+ this.createItemIcon('item-grain-pouch', (graphics) => this.drawGrainPouchIcon(graphics));
+ this.createItemIcon('item-yellow-scarf-charm', (graphics) => this.drawYellowScarfCharmIcon(graphics));
+ this.createItemIcon('item-wind-quiver', (graphics) => this.drawWindQuiverIcon(graphics));
}
private createItemIcon(key: string, draw: (graphics: Phaser.GameObjects.Graphics) => void) {
@@ -480,76 +480,213 @@ export class BootScene extends Phaser.Scene {
graphics.fillCircle(18, 17, 1);
}
- private drawCharmIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, accentColor: number) {
- graphics.fillStyle(baseColor, 1);
- graphics.fillRoundedRect(8, 7, 12, 16, 2);
- graphics.lineStyle(2, accentColor, 1);
- graphics.strokeRoundedRect(8, 7, 12, 16, 2);
- graphics.fillStyle(accentColor, 1);
- graphics.fillCircle(14, 15, 3);
- }
-
- private drawBookIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, pageColor: number) {
- graphics.fillStyle(baseColor, 1);
- graphics.fillRect(6, 6, 16, 18);
- graphics.fillStyle(pageColor, 1);
- graphics.fillRect(9, 8, 10, 14);
- graphics.lineStyle(1, 0x101820, 0.65);
+ private drawPeachCharmIcon(graphics: Phaser.GameObjects.Graphics) {
+ graphics.lineStyle(2, 0xd8b15f, 1);
graphics.beginPath();
- graphics.moveTo(14, 8);
- graphics.lineTo(14, 22);
+ graphics.moveTo(14, 4);
+ graphics.lineTo(14, 8);
+ graphics.moveTo(10, 7);
+ graphics.lineTo(18, 7);
graphics.strokePath();
- }
-
- private drawMapScrollIcon(graphics: Phaser.GameObjects.Graphics, paperColor: number, routeColor: number) {
- graphics.fillStyle(0x8d5a3a, 1);
- graphics.fillRoundedRect(5, 5, 5, 18, 2);
- graphics.fillRoundedRect(18, 5, 5, 18, 2);
- graphics.fillStyle(paperColor, 1);
- graphics.fillRoundedRect(8, 6, 12, 16, 2);
- graphics.lineStyle(1, 0x4e3522, 0.7);
- graphics.strokeRoundedRect(8, 6, 12, 16, 2);
- graphics.lineStyle(2, routeColor, 1);
+ graphics.fillStyle(0x5f8f65, 1);
+ graphics.fillEllipse(18, 7, 7, 4);
+ graphics.fillStyle(0xf0a6a4, 1);
+ graphics.fillEllipse(11, 15, 9, 13);
+ graphics.fillEllipse(17, 15, 9, 13);
+ graphics.fillTriangle(8, 16, 20, 16, 14, 24);
+ graphics.fillStyle(0xf7c7bd, 0.8);
+ graphics.fillEllipse(11, 13, 4, 7);
+ graphics.fillEllipse(17, 13, 4, 7);
+ graphics.lineStyle(1, 0x9b4c3a, 0.85);
graphics.beginPath();
- graphics.moveTo(10, 18);
- graphics.lineTo(13, 14);
- graphics.lineTo(15, 16);
- graphics.lineTo(18, 10);
+ graphics.moveTo(14, 10);
+ graphics.lineTo(14, 23);
+ graphics.moveTo(9, 17);
+ graphics.lineTo(19, 17);
graphics.strokePath();
graphics.fillStyle(0xd8b15f, 1);
- graphics.fillCircle(18, 10, 2);
+ graphics.fillCircle(14, 8, 2);
+ graphics.fillCircle(14, 19, 1);
}
- private drawTokenIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, accentColor: number) {
- graphics.fillStyle(baseColor, 1);
- graphics.fillCircle(14, 14, 9);
- graphics.lineStyle(2, accentColor, 0.9);
- graphics.strokeCircle(14, 14, 7);
- graphics.fillStyle(accentColor, 1);
- graphics.fillTriangle(14, 8, 18, 18, 10, 18);
+ private drawWarManualIcon(graphics: Phaser.GameObjects.Graphics) {
+ graphics.fillStyle(0x253d5a, 1);
+ graphics.fillRoundedRect(6, 5, 17, 20, 2);
+ graphics.fillStyle(0x5b78a0, 1);
+ graphics.fillRoundedRect(8, 6, 13, 18, 1);
+ graphics.fillStyle(0xe8dfca, 1);
+ graphics.fillRect(11, 8, 8, 14);
+ graphics.fillStyle(0xd8b15f, 1);
+ graphics.fillRect(8, 6, 3, 18);
+ graphics.fillRect(10, 5, 11, 2);
+ graphics.fillStyle(0x9b4c3a, 1);
+ graphics.fillTriangle(17, 8, 20, 8, 18, 13);
+ graphics.lineStyle(1, 0x101820, 0.8);
+ graphics.strokeRoundedRect(7, 6, 15, 18, 2);
+ graphics.beginPath();
+ graphics.moveTo(14, 9);
+ graphics.lineTo(14, 22);
+ graphics.moveTo(12, 11);
+ graphics.lineTo(18, 11);
+ graphics.moveTo(12, 15);
+ graphics.lineTo(18, 15);
+ graphics.moveTo(12, 19);
+ graphics.lineTo(17, 19);
+ graphics.strokePath();
+ graphics.fillStyle(0xf2e3bf, 1);
+ graphics.fillCircle(9, 10, 1);
+ graphics.fillCircle(9, 20, 1);
}
- private drawPouchIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, accentColor: number) {
- graphics.fillStyle(baseColor, 1);
- graphics.fillRoundedRect(7, 10, 14, 13, 4);
+ private drawMountainGuideScrollIcon(graphics: Phaser.GameObjects.Graphics) {
+ graphics.fillStyle(0x8d5a3a, 1);
+ graphics.fillRoundedRect(4, 5, 5, 18, 2);
+ graphics.fillRoundedRect(19, 5, 5, 18, 2);
+ graphics.fillStyle(0xcfae72, 1);
+ graphics.fillRoundedRect(7, 6, 14, 16, 2);
+ graphics.fillStyle(0xe8dfca, 0.82);
+ graphics.fillRect(10, 7, 8, 14);
+ graphics.fillStyle(0x6f7f5a, 1);
+ graphics.fillTriangle(9, 19, 13, 13, 16, 19);
+ graphics.fillTriangle(13, 20, 18, 11, 21, 20);
+ graphics.lineStyle(1, 0x4e3522, 0.8);
+ graphics.strokeRoundedRect(7, 6, 14, 16, 2);
+ graphics.beginPath();
+ graphics.moveTo(11, 7);
+ graphics.lineTo(11, 22);
+ graphics.moveTo(17, 7);
+ graphics.lineTo(17, 22);
+ graphics.strokePath();
+ graphics.lineStyle(2, 0x5f8f65, 1);
+ graphics.beginPath();
+ graphics.moveTo(9, 17);
+ graphics.lineTo(12, 14);
+ graphics.lineTo(15, 16);
+ graphics.lineTo(19, 9);
+ graphics.strokePath();
+ graphics.fillStyle(0xd8b15f, 1);
+ graphics.fillCircle(19, 9, 2);
+ graphics.fillCircle(9, 17, 1);
+ }
+
+ private drawBraveryTokenIcon(graphics: Phaser.GameObjects.Graphics) {
+ graphics.fillStyle(0x9b4c3a, 1);
+ graphics.fillTriangle(10, 18, 7, 25, 13, 21);
+ graphics.fillTriangle(18, 18, 21, 25, 15, 21);
+ graphics.fillStyle(0xd8b15f, 1);
+ graphics.fillCircle(14, 13, 9);
+ graphics.fillStyle(0xf2d68b, 1);
+ graphics.fillCircle(14, 13, 6);
+ graphics.lineStyle(2, 0x9b4c3a, 0.95);
+ graphics.strokeCircle(14, 13, 8);
+ graphics.strokeCircle(14, 13, 4);
+ graphics.fillStyle(0x9b4c3a, 1);
+ graphics.fillTriangle(14, 7, 16, 12, 12, 12);
+ graphics.fillTriangle(14, 19, 16, 14, 12, 14);
+ graphics.fillTriangle(8, 13, 13, 11, 13, 15);
+ graphics.fillTriangle(20, 13, 15, 11, 15, 15);
+ graphics.lineStyle(1, 0x5d2d25, 0.9);
+ graphics.beginPath();
+ graphics.moveTo(11, 4);
+ graphics.lineTo(17, 4);
+ graphics.moveTo(10, 22);
+ graphics.lineTo(18, 22);
+ graphics.strokePath();
+ graphics.fillStyle(0x101820, 0.45);
+ graphics.fillCircle(14, 13, 1);
+ }
+
+ private drawGrainPouchIcon(graphics: Phaser.GameObjects.Graphics) {
+ graphics.fillStyle(0x7a5535, 1);
graphics.fillTriangle(10, 11, 18, 11, 14, 5);
- graphics.lineStyle(2, accentColor, 1);
+ graphics.fillRoundedRect(6, 10, 16, 14, 5);
+ graphics.fillStyle(0xa7794a, 1);
+ graphics.fillRoundedRect(8, 11, 12, 12, 4);
+ graphics.fillStyle(0xe8dfca, 1);
+ graphics.fillEllipse(11, 17, 2, 4);
+ graphics.fillEllipse(14, 18, 2, 4);
+ graphics.fillEllipse(17, 16, 2, 4);
+ graphics.lineStyle(2, 0xe8dfca, 0.95);
graphics.beginPath();
graphics.moveTo(8, 13);
graphics.lineTo(20, 13);
+ graphics.moveTo(10, 10);
+ graphics.lineTo(18, 10);
graphics.strokePath();
+ graphics.lineStyle(1, 0x4e3522, 0.85);
+ graphics.strokeRoundedRect(7, 10, 14, 14, 4);
+ graphics.beginPath();
+ graphics.moveTo(9, 15);
+ graphics.lineTo(8, 21);
+ graphics.moveTo(19, 15);
+ graphics.lineTo(20, 21);
+ graphics.strokePath();
+ graphics.fillStyle(0xd8b15f, 1);
+ graphics.fillCircle(14, 12, 1);
}
- private drawQuiverIcon(graphics: Phaser.GameObjects.Graphics, baseColor: number, arrowColor: number) {
- graphics.fillStyle(baseColor, 1);
- graphics.fillRoundedRect(10, 8, 9, 16, 2);
- graphics.lineStyle(2, arrowColor, 1);
+ private drawYellowScarfCharmIcon(graphics: Phaser.GameObjects.Graphics) {
+ graphics.fillStyle(0xd8b15f, 1);
+ graphics.fillRoundedRect(9, 5, 10, 10, 2);
+ graphics.fillTriangle(9, 12, 5, 24, 12, 19);
+ graphics.fillTriangle(19, 12, 23, 24, 16, 19);
+ graphics.fillStyle(0xf2d68b, 1);
+ graphics.fillRoundedRect(11, 7, 6, 6, 1);
+ graphics.fillStyle(0x8b6f2a, 1);
+ graphics.fillCircle(14, 12, 3);
+ graphics.fillTriangle(14, 6, 16, 12, 12, 12);
+ graphics.lineStyle(2, 0x8b6f2a, 0.95);
graphics.beginPath();
- graphics.moveTo(7, 6);
- graphics.lineTo(18, 20);
- graphics.moveTo(13, 5);
- graphics.lineTo(20, 19);
+ graphics.moveTo(10, 6);
+ graphics.lineTo(18, 14);
+ graphics.moveTo(18, 6);
+ graphics.lineTo(10, 14);
+ graphics.moveTo(8, 18);
+ graphics.lineTo(12, 16);
+ graphics.moveTo(20, 18);
+ graphics.lineTo(16, 16);
graphics.strokePath();
+ graphics.lineStyle(1, 0xe8dfca, 0.75);
+ graphics.beginPath();
+ graphics.moveTo(8, 21);
+ graphics.lineTo(11, 19);
+ graphics.moveTo(20, 21);
+ graphics.lineTo(17, 19);
+ graphics.strokePath();
+ graphics.fillStyle(0x9b4c3a, 1);
+ graphics.fillCircle(14, 12, 1);
+ }
+
+ private drawWindQuiverIcon(graphics: Phaser.GameObjects.Graphics) {
+ graphics.fillStyle(0x4f7d92, 1);
+ graphics.fillRoundedRect(9, 8, 10, 17, 2);
+ graphics.fillStyle(0x8bb3c7, 1);
+ graphics.fillRoundedRect(11, 10, 7, 13, 2);
+ graphics.fillStyle(0x2f5f8f, 1);
+ graphics.fillTriangle(9, 9, 20, 8, 16, 13);
+ graphics.fillStyle(0xe8dfca, 1);
+ graphics.fillTriangle(6, 4, 10, 6, 8, 9);
+ graphics.fillTriangle(12, 3, 16, 5, 14, 8);
+ graphics.fillTriangle(18, 4, 22, 6, 20, 9);
+ graphics.lineStyle(2, 0xe8dfca, 1);
+ graphics.beginPath();
+ graphics.moveTo(8, 6);
+ graphics.lineTo(15, 19);
+ graphics.moveTo(14, 5);
+ graphics.lineTo(18, 18);
+ graphics.moveTo(20, 6);
+ graphics.lineTo(17, 20);
+ graphics.strokePath();
+ graphics.lineStyle(1, 0x101820, 0.75);
+ graphics.strokeRoundedRect(10, 9, 9, 15, 2);
+ graphics.beginPath();
+ graphics.moveTo(12, 15);
+ graphics.lineTo(18, 13);
+ graphics.moveTo(12, 19);
+ graphics.lineTo(18, 17);
+ graphics.strokePath();
+ graphics.fillStyle(0xd8b15f, 1);
+ graphics.fillCircle(14, 22, 1);
}
}