forked from public/foundryvtt-reve-de-dragon
Compare commits
17 Commits
foundryvtt
...
foundryvtt
| Author | SHA1 | Date | |
|---|---|---|---|
| da4e18dc3c | |||
| 154a9b7a37 | |||
| fb8189606b | |||
| cfbfad27bd | |||
| f541849306 | |||
| d2d1891838 | |||
| 5580b6d59c | |||
| 40c45c30de | |||
| 1b6c5256cc | |||
| c0e6759164 | |||
| a096590a07 | |||
| 9883048fb5 | |||
| 7bec42c4cf | |||
| 6708dc0da9 | |||
| 96c2da0d05 | |||
| 2b19250e8b | |||
| 957eabcac7 |
@@ -14,6 +14,7 @@ import { MAINS_DIRECTRICES } from "./actor.js";
|
||||
import { RdDBaseActorSheet } from "./actor/base-actor-sheet.js";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { RdDItemBlessure } from "./item/blessure.js";
|
||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/**
|
||||
@@ -83,6 +84,7 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.system.carac);
|
||||
formData.esquives = this.actor.getCompetences("Esquive");
|
||||
formData.combat = RdDCombatManager.listActionsArmes(formData.combat, formData.competences, formData.system.carac);
|
||||
formData.empoignades = this.actor.getEmpoignades();
|
||||
|
||||
this.armesList = formData.combat;
|
||||
|
||||
@@ -254,6 +256,11 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
this.actor.rollCarac('reve-actuel', true);
|
||||
});
|
||||
|
||||
// Suite empoignade
|
||||
this.html.find('.empoignade-label a').click(async event => {
|
||||
let emp = RdDSheetUtility.getItem(event, this.actor)
|
||||
RdDEmpoignade.onAttaqueEmpoignadeFromItem(emp)
|
||||
});
|
||||
// Roll Weapon1
|
||||
this.html.find('.arme-label a').click(async event => {
|
||||
let arme = this._getEventArmeCombat(event);
|
||||
|
||||
@@ -36,6 +36,7 @@ import { RdDBaseActor } from "./actor/base-actor.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
import { RdDItemBlessure } from "./item/blessure.js";
|
||||
import { AppAstrologie } from "./sommeil/app-astrologie.js";
|
||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||
|
||||
const POSSESSION_SANS_DRACONIC = {
|
||||
img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
|
||||
@@ -97,7 +98,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async cleanupConteneurs() {
|
||||
let updates = this.listItems('conteneur')
|
||||
let updates = this.itemTypes['conteneur']
|
||||
.filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0)
|
||||
.map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } });
|
||||
if (updates.length > 0) {
|
||||
@@ -231,7 +232,6 @@ export class RdDActor extends RdDBaseActor {
|
||||
getCompetences(name) {
|
||||
return RdDItemCompetence.findCompetences(this.items, name)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getTache(id) {
|
||||
return this.findItemLike(id, 'tache');
|
||||
@@ -286,7 +286,9 @@ export class RdDActor extends RdDBaseActor {
|
||||
getPossessions() {
|
||||
return this.items.filter(it => it.type == 'possession');
|
||||
}
|
||||
|
||||
getEmpoignades() {
|
||||
return this.items.filter(it => it.type == 'empoignade');
|
||||
}
|
||||
getDemiReve() {
|
||||
return this.system.reve.tmrpos.coord;
|
||||
}
|
||||
@@ -329,8 +331,15 @@ export class RdDActor extends RdDBaseActor {
|
||||
return '';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
hasArmeeMeleeEquipee() { // Return true si l'acteur possède au moins 1 arme de mêlée équipée
|
||||
return this.itemTypes['arme'].find(it => it.system.equipe && it.system.competence != "")
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async roll() {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
|
||||
const carac = mergeObject(duplicate(this.system.carac),
|
||||
{
|
||||
'reve-actuel': this.getCaracReveActuel(),
|
||||
@@ -1086,16 +1095,12 @@ export class RdDActor extends RdDBaseActor {
|
||||
/* -------------------------------------------- */
|
||||
computeIsHautRevant() {
|
||||
if (this.isPersonnage()) {
|
||||
this.system.attributs.hautrevant.value = this.hasItemNamed('tete', 'don de haut-reve')
|
||||
this.system.attributs.hautrevant.value = this.itemTypes['tete'].find(it => Grammar.equalsInsensitive(it.name, 'don de haut-reve'))
|
||||
? "Haut rêvant"
|
||||
: "";
|
||||
}
|
||||
}
|
||||
|
||||
hasItemNamed(type, name) {
|
||||
name = Grammar.toLowerCaseNoAccent(name);
|
||||
return this.listItems(type).find(it => Grammar.toLowerCaseNoAccent(it.name) == name);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async computeMalusArmure() {
|
||||
@@ -1657,9 +1662,9 @@ export class RdDActor extends RdDBaseActor {
|
||||
await this.rollTache(tache.id);
|
||||
}
|
||||
}
|
||||
async actionHerbe(item, onActionItem = async () => {}) {
|
||||
async actionHerbe(item, onActionItem = async () => { }) {
|
||||
if (item.isHerbeAPotion()) {
|
||||
return DialogFabriquerPotion.create(this, item, onActionItem);
|
||||
return DialogFabriquerPotion.create(this, item, onActionItem);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2061,12 +2066,13 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollUnSort(coord) {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
if (EffetsDraconiques.isSortImpossible(this)) {
|
||||
ui.notifications.error("Une queue ou un souffle vous empèche de lancer de sort!");
|
||||
return;
|
||||
}
|
||||
// Duplication car les pts de reve sont modifiés dans le sort
|
||||
let sorts = duplicate(this.$filterSortList(this.getSortList(), coord));
|
||||
let sorts = duplicate(this.$filterSortList(this.itemTypes['sort'], coord));
|
||||
if (sorts.length == 0) {
|
||||
ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
|
||||
return;
|
||||
@@ -2200,6 +2206,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollCarac(caracName, jetResistance = undefined) {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
let selectedCarac = this.getCaracByName(caracName)
|
||||
await this._openRollDialog({
|
||||
name: 'jet-' + caracName,
|
||||
@@ -2267,6 +2274,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollCompetence(idOrName, options = { tryTarget: true }) {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
let rollData = {
|
||||
carac: this.system.carac,
|
||||
competence: this.getCompetence(idOrName)
|
||||
@@ -2338,7 +2346,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
async getTacheBlessure(blesse, blessure) {
|
||||
const gravite = blessure?.system.gravite ?? 0;
|
||||
if (gravite > 0) {
|
||||
const tache = this.listItems('tache').find(it => it.system.itemId == blessure.id)
|
||||
const tache = this.itemTypes['tache'].find(it => it.system.itemId == blessure.id)
|
||||
?? await RdDItemBlessure.createTacheSoinBlessure(this, gravite);
|
||||
await blessure?.updateTacheSoinBlessure(tache);
|
||||
return tache
|
||||
@@ -2347,6 +2355,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
}
|
||||
|
||||
async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
const competence = this.getCompetence(compName);
|
||||
await this._openRollDialog({
|
||||
name: 'jet-competence',
|
||||
@@ -2367,6 +2376,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollTache(id, options = {}) {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
const tacheData = this.getTache(id)
|
||||
const compData = this.getCompetence(tacheData.system.competence)
|
||||
compData.system.defaut_carac = tacheData.system.carac; // Patch !
|
||||
@@ -2633,7 +2643,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
/* -------------------------------------------- */
|
||||
_getSignesDraconiques(coord) {
|
||||
const type = TMRUtility.getTMRType(coord);
|
||||
return this.listItems("signedraconique").filter(it => it.system.typesTMR.includes(type));
|
||||
return this.itemTypes["signedraconique"].filter(it => it.system.typesTMR.includes(type));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -2840,8 +2850,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async resetNombresAstraux() {
|
||||
let toDelete = this.listItems('nombreastral');
|
||||
const deletions = toDelete.map(it => it._id);
|
||||
const deletions = this.itemTypes['nombreastral'].map(it => it._id);
|
||||
await this.deleteEmbeddedDocuments("Item", deletions);
|
||||
}
|
||||
|
||||
@@ -2865,7 +2874,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
async supprimerAnciensNombresAstraux() {
|
||||
const calendrier = game.system.rdd.calendrier;
|
||||
if (calendrier) {
|
||||
const toDelete = this.listItems('nombreastral')
|
||||
const toDelete = this.itemTypes['nombreastral']
|
||||
.filter(it => calendrier.isAfterIndexDate(it.system.jourindex))
|
||||
.map(it => it._id);
|
||||
await this.deleteEmbeddedDocuments("Item", toDelete);
|
||||
@@ -2923,11 +2932,6 @@ export class RdDActor extends RdDBaseActor {
|
||||
return entry && entry.length > 0 ? carac[entry[0]] : undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getSortList() {
|
||||
return this.listItems("sort");
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
countMonteeLaborieuse() { // Return +1 par queue/ombre/souffle Montée Laborieuse présente
|
||||
let countMonteeLaborieuse = EffetsDraconiques.countMonteeLaborieuse(this);
|
||||
@@ -2987,8 +2991,8 @@ export class RdDActor extends RdDBaseActor {
|
||||
mode: mode,
|
||||
fatigue: RdDUtility.calculFatigueHtml(fatigue, endurance),
|
||||
draconic: this.getDraconicList(),
|
||||
sort: this.getSortList(),
|
||||
signes: this.listItems("signedraconique"),
|
||||
sort: this.itemTypes['sort'],
|
||||
signes: this.itemTypes['signedraconique'],
|
||||
caracReve: this.system.carac.reve.value,
|
||||
pointsReve: this.getReveActuel(),
|
||||
isRapide: isRapide,
|
||||
@@ -3128,7 +3132,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
/* -------------------------------------------- */
|
||||
async equiperObjet(itemID) {
|
||||
let item = this.getEmbeddedDocument('Item', itemID);
|
||||
if (item && ['arme', 'armure'].includes(item.type)) {
|
||||
if (item?.isEquipable()) {
|
||||
const isEquipe = !item.system.equipe;
|
||||
await this.updateEmbeddedDocuments('Item', [{ _id: item.id, "system.equipe": isEquipe }]);
|
||||
this.computeEncTotal(); // Mise à jour encombrement
|
||||
@@ -3754,6 +3758,9 @@ export class RdDActor extends RdDBaseActor {
|
||||
case 'casetmr':
|
||||
await this.onDeleteOwnedCaseTmr(item, options, id);
|
||||
break;
|
||||
case 'empoignade':
|
||||
await RdDEmpoignade.deleteLinkedEmpoignade(this.id, item)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export class RdDBaseActor extends Actor {
|
||||
case "msg_refresh_nombre_astral":
|
||||
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static remoteActorCall(callData, userId = undefined) {
|
||||
@@ -109,7 +109,6 @@ export class RdDBaseActor extends Actor {
|
||||
isEntite() { return this.type == 'entite'; }
|
||||
isPersonnage() { return this.type == 'personnage'; }
|
||||
isVehicule() { return this.type == 'vehicule'; }
|
||||
|
||||
getItem(id, type = undefined) {
|
||||
const item = this.items.get(id);
|
||||
if (type == undefined || (item?.type == type)) {
|
||||
@@ -119,7 +118,7 @@ export class RdDBaseActor extends Actor {
|
||||
}
|
||||
|
||||
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
|
||||
filterItems(filter, type = undefined) { return this.listItems(type)?.filter(filter) ?? []; }
|
||||
filterItems(filter, type = undefined) { return type ? this.itemTypes[type]?.filter(filter) ?? [] : []; }
|
||||
findItemLike(idOrName, type) {
|
||||
return this.getItem(idOrName, type)
|
||||
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
|
||||
@@ -244,13 +243,16 @@ export class RdDBaseActor extends Actor {
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const cout = Number(achat.prixTotal ?? 0);
|
||||
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
|
||||
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined;
|
||||
const vente = achat.vente;
|
||||
const quantite = (achat.choix.nombreLots ?? 1) * (vente.tailleLot);
|
||||
const itemVendu = vendeur?.getItem(vente.item._id);
|
||||
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
|
||||
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id) ?? achat.vente.item;
|
||||
if (!itemVendu) {
|
||||
ui.notifications.warn("Erreur sur achat: rien à acheter<br>Si possible, transmettez les logs de la console aux développeurs");
|
||||
console.log('Erreur sur achat: rien à acheter', achat);
|
||||
return;
|
||||
}
|
||||
if (!this.verifierQuantite(vendeur, itemVendu, quantite)) {
|
||||
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
|
||||
return
|
||||
@@ -262,13 +264,13 @@ export class RdDBaseActor extends Actor {
|
||||
await this.decrementerVente(vendeur, itemVendu, quantite, cout);
|
||||
if (acheteur) {
|
||||
await acheteur.depenserSols(cout);
|
||||
const createdItemId = await acheteur.creerQuantiteItem(vente.item, quantite);
|
||||
await acheteur.consommerNourritureAchetee(achat, vente, createdItemId);
|
||||
const createdItemId = await acheteur.creerQuantiteItem(achat.vente.item, quantite);
|
||||
await acheteur.consommerNourritureAchetee(achat, achat.vente, createdItemId);
|
||||
}
|
||||
if (cout > 0) {
|
||||
RdDAudio.PlayContextAudio("argent");
|
||||
}
|
||||
const chatAchatItem = duplicate(vente);
|
||||
const chatAchatItem = duplicate(achat.vente);
|
||||
chatAchatItem.quantiteTotal = quantite;
|
||||
ChatMessage.create({
|
||||
user: achat.userId,
|
||||
@@ -277,16 +279,16 @@ export class RdDBaseActor extends Actor {
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', chatAchatItem)
|
||||
});
|
||||
|
||||
if (!vente.quantiteIllimite) {
|
||||
if (vente.quantiteNbLots <= achat.choix.nombreLots) {
|
||||
if (!achat.vente.quantiteIllimite) {
|
||||
if (achat.vente.quantiteNbLots <= achat.choix.nombreLots) {
|
||||
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
|
||||
}
|
||||
else if (achat.chatMessageIdVente) {
|
||||
vente["properties"] = itemVendu.getProprietes();
|
||||
vente.quantiteNbLots -= achat.choix.nombreLots;
|
||||
vente.jsondata = JSON.stringify(vente.item);
|
||||
achat.vente.properties = itemVendu.getProprietes();
|
||||
achat.vente.quantiteNbLots -= achat.choix.nombreLots;
|
||||
achat.vente.jsondata = JSON.stringify(achat.vente.item);
|
||||
const messageVente = game.messages.get(achat.chatMessageIdVente);
|
||||
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente) });
|
||||
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', achat.vente) });
|
||||
messageVente.render(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export class DialogItemAchat extends Dialog {
|
||||
}
|
||||
|
||||
return {
|
||||
item: (json ? JSON.parse(json) : undefined),
|
||||
item: JSON.parse(json),
|
||||
vendeur,
|
||||
acheteur,
|
||||
nbLots: parseInt(chatButton.attributes['data-quantiteNbLots']?.value),
|
||||
@@ -34,7 +34,6 @@ export class DialogItemAchat extends Dialog {
|
||||
const venteData = {
|
||||
item,
|
||||
actingUserId: game.user.id,
|
||||
vendeurId: vendeur?.id,
|
||||
vendeur,
|
||||
acheteur,
|
||||
tailleLot,
|
||||
|
||||
@@ -165,7 +165,7 @@ export class RdDItemArme extends Item {
|
||||
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { system: { niveau: -6 } };
|
||||
let init = RdDCombatManager.calculInitiative(corpsACorps.system.niveau, carac['melee'].value);
|
||||
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.system.niveau, initiative: init }));
|
||||
//armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
|
||||
armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
|
||||
}
|
||||
|
||||
static corpsACorps(mainsNuesActor) {
|
||||
|
||||
@@ -34,6 +34,7 @@ const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
|
||||
const typesObjetsEffet = ["possession", "poison", "maladie", "blessure"]
|
||||
const typesObjetsCompetence = ["competence", "competencecreature"]
|
||||
const typesObjetsTemporels = ["blessure", "poison", "maladie", "queue", "ombre", "souffle", "signedraconique", "rencontre"]
|
||||
const typesObjetsEquipable = ['arme', 'armure', 'objet'];
|
||||
const typesEnvironnement = typesInventaireMateriel;
|
||||
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
|
||||
const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc
|
||||
@@ -75,11 +76,16 @@ export const defaultItemImg = {
|
||||
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
|
||||
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
|
||||
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
|
||||
empoignade: "systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp"
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItem extends Item {
|
||||
|
||||
static get defaultIcon() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static getDefaultImg(itemType) {
|
||||
return game.system.rdd.itemClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
||||
}
|
||||
@@ -138,10 +144,6 @@ export class RdDItem extends Item {
|
||||
super(docData, context);
|
||||
}
|
||||
|
||||
static get defaultIcon() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getUniteQuantite() {
|
||||
switch (this.type) {
|
||||
case "monnaie": return "(Pièces)"
|
||||
@@ -157,6 +159,10 @@ export class RdDItem extends Item {
|
||||
return '';
|
||||
}
|
||||
|
||||
isEquipable() {
|
||||
return typesObjetsEquipable.includes(this.type)
|
||||
}
|
||||
|
||||
isCompetencePersonnage() { return this.type == 'competence' }
|
||||
isCompetenceCreature() { return this.type == 'competencecreature' }
|
||||
isConteneur() { return this.type == 'conteneur'; }
|
||||
@@ -366,6 +372,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
this.system.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
|
||||
}
|
||||
this.equipable = this.isEquipable();
|
||||
}
|
||||
|
||||
prepareDataPotion() {
|
||||
|
||||
@@ -24,6 +24,9 @@ export class RdDBonus {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isDefenseAttaqueFinesse(rollData) {
|
||||
if (rollData.isEmpoignade && rollData.rolled?.isPart) {
|
||||
return true
|
||||
}
|
||||
return rollData.attackerRoll?.particuliere == 'finesse';
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { RdDRollTables } from "./rdd-rolltables.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
import { Targets } from "./targets.js";
|
||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const premierRoundInit = [
|
||||
@@ -57,6 +58,7 @@ export class RdDCombatManager extends Combat {
|
||||
ChatUtility.removeChatMessageContaining(`<div data-combatid="${this.id}" data-combatmessage="actor-turn-summary">`)
|
||||
game.messages.filter(m => ChatUtility.getMessageData(m, 'attacker-roll') != undefined && ChatUtility.getMessageData(m, 'defender-roll') != undefined)
|
||||
.forEach(it => it.delete());
|
||||
RdDEmpoignade.deleteAllEmpoignades()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,13 +93,26 @@ export class RdDCombatManager extends Combat {
|
||||
}
|
||||
} else {
|
||||
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
|
||||
const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.system.competence;
|
||||
let compName = "Corps à corps"
|
||||
if (armeCombat) {
|
||||
if (armeCombat.system.competence != "") {
|
||||
compName = armeCombat.system.competence
|
||||
}
|
||||
if (armeCombat.system.lancer != "") {
|
||||
compName = armeCombat.system.lancer
|
||||
}
|
||||
if (armeCombat.system.tir != "") {
|
||||
compName = armeCombat.system.tir
|
||||
}
|
||||
}
|
||||
const competence = RdDItemCompetence.findCompetence(combatant.actor.items, compName);
|
||||
if (competence) {
|
||||
if (competence && competence.system.defaut_carac) {
|
||||
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
|
||||
const niveau = competence.system.niveau;
|
||||
const bonusEcaille = (armeCombat?.system.magique) ? armeCombat.system.ecaille_efficacite : 0;
|
||||
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille);
|
||||
} else {
|
||||
ui.notifications.warn(`Votre arme ${armeCombat.name} n'a pas de compétence renseignée`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,7 +259,7 @@ export class RdDCombatManager extends Combat {
|
||||
} else if (actor.isPersonnage()) {
|
||||
// Recupération des items 'arme'
|
||||
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
|
||||
//.concat(RdDItemArme.empoignade())
|
||||
.concat(RdDItemArme.empoignade())
|
||||
.concat(RdDItemArme.mainsNues());
|
||||
|
||||
const competences = actor.itemTypes['competence'];
|
||||
@@ -737,17 +752,11 @@ export class RdDCombat {
|
||||
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
|
||||
return;
|
||||
}
|
||||
if (arme.system.cac == 'empoignade' && this.attacker.isCombatTouche()) {
|
||||
ChatMessage.create({
|
||||
alias: this.attacker.name,
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-actor-perte-empoignade.html', {
|
||||
attacker: this.attacker,
|
||||
competence: competence
|
||||
})
|
||||
});
|
||||
if (arme.system.cac == 'empoignade') {
|
||||
RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender)
|
||||
return;
|
||||
}
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this.attacker)
|
||||
|
||||
let rollData = this._prepareAttaque(competence, arme);
|
||||
console.log("RdDCombat.attaque >>>", rollData);
|
||||
|
||||
314
module/rdd-empoignade.js
Normal file
314
module/rdd-empoignade.js
Normal file
@@ -0,0 +1,314 @@
|
||||
/* -------------------------------------------- */
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDRoll } from "./rdd-roll.js";
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDEmpoignade {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static init() {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static checkEmpoignadeEnCours(actor) {
|
||||
// TODO: autoriser la perception? la comédie/séduction?
|
||||
if (RdDEmpoignade.isEmpoignadeEnCours(actor)) {
|
||||
ui.notifications.warn("Une empoignade est en cours ! Normalement, vous ne pouvez rien faire d'autre que continuer l'empoignade ou la rompre.")
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isEmpoignadeEnCours(actor) {
|
||||
return actor.itemTypes['empoignade'].find(it => it.system.pointsemp > 0)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getEmpoignadeById(actor, id) {
|
||||
let emp = actor.itemTypes['empoignade'].find(it => it.system.empoignadeid == id)
|
||||
return emp && duplicate(emp) || undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getEmpoignade(attacker, defender) {
|
||||
let emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id)
|
||||
if (!emp) {
|
||||
emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
|
||||
}
|
||||
if (emp) {
|
||||
return duplicate(emp);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getMalusTaille(emp, attacker, defender) {
|
||||
// Si pas empoigné, alors 0
|
||||
if (emp.system.pointsemp == 0) {
|
||||
return 0
|
||||
}
|
||||
// Malus de -1 si différence de taille de 2 ou plus (p 135)
|
||||
if (attacker.system.carac.taille.value < defender.system.carac.taille.value - 1) {
|
||||
return attacker.system.carac.taille.value - (defender.system.carac.taille.value - 1)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignadeValidee(attacker, defender) {
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
const isNouvelle = empoignade == undefined;
|
||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||
|
||||
let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
|
||||
|
||||
let rollData = {
|
||||
mode: mode,
|
||||
isEmpoignade: true,
|
||||
competence: attacker.getCompetence("Corps à corps"),
|
||||
selectedCarac: attacker.system.carac.melee,
|
||||
empoignade: empoignade,
|
||||
attackerId: attacker.id,
|
||||
attackerName: attacker.name,
|
||||
defenderName: defender.name,
|
||||
defenderId: defender.id,
|
||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
||||
}
|
||||
if (attacker.isCreatureEntite()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||
}
|
||||
if (empoignade.system.pointsemp >= 2) {
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
} else {
|
||||
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignade(attacker, defender) {
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
const isNouvelle = empoignade == undefined;
|
||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||
//console.log("W.", empoignade, defender.hasArmeeMeleeEquipee())
|
||||
if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) {
|
||||
ChatUtility.createChatWithRollMode(attacker.name, {
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.html`, { attacker: attacker, defender: defender })
|
||||
})
|
||||
} else {
|
||||
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignadeFromItem(empoignade) {
|
||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
|
||||
const dialog = await RdDRoll.create(attacker, rollData,
|
||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
|
||||
{
|
||||
name: 'jet-empoignade',
|
||||
label: 'Empoigner',
|
||||
callbacks: [
|
||||
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, true, isNouvelle) },
|
||||
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, false, isNouvelle) },
|
||||
]
|
||||
});
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $onRollEmpoignade(rollData, isSuccess, isNouvelle = false) {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
|
||||
let empoignade = rollData.empoignade
|
||||
empoignade.isSuccess = isSuccess;
|
||||
|
||||
if (isSuccess && isNouvelle) {
|
||||
// Creer l'empoignade sur attaquant/defenseur
|
||||
await attacker.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
||||
await defender.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
||||
}
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onDefenseEmpoignade(rollData, defenseMode, competenceName = "Corps à corps", carac = "melee") {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
if (!empoignade) {
|
||||
ui.notifications.warn("Une erreur s'est produite : Aucune empoignade trouvée !!")
|
||||
return
|
||||
}
|
||||
|
||||
empoignade = duplicate(empoignade)
|
||||
rollData.mode = defenseMode
|
||||
rollData.empoignade = empoignade
|
||||
rollData.competence = defender.getCompetence(competenceName),
|
||||
rollData.selectedCarac = defender.system.carac[carac],
|
||||
rollData.malusTaille = RdDEmpoignade.getMalusTaille(empoignade, defender, attacker)
|
||||
|
||||
await RdDEmpoignade.$rollDefenseEmpoignade(defender, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $rollDefenseEmpoignade(defender, rollData) {
|
||||
const dialog = await RdDRoll.create(defender, rollData,
|
||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.html' },
|
||||
{
|
||||
name: 'empoignade',
|
||||
label: 'Contrer',
|
||||
callbacks: [
|
||||
{ action: async (r) => await RdDEmpoignade.$onRollContrerLiberer(r) }
|
||||
]
|
||||
}
|
||||
);
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $onRollContrerLiberer(rollData) {
|
||||
let empoignade = rollData.empoignade
|
||||
|
||||
if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) {
|
||||
empoignade.system.pointsemp++
|
||||
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
||||
}
|
||||
if (rollData.mode == "contrer-liberer" && !rollData.rolled.isSuccess) {
|
||||
empoignade.system.pointsemp--
|
||||
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
||||
}
|
||||
|
||||
if (empoignade.system.pointsemp >= 2) {
|
||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
}
|
||||
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.html')
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $updateEtatEmpoignade(empoignade) {
|
||||
console.log("UPDATE Empoignade", empoignade)
|
||||
|
||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||
let update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
||||
await defender.updateEmbeddedDocuments('Item', [update])
|
||||
|
||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
||||
update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
||||
await attacker.updateEmbeddedDocuments('Item', [update])
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $deleteEmpoignade(empoignade) {
|
||||
console.log("DELETE Empoignade", empoignade)
|
||||
|
||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||
await defender.deleteEmbeddedDocuments('Item', [emp._id])
|
||||
|
||||
//let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
//emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
||||
//await attacker.deleteEmbeddedDocuments('Item', [emp._id])
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async entrainerAuSol(rollData) {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
empoignade.system.ausol = true
|
||||
await this.$updateEtatEmpoignade(empoignade)
|
||||
|
||||
await attacker.setEffect(STATUSES.StatusProne, true);
|
||||
await defender.setEffect(STATUSES.StatusProne, true);
|
||||
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async projeterAuSol(rollData) {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
await defender.setEffect(STATUSES.StatusProne, true);
|
||||
await this.$deleteEmpoignade(empoignade)
|
||||
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static async perteEndurance(rollData, perteMode) {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
//console.log("Perte d'endurance :!!!", perteMode)
|
||||
let endValue = defender.system.sante.endurance.value
|
||||
if (perteMode == "end0") {
|
||||
await defender.santeIncDec("endurance", -endValue);
|
||||
}
|
||||
if (perteMode == "end1") {
|
||||
await defender.santeIncDec("endurance", -(endValue - 1));
|
||||
}
|
||||
if (perteMode == "endmoitie") {
|
||||
await defender.santeIncDec("endurance", -Math.floor(endValue / 2));
|
||||
}
|
||||
if (perteMode == "endquart") {
|
||||
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4)));
|
||||
}
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async deleteAllEmpoignades() {
|
||||
for (let actor of game.actors) {
|
||||
let empIds = actor.itemTypes["empoignade"].map(it => it.id)
|
||||
await actor.deleteEmbeddedDocuments('Item', empIds)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async deleteLinkedEmpoignade(actorId, empoignade) {
|
||||
let actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid
|
||||
let actor = game.actors.get(actorDeleteId)
|
||||
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
|
||||
if (emp) {
|
||||
await actor.deleteEmbeddedDocuments('Item', [emp._id])
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createEmpoignade(attacker, defender) {
|
||||
return await Item.create({
|
||||
name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name,
|
||||
type: 'empoignade',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
||||
system: { description: "", empoignadeid: randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name }
|
||||
},
|
||||
{
|
||||
temporary: true
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,7 @@ export class SystemReveDeDragon {
|
||||
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
||||
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
|
||||
"nombreastral", "tache", "maladie", "poison", "possession",
|
||||
"tarot", "extraitpoetique"
|
||||
"tarot", "extraitpoetique", "empoignade"
|
||||
], makeDefault: true
|
||||
});
|
||||
CONFIG.Combat.documentClass = RdDCombatManager;
|
||||
|
||||
@@ -15,6 +15,7 @@ import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
import { RdDRaretes } from "./item/raretes.js";
|
||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// This table starts at 0 -> niveau -10
|
||||
@@ -688,6 +689,44 @@ export class RdDUtility {
|
||||
RdDPossession.onDefensePossession(attackerId, defenderId, possessionId)
|
||||
});
|
||||
|
||||
html.on("click", '.defense-empoignade-cac', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
|
||||
});
|
||||
html.on("click", '.defense-empoignade-esquive', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
|
||||
});
|
||||
html.on("click", '.empoignade-poursuivre', event => {
|
||||
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
||||
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
||||
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
|
||||
});
|
||||
html.on("click", '.empoignade-entrainer-sol', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
RdDEmpoignade.entrainerAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
});
|
||||
html.on("click", '.empoignade-projeter-sol', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
RdDEmpoignade.projeterAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
});
|
||||
html.on("change", '.empoignade-perte-endurance', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
if (event.currentTarget.value && event.currentTarget.value != "none") {
|
||||
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
}
|
||||
});
|
||||
|
||||
// gestion bouton tchat Acheter
|
||||
html.on("click", '.button-acheter', event => {
|
||||
const venteData = DialogItemAchat.preparerAchat(event.currentTarget);
|
||||
|
||||
@@ -139,6 +139,12 @@ export const referenceAjustements = {
|
||||
isUsed: (rollData, actor) => rollData.ethylisme != undefined,
|
||||
getLabel: (rollData, actor) => "Ethylisme - " + RdDUtility.getNomEthylisme(rollData.ethylisme),
|
||||
getValue: (rollData, actor) => rollData.ethylisme,
|
||||
},
|
||||
tailleempoignade: {
|
||||
isVisible: (rollData, actor) => rollData.isEmpoignade,
|
||||
isUsed: (rollData, actor) => rollData.isEmpoignade,
|
||||
getLabel: (rollData, actor) => "Malus de taille",
|
||||
getValue: (rollData, actor) => rollData.malusTaille,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SYSTEM_RDD } from "../constants.js";
|
||||
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "../constants.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
||||
|
||||
@@ -57,7 +57,7 @@ export class AppAstrologie extends Application {
|
||||
if (this.actor) {
|
||||
return {
|
||||
actor: this.actor,
|
||||
nombres: this._organizeNombresAstraux(this.actor.listItems('nombreastral')),
|
||||
nombres: this._organizeNombresAstraux(this.actor.itemTypes['nombreastral']),
|
||||
ajustements: CONFIG.RDD.difficultesLibres,
|
||||
etat: this.actor.getEtatGeneral(),
|
||||
astrologie: this.actor.getCompetence('Astrologie')
|
||||
|
||||
@@ -116,6 +116,7 @@ export class RdDCalendrier extends Application {
|
||||
if (setting.key == SYSTEM_RDD + '.' + WORLD_TIMESTAMP_SETTING) {
|
||||
this.timestamp = RdDTimestamp.getWorldTime();
|
||||
this.positionAiguilles()
|
||||
this.render(false);
|
||||
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
{"_id":"UQYy9WjsKqqrjLc7","name":"Guerrier Sorde","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.UQYy9WjsKqqrjLc7"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>@JournalEntry[vid6uJc66QFgHSUr]{Note sur les invocations de créatures}</p>\n<p>Le Guerrier Sorde a l’apparence d’un humanoïde entièrement revêtu d’une armure de plaques, visière du heaume toujours baissée, dissimulant son visage. Il est armé d’une épée sorde, d’un bouclier moyen et d’une dague. La seule tâche que l’on puisse lui demander est de faire usage de ses armes. Une fois invoqué, il attaque toute créature que le haut-rêvant lui désigne expressément, et se bat contre elle jusqu’à ce qu’il l’extermine ou reçoive un contre-ordre. On peut alors lui ordonner de commencer un autre combat, à condition que le délai entre deux combats n’excède pas 10 rounds, faute de quoi il considère sa tâche accomplie et se dématérialise. S’il est invoqué alors qu’il n’y a pas de créature à combattre immédiatement, il ne patiente que jusqu’à la fin de l’heure en cours, après quoi il s’estime dérangé pour rien et se dématérialise. Durant le délai, il peut accompagner le haut-rêvant où qu’il aille, mais sans pouvoir s’éloigner de lui de plus de E1 mètres. Sa vitesse est limitée à 12 m/round, il ne court, n’escalade ni ne nage jamais. Il n’obéit qu’au haut-rêvant qui l’a invoqué. Le rituel peut être répété pour invoquer plusieurs Guerriers Sordes dans un même combat. Tous ont les mêmes caractéristiques. La PERCEPTION indiquée tient compte des malus dus au heaume. Les Guerriers Sordes sont normalement affectés par les suggestions et illusions d’Hypnos, avec un JR standard r-8, ainsi que par les sorts individuels de Thananatos.</p>\n<p>@JournalEntry[R3q4vUTEfyxYgmGr]{Communication avec les créatures invoquées}</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Tâche","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"special","caseTMRspeciale":"Cité Sordide D13","ptreve":"7","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426561,"modifiedTime":1667260032848,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"VG89vfk7KsO01eJv","name":"Secouriste blanc","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.VG89vfk7KsO01eJv"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>@JournalEntry[vid6uJc66QFgHSUr]{Note sur les invocations de créatures}</p>\n<p>Le Secouriste blanc ne peut être invoqué que pendant un combat ou au terme de celui-ci. Sa tâche consiste à prendre les blessés en charge, premiers soins et soins complets, ce qu’il fait spontanément. En plein combat, il peut même s’approcher de la mêlée pour tirer en arrière d’éventuels tombés à terre. Quand il a plusieurs blessés à soigner, il commence par le plus proche de lui. Mais l’invocateur peut lui désigner un blessé à soigner en priorité.</p>\n<p>Le Secouriste possède son propre matériel de chirurgie, mais il n’a aucun consommable (eau, chiffons) qu’il faut lui fournir.</p>\n<p>Pour la résolution des soins, le Secouriste ne joue pas de jet de Chirurgie. À la place, c’est le blessé qui joue des jets de CHANCE, pour déterminer les points de tâche obtenus :</p>\n<table style=\"height: 102px; width: 260px;\" border=\"0\">\n<tbody>\n<tr style=\"height: 17px;\">\n<td style=\"height: 17px; width: 119px;\">Particulière :</td>\n<td style=\"height: 17px; width: 134px;\">4 points</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Significative :</td>\n<td style=\"width: 134px; height: 17px;\">3 points</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Normale :</td>\n<td style=\"width: 134px; height: 17px;\">2 points</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Échec :</td>\n<td style=\"width: 134px; height: 17px;\">1 pt</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Échec particulier :</td>\n<td style=\"width: 134px; height: 17px;\">0 pt</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Échec total :</td>\n<td style=\"width: 134px; height: 17px;\">0 pt (et sans malus)</td>\n</tr>\n</tbody>\n</table>\n<p>Le Secouriste disparaît dès que le combat est terminé ET que tous les blessés ont été soignés.</p>\n<p>@JournalEntry[R3q4vUTEfyxYgmGr]{Communication avec les créatures invoquées}</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Tâche ou fin HN","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire Blanc G4","ptreve":"7","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426561,"modifiedTime":1667260032851,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"WvTkEYb216X0XiJc","name":"Voix d'Hypnos","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.WvTkEYb216X0XiJc"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>Les rituels de lecture d’Hypnos sont d’étonnantes démonstrations d’auto-suggestion. Aidé par un support, le haut-rêvant se persuade qu’il peut voir ou entendre à distance, et il le fait. Couplé à l’ultime forme d’illusion que sont les invocations, il peut pareillement projeter son image ou sa voix à distance. Tous obéissent aux règles usuelles d’application des rituels. Si un rituel de lecture est paramétré sur une personne et que celle-ci est morte ou a changé de rêve, aucun effet ne se produit, mais les points de rêve sont tout de même dépensés.</p>\n<p>Le rituel de Voix d’Hypnos permet de détecter le mensonge. Il n’y a pas de véritable ciblage, le rituel opère sur le haut-rêvant directement sans passer par un support. Lors du paramétrage, le haut-rêvant se reporte à une certaine conversation de son choix, datant au maximum de 12 heures. La conversation peut avoir eu plusieurs interlocuteurs, mais Voix d’Hypnos ne fonctionne que sur un seul d’entre eux à la fois.</p>\n<p>Pour les détecter tous, il faut recommencer autant de fois le rituel. Puis, le sort étant ciblé sur lui-même, le haut-rêvant se plonge dans un état hypnotique dans lequel il réentend toute la conversation, comme si on repassait la bande. La durée de réécoute est d’un round, quelle qu’ait été la conversation, le temps mental du haut-rêvant devenant élastique. Tant que son interlocuteur dit la vérité, sa voix est mélodieuse ; dès qu’il ment <em>volontairement</em>, elle devient horrible et grinçante. On ne peut ainsi détecter que les mensonges volontaires, pas les mensonges inconscients ou par omission.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"1 round","JR":"Aucun","cible":"Soi-même","difficulte":"-4","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"4","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032852,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.Y4r9kTN2brWC2N0n"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"<p>Les rituels de Lecture d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d’approfondir les informations fournies par Détection d’Aura. Pratiquer Lecture d’Aura quand il n’y a pas d’aura revient à demander une magie impossible et crée immédiatement une déchirure du rêve.</p>\n<p>Lecture d’Aura est effectuée en plusieurs étapes, toutes étant de difficulté R-3 et coûtant 3 points de rêve. La première a toujours lieu dans un sanctuaire et ne fait que révéler dans quel(s) autre(s) genre(s) de case(s) le haut-rêvant doit se rendre pour continuer sa lecture. Là, il apprend quel genre de magie a été produit ou à quel type de rêve il a affaire, de même que les cases spécifiques concernées. Enfin dans les cases spécifiques, le haut-rêvant peut apprendre la force du rêve ou de la magie en cours, c’est-à-dire pratiquement la difficulté et le nombre de points de rêve impliqués, information indispensable dans l’optique d’une annulation de magie.</p>\n<p>Lecture d’Aura révèle également la couleur de l’aura (fixe ou pulsative) comme Détection d’Aura. Pour les créatures vivantes, on peut donc sauter l’étape de Détection d’Aura et commencer directement par la lecture, puisqu’on est sûr de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la détection si, en l’absence finale d’une aura, on ne veut pas créer de magie impossible. Effectuée sur une créature non soumise à un effet magique ni sous l’emprise d’une entité, Lecture d’Aura indique toujours le Fleuve. Là, dans n’importe quelle case du Fleuve, le haut-rêvant se contente d’apprendre qu’il a affaire à une créature vivante et douée de rêve.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032849,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.Y4r9kTN2brWC2N0n"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"<p>Les rituels de Lecture d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d’approfondir les informations fournies par Détection d’Aura. Pratiquer Lecture d’Aura quand il n’y a pas d’aura revient à demander une magie impossible et crée immédiatement une déchirure du rêve.</p>\n<p>Lecture d’Aura est effectuée en plusieurs étapes, toutes étant de difficulté R-3 et coûtant 3 points de rêve. La première a toujours lieu dans un sanctuaire et ne fait que révéler dans quel(s) autre(s) genre(s) de case(s) le haut-rêvant doit se rendre pour continuer sa lecture. Là, il apprend quel genre de magie a été produit ou à quel type de rêve il a affaire, de même que les cases spécifiques concernées. Enfin dans les cases spécifiques, le haut-rêvant peut apprendre la force du rêve ou de la magie en cours, c’est-à-dire pratiquement la difficulté et le nombre de points de rêve impliqués, information indispensable dans l’optique d’une annulation de magie.</p>\n<p>Lecture d’Aura révèle également la couleur de l’aura (fixe ou pulsative) comme Détection d’Aura. Pour les créatures vivantes, on peut donc sauter l’étape de Détection d’Aura et commencer directement par la lecture, puisqu’on est sûr de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la détection si, en l’absence finale d’une aura, on ne veut pas créer de magie impossible. Effectuée sur une créature non soumise à un effet magique ni sous l’emprise d’une entité, Lecture d’Aura indique toujours le Fleuve. Là, dans n’importe quelle case du Fleuve, le haut-rêvant se contente d’apprendre qu’il a affaire à une créature vivante et douée de rêve.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.6","coreVersion":"10.291","createdTime":1667259426562,"modifiedTime":1681495249423,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"YOJsOLpHTQYreZ6i","name":"Soufflet","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.YOJsOLpHTQYreZ6i"}},"system":{"description":"<p>Le Soufflet peut être dirigé contre toute créature, humanoïde ou animale. Son effet, instantané, est celui d’une gifle magistrale, causant ses dommages sur la table des Coups non mortels. Le +dom de l’agression est égal au nombre de points de rêve dépensés. Sauf pour les animaux qui peuvent faire jouer entièrement leur protection naturelle, la protection applicable peut être au maximum de 2 points.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Humanoïde selon HN, animal r-8","cible":"Toutes créatures","difficulte":"-6","portée":"","caseTMR":"gouffre","caseTMRspeciale":"","ptreve":"1+","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032851,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"aYOfXEuDp6xGDO4N","name":"Égarement","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.aYOfXEuDp6xGDO4N"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>L’effet d’Égarement ne s’applique qu’aux humanoïdes. L’apport massif de pseudo-souvenirs, informulés et insaisissables, empêche l’humanoïde visé de se concentrer sur son activité intellectuelle, manuelle ou verbale. Il ne fait plus ou ne dit plus que des <em>bêtises</em>, en termes de jeu des échecs totaux. Un intellectuel devient incapable de lire ou d’écrire, un artisan se tape sur les doigts, un musicien rate tous ses accords, un orateur bafouille, etc. L’état d’égarement dure jusqu’à la fin de l’heure en cours + une heure complète, ou se dissipe de lui-même dès qu’il y a stress, par exemple une agression. Ce sort est donc totalement inutile et inefficace en combat.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Une heure","JR":"Selon HN","cible":"Humanoïde","difficulte":"-4","portée":"","caseTMR":"desolation","caseTMRspeciale":"","ptreve":"4","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032847,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"cghxHRstw7cXLEm4","name":"Invoquer son image","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.cghxHRstw7cXLEm4"}},"system":{"description":"<p>Les rituels de lecture d’Hypnos sont d’étonnantes démonstrations d’auto-suggestion. Aidé par un support, le haut-rêvant se persuade qu’il peut voir ou entendre à distance, et il le fait. Couplé à l’ultime forme d’illusion que sont les invocations, il peut pareillement projeter son image ou sa voix à distance. Tous obéissent aux règles usuelles d’application des rituels. Si un rituel de lecture est paramétré sur une personne et que celle-ci est morte ou a changé de rêve, aucun effet ne se produit, mais les points de rêve sont tout de même dépensés.</p>\n<p>Ce rituel est comme le négatif de @Item[Ew5JzQ2lzcpGoF11]{Miroir d'Hypnos}. Les conditions de ciblage et de paramétrage en sont exactement les mêmes. Lorsqu’un mouvement apparaît au centre du miroir, provoquant l’état hypnotique, le haut-rêvant peut commencer à effectuer des gestes, des mimiques, ou montrer ostensiblement un objet qu’il tient sur lui, mais sans pouvoir se déplacer. Dans l’instant même, un hologramme de lui-même, grandeur nature et fidèle jusqu’au moindre geste, prend naissance près de la personne ou au centre du lieu choisi.</p>\n<p>Les spectateurs peuvent se déplacer à travers l’hologramme, ce n’est qu’une illusion sans substance. Par ce rituel, le haut-rêvant ne peut communiquer aucun son, et lui-même n’entend ni ne voit rien. Il ne peut pas savoir comment est accueillie sa \"visite\". La communication est de 1 round par point de rêve dépensé.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Selon r dépensé","JR":"Aucun","cible":"Un miroir","difficulte":"-6","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1+","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032849,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
@@ -39,7 +39,7 @@
|
||||
{"_id":"qqcLydulFkL25Ipc","name":"Conjurer l'oubli","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.qqcLydulFkL25Ipc"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>Ce rituel permet de faire renaître chez la cible un souvenir oublié, la cause de l’oubli pouvant être magique ou naturelle. Le souvenir oublié peut appartenir à une précédente incarnation si le gardien des rêves l’estime possible ou pertinent. Dans tous les cas, le souvenir ne peut revenir que sous la forme d’une <em>réponse </em>à une <em>question </em>précise. Et l’accomplissement du rituel ne permet qu’une seule question-réponse.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Une question","JR":"Aucun","cible":"Humanoïde","difficulte":"-4","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"4","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032846,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"rrSE9c7KKsqcKueo","name":"Nonechalepasse","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.rrSE9c7KKsqcKueo"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>@JournalEntry[vid6uJc66QFgHSUr]{Note sur les invocations de créatures}</p>\n<p>Le Nonechalepasse a la même apparence physique et le même armement que le Guerrier Sorde. C’est en fait une variante de ce dernier. Il est invoqué pour garder ou veiller sur quelque chose : une porte, un coffre, un pont, etc. L’ayant invoqué, le haut-rêvant doit lui indiquer expressément sur quoi il doit veiller, et le Nonechalepasse ne laissera personne d’autre que l’invocateur franchir la limite indiquée, c’est-à-dire pas même ses compagnons. La garde peut avoir lieu en la présence du haut-rêvant, ou en son absence s’il désire vaquer à d’autres affaires, et dure jusqu’à la fin de son heure de naissance. Dès qu’une créature est en voie d’enfreindre la consigne donnée, le Nonechalepasse l’en prévient en clamant son propre nom à plusieurs reprises ; et si la créature insiste, il la combat jusqu’à ce qu’il l’extermine ou qu’elle recule et s’enfuie. Les Nonechalepasses ont tous les mêmes caractéristiques que les Guerriers Sordes et sont comme eux affectés par les sorts.</p>\n<p>@JournalEntry[R3q4vUTEfyxYgmGr]{Communication avec les créatures invoquées}</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Tâche","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"special","caseTMRspeciale":"Cité Jalouse M1","ptreve":"7","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032850,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"sVA94h9Reimmfw5B","name":"Suggestion","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.sVA94h9Reimmfw5B"}},"system":{"description":"<p>L’effet de Suggestion ne s’applique qu’aux humanoïdes. Comme l’indique le titre, c’est la suggestion à l’état pur. Il permet de donner un ordre bref à la victime, et cette dernière ne pourra pas s’empêcher d’y obéir machinalement. Il est impératif que la victime puisse obéir à l’ordre de façon <em>immédiate</em>, dans la seconde qui suit l’ordre, et que l’action soit uniquement <em>physique</em>, ni mentale ni réfléchie. Si la Suggestion est telle qu’elle oblige la victime à une autre action préalable ou si l’action demandée ne peut être qu’une action réfléchie, pensée, la Suggestion avorte automatiquement.</p>\n<p>Un passant a sa bourse accrochée à la ceinture. On lui donne l’ordre de suggestion : \"donne ta bourse !\" L’effet avorte automatiquement. En effet, le passant doit d’abord en dénouer les cordons, action préalable, et qui plus est réfléchie. Si le passant avait déjà sa bourse à la main, l’ordre : \"donne ta bourse !\" ou \"donne\"! tout court, pouvant être obéi de façon <em>immédiate</em>, aurait été accepté.</p>\n<p>Des ordres tels que \"réponds à la question \" ou \" dis la vérité\" sont pareillement inacceptables (actions mentales). Si la victime est au bord d’un gouffre, et qu’on lui suggère : \" saute dans le gouffre !\", elle saute. Si elle est à trois mètres du gouffre, la suggestion avorte. Il faut d’abord qu’elle y coure. Des ordres tels que : \"Fuis, saute, plonge, assieds-toi, agenouille-toi, lève les bras, ferme les yeux, hurle, donne (ce que la victime a déjà en main), mange ou bois (ce que la victime a déjà à portée de ses lèvres), lâche (ce qu’elle tient en main), etc.\" sont possibles. Des ordres tels que : \"endors-toi, suicide-toi, va faire ceci, déshabille-toi (actions multiples), écris ceci, avoue, lance tel sort, etc.\" sont impossibles.</p>\n<p>L’ordre donné dans la suggestion doit être unique, c’est-à-dire pratiquement ne comporter qu’un seul verbe. \"Cours et saute !\" est impossible. Quand l’action implique une durée, elle est obéie pendant un round. Si par exemple l’ordre donné est \"cours !\" ou \"fuis !\", la victime courra, fuira, pendant un round. À ce moment, toutefois, l’ordre pourra être donné une seconde fois, et la victime obéira pour la durée d’un nouveau round.</p>\n<p>L’ordre contenu dans la suggestion doit être paramétré lors du lancer. Mais le ciblage de la victime ne le déclenche pas aussitôt. La victime étant maintenant sous l’effet du sort, il faut que l’ordre soit donné réellement, <em>verbalement</em>. La victime doit pouvoir l’entendre et le comprendre (parler la même langue). Peu importe qui donne l’ordre verbal, le haut-rêvant ou quelqu’un d’autre. Chaque 3r dépensés permet verbalement de réitérer l’ordre une fois. Si par exemple 9 points de rêve ont été dépensés, l’ordre \"cours !\" pourra être donné trois fois. Il n’y a aucune limite de temps entre le ciblage et le moment où le premier ordre est donné verbalement, ni non plus entre chaque ordre. Tant que le dernier ordre n’a pas été donné, la victime est sous l’influence du sort, influence qui peut être détectée et lue par Lecture d’Aura. Le libellé de l’ordre est également révélé dans la case spécifique par Lecture d’Aura, et le sort peut être annulé dans cette même case. Dès que le dernier ordre est donné, l’effet se dissipe totalement.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Spéciale","JR":"Selon HN","cible":"Humanoïde","difficulte":"-9","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"3+","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032851,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.xOicgRMCUxJNmVzF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"<p>Les rituels de Détection d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.</p>\n<p>Toutes les créatures vivantes animées (humains, humanoïdes, animaux) ont une caractéristique RÊVE. Les objets enchantés possèdent des points de rêve, de même que les produits de magie naturelle, comme certaines pierres de chance. Les entités de cauchemar, incarnées ou non, en ont également. Quelle qu’elle soit, la présence de rêve émet une aura, laquelle est détectable par Détection d’Aura. Parallèlement, toute cible d’un sort ou d’un rituel, émet une aura propre, quand bien même ladite cible ne possède pas de points de rêve (centre de zone, objet ou plante soumis à une illusion d’Hypnos). Cette aura est également détectable par Détection d’Aura.</p>\n<p>L’aura de présence de rêve se traduit par un halo bleuté constant ; l’aura résultant d’un effet magique par un halo parcouru de pulsations. Quand les deux auras sont présentes conjointement, le halo est pulsatif et d’un bleu plus foncé. On peut toujours effectuer Détection d’Aura sans aucun risque, il y a toujours une réponse. Soit une aura est perçue, constante ou pulsative, et l’on peut tenter une Lecture d’Aura pour en savoir plus ; soit aucune aura n’est perçue et il s’agit de matière inerte, sans rêve, non soumise à un sort.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032847,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.xOicgRMCUxJNmVzF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"<p>Les rituels de Détection d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.</p>\n<p>Toutes les créatures vivantes animées (humains, humanoïdes, animaux) ont une caractéristique RÊVE. Les objets enchantés possèdent des points de rêve, de même que les produits de magie naturelle, comme certaines pierres de chance. Les entités de cauchemar, incarnées ou non, en ont également. Quelle qu’elle soit, la présence de rêve émet une aura, laquelle est détectable par Détection d’Aura. Parallèlement, toute cible d’un sort ou d’un rituel, émet une aura propre, quand bien même ladite cible ne possède pas de points de rêve (centre de zone, objet ou plante soumis à une illusion d’Hypnos). Cette aura est également détectable par Détection d’Aura.</p>\n<p>L’aura de présence de rêve se traduit par un halo bleuté constant ; l’aura résultant d’un effet magique par un halo parcouru de pulsations. Quand les deux auras sont présentes conjointement, le halo est pulsatif et d’un bleu plus foncé. On peut toujours effectuer Détection d’Aura sans aucun risque, il y a toujours une réponse. Soit une aura est perçue, constante ou pulsative, et l’on peut tenter une Lecture d’Aura pour en savoir plus ; soit aucune aura n’est perçue et il s’agit de matière inerte, sans rêve, non soumise à un sort.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.6","coreVersion":"10.291","createdTime":1667259426564,"modifiedTime":1681495242408,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"yNMa8DlBaZyTGFSr","name":"Oubli","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.yNMa8DlBaZyTGFSr"}},"system":{"description":"<p>L’effet d’Oubli ne s’applique qu’aux humanoïdes. C’est une des plus puissantes suggestions hypnotiques. L’effet d’amnésie ne survient pas aussitôt le sort ciblé, mais intervient à la fin de l’heure en cours. À ce moment la victime perd tout souvenir de ce qu’elle a vécu, de ce qu’elle a pu dire ou faire, entre le moment présent et celui où le sort a été ciblé. Pratiquement, cette période est comme un grand trou noir dans sa tête, et aucun moyen normal ne peut lui restituer ses souvenirs. Chaque point de rêve dépensé en plus des 6 de base augmente la durée d’une heure. Soit un haut-rêvant lançant ce sort au cours de l’heure du Dragon et dépensant 8 points : à la fin de l’heure de la Lyre, la victime se retrouve brusquement amnésique de ce qu’elle a pu faire depuis la mi-Dragon jusqu’à maintenant, sans comprendre comment elle est arrivée dans le lieu où elle se trouve actuellement, comme si elle venait de se réveiller d’une période de sommeil noir, encore plus opaque que le gris rêve. Une Lecture d’Aura révèle la présence d’un sort d’Oubli en train d’œuvrer, et Annulation de Magie peut l’annuler selon les règles normales. À défaut, le rituel de Conjurer l’Oubli peut être utilisé, mais ne restitue les souvenirs que sélectivement, en réponse à une question précise. Quand c’est un personnage de joueur qui lance ce sort sur un PNJ, sa mise en œuvre est sans problème. L’inverse est plus délicat. Le mieux est alors de faire sortir de la salle le joueur du personnage victime, et de le faire rentrer au moment où l’amnésie opère. De cette façon, il ne se souvient effectivement de rien. Entre temps, si besoin est par rapport aux autres joueurs, jouer ce personnage comme un PNJ.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Selo n r dépensé","JR":"Selon HN","cible":"Humanoïde","difficulte":"-8","portée":"","caseTMR":"fleuve","caseTMRspeciale":"","ptreve":"6+","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032850,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"yhw8f7HKrmfzAxmj","name":"Sérénité","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.yhw8f7HKrmfzAxmj"}},"system":{"description":"<p>L’effet de sérénité ne s’applique qu’aux humanoïdes. La suggestion d’une intense satisfaction est source d’une sérénité réelle. Pour chaque 3r dépensés, le personnage visé regagne 1 point de moral jusqu’à concurrence de zéro. Neuf points de rêve permettent ainsi de remonter un moral de -3 à zéro. Si trop de points sont dépensés, l’excédent est perdu, le moral ne pouvant dépasser zéro par l’influence de ce sort.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Selon HN","cible":"Humanoïde","difficulte":"-3","portée":"","caseTMR":"collines","caseTMRspeciale":"","ptreve":"3+","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032851,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"ze53LdwhuqUFMvqw","name":"Fou-rire","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.ze53LdwhuqUFMvqw"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>L’effet de Fou-Rire ne s’applique qu’aux humanoïdes. La suggestion d’une idée drolatique plonge la cible dans un irrépressible fou-rire, automatique le premier round. Puis pour les rounds suivants, la cible doit réussir un jet de VOLONTÉ/ <em>moins </em>moral à -5, ou continuer à rire. Tant que la cible rit, elle est considérée en <em>demi-surprise</em>.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Selon HN","cible":"Humanoïde","difficulte":"-5","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"5","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032847,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
|
||||
@@ -1609,14 +1609,18 @@ table.table-nombres-astraux tr:hover {
|
||||
|
||||
|
||||
.window-app.calendar {
|
||||
display: inline-block;
|
||||
background: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
pointer-events: none;
|
||||
max-height: fit-content;
|
||||
}
|
||||
|
||||
.window-app.calendar header.window-header {
|
||||
min-width: fit-content;
|
||||
height: 1.4rem;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
@@ -1632,7 +1636,14 @@ table.table-nombres-astraux tr:hover {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.window-app.calendar .window-content > div {
|
||||
.window-app.calendar .window-content div:is(.calendar-boutons-heure, .horloge-digitale) {
|
||||
pointer-events: all;
|
||||
}
|
||||
.window-app.calendar .window-content div.horloge-analogique {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.window-app.calendar .window-content div.horloge-analogique div.horloge-roue {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
@@ -1783,15 +1794,12 @@ div.horloge-roue div img {
|
||||
div.horloge-analogique {
|
||||
border: none;
|
||||
margin: 0;
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
align-content: center;
|
||||
vertical-align: middle;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
div.horloge-analogique.horloge-analogique-hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
div.horloge-digitale {
|
||||
color: #CCC;
|
||||
background: hsla(0, 0%, 20%, 1);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"id": "foundryvtt-reve-de-dragon",
|
||||
"title": "Rêve de Dragon",
|
||||
"version": "10.7.6",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.6.zip",
|
||||
"version": "10.7.11",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.11.zip",
|
||||
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json",
|
||||
"compatibility": {
|
||||
"minimum": "10",
|
||||
|
||||
@@ -538,7 +538,7 @@
|
||||
"service",
|
||||
"meditation", "rencontre", "queue", "ombre", "souffle", "tete", "casetmr", "signedraconique", "sort", "sortreserve",
|
||||
"nombreastral", "tache", "blessure", "maladie", "poison", "possession",
|
||||
"tarot", "extraitpoetique"
|
||||
"tarot", "extraitpoetique", "empoignade"
|
||||
],
|
||||
"templates": {
|
||||
"description": {
|
||||
@@ -596,6 +596,16 @@
|
||||
"ispossession": false,
|
||||
"dommages": 0
|
||||
},
|
||||
"empoignade": {
|
||||
"templates": ["description"],
|
||||
"empoignadeid": "",
|
||||
"empoigneurid": "",
|
||||
"empoigneid": "",
|
||||
"pointsemp": 0,
|
||||
"empoigneurname": "",
|
||||
"empoignename": "",
|
||||
"ausol": false
|
||||
},
|
||||
"possession": {
|
||||
"templates": ["description"],
|
||||
"typepossession": "",
|
||||
@@ -682,7 +692,7 @@
|
||||
"capacite": 0
|
||||
},
|
||||
"objet": {
|
||||
"templates": ["description", "inventaire"]
|
||||
"templates": ["description", "equipement", "inventaire"]
|
||||
},
|
||||
"monnaie": {
|
||||
"templates": ["description", "inventaire"]
|
||||
|
||||
@@ -40,4 +40,29 @@
|
||||
<span class="initiative-value"></span>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
||||
<ul class="item-list alterne-list">
|
||||
<li class="competence-header flexrow">
|
||||
<span class="competence-title competence-label">Empoignades</span>
|
||||
<span class="competence-title competence-value">Points d'Emp</span>
|
||||
</li>
|
||||
{{#each empoignades as |emp key|}}
|
||||
<li class="item flexrow list-item"
|
||||
data-item-id="{{emp._id}}" data-arme-name="{{emp.name}}">
|
||||
<span class="empoignade-label">
|
||||
<a>
|
||||
{{#if emp.img}}
|
||||
<img class="sheet-competence-img" src="{{emp.img}}"/>
|
||||
{{/if}}
|
||||
<span>{{emp.name}}</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="competence-value">{{emp.system.pointsemp}}</span>
|
||||
<div class="item-controls">
|
||||
<a class="item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
@@ -28,7 +28,7 @@
|
||||
<span class="equipement-actions item-controls">
|
||||
{{#if options.isOwner}}
|
||||
{{#unless item.estContenu}}
|
||||
{{#if (or (eq item.type 'arme') (eq item.type 'armure') )}}
|
||||
{{#if item.equipable}}
|
||||
<a class="item-equip" title="Equiper">{{#if item.system.equipe}}<i class="fas fa-hand-rock"></i>{{else}}<i class="far fa-hand-paper"></i>{{/if}}</a>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
39
templates/chat-empoignade-actions.html
Normal file
39
templates/chat-empoignade-actions.html
Normal file
@@ -0,0 +1,39 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} a empoigné {{defenderName}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
|
||||
<span class='chat-card-button-area'>
|
||||
Au round suivant l'acquisition des 2 points d'Emp, {{attackerName}} peut faire perdre autant de points d'Endurance qu'il souhaite à {{defenderName}}
|
||||
<br>
|
||||
<a class='empoignade-perte-endurance chat-card-button'>
|
||||
<select class='empoignade-perte-endurance'>
|
||||
<option value="none">Faire perdre de l'endurance (selectionnez)</option>
|
||||
<option value="end0">Endurance à 0</option>
|
||||
<option value="end1">Endurance à 1</option>
|
||||
<option value="endmoitie">La moitié de l'endurance</option>
|
||||
<option value="endquart">Le quart de l'endurance</option>
|
||||
</select>
|
||||
</a>
|
||||
|
||||
{{#if empoignade.system.ausol}}
|
||||
|
||||
{{else}}
|
||||
<br>
|
||||
Dès l'acquisition des 2 points d'Emp, {{attackerName}} peut entraîner {{defenderName}} au sol. Les deux protagonistes restent empoignés.
|
||||
<br>
|
||||
<a class='empoignade-entrainer-sol chat-card-button'>
|
||||
Entraîner au sol
|
||||
</a>
|
||||
<br>
|
||||
A la fin du round ou les 2 points d'Emp sont acquis, {{attackerName}} peut projeter {{defenderName}} au sol. Les deux protagonistes ne sont plus empoignés.
|
||||
<br>
|
||||
<a class='empoignade-projeter-sol chat-card-button'>
|
||||
Projeter au sol
|
||||
</a>
|
||||
{{/if}}
|
||||
|
||||
|
||||
</div>
|
||||
7
templates/chat-empoignade-entrainer-sol.html
Normal file
7
templates/chat-empoignade-entrainer-sol.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} a entraîné {{defenderName}} au sol. L'empoignade peut continuer.
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
</div>
|
||||
7
templates/chat-empoignade-perte-endurance.html
Normal file
7
templates/chat-empoignade-perte-endurance.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} a fait perdre de l'endurance à {{defenderName}}, qui reste immobilisé. L'empoignade peut continuer.
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
</div>
|
||||
7
templates/chat-empoignade-projeter-sol.html
Normal file
7
templates/chat-empoignade-projeter-sol.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} a projeté {{defenderName}} au sol. L'empoignade est terminée et a été supprimée.
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
</div>
|
||||
85
templates/chat-empoignade-resultat.html
Normal file
85
templates/chat-empoignade-resultat.html
Normal file
@@ -0,0 +1,85 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{#if (eq mode "empoigner")}}
|
||||
{{attackerName}} tente d'empoigner {{defenderName}}
|
||||
{{/if}}
|
||||
{{#if (eq mode "contrer-empoigner")}}
|
||||
{{defenderName}} tente de contrer l'empoignade de {{attackerName}}
|
||||
{{/if}}
|
||||
{{#if (eq mode "liberer")}}
|
||||
{{attackerName}} tente de se libérer de l'empoignade de {{defenderName}}
|
||||
{{/if}}
|
||||
{{#if (eq mode "contrer-liberer")}}
|
||||
{{defenderName}} tente de contrer la libération de {{attackerName}}
|
||||
{{/if}}
|
||||
</h4>
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
|
||||
|
||||
<hr>
|
||||
<div>
|
||||
|
||||
{{#if (gte empoignade.system.pointsemp 2)}}
|
||||
|
||||
<br><strong>{{defenderName}} est empoigné et immobilisé par {{attackerName}} !</strong>
|
||||
|
||||
{{else}}
|
||||
<span class='chat-card-button-area'>
|
||||
<br>
|
||||
|
||||
{{#if (eq mode "empoigner")}}
|
||||
{{#if empoignade.isSuccess}}
|
||||
<a class='defense-empoignade-cac chat-card-button'
|
||||
data-attackerId='{{attacker.id}}'
|
||||
data-defenderId='{{defender.id}}'
|
||||
data-diff-libre='{{diffLibre}}'
|
||||
data-defense-mode="contrer-empoigner">
|
||||
Contrer l'empoignade (Corps à Corps)
|
||||
</a>
|
||||
{{#if (eq empoignade.system.pointsemp 0)}}
|
||||
<a class='defense-empoignade-esquive chat-card-button'
|
||||
data-attackerId='{{attacker.id}}'
|
||||
data-defenderId='{{defender.id}}'
|
||||
data-diff-libre='{{diffLibre}}'
|
||||
data-defense-mode="contrer-empoigner">
|
||||
Contrer l'empoignade (Esquive)
|
||||
</a>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
La Tentative d'empoignade a échoué !
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if (eq mode "liberer")}}
|
||||
{{#if empoignade.isSuccess}}
|
||||
<a class='defense-empoignade-cac chat-card-button'
|
||||
data-attackerId='{{attacker.id}}'
|
||||
data-defenderId='{{defender.id}}'
|
||||
data-diff-libre='{{diffLibre}}'
|
||||
data-defense-mode="contrer-liberer">
|
||||
Contrer la libération (Corps à Corps)
|
||||
</a>
|
||||
{{else}}
|
||||
La Tentative de libération a échouée !
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if (eq mode "contrer-empoigner")}}
|
||||
{{#if rolled.isSuccess}}
|
||||
La tentative de contrer l'empoignade est un succès!
|
||||
{{else}}
|
||||
La tentative de contrer l'empoignade est un échec!
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if (eq mode "contrer-liberer")}}
|
||||
{{#if rolled.isSuccess}}
|
||||
La tentative de contrer la libération est un succès!
|
||||
{{else}}
|
||||
La tentative de contrer la libération est un échec!
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
<br>Points d'Emp: {{empoignade.system.pointsemp}}
|
||||
|
||||
{{/if}}
|
||||
</div>
|
||||
20
templates/chat-empoignade-valider.html
Normal file
20
templates/chat-empoignade-valider.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} tente d'empoigner {{defenderName}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
|
||||
<span class='chat-card-button-area'>
|
||||
<br>
|
||||
<strong>{{attacker.name}} tente d'empoigner {{defender.name}}, qui est équipé d'une arme de mêlée. {{defender.name}}
|
||||
a automatiquement l'initiative sur {{attacker.name}}, et bénéficie d'un bonus de +4 à son attaque. Assurez vous
|
||||
d'avoir effectué cette attaque avant de poursuivre l'empoignade. Ce cas s'applique également si {{defender.name}}
|
||||
combat à mains nues.</strong>
|
||||
|
||||
<a class='empoignade-poursuivre chat-card-button' data-attackerId='{{attacker.id}}'
|
||||
data-defenderId='{{defender.id}}'>
|
||||
Poursuivre l'empoignade
|
||||
</a>
|
||||
|
||||
</div>
|
||||
22
templates/dialog-roll-defense-empoignade.html
Normal file
22
templates/dialog-roll-defense-empoignade.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<form class="skill-roll-dialog">
|
||||
<h2>
|
||||
{{defenderName}} tente de contrer l'empoignade de {{attackerName}}
|
||||
</h2>
|
||||
<div class="grid grid-2col">
|
||||
<div class="flex-group-left">
|
||||
<img class="chat-icon" src="{{competence.img}}" alt="{{competence.name}}"/>
|
||||
<div class="grid grid-2col">
|
||||
<label for="carac">{{selectedCarac.label}}:</label><label class="flex-grow" name="carac">{{selectedCarac.value}}</label>
|
||||
<label for="competence">{{competence.name}}:</label><label class="flex-grow" name="competence">{{numberFormat competence.system.niveau decimals=0 sign=true}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-group-left">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html"}}
|
||||
<div class="placeholder-ajustements" class="flexrow"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="placeholder-resolution"></div>
|
||||
</form>
|
||||
11
templates/item-empoignade-sheet.html
Normal file
11
templates/item-empoignade-sheet.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<form class="{{cssClass}}" autocomplete="off">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/header-item.html"}}
|
||||
{{!-- Sheet Body --}}
|
||||
<section class="sheet-body">
|
||||
<div class="form-group">
|
||||
<label for="xp">Points d'Empoignade </label>
|
||||
<input class="attribute-value" type="text" name="system.pointsemp" value="{{system.pointsemp}}" data-dtype="Number"/>
|
||||
</div>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html"}}
|
||||
</section>
|
||||
</form>
|
||||
Reference in New Issue
Block a user