Strategy auto-battler — a per-game branch of the webdev-game-stack monorepo
The stack is:
Vibefor frontend (runtime-first reactive framework via@ape-egg/vibe)Stylecheatfor styling (attribute-based CSS framework)Vite+vite-plugin-vibefor dev server / HMRBunfor backend (https://bun.sh)MongoDBfor database (https://www.mongodb.com)
bun install
bun dev
The dev server is reachable both at http://localhost:<port> (printed on start) and at https://webdev-game-stack.test via the local Caddy proxy.
touch server/.env and add:
PORT=1337
CORS_ORIGIN=*
NODE_ENV=development
MONGO_CONNECT=mongodb://wsadmin:qwe123@localhost:27017
SUPPORT_EMAIL_PASSWORD=<password>
PASSWORD_RESET_HASH=<custom_hash>
cd server
bun install
bun run dev
- ✅ Socket server to handle any request (https://github.com/kkortes/async-await-websockets)
- ✅ Account log in
- ✅ Account creation
- ✅ Account password recovery
- ✅ Render backend hosting setup (https://render.com)
- ✅ Vercel frontend hosting setup (https://vercel.com)
- ✅ Vibe + Stylecheat front-end (formerly Svelte + Tailwind)
Source of truth for balancing races, equipment, racial bonuses, and (eventually) player-allocable specs. Pricing is linear — no diminishing returns, no soft caps.
Baseline anchor: 1 spec point = 2 damage = 4 health
Armor in this table assumes the flat-reduction model: each point of armor subtracts 1 damage from every incoming hit (clamped at 0). It does not deplete.
| Stat | 1 spec point = |
|---|---|
Health (maxHealth) |
+4 HP |
Armor (maxArmor) |
+1 armor (flat reduction per hit) |
Damage (damage) |
+2 damage |
Critical Chance (criticalChance) |
+1% |
Critical Damage (criticalDamage) |
+10% |
Block Chance (blockChance) |
+1% |
Dodge Chance (dodgeChance) |
+1% |
Magic Chance (magicChance) |
TBD — mechanic pending |
Modifiers are % multipliers in combatStats.modifiers. Rates below are pegged to default base values so the EV roughly matches the flat-stat table.
| Modifier | 1 spec point = |
|---|---|
modifiers.maxHealth |
+15% |
modifiers.maxArmor |
+10% |
modifiers.damage |
+25% |
modifiers.resistance |
+2% (scales wounded/concussed/exposed thresholds) |
- Linear pricing only. Stats must be honest and easy for the player to calculate.
- Unimplemented stats (currently
magicChance) don't render in any UI until they have gameplay. - When adding a new stat, give it a row here before it ships. If it can't be priced linearly, it doesn't ship.
- Racial bonuses, equipment rolls, and spec choices all draw from the same currency — this table is the contract.
Because stat scaling is linear, equipment doesn't differentiate by stat shape — a higher-level piece is simply more of the same (e.g. armor = its level, so a higher-level armor is a strict upgrade of a lower one). The differentiator is coin cost, spent against a deliberately scarce economy: a player has roughly 25 coins total by level 25, shared across all 6 characters. You can't gear everyone in top equipment — every purchase is a trade-off.
So when pricing current and future equipment:
- Cost is the balancing lever, not stats. A strictly-better item must cost proportionally more coins; price is what gates power, not stat complexity.
- Cheap, low-level gear stays relevant as the affordable pick when coins are tight.
- The only stat-shape trade-off we currently make is heavy armor (
+10armor for−40%hit chance). Everything else competes purely on cost-vs-power along the linear curve.
- Routing is currently MPA-flavored: a Vite middleware in
vite.config.jsmaps URLs topages/*.html(including dynamic routes like/brawlers/:i→pages/brawler-detail.html). Subject to change — could become an SPA later, so feature code shouldn't lean on MPA assumptions. - Vibe is symlinked from
/Users/kortes/Projects/webdev/vibefor live editing during development. Production builds resolve normally from npm. - Global reactive state lives on
$(nowindow.prefix). Component-local state goes throughcomponent(state)+$[id].