Ajust database schema to recent changes
This commit is contained in:
parent
da93fcd82d
commit
042d4479ee
BIN
db.sqlite-shm
BIN
db.sqlite-shm
Binary file not shown.
BIN
db.sqlite-wal
BIN
db.sqlite-wal
Binary file not shown.
23
db/schema.ts
23
db/schema.ts
|
|
@ -1,5 +1,6 @@
|
||||||
import { relations } from 'drizzle-orm';
|
import { relations } from 'drizzle-orm';
|
||||||
import { int, text, sqliteTable as table, primaryKey, blob } from 'drizzle-orm/sqlite-core';
|
import { int, text, sqliteTable as table, primaryKey, blob } from 'drizzle-orm/sqlite-core';
|
||||||
|
import { ABILITIES, MAIN_STATS } from '~/shared/character.util';
|
||||||
|
|
||||||
export const usersTable = table("users", {
|
export const usersTable = table("users", {
|
||||||
id: int().primaryKey({ autoIncrement: true }),
|
id: int().primaryKey({ autoIncrement: true }),
|
||||||
|
|
@ -54,10 +55,9 @@ export const characterTable = table("character", {
|
||||||
owner: int().notNull().references(() => usersTable.id, { onDelete: 'cascade', onUpdate: 'cascade' }),
|
owner: int().notNull().references(() => usersTable.id, { onDelete: 'cascade', onUpdate: 'cascade' }),
|
||||||
people: text().notNull(),
|
people: text().notNull(),
|
||||||
level: int().notNull().default(1),
|
level: int().notNull().default(1),
|
||||||
|
variables: text({ mode: 'json' }).notNull().default('{"health": 0,"mana": 0,"spells": [],"equipment": [],"exhaustion": 0,"sickness": []}'),
|
||||||
aspect: int(),
|
aspect: int(),
|
||||||
notes: text(),
|
notes: text(),
|
||||||
health: int().notNull().default(0),
|
|
||||||
mana: int().notNull().default(0),
|
|
||||||
|
|
||||||
visibility: text({ enum: ['private', 'public'] }).notNull().default('private'),
|
visibility: text({ enum: ['private', 'public'] }).notNull().default('private'),
|
||||||
thumbnail: blob(),
|
thumbnail: blob(),
|
||||||
|
|
@ -83,17 +83,6 @@ export const characterAbilitiesTable = table("character_abilities", {
|
||||||
max: int().notNull().default(0),
|
max: int().notNull().default(0),
|
||||||
}, (table) => [primaryKey({ columns: [table.character, table.ability] })]);
|
}, (table) => [primaryKey({ columns: [table.character, table.ability] })]);
|
||||||
|
|
||||||
export const characterModifiersTable = table("character_modifiers", {
|
|
||||||
character: int().notNull().references(() => characterTable.id, { onDelete: 'cascade', onUpdate: 'cascade' }),
|
|
||||||
modifier: text({ enum: ["strength","dexterity","constitution","intelligence","curiosity","charisma","psyche"] }).notNull(),
|
|
||||||
value: int().notNull().default(0),
|
|
||||||
}, (table) => [primaryKey({ columns: [table.character, table.modifier] })]);
|
|
||||||
|
|
||||||
export const characterSpellsTable = table("character_spell", {
|
|
||||||
character: int().notNull().references(() => characterTable.id, { onDelete: 'cascade', onUpdate: 'cascade' }),
|
|
||||||
value: text().notNull(),
|
|
||||||
}, (table) => [primaryKey({ columns: [table.character, table.value] })]);
|
|
||||||
|
|
||||||
export const characterChoicesTable = table("character_choices", {
|
export const characterChoicesTable = table("character_choices", {
|
||||||
character: int().notNull().references(() => characterTable.id, { onDelete: 'cascade', onUpdate: 'cascade' }),
|
character: int().notNull().references(() => characterTable.id, { onDelete: 'cascade', onUpdate: 'cascade' }),
|
||||||
id: text().notNull(),
|
id: text().notNull(),
|
||||||
|
|
@ -123,8 +112,6 @@ export const characterRelation = relations(characterTable, ({ one, many }) => ({
|
||||||
training: many(characterTrainingTable),
|
training: many(characterTrainingTable),
|
||||||
levels: many(characterLevelingTable),
|
levels: many(characterLevelingTable),
|
||||||
abilities: many(characterAbilitiesTable),
|
abilities: many(characterAbilitiesTable),
|
||||||
modifiers: many(characterModifiersTable),
|
|
||||||
spells: many(characterSpellsTable),
|
|
||||||
choices: many(characterChoicesTable)
|
choices: many(characterChoicesTable)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -137,12 +124,6 @@ export const characterLevelingRelation = relations(characterLevelingTable, ({ on
|
||||||
export const characterAbilitiesRelation = relations(characterAbilitiesTable, ({ one }) => ({
|
export const characterAbilitiesRelation = relations(characterAbilitiesTable, ({ one }) => ({
|
||||||
character: one(characterTable, { fields: [characterAbilitiesTable.character], references: [characterTable.id] })
|
character: one(characterTable, { fields: [characterAbilitiesTable.character], references: [characterTable.id] })
|
||||||
}));
|
}));
|
||||||
export const characterModifierRelation = relations(characterModifiersTable, ({ one }) => ({
|
|
||||||
character: one(characterTable, { fields: [characterModifiersTable.character], references: [characterTable.id] })
|
|
||||||
}));
|
|
||||||
export const characterSpellsRelation = relations(characterSpellsTable, ({ one }) => ({
|
|
||||||
character: one(characterTable, { fields: [characterSpellsTable.character], references: [characterTable.id] })
|
|
||||||
}));
|
|
||||||
export const characterChoicesRelation = relations(characterChoicesTable, ({ one }) => ({
|
export const characterChoicesRelation = relations(characterChoicesTable, ({ one }) => ({
|
||||||
character: one(characterTable, { fields: [characterChoicesTable.character], references: [characterTable.id] })
|
character: one(characterTable, { fields: [characterChoicesTable.character], references: [characterTable.id] })
|
||||||
}));
|
}));
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
DROP TABLE `character_modifiers`;--> statement-breakpoint
|
||||||
|
DROP TABLE `character_spell`;--> statement-breakpoint
|
||||||
|
ALTER TABLE `character` ADD `variables` text DEFAULT '{"health": 0,"mana": 0,"spells": [],"equipment": [],"exhaustion": 0,"sickness": []}' NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE `character` DROP COLUMN `health`;--> statement-breakpoint
|
||||||
|
ALTER TABLE `character` DROP COLUMN `mana`;
|
||||||
|
|
@ -0,0 +1,702 @@
|
||||||
|
{
|
||||||
|
"version": "6",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"id": "05b549e7-5b3f-40f4-9461-05db59391e20",
|
||||||
|
"prevId": "6651137c-a198-4538-86be-7cb8b88ca998",
|
||||||
|
"tables": {
|
||||||
|
"character_abilities": {
|
||||||
|
"name": "character_abilities",
|
||||||
|
"columns": {
|
||||||
|
"character": {
|
||||||
|
"name": "character",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"ability": {
|
||||||
|
"name": "ability",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"name": "value",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"max": {
|
||||||
|
"name": "max",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"character_abilities_character_character_id_fk": {
|
||||||
|
"name": "character_abilities_character_character_id_fk",
|
||||||
|
"tableFrom": "character_abilities",
|
||||||
|
"tableTo": "character",
|
||||||
|
"columnsFrom": [
|
||||||
|
"character"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"character_abilities_character_ability_pk": {
|
||||||
|
"columns": [
|
||||||
|
"character",
|
||||||
|
"ability"
|
||||||
|
],
|
||||||
|
"name": "character_abilities_character_ability_pk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"character_choices": {
|
||||||
|
"name": "character_choices",
|
||||||
|
"columns": {
|
||||||
|
"character": {
|
||||||
|
"name": "character",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"choice": {
|
||||||
|
"name": "choice",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"character_choices_character_character_id_fk": {
|
||||||
|
"name": "character_choices_character_character_id_fk",
|
||||||
|
"tableFrom": "character_choices",
|
||||||
|
"tableTo": "character",
|
||||||
|
"columnsFrom": [
|
||||||
|
"character"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"character_choices_character_id_choice_pk": {
|
||||||
|
"columns": [
|
||||||
|
"character",
|
||||||
|
"id",
|
||||||
|
"choice"
|
||||||
|
],
|
||||||
|
"name": "character_choices_character_id_choice_pk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"character_leveling": {
|
||||||
|
"name": "character_leveling",
|
||||||
|
"columns": {
|
||||||
|
"character": {
|
||||||
|
"name": "character",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"level": {
|
||||||
|
"name": "level",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"choice": {
|
||||||
|
"name": "choice",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"character_leveling_character_character_id_fk": {
|
||||||
|
"name": "character_leveling_character_character_id_fk",
|
||||||
|
"tableFrom": "character_leveling",
|
||||||
|
"tableTo": "character",
|
||||||
|
"columnsFrom": [
|
||||||
|
"character"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"character_leveling_character_level_pk": {
|
||||||
|
"columns": [
|
||||||
|
"character",
|
||||||
|
"level"
|
||||||
|
],
|
||||||
|
"name": "character_leveling_character_level_pk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"character": {
|
||||||
|
"name": "character",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"name": "owner",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"people": {
|
||||||
|
"name": "people",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"level": {
|
||||||
|
"name": "level",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": 1
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"name": "variables",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'{}'"
|
||||||
|
},
|
||||||
|
"aspect": {
|
||||||
|
"name": "aspect",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"name": "notes",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"visibility": {
|
||||||
|
"name": "visibility",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'private'"
|
||||||
|
},
|
||||||
|
"thumbnail": {
|
||||||
|
"name": "thumbnail",
|
||||||
|
"type": "blob",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"character_owner_users_id_fk": {
|
||||||
|
"name": "character_owner_users_id_fk",
|
||||||
|
"tableFrom": "character",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"character_training": {
|
||||||
|
"name": "character_training",
|
||||||
|
"columns": {
|
||||||
|
"character": {
|
||||||
|
"name": "character",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"stat": {
|
||||||
|
"name": "stat",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"level": {
|
||||||
|
"name": "level",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"choice": {
|
||||||
|
"name": "choice",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"character_training_character_character_id_fk": {
|
||||||
|
"name": "character_training_character_character_id_fk",
|
||||||
|
"tableFrom": "character_training",
|
||||||
|
"tableTo": "character",
|
||||||
|
"columnsFrom": [
|
||||||
|
"character"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"character_training_character_stat_level_pk": {
|
||||||
|
"columns": [
|
||||||
|
"character",
|
||||||
|
"stat",
|
||||||
|
"level"
|
||||||
|
],
|
||||||
|
"name": "character_training_character_stat_level_pk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"email_validation": {
|
||||||
|
"name": "email_validation",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"name": "timestamp",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"project_content": {
|
||||||
|
"name": "project_content",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"name": "content",
|
||||||
|
"type": "blob",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"project_files": {
|
||||||
|
"name": "project_files",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"name": "path",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"name": "owner",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"name": "title",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"name": "type",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"navigable": {
|
||||||
|
"name": "navigable",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"private": {
|
||||||
|
"name": "private",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"order": {
|
||||||
|
"name": "order",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"name": "timestamp",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"project_files_path_unique": {
|
||||||
|
"name": "project_files_path_unique",
|
||||||
|
"columns": [
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {
|
||||||
|
"project_files_owner_users_id_fk": {
|
||||||
|
"name": "project_files_owner_users_id_fk",
|
||||||
|
"tableFrom": "project_files",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"user_permissions": {
|
||||||
|
"name": "user_permissions",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"permission": {
|
||||||
|
"name": "permission",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"user_permissions_id_users_id_fk": {
|
||||||
|
"name": "user_permissions_id_users_id_fk",
|
||||||
|
"tableFrom": "user_permissions",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"user_permissions_id_permission_pk": {
|
||||||
|
"columns": [
|
||||||
|
"id",
|
||||||
|
"permission"
|
||||||
|
],
|
||||||
|
"name": "user_permissions_id_permission_pk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"user_sessions": {
|
||||||
|
"name": "user_sessions",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"name": "timestamp",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"user_sessions_user_id_users_id_fk": {
|
||||||
|
"name": "user_sessions_user_id_users_id_fk",
|
||||||
|
"tableFrom": "user_sessions",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"user_sessions_id_user_id_pk": {
|
||||||
|
"columns": [
|
||||||
|
"id",
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"name": "user_sessions_id_user_id_pk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"users_data": {
|
||||||
|
"name": "users_data",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"signin": {
|
||||||
|
"name": "signin",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"lastTimestamp": {
|
||||||
|
"name": "lastTimestamp",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"users_data_id_users_id_fk": {
|
||||||
|
"name": "users_data_id_users_id_fk",
|
||||||
|
"tableFrom": "users_data",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "cascade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"name": "users",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"name": "username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"hash": {
|
||||||
|
"name": "hash",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"name": "state",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"users_username_unique": {
|
||||||
|
"name": "users_username_unique",
|
||||||
|
"columns": [
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
},
|
||||||
|
"users_email_unique": {
|
||||||
|
"name": "users_email_unique",
|
||||||
|
"columns": [
|
||||||
|
"email"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
},
|
||||||
|
"users_hash_unique": {
|
||||||
|
"name": "users_hash_unique",
|
||||||
|
"columns": [
|
||||||
|
"hash"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"views": {},
|
||||||
|
"enums": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
},
|
||||||
|
"internal": {
|
||||||
|
"indexes": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -113,6 +113,13 @@
|
||||||
"when": 1756214160038,
|
"when": 1756214160038,
|
||||||
"tag": "0015_typical_blade",
|
"tag": "0015_typical_blade",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 16,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1756221197092,
|
||||||
|
"tag": "0016_wild_the_anarchist",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -13,7 +13,6 @@ const config = characterConfig as CharacterConfig;
|
||||||
|
|
||||||
const id = useRouter().currentRoute.value.params.id;
|
const id = useRouter().currentRoute.value.params.id;
|
||||||
const { user } = useUserSession();
|
const { user } = useUserSession();
|
||||||
const { add } = useToast();
|
|
||||||
|
|
||||||
const { data, status, error } = await useFetch(`/api/character/${id}`);
|
const { data, status, error } = await useFetch(`/api/character/${id}`);
|
||||||
const compiler = new CharacterCompiler(data.value ?? defaultCharacter);
|
const compiler = new CharacterCompiler(data.value ?? defaultCharacter);
|
||||||
|
|
@ -52,7 +51,7 @@ text-light-purple dark:text-dark-purple border-light-purple dark:border-dark-pur
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="font-bold">Niveau {{ character.level }}</span>
|
<span class="font-bold">Niveau {{ character.level }}</span>
|
||||||
<span>{{ character.race === -1 ? "Race inconnue" : config.peoples[character.race]!.name }}</span>
|
<span>{{ config.peoples[character.race]?.name ?? 'Peuple inconnu' }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col lg:border-l border-light-30 dark:border-dark-30 py-4 ps-4">
|
<div class="flex flex-col lg:border-l border-light-30 dark:border-dark-30 py-4 ps-4">
|
||||||
|
|
@ -132,7 +131,7 @@ text-light-purple dark:text-dark-purple border-light-purple dark:border-dark-pur
|
||||||
<TabsTrigger value="notes" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Notes</TabsTrigger>
|
<TabsTrigger value="notes" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Notes</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
<TabsContent value="features">
|
<TabsContent value="features">
|
||||||
<div class="flex flex-1 flex-col ps-8 gap-4 py-8">
|
<div class="flex flex-1 flex-col ps-8 gap-4 py-4">
|
||||||
<div class="grid grid-cols-3 gap-4">
|
<div class="grid grid-cols-3 gap-4">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="text-lg font-semibold">Actions</span>
|
<span class="text-lg font-semibold">Actions</span>
|
||||||
|
|
@ -157,9 +156,10 @@ text-light-purple dark:text-dark-purple border-light-purple dark:border-dark-pur
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent v-if="character.spellslots > 0" value="spells">
|
<TabsContent v-if="character.spellslots > 0" value="spells">
|
||||||
<div class="flex flex-1 flex-col ps-8 gap-4 py-8">
|
<div class="flex flex-1 flex-col ps-8 gap-4 py-2">
|
||||||
<div class="flex flex-col" v-if="character.lists.spells && character.lists.spells.length > 0">
|
<div class="flex flex-1 justify-between items-center"><span class="italic text-light-70 dark:text-dark-70 text-sm">{{ character.variables.spells.length }} / {{ character.spellslots }} sorts maitrisés</span><Button icon><Icon icon="radix-icons:plus" class="w-6 h-6"/></Button></div>
|
||||||
<div class="pb-4 px-2 mt-4 border-b last:border-none border-light-30 dark:border-dark-30 flex flex-col" v-for="spell of character.lists.spells.map(e => config.spells.find((f: SpellConfig) => f.id === e)).filter(e => !!e)">
|
<div class="flex flex-col" v-if="[...(character.lists.spells ?? []), ...character.variables.spells].length > 0">
|
||||||
|
<div class="pb-4 px-2 mt-4 border-b last:border-none border-light-30 dark:border-dark-30 flex flex-col" v-for="spell of [...(character.lists.spells ?? []), ...character.variables.spells].map(e => config.spells.find((f: SpellConfig) => f.id === e)).filter(e => !!e)">
|
||||||
<div class="flex flex-row justify-between">
|
<div class="flex flex-row justify-between">
|
||||||
<span class="text-lg font-bold">{{ spell.name }}</span>
|
<span class="text-lg font-bold">{{ spell.name }}</span>
|
||||||
<div class="flex flex-row items-center gap-6">
|
<div class="flex flex-row items-center gap-6">
|
||||||
|
|
@ -170,7 +170,7 @@ text-light-purple dark:text-dark-purple border-light-purple dark:border-dark-pur
|
||||||
<span class="">Rang {{ spell.rank }}</span><span>/</span>
|
<span class="">Rang {{ spell.rank }}</span><span>/</span>
|
||||||
<span class="">{{ spellTypeTexts[spell.type] }}</span><span>/</span>
|
<span class="">{{ spellTypeTexts[spell.type] }}</span><span>/</span>
|
||||||
<span class="">{{ spell.cost }} mana</span><span>/</span>
|
<span class="">{{ spell.cost }} mana</span><span>/</span>
|
||||||
<span class="">{{ typeof spell.speed === 'string' ? spell.speed : `${spell.speed} minutes` }}</span>
|
<span class="capitalize">{{ typeof spell.speed === 'string' ? spell.speed : `${spell.speed} minutes` }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import useDatabase from '~/composables/useDatabase';
|
||||||
import { characterTable, userPermissionsTable } from '~/db/schema';
|
import { characterTable, userPermissionsTable } from '~/db/schema';
|
||||||
import { hasPermissions } from '~/shared/auth.util';
|
import { hasPermissions } from '~/shared/auth.util';
|
||||||
import { group } from '~/shared/general.util';
|
import { group } from '~/shared/general.util';
|
||||||
import type { Character, DoubleIndex, Level, MainStat, TrainingLevel } from '~/types/character';
|
import type { Character, Level, MainStat, TrainingLevel } from '~/types/character';
|
||||||
|
|
||||||
export default defineEventHandler(async (e) => {
|
export default defineEventHandler(async (e) => {
|
||||||
let { visibility } = getQuery(e) as { visibility?: "public" | "own" | "admin" };
|
let { visibility } = getQuery(e) as { visibility?: "public" | "own" | "admin" };
|
||||||
|
|
@ -55,8 +55,6 @@ export default defineEventHandler(async (e) => {
|
||||||
with: {
|
with: {
|
||||||
abilities: true,
|
abilities: true,
|
||||||
levels: true,
|
levels: true,
|
||||||
modifiers: true,
|
|
||||||
spells: true,
|
|
||||||
training: true,
|
training: true,
|
||||||
choices: true,
|
choices: true,
|
||||||
user: {
|
user: {
|
||||||
|
|
@ -76,14 +74,11 @@ export default defineEventHandler(async (e) => {
|
||||||
level: character.level,
|
level: character.level,
|
||||||
aspect: character.aspect,
|
aspect: character.aspect,
|
||||||
notes: character.notes,
|
notes: character.notes,
|
||||||
health: character.health,
|
variables: character.variables,
|
||||||
mana: character.mana,
|
|
||||||
|
|
||||||
training: character.training.reduce((p, v) => { if(!(v.stat in p)) p[v.stat] = []; p[v.stat].push([v.level as TrainingLevel, v.choice]); return p; }, {} as Record<MainStat, DoubleIndex<TrainingLevel>[]>),
|
training: character.training.reduce((p, v) => { p[v.stat] ??= {}; p[v.stat][v.level as TrainingLevel] = v.choice; return p; }, {} as Record<MainStat, Partial<Record<TrainingLevel, number>>>),
|
||||||
leveling: character.levels.map(e => [e.level as Level, e.choice] as DoubleIndex<Level>),
|
leveling: group(character.levels, "level", "choice"),
|
||||||
abilities: group(character.abilities, "ability", "value"),
|
abilities: group(character.abilities, "ability", "value"),
|
||||||
spells: character.spells.map(e => e.value),
|
|
||||||
modifiers: group(character.modifiers, "modifier", "value"),
|
|
||||||
choices: character.choices.reduce((p, v) => { p[v.id] ??= []; p[v.id]?.push(v.choice); return p; }, {} as Record<string, number[]>),
|
choices: character.choices.reduce((p, v) => { p[v.id] ??= []; p[v.id]?.push(v.choice); return p; }, {} as Record<string, number[]>),
|
||||||
|
|
||||||
owner: character.owner,
|
owner: character.owner,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { z } from 'zod/v4';
|
import { z } from 'zod/v4';
|
||||||
import useDatabase from '~/composables/useDatabase';
|
import useDatabase from '~/composables/useDatabase';
|
||||||
import { characterAbilitiesTable, characterLevelingTable, characterModifiersTable, characterSpellsTable, characterTable, characterTrainingTable } from '~/db/schema';
|
import { characterAbilitiesTable, characterLevelingTable, characterTable, characterTrainingTable } from '~/db/schema';
|
||||||
import { CharacterValidation } from '#shared/character.util';
|
import { CharacterValidation } from '#shared/character.util';
|
||||||
import { type Ability, type MainStat } from '~/types/character';
|
import { type Ability, type MainStat } from '~/types/character';
|
||||||
|
|
||||||
|
|
@ -32,8 +32,7 @@ export default defineEventHandler(async (e) => {
|
||||||
level: body.data.level,
|
level: body.data.level,
|
||||||
aspect: body.data.aspect,
|
aspect: body.data.aspect,
|
||||||
notes: body.data.notes,
|
notes: body.data.notes,
|
||||||
health: body.data.health,
|
variables: body.data.variables,
|
||||||
mana: body.data.mana,
|
|
||||||
visibility: body.data.visibility,
|
visibility: body.data.visibility,
|
||||||
thumbnail: body.data.thumbnail,
|
thumbnail: body.data.thumbnail,
|
||||||
}).returning({ id: characterTable.id }).get().id;
|
}).returning({ id: characterTable.id }).get().id;
|
||||||
|
|
@ -43,8 +42,6 @@ export default defineEventHandler(async (e) => {
|
||||||
const training = Object.entries(body.data.training).flatMap(e => Object.entries(e[1]).map(_e => ({ character: id, stat: e[0] as MainStat, level: parseInt(_e[0], 10), choice: _e[1]! })));
|
const training = Object.entries(body.data.training).flatMap(e => Object.entries(e[1]).map(_e => ({ character: id, stat: e[0] as MainStat, level: parseInt(_e[0], 10), choice: _e[1]! })));
|
||||||
if(training.length > 0) tx.insert(characterTrainingTable).values(training).run();
|
if(training.length > 0) tx.insert(characterTrainingTable).values(training).run();
|
||||||
|
|
||||||
if(body.data.spells.length > 0) tx.insert(characterSpellsTable).values(body.data.spells.map(e => ({ character: id, value: e }))).run();
|
|
||||||
|
|
||||||
const abilities = Object.entries(body.data.abilities).map(e => ({ character: id, ability: e[0] as Ability, value: e[1] }));
|
const abilities = Object.entries(body.data.abilities).map(e => ({ character: id, ability: e[0] as Ability, value: e[1] }));
|
||||||
if(abilities.length > 0) tx.insert(characterAbilitiesTable).values(abilities).run();
|
if(abilities.length > 0) tx.insert(characterAbilitiesTable).values(abilities).run();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { and, eq, sql } from 'drizzle-orm';
|
|
||||||
import useDatabase from '~/composables/useDatabase';
|
import useDatabase from '~/composables/useDatabase';
|
||||||
import { characterTable } from '~/db/schema';
|
import { characterTable } from '~/db/schema';
|
||||||
import { group } from '~/shared/general.util';
|
import { group } from '~/shared/general.util';
|
||||||
import type { Character, DoubleIndex, Level, MainStat, TrainingLevel } from '~/types/character';
|
import type { Character, CharacterVariables, Level, MainStat, TrainingLevel } from '~/types/character';
|
||||||
|
|
||||||
export default defineEventHandler(async (e) => {
|
export default defineEventHandler(async (e) => {
|
||||||
const id = getRouterParam(e, "id");
|
const id = getRouterParam(e, "id");
|
||||||
|
|
@ -26,9 +25,8 @@ export default defineEventHandler(async (e) => {
|
||||||
with: {
|
with: {
|
||||||
abilities: true,
|
abilities: true,
|
||||||
levels: true,
|
levels: true,
|
||||||
modifiers: true,
|
|
||||||
spells: true,
|
|
||||||
training: true,
|
training: true,
|
||||||
|
choices: true,
|
||||||
user: {
|
user: {
|
||||||
columns: { username: true }
|
columns: { username: true }
|
||||||
}
|
}
|
||||||
|
|
@ -46,15 +44,12 @@ export default defineEventHandler(async (e) => {
|
||||||
level: character.level,
|
level: character.level,
|
||||||
aspect: character.aspect,
|
aspect: character.aspect,
|
||||||
notes: character.notes,
|
notes: character.notes,
|
||||||
health: character.health,
|
variables: character.variables,
|
||||||
mana: character.mana,
|
|
||||||
|
|
||||||
training: character.training.reduce((p, v) => { p[v.stat] ??= {}; p[v.stat][v.level as TrainingLevel] = v.choice; return p; }, {} as Record<MainStat, Partial<Record<TrainingLevel, number>>>),
|
training: character.training.reduce((p, v) => { p[v.stat] ??= {}; p[v.stat][v.level as TrainingLevel] = v.choice; return p; }, {} as Record<MainStat, Partial<Record<TrainingLevel, number>>>),
|
||||||
leveling: character.levels.reduce((p, v) => { p[v.level as Level] = v.choice; return p; }, {} as Partial<Record<Level, number>>),
|
leveling: group(character.levels, "level", "choice"),
|
||||||
abilities: group(character.abilities.map(e => ({ ...e, value: e.value })), "ability", "value"),
|
abilities: group(character.abilities, "ability", "value"),
|
||||||
spells: character.spells.map(e => e.value),
|
choices: character.choices.reduce((p, v) => { p[v.id] ??= []; p[v.id]?.push(v.choice); return p; }, {} as Record<string, number[]>),
|
||||||
modifiers: group(character.modifiers, "modifier", "value"),
|
|
||||||
choices: {},
|
|
||||||
|
|
||||||
owner: character.owner,
|
owner: character.owner,
|
||||||
username: character.user.username,
|
username: character.user.username,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { eq } from 'drizzle-orm';
|
import { eq } from 'drizzle-orm';
|
||||||
import useDatabase from '~/composables/useDatabase';
|
import useDatabase from '~/composables/useDatabase';
|
||||||
import { characterAbilitiesTable, characterChoicesTable, characterLevelingTable, characterModifiersTable, characterSpellsTable, characterTable, characterTrainingTable } from '~/db/schema';
|
import { characterAbilitiesTable, characterChoicesTable, characterLevelingTable, characterTable, characterTrainingTable } from '~/db/schema';
|
||||||
import { CharacterValidation } from '#shared/character.util';
|
import { CharacterValidation } from '#shared/character.util';
|
||||||
import { type Ability, type MainStat } from '~/types/character';
|
import { type Ability, type MainStat } from '~/types/character';
|
||||||
|
|
||||||
|
|
@ -43,16 +43,13 @@ export default defineEventHandler(async (e) => {
|
||||||
level: body.data.level,
|
level: body.data.level,
|
||||||
aspect: body.data.aspect,
|
aspect: body.data.aspect,
|
||||||
notes: body.data.notes,
|
notes: body.data.notes,
|
||||||
health: body.data.health,
|
variables: body.data.variables,
|
||||||
mana: body.data.mana,
|
|
||||||
visibility: body.data.visibility,
|
visibility: body.data.visibility,
|
||||||
thumbnail: body.data.thumbnail,
|
thumbnail: body.data.thumbnail,
|
||||||
}).where(eq(characterTable.id, id)).run();
|
}).where(eq(characterTable.id, id)).run();
|
||||||
|
|
||||||
tx.delete(characterLevelingTable).where(eq(characterLevelingTable.character, id)).run();
|
tx.delete(characterLevelingTable).where(eq(characterLevelingTable.character, id)).run();
|
||||||
tx.delete(characterTrainingTable).where(eq(characterTrainingTable.character, id)).run();
|
tx.delete(characterTrainingTable).where(eq(characterTrainingTable.character, id)).run();
|
||||||
tx.delete(characterModifiersTable).where(eq(characterModifiersTable.character, id)).run();
|
|
||||||
tx.delete(characterSpellsTable).where(eq(characterSpellsTable.character, id)).run();
|
|
||||||
tx.delete(characterAbilitiesTable).where(eq(characterAbilitiesTable.character, id)).run();
|
tx.delete(characterAbilitiesTable).where(eq(characterAbilitiesTable.character, id)).run();
|
||||||
tx.delete(characterChoicesTable).where(eq(characterChoicesTable.character, id)).run();
|
tx.delete(characterChoicesTable).where(eq(characterChoicesTable.character, id)).run();
|
||||||
|
|
||||||
|
|
@ -62,11 +59,6 @@ export default defineEventHandler(async (e) => {
|
||||||
const training = Object.entries(body.data.training).flatMap(e => Object.entries(e[1]).filter(_e => _e[1] !== undefined).map(_e => ({ character: id, stat: e[0] as MainStat, level: parseInt(_e[0]), choice: _e[1]! })));
|
const training = Object.entries(body.data.training).flatMap(e => Object.entries(e[1]).filter(_e => _e[1] !== undefined).map(_e => ({ character: id, stat: e[0] as MainStat, level: parseInt(_e[0]), choice: _e[1]! })));
|
||||||
if(training.length > 0) tx.insert(characterTrainingTable).values(training).run();
|
if(training.length > 0) tx.insert(characterTrainingTable).values(training).run();
|
||||||
|
|
||||||
const modifiers = Object.entries(body.data.modifiers).filter(e => e[1] !== undefined).map((e) => ({ character: id, modifier: e[0] as MainStat, value: e[1] }));
|
|
||||||
if(modifiers.length > 0) tx.insert(characterModifiersTable).values(modifiers).run();
|
|
||||||
|
|
||||||
if(body.data.spells.length > 0) tx.insert(characterSpellsTable).values(body.data.spells.map(e => ({ character: id, value: e }))).run();
|
|
||||||
|
|
||||||
const abilities = Object.entries(body.data.abilities).filter(e => e[1] !== undefined).map(e => ({ character: id, ability: e[0] as Ability, value: e[1], max: 0 }));
|
const abilities = Object.entries(body.data.abilities).filter(e => e[1] !== undefined).map(e => ({ character: id, ability: e[0] as Ability, value: e[1], max: 0 }));
|
||||||
if(abilities.length > 0) tx.insert(characterAbilitiesTable).values(abilities).run();
|
if(abilities.length > 0) tx.insert(characterAbilitiesTable).values(abilities).run();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { eq } from 'drizzle-orm';
|
import { eq } from 'drizzle-orm';
|
||||||
import useDatabase from '~/composables/useDatabase';
|
import useDatabase from '~/composables/useDatabase';
|
||||||
import { characterAbilitiesTable, characterLevelingTable, characterModifiersTable, characterSpellsTable, characterTable, characterTrainingTable } from '~/db/schema';
|
import { characterAbilitiesTable, characterLevelingTable, characterTable, characterTrainingTable } from '~/db/schema';
|
||||||
|
|
||||||
export default defineEventHandler(async (e) => {
|
export default defineEventHandler(async (e) => {
|
||||||
const id = getRouterParam(e, "id");
|
const id = getRouterParam(e, "id");
|
||||||
|
|
@ -36,8 +36,7 @@ export default defineEventHandler(async (e) => {
|
||||||
level: old.level,
|
level: old.level,
|
||||||
aspect: old.aspect,
|
aspect: old.aspect,
|
||||||
notes: old.notes,
|
notes: old.notes,
|
||||||
health: old.health,
|
variables: old.variables,
|
||||||
mana: old.mana,
|
|
||||||
visibility: old.visibility,
|
visibility: old.visibility,
|
||||||
thumbnail: old.thumbnail,
|
thumbnail: old.thumbnail,
|
||||||
}).returning({ id: characterTable.id }).get().id;
|
}).returning({ id: characterTable.id }).get().id;
|
||||||
|
|
@ -48,12 +47,6 @@ export default defineEventHandler(async (e) => {
|
||||||
const training = tx.select().from(characterTrainingTable).where(eq(characterTrainingTable.character, parseInt(id, 10))).all();
|
const training = tx.select().from(characterTrainingTable).where(eq(characterTrainingTable.character, parseInt(id, 10))).all();
|
||||||
if(training.length > 0) tx.insert(characterTrainingTable).values(training.map(e => ({ character: _id, stat: e.stat, level: e.level, choice: e.choice }))).run();
|
if(training.length > 0) tx.insert(characterTrainingTable).values(training.map(e => ({ character: _id, stat: e.stat, level: e.level, choice: e.choice }))).run();
|
||||||
|
|
||||||
const modifiers = tx.select().from(characterModifiersTable).where(eq(characterModifiersTable.character, parseInt(id, 10))).all();
|
|
||||||
if(modifiers.length > 0) tx.insert(characterModifiersTable).values(modifiers.map(e => ({ character: _id, modifier: e.modifier, value: e.value }))).run();
|
|
||||||
|
|
||||||
const spells = tx.select().from(characterSpellsTable).where(eq(characterSpellsTable.character, parseInt(id, 10))).all();
|
|
||||||
if(spells.length > 0) tx.insert(characterSpellsTable).values(spells.map(e => ({ character: _id, value: e.value }))).run();
|
|
||||||
|
|
||||||
const abilities = tx.select().from(characterAbilitiesTable).where(eq(characterAbilitiesTable.character, parseInt(id, 10))).all();
|
const abilities = tx.select().from(characterAbilitiesTable).where(eq(characterAbilitiesTable.character, parseInt(id, 10))).all();
|
||||||
if(abilities.length > 0) tx.insert(characterAbilitiesTable).values(abilities.map(e => ({ character: _id, ability: e.ability, value: e.value, max: e.max }))).run();
|
if(abilities.length > 0) tx.insert(characterAbilitiesTable).values(abilities.map(e => ({ character: _id, ability: e.ability, value: e.value, max: e.max }))).run();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { and, eq, sql } from 'drizzle-orm';
|
import { and, eq, sql } from 'drizzle-orm';
|
||||||
import useDatabase from '~/composables/useDatabase';
|
import useDatabase from '~/composables/useDatabase';
|
||||||
import { characterTable } from '~/db/schema';
|
import { characterTable } from '~/db/schema';
|
||||||
import type { Character, CharacterValues } from '~/types/character';
|
import type { CharacterVariables } from '~/types/character';
|
||||||
|
|
||||||
export default defineEventHandler(async (e) => {
|
export default defineEventHandler(async (e) => {
|
||||||
const id = getRouterParam(e, "id");
|
const id = getRouterParam(e, "id");
|
||||||
|
|
@ -27,7 +27,7 @@ export default defineEventHandler(async (e) => {
|
||||||
|
|
||||||
if(character !== undefined)
|
if(character !== undefined)
|
||||||
{
|
{
|
||||||
return character as CharacterValues;
|
return character as CharacterVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
setResponseStatus(e, 404);
|
setResponseStatus(e, 404);
|
||||||
|
|
|
||||||
|
|
@ -2675,6 +2675,89 @@
|
||||||
"damage"
|
"damage"
|
||||||
],
|
],
|
||||||
"effect": "Place une anomalie visuelle à 3 cases émettant une [[6. Visibilité et lumière#Lumière intense|lumière vive]] à 9 cases. Lorsqu'un être vivant rentre en contact avec l'anomalie, il absorbe toute l'énergie magique et subit 4d8 points de dégâts magique"
|
"effect": "Place une anomalie visuelle à 3 cases émettant une [[6. Visibilité et lumière#Lumière intense|lumière vive]] à 9 cases. Lorsqu'un être vivant rentre en contact avec l'anomalie, il absorbe toute l'énergie magique et subit 4d8 points de dégâts magique"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9jq3pkj7sgfgq6q4ovwoanig6ha8g2ic",
|
||||||
|
"name": "Dévastation élémentaire",
|
||||||
|
"rank": 1,
|
||||||
|
"type": "precision",
|
||||||
|
"cost": 8,
|
||||||
|
"speed": "action",
|
||||||
|
"elements": [
|
||||||
|
"fire",
|
||||||
|
"ice",
|
||||||
|
"thunder"
|
||||||
|
],
|
||||||
|
"effect": "Faites un jet d'attaque soit la [[1. Entrainement#Dextérité|dextérité]], soit l'[[1. Entrainement#L'intelligence|intelligence]], soit la [[1. Entrainement#La psyché|psyché]]. Inflige 10+3d10 dégâts. Si vous attaquez avec la dextérité, vous infligez des dégâts de feu. Si vous attaquez avec l'intelligence, vous infligez des dégâts de glace et si vous attaquez avec la psyché, vous faites des dégâts de foudre.",
|
||||||
|
"concentration": false,
|
||||||
|
"tags": [
|
||||||
|
"damage",
|
||||||
|
"debuff"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "zltvtru98sm0ad9whiw5tty0gy4q2jur",
|
||||||
|
"name": "Soin",
|
||||||
|
"rank": 4,
|
||||||
|
"type": "precision",
|
||||||
|
"cost": 8,
|
||||||
|
"speed": "action",
|
||||||
|
"elements": [
|
||||||
|
"nature"
|
||||||
|
],
|
||||||
|
"effect": "Soigne 10+1d10 PV et guérit l'[[2. Liste des effets#Hébètement|hébètement]], le [[2. Liste des effets#Le saignement|saignement]] et les [[2. Liste des effets#L'empoisonnement|poisons]]. En soignant un personnage agonisant, vous pouvez choisir à la place de le stabiliser et de le ramener à 0 PV.",
|
||||||
|
"concentration": false,
|
||||||
|
"tags": [
|
||||||
|
"support"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bgm3c8vd2xqcwpcul1cakab89p5bfu4t",
|
||||||
|
"name": "Contresort",
|
||||||
|
"rank": 4,
|
||||||
|
"type": "knowledge",
|
||||||
|
"cost": 4,
|
||||||
|
"speed": "reaction",
|
||||||
|
"elements": [
|
||||||
|
"arcana"
|
||||||
|
],
|
||||||
|
"effect": "Perturbe les flux magique pour interrompre une canalisation en cours que vous voyez à portée. Le lanceur de sort doit faire un jet d'attaque avec l'[[1. Entrainement#L'intelligence|intelligence]] maintenir sa canalisation. Vous pouvez augmenter le coût du sort pour augmenter les chances de réussite. La difficulté est égale à 6 - le cout du sort à interrompre + le cout du contresort.",
|
||||||
|
"concentration": false,
|
||||||
|
"tags": [
|
||||||
|
"debuff"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "kd84l3gujh4evsyriti4g9sk1zwbxu8d",
|
||||||
|
"name": "Focalisation destructrice",
|
||||||
|
"rank": 4,
|
||||||
|
"type": "knowledge",
|
||||||
|
"cost": 12,
|
||||||
|
"speed": "action",
|
||||||
|
"elements": [
|
||||||
|
"arcana"
|
||||||
|
],
|
||||||
|
"effect": "Vous focalisez les énergies magiques sur vous, rendant l'utilisation de sort plus complexe pour les autres durant 1 minute. La densité d'énergie anormale vous fait subir 5 points de dégâts par tour. Toute personne à 18 cases de vous subit un malus de -4 pour se [[1. Aspect#Transformations|transformer]], à ces jets d'attaques de sort et à ces difficulté de jet de résistance de sort.",
|
||||||
|
"concentration": true,
|
||||||
|
"tags": [
|
||||||
|
"debuff"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "wj2rxkbw85zd9st8k2w3eezqc1naoy5g",
|
||||||
|
"name": "Domination mentale",
|
||||||
|
"rank": 4,
|
||||||
|
"type": "instinct",
|
||||||
|
"cost": 8,
|
||||||
|
"speed": "action",
|
||||||
|
"elements": [
|
||||||
|
"psyche"
|
||||||
|
],
|
||||||
|
"effect": "La cible touchée doit réussir un [[3. Résistance aux chocs#Le jet de résistance|jet de résistance]] (d12/7 + mod. d'[[1. Entrainement#L'intelligence|intelligence]]) de [[1. Entrainement#La psyché|psyché]] ou est [[2. Liste des effets#Possédé|possédé]].",
|
||||||
|
"concentration": true,
|
||||||
|
"tags": [
|
||||||
|
"debuff"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aspects": [
|
"aspects": [
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,19 @@ export const defaultCharacter: Character = {
|
||||||
name: "",
|
name: "",
|
||||||
people: undefined,
|
people: undefined,
|
||||||
level: 1,
|
level: 1,
|
||||||
health: 0,
|
|
||||||
mana: 0,
|
|
||||||
|
|
||||||
training: MAIN_STATS.reduce((p, v) => { p[v] = { 0: 0 }; return p; }, {} as Record<MainStat, Partial<Record<TrainingLevel, number>>>),
|
training: MAIN_STATS.reduce((p, v) => { p[v] = { 0: 0 }; return p; }, {} as Record<MainStat, Partial<Record<TrainingLevel, number>>>),
|
||||||
leveling: { 1: 0 },
|
leveling: { 1: 0 },
|
||||||
abilities: {},
|
abilities: {},
|
||||||
spells: [],
|
|
||||||
modifiers: {},
|
|
||||||
choices: {},
|
choices: {},
|
||||||
|
variables: {
|
||||||
|
health: 0,
|
||||||
|
mana: 0,
|
||||||
|
spells: [],
|
||||||
|
equipment: [],
|
||||||
|
exhaustion: 0,
|
||||||
|
sickness: [],
|
||||||
|
},
|
||||||
|
|
||||||
owner: -1,
|
owner: -1,
|
||||||
visibility: "private",
|
visibility: "private",
|
||||||
|
|
@ -48,13 +52,7 @@ const defaultCompiledCharacter: (character: Character) => CompiledCharacter = (c
|
||||||
race: character.people!,
|
race: character.people!,
|
||||||
modifier: MAIN_STATS.reduce((p, v) => { p[v] = 0; return p; }, {} as Record<MainStat, number>),
|
modifier: MAIN_STATS.reduce((p, v) => { p[v] = 0; return p; }, {} as Record<MainStat, number>),
|
||||||
level: character.level,
|
level: character.level,
|
||||||
variables: {
|
variables: character.variables,
|
||||||
health: character.health,
|
|
||||||
mana: character.mana,
|
|
||||||
equipment: [],
|
|
||||||
exhaustion: 0,
|
|
||||||
sickness: [],
|
|
||||||
},
|
|
||||||
action: 0,
|
action: 0,
|
||||||
reaction: 0,
|
reaction: 0,
|
||||||
exhaust: 0,
|
exhaust: 0,
|
||||||
|
|
@ -121,7 +119,7 @@ const defaultCompiledCharacter: (character: Character) => CompiledCharacter = (c
|
||||||
freeaction: [],
|
freeaction: [],
|
||||||
reaction: [],
|
reaction: [],
|
||||||
passive: [],
|
passive: [],
|
||||||
spells: character.spells,
|
spells: character.variables.spells,
|
||||||
},
|
},
|
||||||
aspect: "",
|
aspect: "",
|
||||||
notes: character.notes ?? "",
|
notes: character.notes ?? "",
|
||||||
|
|
@ -174,17 +172,26 @@ export const spellTypeTexts: Record<SpellType, string> = { "instinct": "Instinct
|
||||||
export const CharacterValidation = z.object({
|
export const CharacterValidation = z.object({
|
||||||
id: z.number(),
|
id: z.number(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
people: z.number().nullable(),
|
people: z.string().nullable(),
|
||||||
level: z.number().min(1).max(20),
|
level: z.number().min(1).max(20),
|
||||||
aspect: z.number().nullable().optional(),
|
aspect: z.number().nullable().optional(),
|
||||||
notes: z.string().nullable().optional(),
|
notes: z.string().nullable().optional(),
|
||||||
health: z.number().default(0),
|
|
||||||
mana: z.number().default(0),
|
|
||||||
training: z.record(z.enum(MAIN_STATS), z.record(z.enum(TRAINING_LEVELS.map(String)), z.number())),
|
training: z.record(z.enum(MAIN_STATS), z.record(z.enum(TRAINING_LEVELS.map(String)), z.number())),
|
||||||
leveling: z.record(z.enum(LEVELS.map(String)), z.number()),
|
leveling: z.record(z.enum(LEVELS.map(String)), z.number()),
|
||||||
abilities: z.record(z.enum(ABILITIES), z.number()),
|
abilities: z.record(z.enum(ABILITIES), z.number()),
|
||||||
spells: z.string().array(),
|
|
||||||
choices: z.record(z.string(), z.array(z.number())),
|
choices: z.record(z.string(), z.array(z.number())),
|
||||||
|
variables: z.object({
|
||||||
|
health: z.number(),
|
||||||
|
mana: z.number(),
|
||||||
|
exhaustion: z.number(),
|
||||||
|
|
||||||
|
sickness: z.array(z.object({
|
||||||
|
id: z.string(),
|
||||||
|
state: z.number().min(1).max(7).or(z.literal(true)),
|
||||||
|
})),
|
||||||
|
spells: z.array(z.string()),
|
||||||
|
equipment: z.array(z.string()),
|
||||||
|
}),
|
||||||
owner: z.number(),
|
owner: z.number(),
|
||||||
username: z.string().optional(),
|
username: z.string().optional(),
|
||||||
visibility: z.enum(["public", "private"]),
|
visibility: z.enum(["public", "private"]),
|
||||||
|
|
@ -332,15 +339,17 @@ export class CharacterCompiler
|
||||||
protected compile(properties: string[])
|
protected compile(properties: string[])
|
||||||
{
|
{
|
||||||
const queue = properties;
|
const queue = properties;
|
||||||
queue.forEach(property => {
|
for(let i = 0; i < queue.length; i++)
|
||||||
|
{
|
||||||
|
const property = queue[i]!;
|
||||||
const buffer = this._buffer[property];
|
const buffer = this._buffer[property];
|
||||||
|
|
||||||
if(property === "")
|
if(property === "")
|
||||||
return
|
continue
|
||||||
|
|
||||||
if(buffer && buffer._dirty === true)
|
if(buffer && buffer._dirty === true)
|
||||||
{
|
{
|
||||||
let sum = 0;
|
let sum = 0, shortcut = false;
|
||||||
for(let i = 0; i < buffer.list.length; i++)
|
for(let i = 0; i < buffer.list.length; i++)
|
||||||
{
|
{
|
||||||
if(typeof buffer.list[i]!.value === 'string') // Add or set a modifier
|
if(typeof buffer.list[i]!.value === 'string') // Add or set a modifier
|
||||||
|
|
@ -349,13 +358,16 @@ export class CharacterCompiler
|
||||||
if(!modifier)
|
if(!modifier)
|
||||||
{
|
{
|
||||||
queue.push(property);
|
queue.push(property);
|
||||||
return;
|
shortcut = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if(modifier._dirty)
|
else if(modifier._dirty)
|
||||||
{
|
{
|
||||||
//Put it back in queue since its dependencies haven't been resolved yet
|
//Put it back in queue since its dependencies haven't been resolved yet
|
||||||
|
queue.push(buffer.list[i]!.value as string);
|
||||||
queue.push(property);
|
queue.push(property);
|
||||||
return;
|
shortcut = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -374,6 +386,9 @@ export class CharacterCompiler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(shortcut === true)
|
||||||
|
continue;
|
||||||
|
|
||||||
const path = property.split("/");
|
const path = property.split("/");
|
||||||
const object = path.length === 1 ? this._result : path.slice(0, -1).reduce((p, v) => { p[v] ??= {}; return p[v]; }, this._result as any);
|
const object = path.length === 1 ? this._result : path.slice(0, -1).reduce((p, v) => { p[v] ??= {}; return p[v]; }, this._result as any);
|
||||||
|
|
||||||
|
|
@ -383,7 +398,7 @@ export class CharacterCompiler
|
||||||
this._buffer[property]!.value = sum;
|
this._buffer[property]!.value = sum;
|
||||||
this._buffer[property]!._dirty = false;
|
this._buffer[property]!._dirty = false;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class CharacterBuilder extends CharacterCompiler
|
export class CharacterBuilder extends CharacterCompiler
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,11 @@ export type SpellElement = typeof SPELL_ELEMENTS[number];
|
||||||
export type Alignment = typeof ALIGNMENTS[number];
|
export type Alignment = typeof ALIGNMENTS[number];
|
||||||
|
|
||||||
export type FeatureID = string;
|
export type FeatureID = string;
|
||||||
|
export type TextID = string;
|
||||||
export type Resistance = string;
|
export type Resistance = string;
|
||||||
|
|
||||||
|
export type Dice = `${number}d${4 | 6 | 8 | 10 | 12 | 20}`;
|
||||||
|
|
||||||
export type Character = {
|
export type Character = {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
|
@ -20,16 +23,12 @@ export type Character = {
|
||||||
level: number;
|
level: number;
|
||||||
aspect?: number;
|
aspect?: number;
|
||||||
notes?: string | null;
|
notes?: string | null;
|
||||||
health: number;
|
|
||||||
mana: number;
|
|
||||||
|
|
||||||
training: Record<MainStat, Partial<Record<TrainingLevel, number>>>;
|
training: Record<MainStat, Partial<Record<TrainingLevel, number>>>;
|
||||||
leveling: Partial<Record<Level, number>>;
|
leveling: Partial<Record<Level, number>>;
|
||||||
abilities: Partial<Record<Ability, number>>; //First is the ability, second is the max increment
|
abilities: Partial<Record<Ability, number>>;
|
||||||
spells: string[]; //Spell ID
|
variables: CharacterVariables;
|
||||||
modifiers: Partial<Record<MainStat, number>>;
|
choices: Record<FeatureID, number[]>;
|
||||||
|
|
||||||
choices: Record<string, number[]>;
|
|
||||||
|
|
||||||
owner: number;
|
owner: number;
|
||||||
username?: string;
|
username?: string;
|
||||||
|
|
@ -40,8 +39,9 @@ export type CharacterVariables = {
|
||||||
mana: number;
|
mana: number;
|
||||||
exhaustion: number;
|
exhaustion: number;
|
||||||
|
|
||||||
sickness: Array<{ id: string, progress: number | true }>;
|
sickness: Array<{ id: string, state: number | true }>;
|
||||||
equipment: Array<string>;
|
spells: string[]; //Spell ID
|
||||||
|
equipment: string[]; //Equipment ID
|
||||||
};
|
};
|
||||||
export type CharacterConfig = {
|
export type CharacterConfig = {
|
||||||
peoples: Record<string, RaceConfig>;
|
peoples: Record<string, RaceConfig>;
|
||||||
|
|
@ -51,8 +51,35 @@ export type CharacterConfig = {
|
||||||
spells: SpellConfig[];
|
spells: SpellConfig[];
|
||||||
aspects: AspectConfig[];
|
aspects: AspectConfig[];
|
||||||
features: Record<FeatureID, Feature>;
|
features: Record<FeatureID, Feature>;
|
||||||
|
enchantments: Record<string, { name: string, effect: FeatureEffect[] }>; //TODO
|
||||||
|
items: Record<string, ItemConfig & { enchantments: string[] }>;
|
||||||
lists: Record<string, { id: string, name: string, [key: string]: any }[]>;
|
lists: Record<string, { id: string, name: string, [key: string]: any }[]>;
|
||||||
texts: Record<string, Localized>;
|
texts: Record<TextID, Localized>;
|
||||||
|
};
|
||||||
|
export type ItemConfig = { id: string, weight?: number, price?: number, power: number } & (ArmorConfig | WeaponConfig | WondrousConfig | MundaneConfig);
|
||||||
|
type ArmorConfig = {
|
||||||
|
category: 'armor';
|
||||||
|
name: string; //TODO -> TextID
|
||||||
|
description: TextID;
|
||||||
|
life: number;
|
||||||
|
absorb: number;
|
||||||
|
};
|
||||||
|
type WeaponConfig = {
|
||||||
|
category: 'armor';
|
||||||
|
name: string; //TODO -> TextID
|
||||||
|
description: TextID;
|
||||||
|
damage: Dice;
|
||||||
|
};
|
||||||
|
type WondrousConfig = {
|
||||||
|
category: 'armor';
|
||||||
|
name: string; //TODO -> TextID
|
||||||
|
description: TextID;
|
||||||
|
effect: FeatureEffect[];
|
||||||
|
};
|
||||||
|
type MundaneConfig = {
|
||||||
|
category: 'armor';
|
||||||
|
name: string; //TODO -> TextID
|
||||||
|
description: TextID;
|
||||||
};
|
};
|
||||||
export type SpellConfig = {
|
export type SpellConfig = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue