265 lines
8.4 KiB
TypeScript
265 lines
8.4 KiB
TypeScript
import { and, eq } from 'drizzle-orm';
|
|
import useDatabase from '~/composables/useDatabase';
|
|
import { characterTable } from '~/db/schema';
|
|
import type { Character, CharacterConfig, CompiledCharacter, DoubleIndex, Feature, MainStat, TrainingLevel, TrainingOption } from '~/types/character';
|
|
import characterData from '#shared/character-config.json';
|
|
import { users } from '~/drizzle/schema';
|
|
|
|
export default defineEventHandler(async (e) => {
|
|
const id = getRouterParam(e, "id");
|
|
if(!id)
|
|
{
|
|
setResponseStatus(e, 400);
|
|
return;
|
|
}
|
|
|
|
const db = useDatabase();
|
|
const character = db.select({
|
|
id: characterTable.id,
|
|
name: characterTable.name,
|
|
progress: characterTable.progress,
|
|
owner: characterTable.owner,
|
|
username: users.username
|
|
}).from(characterTable).leftJoin(users, eq(characterTable.owner, users.id)).where(and(eq(characterTable.id, parseInt(id)))).get();
|
|
|
|
if(character !== undefined)
|
|
{
|
|
return compileCharacter(character as Character & { username: string });
|
|
}
|
|
|
|
setResponseStatus(e, 404);
|
|
return;
|
|
}/* , { name: "character", getKey: (e) => getRouterParam(e, "id") || 'error' } */);
|
|
|
|
/*
|
|
Athlétisme
|
|
La capacité à effectuer un acte physique intense ou prolongé. Permet de pousser, contraindre, nager, courir.
|
|
|
|
Force + Constitution.
|
|
|
|
Acrobatique
|
|
La capacité à se mouvoir avec souplesse sous la contrainte. Permet d'escalader, d'enjamber, de sauter.
|
|
|
|
Force + Dextérité.
|
|
|
|
Intimidation
|
|
La capacité à intimider et inspirer la crainte.
|
|
|
|
Force + Charisme.
|
|
|
|
Doigté
|
|
La capacité à faire des actions précises avec ses mains. Permet de voler à la tire, de crocheter.
|
|
|
|
Dextérité + Dextérité.
|
|
|
|
Discrétion
|
|
La capacité à dissimuler sa présence. Permet de se cacher, de se mouvoir sans bruit.
|
|
|
|
Dextérité + Dextérité.
|
|
|
|
Survie
|
|
La capacité à survivre dans des conditions difficiles. Permet de pister, de collecter de la nourriture, de retrouver son chemin.
|
|
|
|
Constitution + Psyché.
|
|
|
|
Enquête
|
|
La capacité à demander au MJ de l'aide parce que vous puez la merde.
|
|
|
|
Intelligence + Curiosité.
|
|
|
|
Histoire
|
|
La capacité à connaitre le passé du monde.
|
|
|
|
Intelligence + Curiosité.
|
|
|
|
Religion
|
|
La capacité a connaitre les pratiques et les coutumes religieuses.
|
|
|
|
Intelligence + Curiosité.
|
|
|
|
Arcanes
|
|
La capacité à comprendre et percevoir la magie. Permet de comprendre un sort en cours, de détecter de la magie.
|
|
|
|
Intelligence + Psyché.
|
|
|
|
Compréhension
|
|
La capacité à déterminer les intentions des interlocuteurs. Permet de déceler des mensonges, de l'influence.
|
|
|
|
Intelligence + Charisme.
|
|
|
|
Perception
|
|
La capacité à observer le monde à travers ces sens. Permet d'observer, d'entendre, de sentir.
|
|
|
|
Curiosité + Curiosité.
|
|
|
|
Représentation
|
|
La capacité à se mettre en scène et à utiliser les arts. Permet de se produire en spectacle, de jouer d'un instrument, de chanter, de danser.
|
|
|
|
Curiosité + Charisme.
|
|
|
|
Médicine
|
|
La capacité à apporter des soins. Permet de stabiliser un joueur mourant, de soigner durant un repos.
|
|
|
|
Curiosité + Psyché.
|
|
|
|
Persuasion
|
|
Charisme + Psyché.
|
|
|
|
Dressage
|
|
Charisme + Psyché.
|
|
|
|
Mensonge
|
|
Charisme + Psyché.
|
|
*/
|
|
function compileCharacter(character: Character & { username?: string }): CompiledCharacter
|
|
{
|
|
const config = characterData as CharacterConfig;
|
|
const race = character.progress.race.index !== undefined ? config.peoples[character.progress.race.index] : undefined;
|
|
const raceOptions = race ? character.progress.race.progress!.map(e => race.options[e[0]][e[1]]) : [];
|
|
const features = Object.entries(config.training).map(e => [e[0], getFeaturesOf(e[0] as MainStat, character.progress.training[e[0] as MainStat])]) as [MainStat, TrainingOption[]][];
|
|
|
|
const compiled: CompiledCharacter = {
|
|
id: character.id,
|
|
owner: character.owner,
|
|
username: character.username,
|
|
name: character.name,
|
|
health: raceOptions.reduce((p, v) => p + (v.health ?? 0), 0),
|
|
mana: raceOptions.reduce((p, v) => p + (v.mana ?? 0), 0),
|
|
race: character.progress.race.index ?? -1,
|
|
modifier: features.map(e => [e[0], Math.floor(e[1].length / 3)] as [MainStat, number]).reduce((p, v) => { p[v[0]] = v[1]; return p }, {} as Record<MainStat, number>),
|
|
level: character.progress.level,
|
|
features: {
|
|
action: [],
|
|
reaction: [],
|
|
freeaction: [],
|
|
misc: [],
|
|
},
|
|
abilities: {
|
|
athletics: 0,
|
|
acrobatics: 0,
|
|
intimidation: 0,
|
|
sleightofhand: 0,
|
|
stealth: 0,
|
|
survival: 0,
|
|
investigation: 0,
|
|
history: 0,
|
|
religion: 0,
|
|
arcana: 0,
|
|
understanding: 0,
|
|
perception: 0,
|
|
performance: 0,
|
|
medecine: 0,
|
|
persuasion: 0,
|
|
animalhandling: 0,
|
|
deception: 0
|
|
},
|
|
spellslots: 0,
|
|
spellranks: {
|
|
instinct: 0,
|
|
knowledge: 0,
|
|
precision: 0
|
|
},
|
|
speed: false,
|
|
defense: {
|
|
static: 6,
|
|
activeparry: 0,
|
|
activedodge: 0,
|
|
passiveparry: 0,
|
|
passivedodge: 0,
|
|
},
|
|
mastery: {
|
|
strength: 0,
|
|
dexterity: 0,
|
|
shield: 0,
|
|
armor: 0,
|
|
multiattack: 1,
|
|
magicpower: 0,
|
|
magicspeed: 0,
|
|
magicelement: 0
|
|
},
|
|
resistance: {
|
|
stun: [0, 0],
|
|
bleed: [0, 0],
|
|
posion: [0, 0],
|
|
fear: [0, 0],
|
|
influence: [0, 0],
|
|
charm: [0, 0],
|
|
possesion: [0, 0],
|
|
precision: [0, 0],
|
|
knowledge: [0, 0],
|
|
instinct: [0, 0]
|
|
},
|
|
initiative: 0,
|
|
aspect: "",
|
|
};
|
|
|
|
features.forEach(e => e[1].forEach((_e, i) => applyTrainingOption(e[0], _e, compiled, i === e[1].length - 1)));
|
|
specialFeatures(compiled, character.progress.training);
|
|
|
|
Object.entries(character.progress.abilities).forEach(e => compiled.abilities[e[0]] += e[1][0]);
|
|
|
|
return compiled;
|
|
}
|
|
function applyTrainingOption(stat: MainStat, option: TrainingOption, character: CompiledCharacter, last: boolean)
|
|
{
|
|
if(option.health) character.health += option.health;
|
|
if(option.mana) character.mana += option.mana;
|
|
if(option.mastery) character.mastery[option.mastery]++;
|
|
if(option.speed) character.speed = option.speed;
|
|
if(option.initiative) character.initiative += option.initiative;
|
|
if(option.spellrank) character.spellranks[option.spellrank]++;
|
|
if(option.defense) option.defense.forEach(e => character.defense[e]++);
|
|
if(option.resistance) option.resistance.forEach(e => character.resistance[e[0]][e[1] === "attack" ? 0 : 1]++);
|
|
|
|
option.description.forEach(line => !line.disposable && (last || !line.replaced) && character.features[line.category ?? "misc"].push(line.text));
|
|
|
|
//if(option.features) option.features.forEach(e => applyFeature(e, character));
|
|
}
|
|
function specialFeatures(character: CompiledCharacter, levels: Record<MainStat, DoubleIndex<TrainingLevel>[]>)
|
|
{
|
|
//Cap la défense
|
|
const strengthCap3 = levels.strength.some(e => e[0] === 0);
|
|
const strengthCap6 = levels.strength.some(e => e[0] === 1);
|
|
const strengthUncapped = levels.strength.some(e => e[0] === 2);
|
|
|
|
const dexterityCap3 = levels.dexterity.some(e => e[0] === 0);
|
|
const dexterityCap3Stat = levels.dexterity.some(e => e[0] === 1);
|
|
const dexterityUncapped = levels.dexterity.some(e => e[0] === 2);
|
|
|
|
if(!strengthUncapped || !dexterityUncapped)
|
|
{
|
|
if(strengthCap6)
|
|
{
|
|
character.defense = {
|
|
static: 6,
|
|
activeparry: 0,
|
|
activedodge: 0,
|
|
passiveparry: 0,
|
|
passivedodge: 0,
|
|
};
|
|
}
|
|
else if(strengthCap3 || dexterityCap3)
|
|
{
|
|
character.defense = {
|
|
static: 3,
|
|
activeparry: 0,
|
|
activedodge: 0,
|
|
passiveparry: 0,
|
|
passivedodge: 0,
|
|
};
|
|
}
|
|
else if(dexterityCap3Stat)
|
|
{
|
|
character.defense.static = 3;
|
|
}
|
|
}
|
|
}/*
|
|
function applyFeature(feature: Feature, character: CompiledCharacter)
|
|
{
|
|
|
|
} */
|
|
export function getFeaturesOf(stat: MainStat, progression: DoubleIndex<TrainingLevel>[]): TrainingOption[]
|
|
{
|
|
const config = characterData as CharacterConfig;
|
|
return progression.map(e => config.training[stat][e[0]][e[1]]);
|
|
} |