Version 12.0.16 - Le secret d'Astrobazzarh #718
@ -1,4 +1,12 @@
|
||||
# 12.0
|
||||
## 12.0.18 - A la barbe d'Astrobazzarh
|
||||
- Ajout du portrait sur les feuilles simplifiées
|
||||
|
||||
## 12.0.16 - Le secret d'Astrobazzarh
|
||||
- Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués)
|
||||
- Les noms affichés dans les automatisations de combat sont maintenant ceux des tokens plutôt que ceux des acteurs
|
||||
- Ajout d'une option pour la localisation des blessures
|
||||
|
||||
## 12.0.15 - Le messager d'Astrobazzarh
|
||||
- Correction des faces de dés personalisés dice-so-nice
|
||||
- Les messages de maladies ne sont plus publics
|
||||
|
@ -220,18 +220,18 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
||||
// Points de reve actuel
|
||||
this.html.find('.roll-reve-actuel').click(async event => this.actor.rollCarac('reve-actuel', true))
|
||||
this.html.find('.empoignade-label a').click(async event => RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor)))
|
||||
this.html.find('.roll-arme').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event))))
|
||||
|
||||
this.html.find('.roll-arme').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event)), 'competence'))
|
||||
|
||||
// Initiative pour l'arme
|
||||
this.html.find('.arme-initiative a').click(async event => {
|
||||
let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id);
|
||||
let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id)
|
||||
if (combatant) {
|
||||
let action = this._getEventArmeCombat(event);
|
||||
RdDCombatManager.rollInitiativeAction(combatant._id, action);
|
||||
RdDCombatManager.rollInitiativeAction(combatant._id, this._getEventArmeCombat(event));
|
||||
} else {
|
||||
ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat.");
|
||||
}
|
||||
});
|
||||
})
|
||||
// Display TMR
|
||||
|
||||
this.html.find('.button-tmr').click(async event => this.actor.displayTMR("normal"))
|
||||
|
@ -1548,7 +1548,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') {
|
||||
if (!Misc.firstConnectedGM()){
|
||||
if (!Misc.isFirstConnectedGM()){
|
||||
return
|
||||
}
|
||||
hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
|
||||
@ -3011,7 +3011,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async onCreateOwnedDraconique(item, options, id) {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
let draconique = Draconique.all().find(it => it.match(item));
|
||||
if (draconique) {
|
||||
await draconique.onActorCreateOwned(this, item)
|
||||
@ -3023,7 +3023,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async onDeleteOwnedDraconique(item, options, id) {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
let draconique = Draconique.all().find(it => it.match(item));
|
||||
if (draconique) {
|
||||
await draconique.onActorDeleteOwned(this, item)
|
||||
@ -3033,7 +3033,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async onDeleteOwnedCaseTmr(item, options, id) {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
let draconique = Draconique.all().find(it => it.isCase(item));
|
||||
if (draconique) {
|
||||
await draconique.onActorDeleteCaseTmr(this, item)
|
||||
|
@ -327,14 +327,15 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
const competence = this.getCompetence(idOrName);
|
||||
let rollData = { carac: this.system.carac, competence: competence, arme: options.arme }
|
||||
if (competence.type == ITEM_TYPES.competencecreature) {
|
||||
const token = RdDUtility.getSelectedToken(this)
|
||||
const arme = RdDItemCompetenceCreature.armeCreature(competence)
|
||||
if (arme && options.tryTarget && Targets.hasTargets()) {
|
||||
Targets.selectOneToken(target => {
|
||||
Targets.selectOneTargetToken(target => {
|
||||
if (arme.action == "possession") {
|
||||
RdDPossession.onAttaquePossession(target, this, competence)
|
||||
}
|
||||
else {
|
||||
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme)
|
||||
RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme)
|
||||
}
|
||||
});
|
||||
return;
|
||||
@ -364,7 +365,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
* @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession
|
||||
* @returns
|
||||
*/
|
||||
rollArme(arme, categorieArme = "competence") {
|
||||
rollArme(arme, categorieArme, token) {
|
||||
token = token ?? RdDUtility.getSelectedToken(this)
|
||||
const compToUse = this.$getCompetenceArme(arme, categorieArme)
|
||||
if (!RdDItemArme.isArmeUtilisable(arme)) {
|
||||
ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`)
|
||||
@ -385,7 +387,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
return
|
||||
}
|
||||
|
||||
Targets.selectOneToken(target => {
|
||||
Targets.selectOneTargetToken(target => {
|
||||
if (Targets.isTargetEntite(target)) {
|
||||
ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`);
|
||||
return
|
||||
@ -395,7 +397,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
if (competence.isCompetencePossession()) {
|
||||
return RdDPossession.onAttaquePossession(target, this, competence);
|
||||
}
|
||||
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme);
|
||||
RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme);
|
||||
})
|
||||
}
|
||||
|
||||
@ -413,48 +415,47 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
/* -------------------------------------------- */
|
||||
async encaisser() { await RdDEncaisser.encaisser(this) }
|
||||
|
||||
async encaisserDommages(rollData, attacker = undefined, show = undefined) {
|
||||
async encaisserDommages(rollData, attacker = undefined, show = undefined, attackerToken = undefined, defenderToken = undefined) {
|
||||
if (attacker && !await attacker.accorder(this, 'avant-encaissement')) {
|
||||
return;
|
||||
}
|
||||
const armure = await this.computeArmure(rollData);
|
||||
if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) {
|
||||
await this.encaisserDommagesValidationGR(rollData, armure, attacker?.id, show);
|
||||
await this.encaisserDommagesValidationGR(rollData, armure, show, attackerToken, defenderToken);
|
||||
}
|
||||
else {
|
||||
const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE });
|
||||
await this.$onEncaissement(jet, show, attacker);
|
||||
const jet = await RdDUtility.jetEncaissement(this, rollData, armure, { showDice: SHOW_DICE });
|
||||
await this.$onEncaissement(jet, show, attackerToken, defenderToken)
|
||||
}
|
||||
}
|
||||
|
||||
async encaisserDommagesValidationGR(rollData, armure, attackerId, show) {
|
||||
async encaisserDommagesValidationGR(rollData, armure, show, attackerToken, defenderToken) {
|
||||
if (!game.user.isGM) {
|
||||
RdDBaseActor.remoteActorCall({
|
||||
tokenId: this.token?.id,
|
||||
actorId: this.id,
|
||||
method: 'encaisserDommagesValidationGR',
|
||||
args: [rollData, armure, attackerId, show]
|
||||
});
|
||||
args: [rollData, armure, show, attackerToken, defenderToken]
|
||||
})
|
||||
} else {
|
||||
const attacker = game.actors.get(attackerId);
|
||||
DialogValidationEncaissement.validerEncaissement(this, rollData, armure,
|
||||
jet => this.$onEncaissement(jet, show, attacker));
|
||||
jet => this.$onEncaissement(jet, show, attackerToken, defenderToken));
|
||||
}
|
||||
}
|
||||
|
||||
async $onEncaissement(jet, show, attacker) {
|
||||
await this.onAppliquerJetEncaissement(jet, attacker);
|
||||
await this.$afficherEncaissement(jet, show);
|
||||
async $onEncaissement(jet, show, attackerToken, defenderToken) {
|
||||
await this.onAppliquerJetEncaissement(jet, attackerToken);
|
||||
await this.$afficherEncaissement(jet, show, defenderToken);
|
||||
}
|
||||
|
||||
async onAppliquerJetEncaissement(encaissement, attacker) { }
|
||||
async onAppliquerJetEncaissement(encaissement, attackerToken) { }
|
||||
|
||||
async $afficherEncaissement(encaissement, show) {
|
||||
async $afficherEncaissement(encaissement, show, defenderToken) {
|
||||
foundry.utils.mergeObject(encaissement, {
|
||||
alias: this.name,
|
||||
alias: defenderToken?.name ?? this.name,
|
||||
hasPlayerOwner: this.hasPlayerOwner,
|
||||
show: show ?? {}
|
||||
});
|
||||
}, {overwrite: false});
|
||||
|
||||
await ChatUtility.createChatWithRollMode(
|
||||
{
|
||||
|
@ -89,9 +89,9 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
async onAppliquerJetEncaissement(encaissement, attacker) {
|
||||
async onAppliquerJetEncaissement(encaissement, attackerToken) {
|
||||
const santeOrig = foundry.utils.duplicate(this.system.sante);
|
||||
const blessure = await this.ajouterBlessure(encaissement, attacker); // Will update the result table
|
||||
const blessure = await this.ajouterBlessure(encaissement, attackerToken); // Will update the result table
|
||||
const perteVie = await this.santeIncDec("vie", -encaissement.vie);
|
||||
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique());
|
||||
|
||||
@ -169,7 +169,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async ajouterBlessure(encaissement, attacker = undefined) {
|
||||
async ajouterBlessure(encaissement, attackerToken = undefined) {
|
||||
if (encaissement.gravite < 0) return;
|
||||
if (encaissement.gravite > 0) {
|
||||
while (this.countBlessures(it => it.system.gravite == encaissement.gravite) >= RdDItemBlessure.maxBlessures(encaissement.gravite) && encaissement.gravite <= 6) {
|
||||
@ -181,7 +181,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
}
|
||||
}
|
||||
const endActuelle = this.getEnduranceActuelle();
|
||||
const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg?.loc.label ?? '', attacker);
|
||||
const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken);
|
||||
if (blessure.isCritique()) {
|
||||
encaissement.endurance = endActuelle;
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ export class RdDBaseActor extends Actor {
|
||||
}
|
||||
|
||||
async creerObjetParMJ(object) {
|
||||
if (!Misc.isUniqueConnectedGM()) {
|
||||
if (!Misc.isFirstConnectedGM()) {
|
||||
RdDBaseActor.remoteActorCall({
|
||||
tokenId: this.token?.id,
|
||||
actorId: this.id,
|
||||
@ -335,7 +335,7 @@ export class RdDBaseActor extends Actor {
|
||||
ui.notifications.info("Inutile de se vendre à soi-même");
|
||||
return;
|
||||
}
|
||||
if (!Misc.isUniqueConnectedGM()) {
|
||||
if (!Misc.isFirstConnectedGM()) {
|
||||
RdDBaseActor.remoteActorCall({
|
||||
actorId: achat.vendeurId ?? achat.acheteurId,
|
||||
method: 'achatVente',
|
||||
|
@ -74,7 +74,7 @@ export class RdDEntite extends RdDBaseActorReve {
|
||||
return [STATUSES.StatusComma].includes(effectId);
|
||||
}
|
||||
|
||||
async onAppliquerJetEncaissement(encaissement, attacker) {
|
||||
async onAppliquerJetEncaissement(encaissement, attackerToken) {
|
||||
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
|
||||
foundry.utils.mergeObject(encaissement, {
|
||||
resteEndurance: perteEndurance.newValue,
|
||||
|
@ -327,7 +327,8 @@ export class Mapping {
|
||||
const txtByCategories = Object.values(byCategories)
|
||||
.map(it => it.competencesParNiveau)
|
||||
.map(byNiveau => {
|
||||
const niveaux = Object.keys(byNiveau).map(it => Number(it)).sort(Misc.ascending())
|
||||
const niveaux = Object.keys(byNiveau)
|
||||
.map(it => Number(it)).sort(Misc.ascending())
|
||||
if (niveaux.length == 0) {
|
||||
return ''
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ export class ChatUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onRemoveMessages(socketData) {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
if (socketData.part) {
|
||||
const toDelete = game.messages.filter(it => it.content.includes(socketData.part));
|
||||
toDelete.forEach(it => it.delete());
|
||||
@ -63,7 +63,7 @@ export class ChatUtility {
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static removeMessages(socketData) {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
ChatUtility.onRemoveMessages(socketData);
|
||||
}
|
||||
else {
|
||||
@ -161,7 +161,7 @@ export class ChatUtility {
|
||||
/* -------------------------------------------- */
|
||||
static handleGMChatMessage(socketData) {
|
||||
console.log("blindMessageToGM", socketData);
|
||||
if (Misc.firstConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
ChatMessage.create({
|
||||
user: game.user.id,
|
||||
whisper: ChatUtility.getGMs(),
|
||||
|
@ -8,14 +8,13 @@ import { RdDUtility } from "./rdd-utility.js";
|
||||
export class DialogValidationEncaissement extends Dialog {
|
||||
|
||||
static async validerEncaissement(actor, rollData, armure, onEncaisser) {
|
||||
let encaissement = await RdDUtility.jetEncaissement(rollData, armure, { showDice: HIDE_DICE });
|
||||
const encaissement = await RdDUtility.jetEncaissement(actor, rollData, armure, { showDice: HIDE_DICE });
|
||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', {
|
||||
actor: actor,
|
||||
rollData: rollData,
|
||||
encaissement: encaissement
|
||||
});
|
||||
const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, onEncaisser);
|
||||
dialog.render(true);
|
||||
new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, onEncaisser).render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -56,14 +55,14 @@ export class DialogValidationEncaissement extends Dialog {
|
||||
this.html = html;
|
||||
this.html.find('input.encaissement-roll-result').keyup(async event => {
|
||||
this.forceDiceResult.total = event.currentTarget.value;
|
||||
this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: HIDE_DICE, forceDiceResult: this.forceDiceResult});
|
||||
this.encaissement = await RdDUtility.jetEncaissement(this.actor, this.rollData, this.armure, { showDice: HIDE_DICE, forceDiceResult: this.forceDiceResult});
|
||||
this.html.find('label.encaissement-total').text(this.encaissement.total);
|
||||
this.html.find('label.encaissement-blessure').text(this.encaissement.blessures)
|
||||
});
|
||||
}
|
||||
|
||||
async onValider() {
|
||||
this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: SHOW_DICE, forceDiceResult: this.forceDiceResult});
|
||||
this.encaissement = await RdDUtility.jetEncaissement(this.actor, this.rollData, this.armure, { showDice: SHOW_DICE, forceDiceResult: this.forceDiceResult});
|
||||
this.onEncaisser(this.encaissement)
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isNiveauBase(item) {
|
||||
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.type);
|
||||
return item.system.niveau == undefined || Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.type);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -267,10 +267,17 @@ export class RdDItemSheet extends ItemSheet {
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
if (this.item.type == 'sort') {
|
||||
// Données de bonus de cases ?
|
||||
formData['system.bonuscase'] = RdDItemSort.buildBonuscaseFromArrays(formData.bonusValue, formData.caseValue);
|
||||
switch (this.item.type) {
|
||||
case ITEM_TYPES.sort:
|
||||
// Données de bonus de cases ?
|
||||
formData['system.bonuscase'] = RdDItemSort.buildBonuscaseFromArrays(formData.bonusValue, formData.caseValue)
|
||||
break
|
||||
case ITEM_TYPES.competence:
|
||||
if (formData['system.niveau'] == undefined) {
|
||||
formData['system.niveau'] = formData['system.base']
|
||||
}
|
||||
}
|
||||
|
||||
return this.item.update(formData);
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ export class Misc {
|
||||
return document
|
||||
}
|
||||
}
|
||||
else if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) {
|
||||
else if (Misc.isFirstConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) {
|
||||
return document
|
||||
}
|
||||
return undefined
|
||||
@ -206,14 +206,14 @@ export class Misc {
|
||||
}
|
||||
|
||||
static isOwnerPlayerOrUniqueConnectedGM(actor) {
|
||||
return Misc.isOwnerPlayer(actor) ?? Misc.isUniqueConnectedGM();
|
||||
return Misc.isOwnerPlayer(actor) ?? Misc.isFirstConnectedGM();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns true pour un seul utilisateur: le premier GM connecté par ordre d'id
|
||||
*/
|
||||
static isUniqueConnectedGM() {
|
||||
return game.user.id == Misc.firstConnectedGMId();
|
||||
static isFirstConnectedGM() {
|
||||
return game.user == Misc.firstConnectedGM();
|
||||
}
|
||||
|
||||
static firstConnectedGMId() {
|
||||
|
@ -53,7 +53,7 @@ export class RdDCombatManager extends Combat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async onPreDeleteCombat() {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
await this.finDeRound({ terminer: true })
|
||||
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)
|
||||
@ -291,7 +291,7 @@ export class RdDCombatManager extends Combat {
|
||||
/* -------------------------------------------- */
|
||||
static processPremierRoundInit() {
|
||||
// Check if we have the whole init !
|
||||
if (Misc.isUniqueConnectedGM() && game.combat.current.round == 1) {
|
||||
if (Misc.isFirstConnectedGM() && game.combat.current.round == 1) {
|
||||
let initMissing = game.combat.combatants.find(it => !it.initiative);
|
||||
if (!initMissing) { // Premier round !
|
||||
for (let combatant of game.combat.combatants) {
|
||||
@ -454,10 +454,10 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static combatNouveauTour(combat) {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId);
|
||||
if (turn?.actor) {
|
||||
RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token.id);
|
||||
RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token);
|
||||
// TODO Playaudio for player??
|
||||
}
|
||||
}
|
||||
@ -469,52 +469,51 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static rddCombatTarget(target, attacker) {
|
||||
const defender = target?.actor;
|
||||
const defenderTokenId = target?.id;
|
||||
return new RdDCombat(attacker, defender, defenderTokenId, target)
|
||||
static rddCombatTarget(target, attacker, attackerToken) {
|
||||
return new RdDCombat(attacker, attackerToken?.id, target?.actor, target?.id, target)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static rddCombatForAttackerAndDefender(attackerId, defenderTokenId) {
|
||||
const attacker = game.actors.get(attackerId);
|
||||
let defender = defenderTokenId ? canvas.tokens.get(defenderTokenId)?.actor : undefined;
|
||||
static rddCombatForAttackerAndDefender(attackerId, attackerTokenId, defenderTokenId) {
|
||||
const attacker = game.actors.get(attackerId)
|
||||
const defenderToken = defenderTokenId ? canvas.tokens.get(defenderTokenId) : undefined
|
||||
let defender = defenderToken?.actor;
|
||||
let target = undefined
|
||||
if (!defenderTokenId || !defender) {
|
||||
console.warn(`RdDCombat.rddCombatForAttackerAndDefender: appel avec defenderTokenId ${defenderTokenId} incorrect, ou pas de defender correspondant`);
|
||||
target = Targets.getTarget()
|
||||
if (!target) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
defenderTokenId = target.id;
|
||||
defender = target.actor;
|
||||
if (!defenderTokenId || !defender) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
return new RdDCombat(attacker, defender, defenderTokenId, target)
|
||||
return new RdDCombat(attacker, attackerTokenId, defender, defenderTokenId, target)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onMsgEncaisser(msg) {
|
||||
let defender = canvas.tokens.get(msg.defenderTokenId).actor;
|
||||
if (Misc.isOwnerPlayerOrUniqueConnectedGM()) {
|
||||
let attackerRoll = msg.attackerRoll;
|
||||
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined;
|
||||
let defender = canvas.tokens.get(msg.defenderToken.id).actor;
|
||||
|
||||
defender.encaisserDommages(attackerRoll, attacker);
|
||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
||||
defender.encaisserDommages(attackerRoll, attacker, msg.attackerToken);
|
||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id);
|
||||
rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onMsgDefense(msg) {
|
||||
let defenderToken = canvas.tokens.get(msg.defenderTokenId);
|
||||
if (defenderToken && Misc.isUniqueConnectedGM()) {
|
||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
||||
rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme);
|
||||
rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll);
|
||||
let defenderToken = canvas.tokens.get(msg.defenderToken.id)
|
||||
if (defenderToken && Misc.isFirstConnectedGM()) {
|
||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id)
|
||||
rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme)
|
||||
rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll)
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,6 +544,7 @@ export class RdDCombat {
|
||||
html.on("click", button, event => {
|
||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(
|
||||
event.currentTarget.attributes['data-attackerId']?.value,
|
||||
event.currentTarget.attributes['data-attackerTokenId']?.value,
|
||||
event.currentTarget.attributes['data-defenderTokenId']?.value);
|
||||
if (rddCombat) {
|
||||
rddCombat.onEvent(button, event);
|
||||
@ -560,22 +560,38 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(attacker, defender, defenderTokenId, target) {
|
||||
constructor(attacker, attackerTokenId, defender, defenderTokenId, target) {
|
||||
this.attacker = attacker
|
||||
this.defender = defender
|
||||
this.target = target
|
||||
this.attackerId = this.attacker.id
|
||||
this.defenderId = this.defender.id
|
||||
this.attackerTokenId = attackerTokenId
|
||||
this.defenderTokenId = defenderTokenId
|
||||
this.attackerToken = RdDCombat.$extractAttackerTokenData(attacker, attackerTokenId)
|
||||
this.defenderToken = RdDCombat.$extractDefenderTokenData(defender, defenderTokenId, target)
|
||||
}
|
||||
|
||||
static $extractAttackerTokenData(attacker, attackerTokenId) {
|
||||
const token = canvas.tokens.get(attackerTokenId);
|
||||
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(attackerTokenId, attacker)
|
||||
}
|
||||
|
||||
static $extractDefenderTokenData(defender, defenderTokenId, target) {
|
||||
if (target) {
|
||||
return Targets.extractTokenData(target)
|
||||
}
|
||||
const token = canvas.tokens.get(defenderTokenId);
|
||||
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(defenderTokenId, defender)
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async onEvent(button, event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const defenderRoll = ChatUtility.getMessageData(chatMessage, 'defender-roll');
|
||||
const attackerRoll = defenderRoll?.attackerRoll ?? ChatUtility.getMessageData(chatMessage, 'attacker-roll');
|
||||
console.log('RdDCombat', attackerRoll, defenderRoll);
|
||||
const defenderTokenId = event.currentTarget.attributes['data-defenderTokenId']?.value;
|
||||
|
||||
const armeParadeId = event.currentTarget.attributes['data-armeid']?.value;
|
||||
const competence = event.currentTarget.attributes['data-competence']?.value;
|
||||
@ -585,7 +601,7 @@ export class RdDCombat {
|
||||
case '#particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value);
|
||||
case '#parer-button': return this.parade(attackerRoll, armeParadeId);
|
||||
case '#esquiver-button': return this.esquive(attackerRoll, compId, competence);
|
||||
case '#encaisser-button': return this.encaisser(attackerRoll, defenderRoll, defenderTokenId);
|
||||
case '#encaisser-button': return this.encaisser(attackerRoll, defenderRoll);
|
||||
case '#echec-total-attaque': return this._onEchecTotal(attackerRoll);
|
||||
|
||||
case '#appel-chance-attaque': return this.attacker.rollAppelChance(
|
||||
@ -702,7 +718,7 @@ export class RdDCombat {
|
||||
})
|
||||
}
|
||||
else {
|
||||
const defenderToken = canvas.tokens.get(this.defenderTokenId);
|
||||
const defenderToken = canvas.tokens.get(this.defenderTokenId)
|
||||
const dist = this.distance(_token, defenderToken)
|
||||
const isVisible = this.isVisible(_token, defenderToken)
|
||||
const portee = this._ajustementPortee(dist, rollData.arme)
|
||||
@ -769,7 +785,7 @@ export class RdDCombat {
|
||||
}
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this.attacker)
|
||||
|
||||
let rollData = this._prepareAttaque(competence, arme);
|
||||
let rollData = this._prepareAttaque(competence, arme)
|
||||
console.log("RdDCombat.attaque >>>", rollData);
|
||||
if (arme) {
|
||||
this.attacker.verifierForceMin(arme);
|
||||
@ -795,15 +811,18 @@ export class RdDCombat {
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_prepareAttaque(competence, arme) {
|
||||
let rollData = {
|
||||
alias: this.attackerToken.name,
|
||||
passeArme: foundry.utils.randomID(16),
|
||||
mortalite: arme?.system.mortalite,
|
||||
competence: competence,
|
||||
surprise: this.attacker.getSurprise(true),
|
||||
surpriseDefenseur: this.defender.getSurprise(true),
|
||||
targetToken: Targets.extractTokenData(this.target),
|
||||
sourceToken: this.attackerToken,
|
||||
targetToken: this.defenderToken,
|
||||
essais: {}
|
||||
};
|
||||
|
||||
@ -848,9 +867,10 @@ export class RdDCombat {
|
||||
alias: this.attacker.name,
|
||||
whisper: ChatUtility.getOwners(this.attacker),
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html', {
|
||||
alias: this.attacker.name,
|
||||
alias: this.attackerToken.name,
|
||||
attackerId: this.attackerId,
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
attackerToken: this.attackerToken,
|
||||
defenderToken: this.defenderToken,
|
||||
isForce: isForce,
|
||||
isFinesse: isFinesse,
|
||||
isRapide: isRapide,
|
||||
@ -867,7 +887,7 @@ export class RdDCombat {
|
||||
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite());
|
||||
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
|
||||
attackerRoll.show = {
|
||||
cible: this.target ? this.defender.name : 'la cible',
|
||||
cible: this.defenderToken?.name ?? 'la cible',
|
||||
isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge')
|
||||
}
|
||||
await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html');
|
||||
@ -908,7 +928,8 @@ export class RdDCombat {
|
||||
attacker: this.attacker,
|
||||
attackerId: this.attackerId,
|
||||
esquives: esquives,
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
attackerToken: this.attackerToken,
|
||||
defenderToken: this.defenderToken,
|
||||
mainsNues: attackerRoll.dmg.mortalite != 'mortel' && corpsACorps,
|
||||
armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme),
|
||||
diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0,
|
||||
@ -919,7 +940,7 @@ export class RdDCombat {
|
||||
dmg: attackerRoll.dmg,
|
||||
};
|
||||
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
await this._chatMessageDefense(paramChatDefense, defenderRoll);
|
||||
}
|
||||
else {
|
||||
@ -932,7 +953,7 @@ export class RdDCombat {
|
||||
const choixDefense = await ChatMessage.create({
|
||||
// message privé: du défenseur à lui même (et aux GMs)
|
||||
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
|
||||
alias: this.attacker.name,
|
||||
alias: this.attackerToken.name,
|
||||
whisper: ChatUtility.getOwners(this.defender),
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html', paramDemandeDefense),
|
||||
});
|
||||
@ -946,8 +967,9 @@ export class RdDCombat {
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||
msg: "msg_defense", data: {
|
||||
attackerId: this.attacker?.id,
|
||||
attackerToken: this.attackerToken,
|
||||
defenderId: this.defender?.id,
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
defenderToken: this.defenderToken,
|
||||
defenderRoll: defenderRoll,
|
||||
paramChatDefense: paramChatDefense,
|
||||
rollMode: true
|
||||
@ -980,7 +1002,8 @@ export class RdDCombat {
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
|
||||
attackerId: this.attackerId,
|
||||
attacker: this.attacker,
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
attackerToken: this.attackerToken,
|
||||
defenderToken: this.defenderToken,
|
||||
essais: attackerRoll.essais
|
||||
})
|
||||
});
|
||||
@ -1052,8 +1075,11 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
_prepareParade(attackerRoll, armeParade, competenceParade) {
|
||||
let defenderRoll = {
|
||||
alias: this.defenderToken?.name,
|
||||
passeArme: attackerRoll.passeArme,
|
||||
diffLibre: attackerRoll.diffLibre,
|
||||
attackerToken: this.attackerToken,
|
||||
defenderToken: this.defenderToken,
|
||||
attackerRoll: attackerRoll,
|
||||
competence: this.defender.getCompetence(competenceParade),
|
||||
arme: armeParade,
|
||||
@ -1133,8 +1159,11 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
_prepareEsquive(attackerRoll, competence) {
|
||||
let rollData = {
|
||||
alias: this.defenderToken?.name,
|
||||
passeArme: attackerRoll.passeArme,
|
||||
diffLibre: attackerRoll.diffLibre,
|
||||
attackerToken: this.attackerToken,
|
||||
defenderToken: this.defenderToken,
|
||||
attackerRoll: attackerRoll,
|
||||
competence: competence,
|
||||
surprise: this.defender.getSurprise(true),
|
||||
@ -1276,9 +1305,8 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async encaisser(attackerRoll, defenderRoll, defenderTokenId) {
|
||||
defenderTokenId = defenderTokenId || this.defenderTokenId;
|
||||
console.log("RdDCombat.encaisser >>>", attackerRoll, defenderTokenId);
|
||||
async encaisser(attackerRoll, defenderRoll) {
|
||||
console.log("RdDCombat.encaisser >>>", attackerRoll, defenderRoll);
|
||||
|
||||
if (defenderRoll?.rolled && RdDCombat.isEchecTotal(defenderRoll)) {
|
||||
this._onEchecTotal(defenderRoll);
|
||||
@ -1286,18 +1314,19 @@ export class RdDCombat {
|
||||
|
||||
if (Misc.isOwnerPlayerOrUniqueConnectedGM(this.defender)) {
|
||||
attackerRoll.attackerId = this.attackerId;
|
||||
attackerRoll.defenderTokenId = defenderTokenId;
|
||||
attackerRoll.defenderTokenId = this.defenderToken.id;
|
||||
|
||||
await this.computeRecul(defenderRoll);
|
||||
await this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll?.show);
|
||||
await this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll?.show, this.attackerToken, this.defenderToken);
|
||||
}
|
||||
else { // envoi à un GM: les joueurs n'ont pas le droit de modifier les personnages qu'ils ne possèdent pas
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||
msg: "msg_encaisser",
|
||||
data: {
|
||||
attackerId: this.attackerId,
|
||||
defenderTokenId: defenderTokenId,
|
||||
attackerRoll: attackerRoll
|
||||
attackerRoll: attackerRoll,
|
||||
attackerToken: this.attackerToken,
|
||||
defenderToken: this.defenderToken
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1305,28 +1334,28 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async displayActorCombatStatus(combat, actor, tokenId) {
|
||||
static async displayActorCombatStatus(combat, actor, token) {
|
||||
let formData = {
|
||||
combatId: combat._id,
|
||||
alias: actor.name,
|
||||
alias: token.name ?? actor.name,
|
||||
etatGeneral: actor.getEtatGeneral(),
|
||||
isSonne: actor.getSonne(),
|
||||
blessuresStatus: actor.computeResumeBlessure(),
|
||||
SConst: actor.getSConst(),
|
||||
actorId: actor.id,
|
||||
actor: actor,
|
||||
tokenId: tokenId,
|
||||
tokenId: token.id,
|
||||
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
|
||||
isCritique: actor.countBlessures(it => it.isCritique()) > 0
|
||||
}
|
||||
await ChatMessage.create({
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-acteur.hbs`, formData),
|
||||
alias: actor.name
|
||||
alias: token.name ?? actor.name
|
||||
})
|
||||
await ChatMessage.create({
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs`, formData),
|
||||
whisper: ChatUtility.getOwners(actor),
|
||||
alias: actor.name
|
||||
alias: token.name ?? actor.name
|
||||
});
|
||||
}
|
||||
}
|
@ -278,7 +278,7 @@ export class SystemReveDeDragon {
|
||||
/* Foundry VTT Initialization */
|
||||
/* -------------------------------------------- */
|
||||
game.system.rdd.calendrier = new RdDCalendrier()
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
new Migrations().migrate()
|
||||
this.messageDeBienvenue()
|
||||
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => {
|
||||
|
@ -72,6 +72,6 @@ export class RdDEncaisser extends Dialog {
|
||||
encaisserSpecial: this.encaisserSpecial,
|
||||
mortalite: mortalite
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ export class RdDTokenHud {
|
||||
// initiative
|
||||
await RdDTokenHud.addExtensionHudInit(html, combatant, actions);
|
||||
// combat
|
||||
await RdDTokenHud.addExtensionHudCombat(html, combatant, actions);
|
||||
await RdDTokenHud.addExtensionHudCombat(html, combatant, token, actions);
|
||||
}
|
||||
|
||||
|
||||
@ -68,8 +68,8 @@ export class RdDTokenHud {
|
||||
});
|
||||
}
|
||||
|
||||
static async addExtensionHudCombat(html, combatant, actions) {
|
||||
const hudData = { combatant, actions, commandes: [] };
|
||||
static async addExtensionHudCombat(html, combatant, token, actions) {
|
||||
const hudData = { combatant, token, actions, commandes: [] };
|
||||
const controlIconTarget = html.find('.control-icon[data-action=target]');
|
||||
await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData,
|
||||
(event) => {
|
||||
@ -80,7 +80,7 @@ export class RdDTokenHud {
|
||||
combatant.actor.conjurerPossession(possession);
|
||||
}
|
||||
else {
|
||||
combatant.actor.rollArme(action);
|
||||
combatant.actor.rollArme(action, 'competence', token)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -563,14 +563,14 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) {
|
||||
static async jetEncaissement(actor, rollData, armure, options = { showDice: HIDE_DICE }) {
|
||||
const diff = Math.abs(rollData.diffLibre);
|
||||
let formula = RdDUtility.formuleEncaissement(diff, options)
|
||||
const roll = await RdDDice.roll(formula, options);
|
||||
|
||||
RdDUtility.remplaceDeMinParDifficulte(roll, diff, options);
|
||||
|
||||
return await RdDUtility.prepareEncaissement(rollData, roll, armure);
|
||||
return await RdDUtility.prepareEncaissement(actor, rollData, roll, armure);
|
||||
}
|
||||
|
||||
static remplaceDeMinParDifficulte(roll, diff, options) {
|
||||
@ -602,15 +602,20 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async prepareEncaissement(rollData, roll, armure) {
|
||||
static async prepareEncaissement(actor, rollData, roll, armure) {
|
||||
// La difficulté d'ataque s'ajoute aux dégâts
|
||||
const bonusDegatsDiffLibre = ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(rollData.diffLibre ?? 0) : 0
|
||||
const jetTotal = roll.total + rollData.dmg.total - armure + bonusDegatsDiffLibre
|
||||
const encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite);
|
||||
const over20 = Math.max(jetTotal - 20, 0);
|
||||
encaissement.dmg = rollData.dmg;
|
||||
encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type);
|
||||
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;';
|
||||
encaissement.dmg = rollData.dmg
|
||||
if (ReglesOptionnelles.isUsing('localisation-aleatoire')){
|
||||
encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(actor.type)
|
||||
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'
|
||||
}
|
||||
else{
|
||||
encaissement.dmg.loc = {label:''}
|
||||
}
|
||||
encaissement.dmg.bonusDegatsDiffLibre = bonusDegatsDiffLibre
|
||||
encaissement.roll = roll;
|
||||
encaissement.armure = armure;
|
||||
@ -741,6 +746,15 @@ export class RdDUtility {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static getSelectedToken(actor) {
|
||||
if (canvas.tokens.controlled.length > 0) {
|
||||
const tokens = canvas.tokens.controlled
|
||||
.filter(it => it.actor.id == actor.id)
|
||||
return tokens[0]
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
static getSelectedActor(msgPlayer = undefined) {
|
||||
if (canvas.tokens.controlled.length == 1) {
|
||||
let token = canvas.tokens.controlled[0];
|
||||
|
@ -11,6 +11,7 @@ const listeReglesOptionnelles = [
|
||||
{ group: 'Récupération', name: 'recuperation-moral', descr: "Le moral revient vers 0 durant Château Dormant"},
|
||||
|
||||
|
||||
{ group: 'Règles de combat', name: 'localisation-aleatoire', descr: "Proposer une localisation aléatoire des blessures" },
|
||||
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
||||
{ group: 'Règles de combat', name: 'resistanceArmeParade', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" },
|
||||
{ group: 'Règles de combat', name: 'deteriorationArmure', descr: "Tenir compte de la détérioration des armures" },
|
||||
|
@ -186,7 +186,7 @@ export class AppAstrologie extends Application {
|
||||
date: this.html.find('[name="joursAstrologie"]').val(),
|
||||
userId: game.user.id
|
||||
}
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
game.system.rdd.calendrier.requestNombreAstral(socketData);
|
||||
} else {
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||
|
@ -13,18 +13,21 @@ export class Targets {
|
||||
static extractTokenData(target) {
|
||||
return { id: target?.id, name: target?.document.name, img: target?.document.texture.src ?? target?.actor.img ?? 'icons/svg/mystery-man.svg' };
|
||||
}
|
||||
|
||||
static buildActorTokenData(tokenId, actor) {
|
||||
return { id: tokenId, name: actor.name, img: actor.img ?? 'icons/svg/mystery-man.svg' };
|
||||
}
|
||||
static isTargetEntite(target) {
|
||||
return target?.actor.type == 'entite' && target?.actor.system.definition.typeentite == ENTITE_NONINCARNE;
|
||||
}
|
||||
|
||||
static async selectOneToken(onSelectTarget = target => { }) {
|
||||
const targets = Targets.listTargets();
|
||||
static async selectOneTargetToken(onSelectTarget = target => { }) {
|
||||
const targets = Targets.listTargets()
|
||||
switch (targets.length) {
|
||||
case 0: return;
|
||||
case 0:
|
||||
return
|
||||
case 1:
|
||||
onSelectTarget(targets[0]);
|
||||
return;
|
||||
onSelectTarget(targets[0])
|
||||
return
|
||||
default:
|
||||
{
|
||||
const selectData = {
|
||||
@ -32,7 +35,7 @@ export class Targets {
|
||||
label: "Choisir une seule des cibles",
|
||||
list: targets.map(it => Targets.extractTokenData(it))
|
||||
};
|
||||
DialogSelect.select(selectData, onSelectTarget);
|
||||
DialogSelect.select(selectData, onSelectTarget)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ export class RdDCalendrier extends Application {
|
||||
constructor() {
|
||||
super();
|
||||
this.timestamp = RdDTimestamp.getWorldTime();
|
||||
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
|
||||
if (Misc.isFirstConnectedGM()) { // Uniquement si GM
|
||||
RdDTimestamp.setWorldTime(this.timestamp);
|
||||
this.rebuildNombresAstraux(); // Ensure always up-to-date
|
||||
}
|
||||
@ -258,7 +258,7 @@ export class RdDCalendrier extends Application {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rebuildNombresAstraux() {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
const nombresAstraux = this.getNombresAstraux()
|
||||
let newNombresAstraux = [];
|
||||
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
||||
@ -337,7 +337,7 @@ export class RdDCalendrier extends Application {
|
||||
/* -------------------------------------------- */
|
||||
async requestNombreAstral(request) {
|
||||
const actor = game.actors.get(request.id);
|
||||
if (Misc.isUniqueConnectedGM()) { // Only once
|
||||
if (Misc.isFirstConnectedGM()) { // Only once
|
||||
console.log(request);
|
||||
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
|
||||
let niveau = Number(request.astrologie.system.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
||||
|
@ -1561,6 +1561,11 @@ div.control-icon.token-hud-icon {
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.chat-inline-icon {
|
||||
border: 0;
|
||||
padding: 1px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
#sidebar-tabs {
|
||||
flex: 0 0 28px;
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"id": "foundryvtt-reve-de-dragon",
|
||||
"title": "Rêve de Dragon",
|
||||
"version": "12.0.15",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.15.zip",
|
||||
"version": "12.0.17",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.17.zip",
|
||||
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json",
|
||||
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
|
||||
"compatibility": {
|
||||
|
@ -1,11 +1,17 @@
|
||||
<form class="{{cssClass}}" autocomplete="off" >
|
||||
<section class="sheet-header">
|
||||
<div class="flexrow">
|
||||
<div class="flex-group-left flex-grow-0-5">
|
||||
<h1 class="charname">{{name}}
|
||||
</h1>
|
||||
<section class="sheet-header flexrow">
|
||||
<div class="flex-grow-0-5">
|
||||
<img class="profile-img" src="{{img}}" data-edit="img" data-tooltip="{{name}}" />
|
||||
</div>
|
||||
<div class="flexcol flex-grow-2">
|
||||
<div>
|
||||
<h1 class="charname">{{name}}</h1>
|
||||
</div>
|
||||
<div class="flex-group-right flex-grow-3">
|
||||
<div>
|
||||
<a class="button-appel-chance"><img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/appel-chance.svg" data-tooltip="Appel à la chance"/></a>
|
||||
<a class="button-encaissement"><img class="button-img" src="icons/svg/bones.svg" data-tooltip="Encaisser des dommages"/></a>
|
||||
<a class="button-ethylisme"><img class="button-img" src="icons/svg/tankard.svg" data-tooltip="Boire"/></a>
|
||||
<a class="button-repos"><img class="button-img" src="icons/svg/sleep.svg" data-tooltip="Se reposer"/></a>
|
||||
{{#if system.attributs.hautrevant.value}}
|
||||
<a class="button-tmr" data-tooltip="Montée dans les Terres Médianes !" {{#if hautreve.isDemiReve}}disabled{{/if}}>
|
||||
<img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/icon-tmr-normal.svg"/>
|
||||
@ -17,10 +23,6 @@
|
||||
<img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/icon-tmr-view.svg"/>
|
||||
</a>
|
||||
{{/if}}
|
||||
<a class="button-appel-chance"><img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/appel-chance.svg" data-tooltip="Appel à la chance"/></a>
|
||||
<a class="button-encaissement"><img class="button-img" src="icons/svg/bones.svg" data-tooltip="Encaisser des dommages"/></a>
|
||||
<a class="button-ethylisme"><img class="button-img" src="icons/svg/tankard.svg" data-tooltip="Boire"/></a>
|
||||
<a class="button-repos"><img class="button-img" src="icons/svg/sleep.svg" data-tooltip="Se reposer"/></a>
|
||||
{{#if @root.options.isGM}}
|
||||
<a class="button-remise-a-neuf"><img class="button-img" src="icons/svg/regen.svg" data-tooltip="Remise à neuf"/></a>
|
||||
{{/if}}
|
||||
|
@ -3,20 +3,22 @@
|
||||
<br>
|
||||
{{#if (eq attacker.type 'personnage')}}
|
||||
{{#unless essais.attaqueChance}}
|
||||
<a class='chat-card-button' id='appel-chance-attaque' data-attackerId='{{attackerId}}'
|
||||
data-defenderTokenId='{{defenderTokenId}}'>Faire appel à la chance</a>
|
||||
<a class='chat-card-button' id='appel-chance-attaque'
|
||||
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
|
||||
Faire appel à la chance</a>
|
||||
</a>
|
||||
<br>
|
||||
{{/unless}}
|
||||
{{#if (gt attacker.system.compteurs.destinee.value 0)}}
|
||||
<a class='chat-card-button' id='appel-destinee-attaque' data-attackerId='{{attackerId}}'
|
||||
data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a>
|
||||
<a class='chat-card-button' id='appel-destinee-attaque'
|
||||
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
|
||||
Utiliser la destinée</a>
|
||||
</a>
|
||||
<br>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<a class='chat-card-button' id='echec-total-attaque' data-attackerId='{{attackerId}}'
|
||||
data-defenderTokenId='{{defenderTokenId}}'>
|
||||
<a class='chat-card-button' id='echec-total-attaque'
|
||||
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
|
||||
Tirer la maladresse !
|
||||
</a>
|
||||
</div>
|
@ -1,17 +1,17 @@
|
||||
<div data-passearme="{{passeArme}}">
|
||||
{{#if (eq surprise 'totale')}}
|
||||
<span><strong>{{defender.name}}</strong> est totalement surpris</span>
|
||||
<span><strong>{{defenderToken.name}}</strong> est totalement surpris</span>
|
||||
{{else if essais.defense}}
|
||||
<span><strong>{{defender.name}}</strong> doit :</span>
|
||||
<span><strong>{{defenderToken.name}}</strong> doit :</span>
|
||||
{{else}}
|
||||
<span><strong>{{defender.name}}</strong> doit se défendre
|
||||
<span><strong>{{defenderToken.name}}</strong> doit se défendre
|
||||
{{~#if (eq surprise 'demi')}} avec une significative {{/if}} d'une attaque
|
||||
{{~#if attaqueParticuliere}} <strong>particulière en
|
||||
{{~#if (eq attaqueParticuliere 'finesse')}} finesse
|
||||
{{else if (eq attaqueParticuliere 'force')}} force
|
||||
{{else if (eq attaqueParticuliere 'rapidite')}} rapidité
|
||||
{{/if~}}</strong>
|
||||
{{/if}} de {{attacker.name}} ({{attaqueArme.name}}):
|
||||
{{/if}} de {{attackerToken.name}} ({{attaqueArme.name}}):
|
||||
</span>
|
||||
{{/if}}
|
||||
<span class='chat-card-button-area'>
|
||||
@ -20,15 +20,17 @@
|
||||
{{#if essais.defense}}
|
||||
{{#unless essais.defenseChance}}
|
||||
{{#if (eq defender.type 'personnage')}}
|
||||
<a class='chat-card-button' id='appel-chance-defense' data-attackerId='{{attackerId}}'
|
||||
data-defenderTokenId='{{defenderTokenId}}'>Faire appel à la chance</a>
|
||||
<a class='chat-card-button' id='appel-chance-defense'
|
||||
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
|
||||
Faire appel à la chance</a>
|
||||
</a>
|
||||
<br>
|
||||
{{/if}}
|
||||
{{#if (eq defender.type 'personnage')}}
|
||||
{{#if (gt defender.system.compteurs.destinee.value 0)}}
|
||||
<a class='chat-card-button' id='appel-destinee-defense' data-attackerId='{{attackerId}}'
|
||||
data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a>
|
||||
<a class='chat-card-button' id='appel-destinee-defense'
|
||||
data-attackerId='{{attackerId}}' data-attackerTokenId='{{attackerToken.id}}' data-defenderTokenId='{{defenderToken.id}}'>
|
||||
Utiliser la destinée</a>
|
||||
</a>
|
||||
<br>
|
||||
{{/if}}
|
||||
@ -36,24 +38,26 @@
|
||||
{{/unless}}
|
||||
{{else}}
|
||||
{{#each armes as |arme key|}}
|
||||
<a class='chat-card-button' id='parer-button' data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderTokenId}}'
|
||||
data-armeid='{{arme._id}}'>
|
||||
<a class='chat-card-button' id='parer-button'
|
||||
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
|
||||
data-armeid='{{arme._id}}'>
|
||||
Parer avec {{arme.name}} à {{../diffLibre }}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}}
|
||||
</a>
|
||||
<br>
|
||||
{{/each}}
|
||||
{{#if mainsNues}}
|
||||
<a class='chat-card-button' id='parer-button' data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderTokenId}}'
|
||||
data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'>
|
||||
<a class='chat-card-button' id='parer-button'
|
||||
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'
|
||||
data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'>
|
||||
Parer à mains nues à {{diffLibre}}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}}
|
||||
</a>
|
||||
<br>
|
||||
{{/if}}
|
||||
{{#if (ne attaqueCategorie 'tir')}}
|
||||
{{#each esquives as |esquive key|}}
|
||||
<a class='chat-card-button' id='esquiver-button' data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderTokenId}}'
|
||||
data-compid='{{esquive._id}}' data-competence='{{esquive.name}}'>
|
||||
{{log 'esquive' esquive}}
|
||||
<a class='chat-card-button' id='esquiver-button'
|
||||
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
|
||||
data-compid='{{esquive._id}}' data-competence='{{esquive.name}}'>
|
||||
{{esquive.name}} à {{../diffLibre}} {{#if esquive.system.nbUsage}} (Utilisations : {{esquive.system.nbUsage}}){{/if}}
|
||||
</a>
|
||||
<br>
|
||||
@ -61,8 +65,8 @@
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
<a class='chat-card-button' id='encaisser-button' data-attackerId='{{attackerId}}'
|
||||
data-defenderTokenId='{{defenderTokenId}}'>
|
||||
<a class='chat-card-button' id='encaisser-button'
|
||||
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
|
||||
Encaisser à {{plusMoins dmg.total}}
|
||||
{{#if (eq dmg.mortalite 'non-mortel')~}}
|
||||
(non-mortel) !
|
||||
|
@ -1,5 +1,4 @@
|
||||
{{#if isGM}}
|
||||
{{log this}}
|
||||
<span>
|
||||
{{#if (gt endurance 0)}}
|
||||
De plus, {{alias}} a perdu {{endurance}} points d'endurance
|
||||
@ -18,18 +17,18 @@
|
||||
</h4>
|
||||
<div>
|
||||
Jet d'encaissement de {{roll.total}}
|
||||
{{#unless (eq armure 0)}}, l'armure a protègé de {{armure}}
|
||||
{{~#unless (eq armure 0)}}, l'armure a protègé de {{armure}}
|
||||
{{~#unless (eq penetration 0)}} (pénétration de {{penetration}}){{/unless}}
|
||||
{{~/unless}}, total: <span class="rdd-roll-echec">{{total}}</span>
|
||||
{{~/unless~}}, total: <span class="rdd-roll-echec">{{total}}</span>
|
||||
<br>
|
||||
{{alias}}
|
||||
{{#if (eq dmg.mortalite 'entiteincarnee')}}subit le coup
|
||||
{{else if mort}}vient de mourir
|
||||
{{else if blessure}}
|
||||
{{#if (gt blessure.system.gravite 0)}}subit une blessure {{blessure.system.label}}
|
||||
{{else}}subit une contusion
|
||||
{{~else~}}subit une contusion
|
||||
{{~/if~}}
|
||||
{{else}}s'en sort sans une égratignure
|
||||
{{~else~}}s'en sort sans une égratignure
|
||||
{{~/if~}}
|
||||
|
||||
{{~#unless (eq dmg.mortalite 'entiteincarnee')}}
|
||||
@ -39,11 +38,11 @@
|
||||
{{/unless~}}
|
||||
{{~#if (gt endurance 0)}}
|
||||
{{~#if hasPlayerOwner}}, a perdu {{endurance}} points d'endurance
|
||||
{{#if (ne vie 0)}}, <span class="rdd-roll-echec">{{vie}} points de vie</span>{{/if}}
|
||||
{{~#if (ne vie 0)}}, <span class="rdd-roll-echec">{{vie}} points de vie</span>{{/if~}}
|
||||
{{/if}}
|
||||
{{#if (ne dmg.mortalite 'entiteincarnee')}}
|
||||
{{#if (gt endurance 1)}}et
|
||||
{{#if sonne}}est <strong>sonné</strong><img class="chat-icon" src="icons/svg/stoned.svg" data-tooltip="charge" height="16" width="16" /> jusqu'à la fin du prochain round{{else}}n'est pas sonné{{/if}}!
|
||||
{{#if sonne}}est <strong>sonné</strong><img class="chat-inline-icon" src="icons/svg/stoned.svg" data-tooltip="charge" height="16" width="16" /> jusqu'à la fin du prochain round{{else}}n'est pas sonné{{/if}}!
|
||||
{{#if hasPlayerOwner}}Jet d'endurance : {{jetEndurance}} / {{resteEndurance}}{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
Loading…
Reference in New Issue
Block a user