From 8163fb8fcbcaec53532b5166a599ff02cb7b35cb Mon Sep 17 00:00:00 2001 From: Natalie Date: Sun, 26 Apr 2026 16:03:12 -0700 Subject: [PATCH] =?UTF-8?q?feat(@projects/@magic-civilization):=20?= =?UTF-8?q?=E2=9C=A8=20add=20core=20unit=20data=20schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .project/designs/app/index.html | 19 ++++++ .project/designs/app/package.json | 25 ++++++++ .project/designs/app/src/data/units.ts | 88 ++++++++++++++++++++++++++ .project/designs/app/src/theme.ts | 56 ++++++++++++++++ .project/designs/app/tsconfig.json | 15 +++++ .project/designs/app/vite.config.ts | 7 ++ 6 files changed, 210 insertions(+) create mode 100644 .project/designs/app/index.html create mode 100644 .project/designs/app/package.json create mode 100644 .project/designs/app/src/data/units.ts create mode 100644 .project/designs/app/src/theme.ts create mode 100644 .project/designs/app/tsconfig.json create mode 100644 .project/designs/app/vite.config.ts diff --git a/.project/designs/app/index.html b/.project/designs/app/index.html new file mode 100644 index 00000000..83a4350f --- /dev/null +++ b/.project/designs/app/index.html @@ -0,0 +1,19 @@ + + + + + + Age of Dwarves — Design System + + + + + +
+ + + diff --git a/.project/designs/app/package.json b/.project/designs/app/package.json new file mode 100644 index 00000000..406f4d1c --- /dev/null +++ b/.project/designs/app/package.json @@ -0,0 +1,25 @@ +{ + "name": "@magic-civ/designs", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.5.3", + "styled-components": "^6.1.18" + }, + "devDependencies": { + "@types/react": "^19.1.2", + "@types/react-dom": "^19.1.2", + "@types/styled-components": "^5.1.34", + "@vitejs/plugin-react": "^4.4.1", + "typescript": "^5.8.3", + "vite": "^6.3.3" + } +} diff --git a/.project/designs/app/src/data/units.ts b/.project/designs/app/src/data/units.ts new file mode 100644 index 00000000..761471da --- /dev/null +++ b/.project/designs/app/src/data/units.ts @@ -0,0 +1,88 @@ +export type AttackType = "blade" | "pierce" | "crush" | "trample" | "siege"; +export type ArmorType = "unarmored" | "light" | "medium" | "armored" | "heavy" | "plate" | "fortified"; + +export interface Unit { + id: string; + name: string; + tier: number; + archetype: string; + attackType: AttackType; + armor: ArmorType; + hp: number; + attack: number; + defense: number; + rangedAttack: number; + range: number; + movement: number; + keywords: string[]; + race?: string; + unique?: boolean; +} + +// Sourced from public/games/age-of-dwarves/data/units/*.json +export const UNITS: Record = { + warrior: { + id: "warrior", name: "Warrior", tier: 1, archetype: "Light Melee", + attackType: "blade", armor: "light", + hp: 80, attack: 14, defense: 8, rangedAttack: 0, range: 0, movement: 2, + keywords: [], + }, + berserker: { + id: "berserker", name: "Berserker", tier: 2, archetype: "Light Melee", + attackType: "blade", armor: "light", + hp: 90, attack: 20, defense: 6, rangedAttack: 0, range: 0, movement: 2, + keywords: ["rage", "no_shield"], + race: "dwarf", unique: true, + }, + ironwarden: { + id: "ironwarden", name: "Ironwarden", tier: 4, archetype: "Heavy Melee", + attackType: "blade", armor: "heavy", + hp: 110, attack: 22, defense: 18, rangedAttack: 0, range: 0, movement: 2, + keywords: ["formation", "shield_wall"], + race: "dwarf", unique: true, + }, + spearmen: { + id: "spearmen", name: "Spearmen", tier: 1, archetype: "Anti-Cavalry", + attackType: "pierce", armor: "medium", + hp: 60, attack: 8, defense: 8, rangedAttack: 0, range: 0, movement: 1, + keywords: ["reach"], + }, + pikeman: { + id: "pikeman", name: "Pikeman", tier: 2, archetype: "Anti-Cavalry", + attackType: "pierce", armor: "armored", + hp: 100, attack: 10, defense: 14, rangedAttack: 0, range: 0, movement: 2, + keywords: ["zoc", "anti_cavalry"], + }, + cavalry: { + id: "cavalry", name: "Cavalry", tier: 3, archetype: "Cavalry", + attackType: "blade", armor: "light", + hp: 70, attack: 16, defense: 6, rangedAttack: 0, range: 0, movement: 4, + keywords: ["fast", "flanking"], + }, + archer: { + id: "archer", name: "Archer", tier: 1, archetype: "Ranged", + attackType: "pierce", armor: "light", + hp: 50, attack: 10, defense: 4, rangedAttack: 12, range: 2, movement: 2, + keywords: ["ranged"], + }, + runesmith: { + id: "runesmith", name: "Runesmith", tier: 2, archetype: "Ranged", + attackType: "pierce", armor: "armored", + hp: 70, attack: 8, defense: 12, rangedAttack: 18, range: 2, movement: 1, + keywords: ["ranged", "heavy_armor"], + race: "dwarf", unique: true, + }, +}; + +// From COMBAT_SYSTEM.md +export const DAMAGE_MATRIX: Record> = { + blade: { unarmored: 1.25, light: 1.25, medium: 1.00, armored: 0.75, heavy: 0.75, plate: 0.50, fortified: 0.25 }, + pierce: { unarmored: 1.00, light: 1.00, medium: 1.25, armored: 1.00, heavy: 1.00, plate: 0.75, fortified: 0.50 }, + crush: { unarmored: 0.75, light: 0.75, medium: 1.00, armored: 1.25, heavy: 1.25, plate: 1.50, fortified: 1.75 }, + trample: { unarmored: 2.00, light: 1.50, medium: 1.00, armored: 0.50, heavy: 0.50, plate: 0.25, fortified: 0.00 }, + siege: { unarmored: 0.50, light: 0.50, medium: 0.75, armored: 1.00, heavy: 1.00, plate: 1.00, fortified: 2.00 }, +}; + +export function matrixMultiplier(atk: AttackType, armor: ArmorType): number { + return DAMAGE_MATRIX[atk][armor]; +} diff --git a/.project/designs/app/src/theme.ts b/.project/designs/app/src/theme.ts new file mode 100644 index 00000000..c3db9831 --- /dev/null +++ b/.project/designs/app/src/theme.ts @@ -0,0 +1,56 @@ +export const t = { + bg: { + deepest: "#171219", + panel: "#17121e", + surface: "#221a14", + raised: "#2a2018", + list: "#120e1e", + listSel: "#3f2d0d", + menu: "#0e0a17", + btnNormal: "#1f1733", + btnHover: "#331a0d", + btnPressed: "#472f0f", + }, + text: { + title: "#f2d973", + primary: "#e0d8c8", + secondary: "#bfb7a6", + muted: "#b2b2b2", + disabled: "#80806699", + btn: "#e0d199", + btnHover: "#ffeb80", + btnPressed: "#ffffb3", + }, + accent: { + gold: "#d9a020", + goldBright: "#d9b33f", + goldPress: "#ffd14d", + goldRes: "#f2d133", + science: "#66bfff", + sage: "#66b866", + ping: "#ffd973", + }, + sem: { + positive: "#66e666", + goldenAge: "#ffeb66", + negative: "#d95940", + warning: "#e69933", + diplomacy: "#e68c73", + trade: "#ccbf73", + }, + border: { + panel: "#73591fcc", + focus: "#d9b340", + listSel: "#d9b340cc", + divider: "#73591f33", + }, + font: { + heading: "'Grenze Gotisch', serif", + body: "'Bitter', serif", + mono: "monospace", + }, + radius: { panel: "4px", btn: "3px", list: "2px" }, + space: { 1: "4px", 2: "8px", 3: "12px", 4: "14px", 5: "18px", 6: "24px" }, +} as const; + +export type Theme = typeof t; diff --git a/.project/designs/app/tsconfig.json b/.project/designs/app/tsconfig.json new file mode 100644 index 00000000..efdb14c6 --- /dev/null +++ b/.project/designs/app/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true + }, + "include": ["src"] +} diff --git a/.project/designs/app/vite.config.ts b/.project/designs/app/vite.config.ts new file mode 100644 index 00000000..36307958 --- /dev/null +++ b/.project/designs/app/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [react()], + server: { port: 7777 }, +});