reroll OK

This commit is contained in:
rwanoux
2024-04-28 16:35:48 +02:00
parent 74e11d439c
commit 0fada335f4
85 changed files with 1273 additions and 435 deletions
+1
View File
@@ -1 +1,2 @@
packs/** binary
node_modules/
+7 -3
View File
@@ -4,7 +4,11 @@
##TODO
- [ ] envoyer les spécialités utilisables au rollDialog
- [ ] refacto des template chat de roll
- [ ] gérer les dés de totems humains et adapté : couleur différente/double succès
- [ ] gérer les rerolls depuis chat(cf noc)
- [X] refacto des template chat de roll
- [X] gérer les dés de totems humains et adapté : couleur différente/double succès +update actor
- [X] gérer les rerolls depuis chat(cf noc)
- [X] gérer les rerolls après le jet en fonction du score d'effort et de la carac
- [ ] repasser sur les différents itemTypes et sheets
- [ ] update des reserves de sang-froids lors de jets
- [ ] gérer les rolls d'items
- [ ] ajout des domaines de prédilections
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
File diff suppressed because one or more lines are too long
+5 -6
View File
@@ -91,17 +91,16 @@ export class VermineActorSheet extends ActorSheet {
}
//click on wound radio
html.find('[type="radio"][data-wound]').click(ev => {
this._onWoundClick(ev)
html.find('.hexa [type="radio"]').click(ev => {
this._onClickRadioHexa(ev)
})
}
_onWoundClick(ev) {
_onClickRadioHexa(ev) {
if (!ev.currentTarget.checked) { return }
let woundType = ev.currentTarget.dataset.wound;
let targetProp = "system." + woundType + ".value";
let prop = ev.currentTarget.name;
let update = {};
update[targetProp] = ev.currentTarget.value - 1
update[prop] = ev.currentTarget.value - 1
this.actor.update(update)
+26 -16
View File
@@ -1,6 +1,6 @@
import { onManageActiveEffect, prepareActiveEffectCategories } from "../system/effects.mjs";
import { VermineActorSheet } from "./actor-sheet.mjs";
import { getRollBox } from "../system/dialogs.mjs";
import { RollDialog } from "../system/dialogs.mjs";
import { TotemPicker } from "../system/applications.mjs";
/**
@@ -103,16 +103,35 @@ export class VermineCharacterSheet extends VermineActorSheet {
// Choose Totem
html.find('.chooseTotem').click(this._onTotemButton.bind(this));
html.find('.ability .rollable').click(this._onRoll.bind(this));
html.find('[data-totem-name]').click(this._onClickTotemDice.bind(this))
}
async _onClickTotemDice(ev) {
let el = ev.currentTarget;
let totem = el.dataset.totemName;
let value = parseInt(el.dataset.totemValue);
let oldValue = this.actor.system.adaptation.totems[totem].value;
if (value === oldValue) { value-- };
let updates = {};
updates[`system.adaptation.totems.${totem}.value`] = value;
let totems = this.actor.system.adaptation.totems;
let sumTotems = Object.keys(totems).reduce(function (previous, key) {
return previous + totems[key].value;
}, 0);
if (sumTotems >5) {
ui.notifications.warn('vous ne pouvez pas avoir plus de 5 dés totems')
}
console.log(sumTotems, updates)
await this.actor.update(updates);
}
/**
* Handle clickable rolls.
* @param {Event} event The originating click event
* @private
*/
_onRoll(event) {
async _onRoll(event) {
event.preventDefault();
const element = event.currentTarget;
const dataset = element.dataset;
@@ -129,26 +148,17 @@ export class VermineCharacterSheet extends VermineActorSheet {
// Handle rolls that supply the formula directly.
if (dataset.label) {
dataset.rollType = dataset.type;
/*const label = game.i18n.localize(dataset.label) ? `[ability] ${game.i18n.localize(dataset.label)}` : '';
console.log($(element).attr('for'));
const NoD = this.actor.system.skills[$(element).attr('for').split('.')[2]]?.value || 0
return game.vermine2047.VermineRoll.roll(this.actor.id, label, NoD, 0, {});*/
let data = {
actorId: this.actor.id,
abilities: this.actor.system.abilities,
skills: this.actor.system.skills,
rollType: dataset.rollType,
labelKey: dataset.label,
abilityScore: 0,
skillScore: 0,
label: game.i18n.localize(dataset.label)
};
if (dataset.type == 'ability') {
data.abilityScore = this.actor.system.abilities[dataset.label].value;
} else if (dataset.type == 'skill') {
data.skillScore = this.actor.system.skills[dataset.label].value;
}
getRollBox(data);
let dial = await RollDialog.create(data);
dial.render(true)
return true;
}
}
+127 -118
View File
@@ -35,24 +35,40 @@ export class CombatResultDialog extends Dialog {
}
export class RollDialog extends Dialog {
static async create(rollData) {
let options = { classes: ["vermine-roll"], width: 420, height: 'fit-content', 'z-index': 99999 };
let html = await renderTemplate('systems/vermine2047/templates/roll.hbs', rollData);
static async create(data = {
label: null,
rolltype: null,
NoD: 1,
Reroll: false,
actorId: game.user.character.id
}) {
data.actor = await game.actors.get(data.actorId);
data.config = CONFIG.VERMINE;
let options = { classes: ["nocDialog"], width: 420, height: 'fit-content', 'z-index': 99999 };
let html = await renderTemplate('systems/vermine2047/templates/roll-dialog.hbs', data);
return new RollDialog(actor, rollData, html, options);
return new RollDialog(data, html, options);
}
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
focus: true,
classes: ["dialog vermine-roll"],
});
}
/* -------------------------------------------- */
constructor(data, html, options, close = undefined) {
let conf = {
title: "",
title: "jet de dés",
content: html,
buttons: {
roll: {
icon: '<i class="fas fa-check"></i>',
label: "Lancer !",
callback: () => { this.roll(data.actorId, data.label, data.NoD, data.Reroll) }
callback: () => {
this.roll()
}
},
cancel: {
icon: '<i class="fas fa-times"></i>',
@@ -60,124 +76,117 @@ export class RollDialog extends Dialog {
callback: () => { this.close() }
}
},
close: close
close: close,
}
super(conf, options);
return super({ ...conf, ...data }, options);
this.data = data;
};
getData() {
let context = super.getData();
context.data = this.data;
context.config = CONFIG.VERMINE;
return context;
}
async activateListeners(html) {
super.activateListeners(html);
this.getRollData();
let rollInputs = html.find('[data-roll');
for (let inp of rollInputs) {
inp.addEventListener('change', await this.getRollData.bind(this))
};
let selectAbil = html.find('#ability')[0];
html.find("#self_control")[0].max = selectAbil.value;
selectAbil.addEventListener('change', this._onChangeAbility.bind(this));
let selfControl = html.find('#self_control')[0]
selfControl.addEventListener('change', this._onChangeSelfControl.bind(this));
};
async getRollData(ev) {
console.log(this)
this.rollData = {
actor: this.data.actor,
NoD: this.getDicePool(),
Reroll: this.getReroll(),
difficulty: this.getDifficulty(),
rollLabel: this.data.labelKey,
totems: this.getTotems(),
self_control: this.getSelfControl(),
max_effort: this.getMaxEffort()
}
console.log('____________________________________calculating roll', this.rollData);
};
_onChangeSelfControl(ev) {
let html = this.element[0];
html.querySelector('#self_control_value').innerText = ev.currentTarget.value;
};
getSelfControl() {
let html = this.element[0];
let selfControl = parseInt(html.querySelector('#self_control').value)
return selfControl
}
getMaxEffort() {
let html = this.element[0];
return parseInt(html.querySelector('#ability').value);
}
getTotems() {
let html = this.element[0];
let totems = {
human: html.querySelector('#human-totem').checked,
adapted: html.querySelector('#adapted-totem').checked,
}
return totems
}
_onChangeAbility(ev) {
let html = this.element[0];
let score = html.querySelector('#ability').options[html.querySelector('#ability').selectedIndex].value;
if (!typeof score == "number") {
score = 0
}
html.querySelector('#abilityScore').value = score;
html.querySelector('#self_control').max = score;
}
getDicePool() {
let html = this.element[0];
let abilValue = html.querySelector('#ability').options[html.querySelector('#ability').selectedIndex].value || 0;
let skillValue = html.querySelector('#skill').options[html.querySelector('#skill').selectedIndex].dataset.pool || 0;
let selfControl = html.querySelector('#self_control').value;
let bonuses =
(html.querySelector('#usingSpecialization').checked ? 1 : 0) +
(html.querySelector('#helped').checked ? 1 : 0) +
(html.querySelector('#usingTools').checked ? 1 : 0);
let total = parseInt(abilValue) + parseInt(selfControl) + parseInt(skillValue) + bonuses;
return total || 0;
}
getReroll() {
let html = this.element[0];
let selected = html.querySelector('#skill').selectedIndex;
let reroll = html.querySelector('#skill').options[selected].dataset.reroll || 0;
return parseInt(reroll) || 0;
}
getDifficulty() {
let html = this.element[0];
let selected = html.querySelector('#difficulty').selectedIndex;
let diff = html.querySelector('#difficulty').options[selected].value || 0;
return parseInt(diff) || 0;
}
roll() {
VermineUtils.roll(actorId, label, NoD, Reroll = 0, params = {})
if (this.rollData.self_control > 0) {
if (this.rollData.actor.system.attributes.self_control.value < this.rollData.self_control) {
return ui.notifications.warn('vous navez pas assez de sang-froid')
}
}
return VermineUtils.roll({ ...this.rollData })
}
}
export const getRollBox = async function (data) {
console.log(data)
let actor = await game.actors.get(data.actorId)
let html = await renderTemplate('systems/vermine2047/templates/roll.hbs', data);
let dial = new Dialog({
title: game.i18n.localize("ROLLS.tool"),
content: html,
buttons: {
roll: {
label: game.i18n.localize('ROLLS.roll_dice'),
callback: async (html) => {
let form = html.find('#dice-pool-form');
if (!form[0].checkValidity()) {
throw "Invalid Data";
}
let formData = {};
form.serializeArray().map(item => {
formData[item.name] = item.value;
});
// console.log("roll form data", formData);
let NoD = parseInt(formData.abilityScore, 10);
let Reroll = 0;
// difficulty
data.difficulty = (formData.difficulty != undefined) ? formData.difficulty : 7;
// maîtrise bonus
if (formData.rollType == 'skill') {
NoD += CONFIG.VERMINE.SkillLevels[formData.skillScore].dicePool || 0;
Reroll += CONFIG.VERMINE.SkillLevels[formData.skillScore].reroll || 0;
}
console.log('reroll', Reroll);
// réserves
if (formData.self_control > 0) {
NoD += parseInt(formData.self_control, 10);
let newSelfControl = actor.system.attributes.self_control.value - parseInt(formData.self_control);
if (newSelfControl < 0) {
return async () => {
await ui.notifications.notify(`vous ne disposez pas d'assez de sang-froid`);
dial.render(true);
}
}
await actor.update({
"system.attributes.self_control.value": newSelfControl
})
}
if (formData.group > 0) {
NoD += parseInt(formData.group, 10);
}
// checks
if (formData.usingSpecialization !== undefined && formData.usingSpecialization == 1) {
NoD += 1;
}
if (formData.usingTools !== undefined && formData.usingTools == 1) {
NoD += 1;
}
if (formData.helped !== undefined && formData.helped == 1) {
NoD += 1;
}
if (formData.abilityScore == 0 || !formData.abilityScore) {
ui.notifications.notify(`veuillez saisir une caractéristique`);
dial.render(true);
} else
return VermineUtils.roll(data.actorId, data.label, NoD, Reroll, data);
}
},
close: {
label: game.i18n.localize('Close'),
callback: () => { }
}
},
render: function (h) {
if (h.find('input[name="abilityScore"]').val() == 0 && data.rollType == 'ability') {
h.find('input[name="abilityScore"]').val(data.abilities[data.label].value);
}
h.find('select[name="ability"]').change((event) => {
if (event.target.value != undefined) {
const abilityScore = data.abilities[event.target.value].value;
console.log('ability', abilityScore);
// on enregistre la valeur de la caractéristique
h.find('input[name="abilityScore"]').val(abilityScore);
}
});
h.find('select[name="skill"]').change((event) => {
if (data.rollType == 'skill' && event.target.value != undefined) {
const skillScore = data.skills[event.target.value].value;
// on enregistre la valeur de la compétence
h.find('input[name="skillScore"]').val(skillScore);
// on met à jour les infos de niveaux de compétence
const skillLevel = CONFIG.VERMINE.SkillLevels[skillScore];
if (skillLevel != undefined) {
h.find('#skillLevel').text(game.i18n.localize(skillLevel.label));
h.find('#skillDicePool').text(skillLevel.dicePool);
h.find('#skillReroll').text(skillLevel.reroll);
} else {
h.find('#skillLevel').text('Inconnu');
h.find('#skillDicePool').text(0);
h.find('#skillReroll').text(0);
}
}
});
}
});
dial.render(true);
}
+54
View File
@@ -0,0 +1,54 @@
export async function initUserDice(dice3d) {
let baseColor = game.user.color;
dice3d.addColorset({
name: 'regular_' + game.user.name,
description: "regular dice for " + game.user.name,
category: "vermine 2047",
foreground: '#9F8003',
background: baseColor,
outline: 'black',
texture: 'none',
material: 'plastic',
visibility: 'visible'
});
dice3d.addColorset({
name: 'human_' + game.user.name,
description: "human totem dice for " + game.user.name,
category: "vermine 2047",
foreground: '#9F8003',
background: lightenColor(baseColor, 40),
outline: 'black',
material: 'plastic',
visibility: 'visible'
});
dice3d.addColorset({
name: 'adapted_' + game.user.name,
description: "adapted totem dice for " + game.user.name,
category: "vermine 2047",
foreground: '#9F8003',
background: darkenColor(baseColor, 40),
outline: 'black',
material: 'plastic',
visibility: 'visible'
});
await game.user.setFlag("world", "diceInit", true);
}
export function darkenColor(color, percent) {
const num = parseInt(color.replace('#', ''), 16);
const amt = Math.round(2.55 * percent);
const R = (num >> 16) + amt;
const G = ((num >> 8) & 0x00FF) + amt;
const B = (num & 0x0000FF) + amt;
return '#' + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 + (G < 255 ? G < 1 ? 0 : G : 255) * 0x100 + (B < 255 ? B < 1 ? 0 : B : 255)).toString(16).slice(1);
}
export function lightenColor(color, percent) {
const num = parseInt(color.replace('#', ''), 16);
const amt = Math.round(2.55 * percent);
const R = (num >> 16) - amt;
const G = ((num >> 8) & 0x00FF) - amt;
const B = (num & 0x0000FF) - amt;
return '#' + (0x1000000 + (R < 0 ? 0 : R > 255 ? 255 : R) * 0x10000 + (G < 0 ? 0 : G > 255 ? 255 : G) * 0x100 + (B < 0 ? 0 : B > 255 ? 255 : B)).toString(16).slice(1);
}
+5 -1
View File
@@ -36,7 +36,7 @@ export const preloadHandlebarsTemplates = async function () {
"systems/vermine2047/templates/actor/creature/creature-combat.hbs",
// additional templates
"systems/vermine2047/templates/roll.hbs",
"systems/vermine2047/templates/roll-dialog.hbs",
]);
};
@@ -176,6 +176,7 @@ export const registerHandlebarsHelpers = function () {
Handlebars.registerHelper('skillLevel', function (property, level, options) {
if (level < 1 || level > 5)
return "";
level = parseInt(level);
let levelData = CONFIG.VERMINE.SkillLevels[level];
if (property == 'label') {
return (levelData !== undefined) ? game.i18n.localize(levelData[property]) : "";
@@ -247,6 +248,9 @@ export const registerHandlebarsHelpers = function () {
if (a <= b) { return options.fn(this); }
return options.inverse(this);
});
Handlebars.registerHelper('ifincludes', function (arg1, arg2, options) {
return (arg1.includes(arg2)) ? options.fn(this) : options.inverse(this);
});
Handlebars.registerHelper('repeat', function (times, start, block) {
var accum = '';
+48 -5
View File
@@ -1,13 +1,55 @@
import { RollDialog } from "./dialogs.mjs";
import { initUserDice } from "./dice3d.mjs";
import { VermineUtils } from "./roll.mjs";
import { registerTours } from "./tour.mjs";
export const registerHooks = function () {
/**
* Ready hook loads tables, and override's foundry's entity link functions to provide extension to pseudo entities
*/
CONFIG.debug.hooks = true;
Hooks.once('diceSoNiceReady', async (dice3d) => {
dice3d.addSystem({ id: "Vermine2047", name: "Vermine 2047" }, "preferred");
dice3d.addDicePreset({
type: "d10",
labels: [
"systems/vermine2047/assets/images/die/d10-1.webp",
"systems/vermine2047/assets/images/die/d10-2.webp",
"systems/vermine2047/assets/images/die/d10-3.webp",
"systems/vermine2047/assets/images/die/d10-4.webp",
"systems/vermine2047/assets/images/die/d10-5.webp",
"systems/vermine2047/assets/images/die/d10-6.webp",
"systems/vermine2047/assets/images/die/d10-7.webp",
"systems/vermine2047/assets/images/die/d10-8.webp",
"systems/vermine2047/assets/images/die/d10-9.webp",
"systems/vermine2047/assets/images/die/d10-0.webp",
],
system: "Vermine2047"
});
await initUserDice(dice3d);
});
Hooks.on('renderChatMessage', async (message, html, data) => {
if (message.user._id != game.user._id) { return }
await VermineUtils.chatListenners(html)
})
Hooks.on('updateUser', async () => {
if (game.dice3d) {
initUserDice(game.dice3d)
}
})
Hooks.once("ready", async () => {
console.info("Vermine 2047 | System Initialized.");
await registerTours();
});
// changement de la pause
@@ -34,16 +76,17 @@ export const registerHooks = function () {
return false;
});
Hooks.on('getSceneControlButtons', (controls) => {
/*controls.find((c) => c.name === 'token').tools.push({
Hooks.on('getSceneControlButtons', async (controls) => {
console.log;
controls.find((c) => c.name === 'token').tools.push({
name: 'Dice Roller',
title: game.i18n.localize("VERMINE.RollTool"),
icon: 'fas fa-dice-d6',
icon: 'fas fa-dice-d10',
button: true,
onClick() {
VermineRoll.ui();
RollDialog.create().then(d => d.render(true));
}
});*/
});
});
/* -------------------------------------------- */
+197 -23
View File
@@ -1,20 +1,180 @@
export class VermineUtils {
/**
* Méthode pour effectuer un jet de dés avec différentes options
* @param {Object} options - Les options du jet de dés
* @returns {Roll} - Le résultat du jet de dés
*/
static async roll({ actor, NoD, Reroll = 0, difficulty = 7, self_control = 0, rollLabel = "jet custom", totems = { human: false, adapted: false }, max_effort = 0 }) {
// Déclaration des variables
let formula = "";
let modFormula = null;
static roll(actorId, label, NoD, Reroll = 0, params = {}) {
const actor = game.actors.get(actorId);
let formula = '' + NoD + "d10";
// Vérification des totems humains
if (totems.human) {
NoD--;
modFormula = "(1D10cs>=" + difficulty + `[human_${game.user.name}]*2)`;
await actor.update({
"system.adaptation.totems.human.value": actor.system.adaptation.totems.human.value - 1
})
}
// Vérification des totems adaptés
if (totems.adapted) {
NoD--;
// Construction de la formule modifiée
if (modFormula != null) {
modFormula = modFormula + "+(1D10cs>=" + difficulty + `[adapted_${game.user.name}]*2)`;
} else {
modFormula = "(1D10cs>=" + difficulty + `[adapted_${game.user.name}]*2)`;
}
await actor.update({
"system.adaptation.totems.adapted.value": actor.system.adaptation.totems.adapted.value - 1
})
};
formula += (params.difficulty != undefined) ? "cs>=" + params.difficulty : "cs>=7";
// Construction de la formule de base
let baseFormula = '' + NoD + "d10";
baseFormula += (difficulty != undefined) ? "cs>=" + difficulty : "cs>=7";
baseFormula += `[regular_${game.user.name}]`
// Construction de la formule finale
if (modFormula != null) {
formula = baseFormula + "+" + modFormula;
} else { formula = baseFormula }
// Création du jet de dés
let roll = new Roll(formula, actor.getRollData());
roll.toMessage({
speaker: ChatMessage.getSpeaker({ actor: actor }),
flavor: label,
rollMode: game.settings.get('core', 'rollMode'),
});
await roll.evaluate();
await VermineUtils.showDiceSoNice(roll);
VermineUtils.diplayChatRoll(roll, ...arguments);
return roll;
}
/* -------------------------------------------- */
/**
* Méthode pour gérer les événements de relance de dés
* @param {Object} message - Le message contenant l'événement de relance
* @param {Object} ev - L'événement de relance
*/
static async _onRerollSelect(message, ev) {
// Vérification de l'utilisateur
if (game.user._id != message.user._id) {
ui.notifications.warn('vous ne pouvez pas relancer un dés sur ce jet')
return false
}
// Récupération du nombre de relances autorisé
let rerollCount = ev.currentTarget.closest('div.vermine-roll-message').querySelector('#allowed_reroll')?.innerText;
// Vérification du nombre de relances restantes
if (!rerollCount || parseInt(rerollCount) < 1) {
console.log('no reroll')
ui.notifications.warn("plus de relance possible");
let rerollables = ev.currentTarget.closest('ul').querySelectorAll('.rerollable');
rerollables.forEach(el => el.classList.remove('rerollable'));
// Mise à jour du nombre de relances restantes
ev.currentTarget.closest('div.vermine-roll-message').querySelector('#allowed_reroll').innerText = rerollCount - 1;
let content = ev.currentTarget.closest('div.message-content').outerHTML;
await message.update({
content: content
})
return false
}
ev.currentTarget.classList.add('rerolled');
// Mise en place de la relance
await message.setFlag("world", "reroll", true);
// Récupération de la difficulté et du type de dé
let difficulty = ev.currentTarget.closest('ul').dataset.difficulty;
let diceType = ev.currentTarget.dataset.diceType;
// Mise à jour du nombre de relances restantes
ev.currentTarget.closest('div.vermine-roll-message').querySelector('#allowed_reroll').innerText = rerollCount - 1;
// Construction de la formule de relance
let formula = `1d10cs>=${difficulty}`;
console.log(diceType)
switch (diceType.trim()) {
case 'human':
formula = `(1d10cs>=${difficulty}[human_${game.user.name}])*2`
break;
case 'adapted':
formula = `(1d10cs>=${difficulty}[adapted_${game.user.name}])*2`
break;
default:
formula += `[regular_${game.user.name}]`
break;
};
// Création et évaluation du jet de dés de relance
let reroll = await new Roll(formula);
await reroll.evaluate();
await VermineUtils.showDiceSoNice(reroll);
// mise à jour de l'affichage du dés
console.log(reroll)
let result = reroll.dice[0].results[0].result;
ev.currentTarget.querySelector('span').innerText = result;
//mise à jour du total
let success = reroll.dice[0].results[0].success;
if (success) {
ev.currentTarget.classList.add('success')
let total = parseInt(ev.currentTarget.closest('.vermine-roll-message').querySelector('#total').innerText) + reroll.total
ev.currentTarget.closest('.vermine-roll-message').querySelector('#total').innerText = total
}
// Mise à jour de l'affichagedu message
ev.currentTarget.classList.remove("rerollable")
let content = ev.currentTarget.closest('div.message-content').outerHTML;
console.log(reroll, message);
await message.update({
content: content
})
}
/**
* Méthode pour gérer les événements de chat
* @param {HTMLElement} html - L'élément HTML contenant les événements de chat
*/
static async chatListenners(html) {
let reroll = html.find('#allowed_reroll')[0]?.innerText;
if (!reroll || parseInt(reroll) < 1) {
for (let die of html.find('.die')) {
die.classList.remove("rerollable")
};
} else {
for (let die of html.find('.die')) {
die.classList.add("rerollable")
};
}
html.find('.rerollable').click(async (ev) => {
ev.preventDefault();
let msgId = ev.currentTarget.closest("li.message").dataset.messageId;
let message = await game.messages.get(msgId);
await VermineUtils._onRerollSelect(message, ev);
});
html.find("#effort-reroll").change(ev => {
let label = html.find("#granted-reroll")[0]
label.innerText = ev.currentTarget.value
});
html.find("button.grant-reroll").click(async (ev) => {
html.find("#allowed_reroll")[0].innerText = html.find('#granted-reroll')[0].innerText
let mesEl = ev.currentTarget.closest('[data-message-id]')
let messageId = mesEl.dataset.messageId;
ev.currentTarget.closest('.reroll-from-effort').style.display="none"
let content = ev.currentTarget.closest(".vermine-roll-message").outerHTML;
let message = await game.messages.get(messageId);
await message.update({ content: content });
});
}
/**
* Méthode pour afficher les résultats des dés de manière graphique
* @param {Roll} roll - Le jet de dés à afficher
* @param {string} rollMode - Le mode d'affichage du jet de dés
*/
static async showDiceSoNice(roll, rollMode) {
if (game.modules.get("dice-so-nice")?.active) {
if (game.dice3d) {
@@ -39,22 +199,36 @@ export class VermineUtils {
}
}
/* -------------------------------------------- */
static async chatListeners(html) {
html.on("click", '.roll-dice-bonus', event => {
let rollData = this.getRollDataFromMessage(event)
let msgId = VermineRoll.findChatMessageId(event.currentTarget)
nocUtility.removeChatMessageId(msgId)
let nbDice = $(event.target).data('nb-dice')
console.log(">>>>>", nbDice)
this.rollBonus(rollData, nbDice)
})
/**
* Méthode pour récupérer un jet de dés à partir d'un message
* @param {string} messageId - L'identifiant du message contenant le jet de dés
*/
static async getRollFromMessage(messageId) {
let message = await game.messages.get(messageId);
}
/**
* Méthode pour afficher un jet de dés dans le chat
* @param {Roll} roll - Le jet de dés à afficher
* @param {Object} param - Les paramètres du jet de dés
* @returns {ChatMessage} - Le message affichant le jet de dés
*/
static async diplayChatRoll(roll, param) {
let content = await renderTemplate("systems/vermine2047/templates/roll-message.hbs", { roll, param })
let chatData = {
user: game.user._id,
speaker: ChatMessage.getSpeaker(),
content: content,
roll: roll
};
let msg = await ChatMessage.create(chatData);
await msg.setFlag('world', 'roll', roll);
return msg
}
}
+4 -1
View File
@@ -18,6 +18,7 @@ import { VermineCombat, VermineCombatTracker } from "./system/fight.mjs";
// Import helper/utility classes and constants.
import { preloadHandlebarsTemplates, registerHandlebarsHelpers } from "./system/handlebars-manager.mjs";
import { VERMINE } from "./system/config.mjs";
import { initUserDice } from "./system/dice3d.mjs";
/* -------------------------------------------- */
/* Init Hook */
@@ -37,7 +38,6 @@ Hooks.once('init', async function () {
// Add custom constants for configuration.
CONFIG.VERMINE = VERMINE;
CONFIG.VERMINE.model = game.system.model
console.log('__________________', CONFIG.VERMINE)
/**
* Set an initiative formula for the system
* @type {String}
@@ -97,6 +97,9 @@ Hooks.once('init', async function () {
el.classList.add('game-mode');
el.id = 'game-mode-' + mode;
document.querySelector('#ui-left').prepend(el);
// Preload Handlebars templates.
return preloadHandlebarsTemplates();
+1 -1
View File
@@ -5,7 +5,7 @@
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"launch Foundry11": "cd C:/Program Files/Foundry Virtual Tabletop_V11/resources/app && node main.js",
"launch window Foundry11": "cd C:/Program Files/Foundry Virtual Tabletop_V11/resources/app && node main.js",
"watch": "gulp watch",
"buildStyle": "gulp buildStyles"
},
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000149
MANIFEST-000177
+3 -3
View File
@@ -1,3 +1,3 @@
2024/04/21-11:00:14.926 40b8 Recovering log #147
2024/04/21-11:00:14.930 40b8 Delete type=0 #147
2024/04/21-11:00:14.930 40b8 Delete type=3 #145
2024/04/28-09:24:23.659 2504 Recovering log #176
2024/04/28-09:24:23.664 2504 Delete type=0 #176
2024/04/28-09:24:23.664 2504 Delete type=3 #175
+3 -7
View File
@@ -1,7 +1,3 @@
2024/04/21-08:39:21.586 3594 Recovering log #144
2024/04/21-08:39:21.591 3594 Delete type=0 #144
2024/04/21-08:39:21.591 3594 Delete type=3 #143
2024/04/21-10:20:47.336 5c50 Level-0 table #148: started
2024/04/21-10:20:47.336 5c50 Level-0 table #148: 0 bytes OK
2024/04/21-10:20:47.337 5c50 Delete type=0 #146
2024/04/21-10:20:47.355 5c50 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
2024/04/26-22:48:34.076 b5c Recovering log #174
2024/04/26-22:48:34.079 b5c Delete type=0 #174
2024/04/26-22:48:34.081 b5c Delete type=3 #173
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000149
MANIFEST-000177
+3 -3
View File
@@ -1,3 +1,3 @@
2024/04/21-11:00:14.993 40b8 Recovering log #147
2024/04/21-11:00:14.999 40b8 Delete type=0 #147
2024/04/21-11:00:14.999 40b8 Delete type=3 #145
2024/04/28-09:24:23.727 2504 Recovering log #176
2024/04/28-09:24:23.733 2504 Delete type=0 #176
2024/04/28-09:24:23.733 2504 Delete type=3 #175
+3 -7
View File
@@ -1,7 +1,3 @@
2024/04/21-08:39:21.654 3594 Recovering log #144
2024/04/21-08:39:21.658 3594 Delete type=0 #144
2024/04/21-08:39:21.658 3594 Delete type=3 #143
2024/04/21-10:20:47.365 5c50 Level-0 table #148: started
2024/04/21-10:20:47.365 5c50 Level-0 table #148: 0 bytes OK
2024/04/21-10:20:47.367 5c50 Delete type=0 #146
2024/04/21-10:20:47.367 5c50 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
2024/04/26-22:48:34.179 b5c Recovering log #174
2024/04/26-22:48:34.188 b5c Delete type=0 #174
2024/04/26-22:48:34.188 b5c Delete type=3 #173
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000133
MANIFEST-000161
+3 -3
View File
@@ -1,3 +1,3 @@
2024/04/21-11:00:14.944 40b8 Recovering log #131
2024/04/21-11:00:14.950 40b8 Delete type=0 #131
2024/04/21-11:00:14.950 40b8 Delete type=3 #129
2024/04/28-09:24:23.680 2504 Recovering log #160
2024/04/28-09:24:23.685 2504 Delete type=0 #160
2024/04/28-09:24:23.685 2504 Delete type=3 #159
+3 -7
View File
@@ -1,7 +1,3 @@
2024/04/21-08:39:21.607 3594 Recovering log #128
2024/04/21-08:39:21.613 3594 Delete type=0 #128
2024/04/21-08:39:21.613 3594 Delete type=3 #127
2024/04/21-10:20:47.362 5c50 Level-0 table #132: started
2024/04/21-10:20:47.362 5c50 Level-0 table #132: 0 bytes OK
2024/04/21-10:20:47.363 5c50 Delete type=0 #130
2024/04/21-10:20:47.364 5c50 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
2024/04/26-22:48:34.099 b5c Recovering log #158
2024/04/26-22:48:34.107 b5c Delete type=0 #158
2024/04/26-22:48:34.107 b5c Delete type=3 #157
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000147
MANIFEST-000175
+3 -3
View File
@@ -1,3 +1,3 @@
2024/04/21-11:00:14.982 56d0 Recovering log #145
2024/04/21-11:00:14.987 56d0 Delete type=0 #145
2024/04/21-11:00:14.987 56d0 Delete type=3 #143
2024/04/28-09:24:23.715 d84 Recovering log #174
2024/04/28-09:24:23.721 d84 Delete type=0 #174
2024/04/28-09:24:23.721 d84 Delete type=3 #173
+3 -7
View File
@@ -1,7 +1,3 @@
2024/04/21-08:39:21.641 5300 Recovering log #142
2024/04/21-08:39:21.646 5300 Delete type=0 #142
2024/04/21-08:39:21.647 5300 Delete type=3 #141
2024/04/21-10:20:47.358 5c50 Level-0 table #146: started
2024/04/21-10:20:47.358 5c50 Level-0 table #146: 0 bytes OK
2024/04/21-10:20:47.360 5c50 Delete type=0 #144
2024/04/21-10:20:47.364 5c50 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
2024/04/26-22:48:34.159 1544 Recovering log #172
2024/04/26-22:48:34.165 1544 Delete type=0 #172
2024/04/26-22:48:34.166 1544 Delete type=3 #171
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000043
MANIFEST-000071
+3 -3
View File
@@ -1,3 +1,3 @@
2024/04/21-11:00:14.957 56d0 Recovering log #41
2024/04/21-11:00:14.962 56d0 Delete type=0 #41
2024/04/21-11:00:14.962 56d0 Delete type=3 #39
2024/04/28-09:24:23.691 d84 Recovering log #70
2024/04/28-09:24:23.695 d84 Delete type=0 #70
2024/04/28-09:24:23.695 d84 Delete type=3 #69
+3 -8
View File
@@ -1,8 +1,3 @@
2024/04/21-08:39:21.618 5300 Recovering log #38
2024/04/21-08:39:21.623 5300 Delete type=0 #38
2024/04/21-08:39:21.623 5300 Delete type=3 #37
2024/04/21-10:20:47.360 5c50 Level-0 table #42: started
2024/04/21-10:20:47.360 5c50 Level-0 table #42: 0 bytes OK
2024/04/21-10:20:47.362 5c50 Delete type=0 #40
2024/04/21-10:20:47.364 5c50 Manual compaction at level-0 from '!items!10vhNURxl8FOwfy0' @ 72057594037927935 : 1 .. '!items!vX832Z4LpasxLIIx' @ 0 : 0; will stop at (end)
2024/04/21-10:20:47.364 5c50 Manual compaction at level-1 from '!items!10vhNURxl8FOwfy0' @ 72057594037927935 : 1 .. '!items!vX832Z4LpasxLIIx' @ 0 : 0; will stop at (end)
2024/04/26-22:48:34.121 1544 Recovering log #68
2024/04/26-22:48:34.127 1544 Delete type=0 #68
2024/04/26-22:48:34.127 1544 Delete type=3 #67
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000040
MANIFEST-000068
+3 -3
View File
@@ -1,3 +1,3 @@
2024/04/21-11:00:14.969 40b8 Recovering log #38
2024/04/21-11:00:14.975 40b8 Delete type=0 #38
2024/04/21-11:00:14.975 40b8 Delete type=3 #36
2024/04/28-09:24:23.703 2504 Recovering log #67
2024/04/28-09:24:23.708 2504 Delete type=0 #67
2024/04/28-09:24:23.708 2504 Delete type=3 #66
+3 -8
View File
@@ -1,8 +1,3 @@
2024/04/21-08:39:21.629 3594 Recovering log #35
2024/04/21-08:39:21.634 3594 Delete type=0 #35
2024/04/21-08:39:21.634 3594 Delete type=3 #34
2024/04/21-10:20:47.356 5c50 Level-0 table #39: started
2024/04/21-10:20:47.356 5c50 Level-0 table #39: 0 bytes OK
2024/04/21-10:20:47.358 5c50 Delete type=0 #37
2024/04/21-10:20:47.364 5c50 Manual compaction at level-0 from '!tables!UxgGMRs0kTplpTbe' @ 72057594037927935 : 1 .. '!tables.results!dXo0EN9ieo1tSnRY.ymnitiW2yAuk75M3' @ 0 : 0; will stop at (end)
2024/04/21-10:20:47.364 5c50 Manual compaction at level-1 from '!tables!UxgGMRs0kTplpTbe' @ 72057594037927935 : 1 .. '!tables.results!dXo0EN9ieo1tSnRY.ymnitiW2yAuk75M3' @ 0 : 0; will stop at (end)
2024/04/26-22:48:34.142 b5c Recovering log #65
2024/04/26-22:48:34.148 b5c Delete type=0 #65
2024/04/26-22:48:34.148 b5c Delete type=3 #64
+1 -1
View File
@@ -1 +1 @@
MANIFEST-000147
MANIFEST-000175
+3 -3
View File
@@ -1,3 +1,3 @@
2024/04/21-11:00:14.935 56d0 Recovering log #145
2024/04/21-11:00:14.939 56d0 Delete type=0 #145
2024/04/21-11:00:14.939 56d0 Delete type=3 #143
2024/04/28-09:24:23.670 d84 Recovering log #174
2024/04/28-09:24:23.674 d84 Delete type=0 #174
2024/04/28-09:24:23.675 d84 Delete type=3 #173
+3 -7
View File
@@ -1,7 +1,3 @@
2024/04/21-08:39:21.598 5300 Recovering log #142
2024/04/21-08:39:21.602 5300 Delete type=0 #142
2024/04/21-08:39:21.602 5300 Delete type=3 #141
2024/04/21-10:20:47.353 5c50 Level-0 table #146: started
2024/04/21-10:20:47.353 5c50 Level-0 table #146: 0 bytes OK
2024/04/21-10:20:47.354 5c50 Delete type=0 #144
2024/04/21-10:20:47.355 5c50 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
2024/04/26-22:48:34.087 1544 Recovering log #172
2024/04/26-22:48:34.091 1544 Delete type=0 #172
2024/04/26-22:48:34.092 1544 Delete type=3 #171
Binary file not shown.
Binary file not shown.
+134 -10
View File
@@ -105,10 +105,7 @@ ul.unstyled li {
.actor.sheet form .form {
display: grid;
/*grid:
"sidebar header" 75px
"sidebar nav" minmax(min-content, max-content)
"sidebar content" 1fr/230px 1fr;*/
grid-template-columns: minmax(230px, 1fr) 3fr;
grid-template-rows: 1fr;
align-items: flex-start;
@@ -120,10 +117,28 @@ ul.unstyled li {
grid-row: span 1 / span 1;
background-image: url(/systems/vermine2047/assets/images/ui/barre_laterale.webp);
background-repeat: no-repeat;
background-position: 12% 50%;
background-size: 400%;
background-size: cover;
height: 100%;
box-shadow: -20px 0px 100px #000000b5 inset
width: 240px;
padding: 0 0.3rem;
box-shadow: -20px 0px 100px #000000b5 inset;
.major-totem {
position: relative;
h4 {
position: absolute;
transform: rotate(-8deg);
opacity: 0.7;
transition: 0.2s;
}
&:hover h4 {
opacity: 1;
}
}
}
.actor.sheet .form main {
@@ -134,7 +149,6 @@ ul.unstyled li {
}
.actor.sheet .form aside .image-wrapper {
margin: 1rem auto 3rem;
text-align: center;
}
@@ -211,6 +225,111 @@ ul.unstyled li {
overflow: hidden;
}
.system-vermine2047 .sheet.actor form div.hexa {
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
background: radial-gradient(circle, rgba(255, 255, 255, 0.425) 0%, rgba(0, 0, 0, 0.288) 100%);
height: unset;
max-width: 1.5rem;
aspect-ratio: 1/1;
color: black;
transform: rotate(90deg);
transition: 0.2s;
margin: 0.2rem;
&:hover {
background: radial-gradient(circle, rgba(255, 255, 255, 0.425) 0%, rgba(0, 0, 0, 0.288) 100%);
}
input {
opacity: 1;
min-width: 100%;
min-height: 100%;
opacity: 0
}
&.checked {
&:hover {
background: radial-gradient(circle, rgb(43, 43, 43) 0%, rgba(0, 0, 0, 0.288) 100%);
}
background: radial-gradient(circle, rgb(0, 0, 0) 0%, rgba(0, 0, 0, 0.288) 100%);
}
&.unavailable {
background: radial-gradient(circle, rgba(66, 15, 15, 0.664) 0%, rgba(131, 70, 70, 0.432) 100%);
}
}
.system-vermine2047 .sheet.actor div.minor-totems {
position: relative;
background-color: #929c6f85;
h5 {
position: absolute;
top: 0;
img {
max-width: 2rem;
position: absolute;
bottom: -2rem;
}
}
.totem-dice {
.human-dice,
.adapted-dice {
display: flex;
flex-direction: row;
margin-left: 2rem;
i {
padding-top: 0.5rem;
color: #064930;
}
}
.adapted-dice {
justify-content: flex-end;
margin-left: 0;
margin-right: 2rem;
transform: rotate(180deg);
i {
transform: rotate(180deg);
padding-top: 0.5rem;
color: rgb(85, 52, 2);
}
}
}
.human {
left: 0;
img {
left: 0;
}
}
.adapted {
right: 0;
img {
right: 0
}
}
}
.system-vermine2047 .sheet.actor form input[type=text],
.system-vermine2047 .sheet.actor form input[type=number] {
width: calc(100% - 2px);
@@ -462,8 +581,9 @@ ul.unstyled li {
margin: 0 1rem;
flex: 0.5;
}
&.hexa {
.hexa {
text-align: center;
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
background: radial-gradient(circle, rgba(255, 255, 255, 0.425) 0%, rgba(0, 0, 0, 0.288) 100%);
@@ -471,8 +591,12 @@ ul.unstyled li {
max-width: 1.2rem;
aspect-ratio: 1/1;
color: black;
vertical-align: bottom;
vertical-align: center;
&.checked {
background: radial-gradient(circle, rgb(0, 0, 0) 0%, rgba(0, 0, 0, 0.288) 100%);
}
}
div.specialties {
+178
View File
@@ -0,0 +1,178 @@
ol#chat-log {
header.message-header {
background-color: black;
padding: 0 1rem;
}
.vermine-roll-message {
overflow: hidden;
box-shadow: 0px 0px 30px white inset;
padding: 0;
position: relative;
.flexrow {
align-items: center;
box-shadow: 0px 5px 10px 0px black;
}
h3,
h4 {
text-transform: uppercase;
font-family: "DistressBlack";
margin-top: 1rem;
border-bottom: none;
font-weight: 900;
font-weight: 900;
background: 50% 0%/cover no-repeat url(/systems/vermine2047/assets/images/ui/scotch.webp);
&+span {
font-family: "DistressBlack";
font-size: large;
text-transform: unset;
padding-left: 2rem;
background: -100% 0%/cover no-repeat url(/systems/vermine2047/assets/images/ui/scotch.webp);
&#allowed_reroll {
font-size: large;
}
}
}
h3 {
background: url(/systems/vermine2047/assets/images/ui/scotch.webp);
background-position: center;
background-size: 200%;
}
h4 {
text-align: end;
}
div.roll-total {
transform: rotate(-3deg) scale(1.3) translateX(2rem) translateY(0.5rem);
background: url(/systems/vermine2047/assets/images/ui/scotch.webp);
background-position: center;
background-size: 200%;
margin-bottom: 2rem;
padding: 0;
z-index: +1;
}
div.reroll {
button {
text-transform: uppercase;
font-family: "DistressBlack";
margin-top: 1rem;
box-shadow: 0px 0px 3px black;
background: 50% 0%/cover no-repeat url(/systems/vermine2047/assets/images/ui/scotch.webp);
}
padding: 0 2rem;
padding-bottom: 2rem;
justify-content: end;
text-align: center;
}
ul.roll-results {
list-style: none;
li.die {
position: relative;
max-width: 3rem;
line-height: 3rem;
float: left;
margin: 0.2rem;
background-image: url(/icons/dice/d10black.svg);
background-position: center;
background-repeat: no-repeat;
background-size: contain;
font-weight: 800;
font-size: 1rem;
color: #ffffff;
text-align: center;
transition: 0.3s;
border-bottom: 5px solid rgb(255, 0, 0);
border-radius: 2rem;
&::after {
content: "";
position: absolute;
top: -1rem;
text-wrap: nowrap;
color: black;
font-weight: 100;
font-size: smaller;
text-align: center;
opacity: 0;
}
&:hover::after {
opacity: 1
}
&.human,
&.adapted {
border-top: 5px solid rgb(255, 217, 0);
}
&.rerollable {
cursor: pointer;
&:hover {
transform: translateY(0.5rem)
}
}
&.success {
border-bottom: 5px solid rgb(0, 143, 7);
}
&.adapted {
&::after {
content: "adapté"
}
}
&.human {
&::after {
content: "humain"
}
}
&.rerolled {
transform: translateY(-0rem);
}
span {
text-align: center;
font-size: larger;
text-shadow: 0px 0px 8px black;
}
}
}
}
}
+1
View File
@@ -1,2 +1,3 @@
@import "./base_work.scss";
@import "./style.scss";
@import "./roll.scss"
+17
View File
@@ -32,6 +32,23 @@
"templates": [
"base"
],
"adaptation": {
"value": 1,
"min": 0,
"max": 5,
"totems": {
"human": {
"value": 1,
"min": 0,
"max": 3
},
"adapted": {
"value": 1,
"min": 0,
"max": 3
}
}
},
"identity": {
"height": 0,
"weight": 0,
+99 -30
View File
@@ -1,23 +1,73 @@
<div class="grid grid-2col">
<div>
<h4 class="align-center">{{ localize "VERMINE.self_control"}}</h4>
<p class="align-center">
<input type="number" name="system.attributes.self_control.value"
value="{{ system.attributes.self_control.value }}" data-dtype="Number"
min="{{ system.attributes.self_control.min }}"
max="{{ system.attributes.self_control.max }}" /> / {{
system.attributes.self_control.max }}
</p>
<h4 class="align-center">{{ localize "VERMINE.self_control"}} :
{{@root.system.attributes.self_control.value}}/
{{@root.system.attributes.self_control.max}}
</h4>
<div class="flexrow">
{{#repeat 10 1}}
<div class="hexa
{{#iflteq @index @root.system.attributes.self_control.value }}
checked
{{/iflteq}}
{{#ifgt @index @root.system.attributes.self_control.max }}
unavailable
{{/ifgt}}">
{{#iflteq @index @root.system.attributes.self_control.max }}
<input type="radio" data-dtype="Number"
name="system.attributes.self_control.value"
value="{{@index}}" {{#ife @root.system.attributes.self_control.value
@index
}}checked="checked"{{/ife}}
class="
{{#iflteq @index @root.system.attributes.self_control.max }}
checked
{{/iflteq}}
" />
{{/iflteq}}
</div>
{{/repeat}}
</div>
</div>
<div>
<h4 class="align-center">{{ localize "VERMINE.effort"}}</h4>
<p class="align-center">
<input type="number" name="system.attributes.effort.value"
value="{{ system.attributes.effort.value }}" data-dtype="Number"
min="{{ system.attributes.effort.min }}"
max="{{ system.attributes.effort.max }}" /> / {{
system.attributes.effort.max }}
</p>
<h4 class="align-center">{{ localize "VERMINE.effort"}} :
{{@root.system.attributes.effort.value}}/
{{@root.system.attributes.effort.max}}
</h4>
<div class="flexrow">
{{#repeat 10 1}}
<div
class="hexa
{{#iflteq @index @root.system.attributes.effort.value }}
checked
{{/iflteq}}
{{#ifgt @index @root.system.attributes.effort.max }}
unavailable
{{/ifgt}}">
{{#iflteq @index @root.system.attributes.effort.max }}
<input type="radio" data-dtype="Number"
name="system.attributes.effort.value"
value="{{@index}}" {{#ife @root.system.attributes.effort.value
@index
}}checked="checked"{{/ife}}
class="
{{#iflteq @index @root.system.attributes.effort.value }}
checked
{{/iflteq}}
" />
{{/iflteq}}
</div>
{{#ife @index 1}}
<br />
{{/ife}}
{{/repeat}}
</div>
</div>
</div>
<h4 class="item-name effect-name flexrow">{{ localize
@@ -26,7 +76,11 @@
<li class="row mdb">{{ localize 'VERMINE.wounds.light'}} <span
data-tooltip="seuil">({{
system.minorWound.threshold }})</span>
<div class="flexrow">
{{#repeat system.minorWound.max 1}}
<div class="hexa ability{{#iflteq @index @root.system.minorWound.value }}
checked
{{/iflteq}}">
<input type="radio" data-dtype="Number" name="system.minorWound.value"
value="{{@index}}" {{#ife @root.system.minorWound.value @index
}}checked="checked"{{/ife}} data-wound="minorWound"
@@ -36,36 +90,51 @@
{{/iflteq}}
" />
{{/repeat}}</li>
<li class="row mdb">{{ localize 'VERMINE.wounds.heavy'}} ({{
system.majorWound.threshold }})
</div>
{{/repeat}}
</div>
</li>
<li class="row mdb">{{ localize 'VERMINE.wounds.heavy'}}
<span>({{
system.majorWound.threshold }})</span>
<div class="flexrow">
{{#repeat system.majorWound.max 1}}
<input type="radio" name="system.majorWound.value" value="{{@index}}" {{#ife
@root.system.majorWound.value @index }}checked="checked"{{/ife}}
data-wound="majorWound"
<div class="hexa ability{{#iflteq @index @root.system.majorWound.value }}
checked
{{/iflteq}}">
<input type="radio" data-dtype="Number" name="system.majorWound.value"
value="{{@index}}" {{#ife @root.system.majorWound.value @index
}}checked="checked"{{/ife}} data-wound="majorWound"
class="
{{#iflteq @index @root.system.majorWound.value }}
checked
{{/iflteq}}
" />
</div>
{{/repeat}}
</li>
<li class="row mdb">{{ localize 'VERMINE.wounds.deadly'}} ({{
system.deadlyWound.threshold }})
{{#repeat system.deadlyWound.max 1}}
<input type="radio" name="system.deadlyWound.value" value="{{@index}}"
{{#ife
@root.system.deadlyWound.value @index }}checked="checked"{{/ife}}
data-wound="deadlyWound"
</div>
</li>
<li class="row mdb">{{ localize 'VERMINE.wounds.deadly'}}
<span>({{system.deadlyWound.threshold }})</span>
<div class="flexrow">
{{#repeat system.deadlyWound.max 1}}
<div class="hexa ability{{#iflteq @index @root.system.deadlyWound.value }}
checked
{{/iflteq}}">
<input type="radio" data-dtype="Number" name="system.deadlyWound.value"
value="{{@index}}" {{#ife @root.system.deadlyWound.value @index
}}checked="checked"{{/ife}} data-wound="deadlyWound"
class="
{{#iflteq @index @root.system.deadlyWound.value }}
checked
{{/iflteq}}
" />
</div>
{{/repeat}}
</div>
</li>
</ul>
<h4 class="item-name effect-name flexrow">{{ localize "UI.effects.name"}}</h4>
+43 -3
View File
@@ -2,15 +2,55 @@
<img class="profile-img" src="{{actor.img}}" data-edit="img"
title="{{actor.name}}" height="100" width="100" />
</div>
<div class="minor-totems ">
<h3>{{localize "ITEMS.evolution"}}</h3>
<h5 class="human
{{#ifgt system.adaptation.totems.human.value system.adaptation.totems.adapted.value}}
major
{{/ifgt}}
">{{localize "TOTEMS.human.name"}}
<img src="/systems/vermine2047/assets/images/ui/totems/human.webp" />
</h5>
<h5 class="adapted
{{#ifgt system.adaptation.totems.human.value system.adaptation.totems.adapted.value}}
major
{{/ifgt}}">{{localize "TOTEMS.adapted.name"}}
<img src="/systems/vermine2047/assets/images/ui/totems/adapted.webp" />
</h5>
<div class="totem-dice flexrow flex-group-center">
<div class="human-dice flexrow">
{{#repeat system.adaptation.totems.human.max 1}}
<div class="hexa" data-totem-name="human" data-totem-value="{{@index}}">
{{#ifgteq system.adaptation.totems.human.value @index}}
<div class="human-die"><i class="fas fa-dice-d10"></i></div>
{{/ifgteq}}
</div>
{{/repeat}}
</div>
<div class="adapted-dice flexrow">
{{#repeat system.adaptation.totems.adapted.max 1}}
<div class="hexa" data-totem-name="adapted" data-totem-value="{{@index}}">
{{#ifgteq system.adaptation.totems.adapted.value @index}}
<div class="adapted-die"><i class="fas fa-dice-d10"></i></div>
{{/ifgteq}}</div>
{{/repeat}}
</div>
</div>
</div>
<ul class="padding-with-frieze unstyled paper">
{{#if system.identity.totem }}
<li class="row lgb">
<li class="row lgb major-totem">
<div class="flexcol flex-group-center items-center w-full">
<h4>{{ smarttl 'TOTEMS' system.identity.totem 'name' }}</h4>
<img
src="/systems/vermine2047/assets/images/ui/totems/{{ system.identity.totem }}.webp"
alt="{{ smarttl 'TOTEMS' system.identity.totem 'name' }}" width="80"
height="80"
data-tooltip="{{localize system.identity.totem}}" />
height="80" />
</div>
</li>
{{/if}}
+47 -14
View File
@@ -1,34 +1,67 @@
<form class="{{cssClass}}" autocomplete="off">
<form
class="{{cssClass}}"
autocomplete="off"
>
<header class="sheet-header">
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}"/>
<img
class="profile-img"
src="{{item.img}}"
data-edit="img"
title="{{item.name}}"
/>
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="Name"/></h1>
<h1 class="charname"><input
name="name"
type="text"
value="{{item.name}}"
placeholder="Name"
/></h1>
</div>
</header>
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item active" data-tab="description">{{ localize "VERMINE.stats" }}</a>
</nav>
<section class="sheet-body">
<div class="tab flexrow" data-group="primary" data-tab="description">
<aside style="flex:1">
<div class="flexrow">
<div class="resource">
<label class="resource-label">{{ localize "VERMINE.clew"}}</label>
<input type="number" name="system.level" value="{{system.level}}" data-dtype="Number"/>
<input
type="number"
name="system.level"
value="{{system.level}}"
data-dtype="Number"
/>
</div>
<div class="resource">
<label class="resource-label">{{ localize "VERMINE.mobility"}}</label>
<input type="number" name="system.mobility" value="{{system.mobility}}" data-dtype="Number"/>
<input
type="number"
name="system.mobility"
value="{{system.mobility}}"
data-dtype="Number"
/>
</div>
<div class="resource">
<label class="resource-label">{{ localize "VERMINE.rarity"}}</label>
<input type="number" name="system.rarity" value="{{system.rarity}}" data-dtype="Number"/>
<input
type="number"
name="system.rarity"
value="{{system.rarity}}"
data-dtype="Number"
/>
</div>
<div class="resource">
<label class="resource-label">{{ localize "VERMINE.reliability"}}</label>
<input type="number" name="system.reliability" value="{{system.reliability}}" data-dtype="Number"/>
<input
type="number"
name="system.reliability"
value="{{system.reliability}}"
data-dtype="Number"
/>
</div>
</aside>
<main class="editor-wrapper" style="flex:10">
</div>
<main
class="editor-wrapper"
style="flex:10"
>
{{editor system.description target="system.description" rollData=rollData button=true owner=owner editable=editable}}
</main>
</div>
-1
View File
@@ -9,7 +9,6 @@
data-edit="img"
title="{{item.name}}"
/>
{{log this}}
<div class="header-fields">
<h1 class="charname"><input
name="name"
@@ -1,5 +1,6 @@
<form id="dice-pool-form" class="ecryme-dv-form"
<form id="dice-pool-form" class="vermine form"
data-actor-id="{{ speakerId }}">
<input type="hidden" name="label" id="label" value="{{ label }}" />
<input type="hidden" name="rollType" id="rollType" value="{{ rollType }}" />
<input type="hidden" name="abilityScore" id="abilityScore"
@@ -16,10 +17,12 @@
<strong>{{#if (eq rollType 'skill')}}{{ smarttl "SKILLS" label
}}{{else}}{{ smarttl "ABILITIES" label }}{{/if}}</strong> </span>
</div>
<div class="flexrow row mdb">
<div class="flexrow form-group row mdb">
<label class="label" style="flex: 60%;">{{localize
'VERMINE.difficulty'}}</label>
<select class="info-value" style="max-width: 40%;" data-dtype="String"
<select class="info-value" data-roll="tue" style="max-width: 40%;"
data-dtype="String"
type="number" name="difficulty" id="difficulty" min="3" max="10">
{{#select difficulty }}
<option value="{{ diffLevel 'difficulty' 1}}">{{ diffLevel 'label' 1}} -
@@ -35,31 +38,64 @@
{{/select}}
</select>
</div>
<!--div class="flexrow row">
<input style="text-align: center;" class="numeric-entry" type="number" name="difficulty" value="7" id="difficulty" min="3" max="10">
</div-->
<div class="flexrow row mdb">
<label class="label" style="flex: 60%;">{{localize
'VERMINE.ability'}}</label>
<select class="info-value" style="max-width: 40%;" data-dtype="String"
<select class="info-value" data-roll="true" style="max-width: 40%;"
data-dtype="String"
type="number" name="ability" id="ability" min="1" max="5">
{{#if (eq rollType 'skill')}}<option>-- Choisissez une caractéristique
--</option>{{/if}}
{{#each abilities as |ability key| }}
<option value="{{ key }}" {{#if (eq key @root.label)}}selected{{/if}}>
{{ smarttl "ABILITIES" key }} - {{ ability.value }}</option>
<option>-- Choisissez une caractéristique
--</option>
{{#each config.abilityCategories as |abilCategory catkey|}}
<optgroup label="{{ smarttlk 'ABILITY_CATEGORIES' catkey 'name' }}">
{{#each @root.actor.system.abilities as |abil key|}}
{{#ife abil.category catkey}}
<option value="{{abil.value}}"
{{#ife @root.rollType "ability"}}
{{#ife @root.labelKey key}}
selected="true"
{{/ife}}
{{/ife}}>{{ smarttlk 'ABILITIES' key 'name'
}} / {{abil.value}}</option>
{{/ife}}
{{/each}}
</optgroup>
{{/each}}
</select>
</div>
{{#if (eq rollType 'skill')}}
<div class="flexrow row mdb">
<label class="label" style="flex: 60%;">{{localize
'VERMINE.skill_title'}}</label>
<select class="info-value" style="max-width: 40%;" data-dtype="String"
<select class="info-value" data-roll="true" style="max-width: 40%;"
data-dtype="String"
type="number" name="skill" id="skill" min="1" max="5">
{{#each skills as |skill key| }}
<option value="{{ key }}" {{#if (eq key @root.label)}}selected{{/if}}>
{{ smarttl "SKILLS" key }} - {{ skill.value }}</option>
<option>-- Choisissez une caractéristique
--</option>
{{#each config.skillCategories as |skillCategory catkey|}}
<optgroup label="{{ smarttlk 'SKILLS_CATEGORIES' catkey 'name' }}">
{{#each @root.actor.system.skills as |skill key|}}
{{#ife skill.category catkey}}
<option value="{{skill.value}}" data-pool="{{skillLevel "dicePool"
skill.value}}"
data-reroll="{{skillLevel "reroll" skill.value}}"
{{#ife @root.rollType "skill"}}
{{#ife @root.labelKey key}}
selected="true"
{{/ife}}
{{/ife}}>
<b>{{ smarttlk 'SKILLS' key 'name' }},</b>
<i>dés:{{skillLevel "dicePool" skill.value}},
relances:{{skillLevel "reroll" skill.value}}</i>
</option>
{{/ife}}
{{/each}}
</optgroup>
{{/each}}
</select>
</div>
@@ -75,31 +111,52 @@
</div>
<div class="flexrow row smb">
<label class="label">{{localize 'VERMINE.specialty'}} (+1D)</label>
<input type="checkbox" name="usingSpecialization" id="usingSpecialization"
<input type="checkbox" data-roll="true" name="usingSpecialization"
id="usingSpecialization"
value="1" {{#if specialty}}checked{{/if}}>
</div>
{{/if}}
<div class="flexrow row smb">
<label class="label">{{localize 'VERMINE.help'}} (+1D)</label>
<input type="checkbox" name="helped" id="helped" value="1" {{#if
<input type="checkbox" data-roll="true" name="helped" id="helped"
value="1" {{#if
help}}checked{{/if}}>
</div>
<div class="flexrow row mdb">
<label class="label">{{localize 'VERMINE.tooling'}} (+1D)</label>
<input type="checkbox" name="usingTools" id="usingTools" value="1" {{#if
<input type="checkbox" data-roll="true" name="usingTools" id="usingTools"
value="1" {{#if
help}}checked{{/if}}>
</div>
<div class="flexrow row mdb">
<label class="label" style="flex: 80%;">{{localize
'VERMINE.self_control'}}</label>
<input type="number" class="numeric-entry" style="text-align: center;"
name="self_control" id="self_control" min="0" max="5" value="0">
'VERMINE.self_control'}} <span id="self_control_value"></span>
</label>
<input type="range" id="self_control" data-roll="true" name="self_control"
min="0"
max="0" value="0" />
</div>
<div class="flexrow">
<h4 class="label">utiliser des dés totems ?
</h4>
<div class="totem-human">
<label for="human-totem">totem humain </label>
<input type="checkbox" data-roll="true" name="human-totem"
id="human-totem"
value="1">
</div>
<div class="totem-adapted">
<label for="human-totem">totem adapté </label>
<input type="checkbox" data-roll="true" name="adapted-totem"
id="adapted-totem"
value="1">
</div>
</div>
<div class="flexrow row mdb">
<label class="label" style="flex: 80%;">{{localize
'VERMINE.group'}}</label>
<input type="number" class="numeric-entry" style="text-align: center;"
name="group" id="group" min="0" max value="0">
<input type="number" data-roll="true" class="numeric-entry"
style="text-align: center;"
name="group" id="group" min="0" max="5" value="0">
</div>
</div>
<p><input type="hidden" name="speakerId" value="{{ speakerId }}" />
+68 -19
View File
@@ -1,26 +1,75 @@
<div class="ecryme-dv roll attribute">
<div class="dice-roll">
<div class="dice-result">
<div class="dice-formula">
{{ ` + dicePool + `d6 }}
<div class="vermine-roll-message">
{{log this}}
<h3>{{param.actor.name}} : test de {{param.rollLabel}}</h3>
<div class="flexrow">
<h4>difficulté</h4>
<span id="difficulty">{{param.difficulty}}</span>
</div>
<div class="dice-tooltip expanded">
<section class="tooltip-part flexrow">
<div class="" style="flex:60%;">
<div class="parameters">
{{ targetText }}
<ul class="flexrow roll-results initial-roll"
data-difficulty="{{param.difficulty}}">
{{#each roll.dice as |dieType index|}}
{{#each dieType.results as |die index|}}
<li class="roll die flexcol
{{#if die.success}}
success
{{/if}}
{{#ifincludes dieType.options.flavor "adapted"}}
adapted
{{/ifincludes}}
{{#ifincludes dieType.options.flavor "regular"}}
regular
{{/ifincludes}}
{{#ifincludes dieType.options.flavor "human"}}
human
{{/ifincludes}}
{{#ifgt @root.param.Reroll 0}}
rerollable
{{/ifgt}}
"
data-dice-type="
{{#ifincludes dieType.options.flavor "adapted"}}
adapted
{{/ifincludes}}
{{#ifincludes dieType.options.flavor "regular"}}
regular
{{/ifincludes}}
{{#ifincludes dieType.options.flavor "human"}}
human
{{/ifincludes}}">
<span>{{die.result}}</span>
</li>
{{/each}}
{{/each}}
</ul>
<div class="roll-total flexrow">
<h4>nombre de succès :</h4>
<span id="total">{{roll._total}}</span>
</div>
<div class="dice">
<ol class="dice-rolls">{{ diceString }}</ol>
<div class="reroll flexrow">
<div class="reroll-from-effort ">
<div class="flexcol">
<h4 class="flexcol">
<span>effort</span>
</h4>
<input type="range" min="0"
{{#iflt param.max_effort param.actor.system.attributes.effort.value}}
max="{{param.max_effort}}"
{{/iflt}}
{{#iflteq param.actor.system.attributes.effort.value param.max_effort }}
max="{{param.actor.system.attributes.effort.value}}"
{{/iflteq}}
value="0"
id="effort-reroll">
</input>
</div>
<button class="grant-reroll" data-tooltip="s'accorder des relances"> <span id="granted-reroll">0</span> </button>
</div>
<div class="align-center">
Résultat
<p style="font-weight:bold; font-size:2em;">{{ (total + skill + _trait + _usingSpecialization + _used).toString() }}</p>
</div>
</section>
</div>` +
`<h4 class="dice-total">{{ successText }}</h4>
<div class="reroll-fromroll">
<h4>relances possibles : </h4>
<span id="allowed_reroll">{{param.Reroll}}</span>
</div>
</div>
</div>