Add character duplication, fix prelevel unselect and ability points calculation
This commit is contained in:
parent
ab2778c626
commit
5e6f296c56
BIN
db.sqlite-shm
BIN
db.sqlite-shm
Binary file not shown.
BIN
db.sqlite-wal
BIN
db.sqlite-wal
Binary file not shown.
|
|
@ -85,7 +85,7 @@ const trainingSpent = computed(() => Object.values(maxTraining.value).reduce((p,
|
||||||
const modifiers = computed(() => Object.entries(maxTraining.value).reduce((p, v) => { p[v[0] as MainStat] = Math.floor(v[1] / 3) + (data.value.progress.modifiers ? (data.value.progress.modifiers[v[0] as MainStat] ?? 0) : 0); return p; }, {} as Record<MainStat, number>))
|
const modifiers = computed(() => Object.entries(maxTraining.value).reduce((p, v) => { p[v[0] as MainStat] = Math.floor(v[1] / 3) + (data.value.progress.modifiers ? (data.value.progress.modifiers[v[0] as MainStat] ?? 0) : 0); return p; }, {} as Record<MainStat, number>))
|
||||||
const modifierPoints = computed(() => (selectedRaceOptions.value ? selectedRaceOptions.value.reduce((p, v) => p + (v?.modifier ?? 0), 0) : 0) + training.value.reduce((p, v) => p + v[1].reduce((_p, _v) => _p + (_v?.modifier ?? 0), 0), 0));
|
const modifierPoints = computed(() => (selectedRaceOptions.value ? selectedRaceOptions.value.reduce((p, v) => p + (v?.modifier ?? 0), 0) : 0) + training.value.reduce((p, v) => p + v[1].reduce((_p, _v) => _p + (_v?.modifier ?? 0), 0), 0));
|
||||||
const modifierSpent = computed(() => Object.values(data.value.progress.modifiers ?? {}).reduce((p, v) => p + v, 0));
|
const modifierSpent = computed(() => Object.values(data.value.progress.modifiers ?? {}).reduce((p, v) => p + v, 0));
|
||||||
const abilityPoints = computed(() => training.value.flatMap(e => e[1].filter(_e => _e.ability !== undefined)).reduce((p, v) => p + v.ability!, 0));
|
const abilityPoints = computed(() => (selectedRaceOptions.value ? selectedRaceOptions.value.reduce((p, v) => p + (v?.abilities ?? 0), 0) : 0) + training.value.flatMap(e => e[1].filter(_e => _e.ability !== undefined)).reduce((p, v) => p + v.ability!, 0));
|
||||||
const abilityMax = computed(() => Object.entries(characterConfig.abilities).reduce((p, v) => { p[v[0] as Ability] = abilitySpecialFeatures("max", data.value.progress.training.curiosity, Math.floor(maxTraining.value[v[1].max[0]] / 3) + Math.floor(maxTraining.value[v[1].max[1]] / 3)); return p; }, {} as Record<Ability, number>));
|
const abilityMax = computed(() => Object.entries(characterConfig.abilities).reduce((p, v) => { p[v[0] as Ability] = abilitySpecialFeatures("max", data.value.progress.training.curiosity, Math.floor(maxTraining.value[v[1].max[0]] / 3) + Math.floor(maxTraining.value[v[1].max[1]] / 3)); return p; }, {} as Record<Ability, number>));
|
||||||
const abilitySpent = computed(() => Object.values(data.value.progress.abilities ?? {}).reduce((p, v) => p + v[0], 0));
|
const abilitySpent = computed(() => Object.values(data.value.progress.abilities ?? {}).reduce((p, v) => p + v[0], 0));
|
||||||
|
|
||||||
|
|
@ -119,9 +119,9 @@ function selectRaceOption(level: Level, choice: number)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(character.progress.race.progress.some(e => e[0] === level))
|
if(character.progress.race.progress.some(e => e[0] == level))
|
||||||
{
|
{
|
||||||
character.progress.race.progress.splice(character.progress.race.progress.findIndex(e => e[0] === level), 1, [level, choice]);
|
character.progress.race.progress.splice(character.progress.race.progress.findIndex(e => e[0] == level), 1, [level, choice]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -143,9 +143,9 @@ function switchTrainingOption(stat: MainStat, level: TrainingLevel, choice: numb
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(character.progress.training[stat].some(e => e[0] === level))
|
if(character.progress.training[stat].some(e => e[0] == level))
|
||||||
{
|
{
|
||||||
if(character.progress.training[stat].some(e => e[0] === level && e[1] === choice))
|
if(character.progress.training[stat].some(e => e[0] == level && e[1] === choice))
|
||||||
{
|
{
|
||||||
for(let i = 15; i >= level; i --) //Invalidate higher levels
|
for(let i = 15; i >= level; i --) //Invalidate higher levels
|
||||||
{
|
{
|
||||||
|
|
@ -155,7 +155,7 @@ function switchTrainingOption(stat: MainStat, level: TrainingLevel, choice: numb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
character.progress.training[stat].splice(character.progress.training[stat].findIndex(e => e[0] === level), 1, [level, choice]);
|
character.progress.training[stat].splice(character.progress.training[stat].findIndex(e => e[0] == level), 1, [level, choice]);
|
||||||
}
|
}
|
||||||
else if(trainingPoints.value && trainingPoints.value > 0)
|
else if(trainingPoints.value && trainingPoints.value > 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,14 @@ async function deleteCharacter(id: number)
|
||||||
add({ content: 'Personnage supprimé', type: 'info', duration: 25000, timer: true, });
|
add({ content: 'Personnage supprimé', type: 'info', duration: 25000, timer: true, });
|
||||||
characters.value = characters.value?.filter(e => e.id !== id);
|
characters.value = characters.value?.filter(e => e.id !== id);
|
||||||
}
|
}
|
||||||
|
async function duplicateCharacter(id: number)
|
||||||
|
{
|
||||||
|
loading.value = true;
|
||||||
|
const newId = await useRequestFetch()(`/api/character/${id}/duplicate`, { method: 'post' });
|
||||||
|
loading.value = false;
|
||||||
|
add({ content: 'Personnage dupliqué', type: 'info', duration: 25000, timer: true, });
|
||||||
|
useRouter().push({ name: 'character-id', params: { id: newId } });
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -38,9 +46,10 @@ async function deleteCharacter(id: number)
|
||||||
<NuxtLink class="flex-1 text-xl font-bold hover:text-accent-blue truncate" :to="{ name: 'character-id', params: { id: character.id } }" :title="character.name">{{ character.name }}</NuxtLink>
|
<NuxtLink class="flex-1 text-xl font-bold hover:text-accent-blue truncate" :to="{ name: 'character-id', params: { id: character.id } }" :title="character.name">{{ character.name }}</NuxtLink>
|
||||||
<span class="flex-1 text-sm truncate">Niveau {{ character.progress.level }}</span>
|
<span class="flex-1 text-sm truncate">Niveau {{ character.progress.level }}</span>
|
||||||
<div class="flex flex-row gap-8">
|
<div class="flex flex-row gap-8">
|
||||||
<NuxtLink class="font-bold text-accent-blue hover:text-opacity-50" :to="{ name: 'character-id-edit', params: { id: character.id } }">Editer</NuxtLink>
|
<NuxtLink class="text-accent-blue hover:text-opacity-50" :to="{ name: 'character-id-edit', params: { id: character.id } }">Editer</NuxtLink>
|
||||||
|
<span class="text-accent-blue hover:text-opacity-50 cursor-pointer" @click="duplicateCharacter(character.id)">Dupliquer</span>
|
||||||
<AlertDialogRoot>
|
<AlertDialogRoot>
|
||||||
<AlertDialogTrigger asChild><span class="font-bold text-light-red dark:text-dark-red hover:text-opacity-50 cursor-pointer">Supprimer</span></AlertDialogTrigger>
|
<AlertDialogTrigger asChild><span class="text-light-red dark:text-dark-red hover:text-opacity-50 cursor-pointer">Supprimer</span></AlertDialogTrigger>
|
||||||
<AlertDialogPortal>
|
<AlertDialogPortal>
|
||||||
<AlertDialogOverlay class="bg-light-0 dark:bg-dark-0 opacity-70 fixed inset-0 z-40" />
|
<AlertDialogOverlay class="bg-light-0 dark:bg-dark-0 opacity-70 fixed inset-0 z-40" />
|
||||||
<AlertDialogContent
|
<AlertDialogContent
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { eq } from 'drizzle-orm';
|
||||||
|
import useDatabase from '~/composables/useDatabase';
|
||||||
|
import { characterTable } from '~/db/schema';
|
||||||
|
|
||||||
|
export default defineEventHandler(async (e) => {
|
||||||
|
const id = getRouterParam(e, "id");
|
||||||
|
if(!id)
|
||||||
|
{
|
||||||
|
setResponseStatus(e, 400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = useDatabase();
|
||||||
|
const old = db.select().from(characterTable).where(eq(characterTable.id, parseInt(id))).get();
|
||||||
|
|
||||||
|
if(!old)
|
||||||
|
{
|
||||||
|
setResponseStatus(e, 404);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = await getUserSession(e);
|
||||||
|
if(!session.user || old.owner !== session.user.id || session.user.state !== 1)
|
||||||
|
{
|
||||||
|
setResponseStatus(e, 401);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const returned = await db.insert(characterTable).values({
|
||||||
|
name: `Copie de ${old.name}`,
|
||||||
|
progress: old.progress,
|
||||||
|
owner: session.user.id,
|
||||||
|
}).returning({ id: characterTable.id });
|
||||||
|
|
||||||
|
setResponseStatus(e, 201);
|
||||||
|
return returned[0].id;
|
||||||
|
});
|
||||||
|
|
@ -2079,9 +2079,10 @@
|
||||||
"description": [
|
"description": [
|
||||||
{
|
{
|
||||||
"text": "Vous augmentez le modifieur de votre choix de 1.",
|
"text": "Vous augmentez le modifieur de votre choix de 1.",
|
||||||
"disposable": false
|
"disposable": true
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"modifier": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": [
|
"description": [
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue