Compare commits

..

20 Commits

Author SHA1 Message Date
1bbefd3499 Astrologie ! 2022-12-25 18:00:42 +01:00
bcb377db7a Gestion de l'astrologie 2022-12-23 23:24:09 +01:00
7a8cf9f8fd Welcome page and init info message 2022-12-23 16:38:41 +01:00
d74f7784bb Fix bougette sur PNJ/Creatures 2022-12-04 13:49:00 +01:00
6d6fec99b0 Fix bougette sur PNJ/Creatures 2022-12-04 13:48:37 +01:00
884823a1bc Init again !!!! 2022-12-02 13:16:42 +01:00
399c22d623 Init again !!!! 2022-12-02 13:15:48 +01:00
085265df5d initiative bugfix 2022-12-01 23:57:33 +01:00
593db9ba5b initiative bugfix 2022-12-01 23:46:27 +01:00
ac96f3ca67 Enhance initiative + fix combat 2022-11-30 20:58:27 +01:00
b2fe67ab05 Enhance tokens/actor management + auto effects 2022-11-30 12:12:44 +01:00
47178d7359 Use bougette v1.2 2022-11-29 15:23:05 +01:00
e1c7304551 Add a PC list summary 2022-11-25 20:47:28 +01:00
7b4e5bcbfa Add a PC list summary 2022-11-25 15:50:12 +01:00
31bd83b0ab Add a PC list summary 2022-11-25 15:50:07 +01:00
e35187433e Fix malus dice (again) and scroll rendering 2022-11-25 14:24:03 +01:00
5e7dc3ad9d Display effects in main sheet (left) and manage it for defense and damages 2022-11-25 08:49:37 +01:00
add6893864 Logo is rotating again 2022-11-25 07:37:44 +01:00
3a591e750a Ajout aide + effets 2022-11-23 21:37:46 +01:00
fe1cda67c4 Ajout aide + effets 2022-11-23 21:34:51 +01:00
49 changed files with 1753 additions and 5339 deletions

BIN
assets/bol_monnaies_v1_2.pdf Executable file

Binary file not shown.

View File

@ -1,3 +1,9 @@
# v10.4.0
- Ajout de la gestion d'effets
- Aide intégré
- Intégration du PDF de la bougette
# v10.3.3
- Nouvelles clés de traduction

View File

@ -59,8 +59,6 @@ a:hover {
top: -50px;
left: calc(50% - 100px);
opacity: 0.7;
-webkit-animation: rotation 10s infinite linear;
animation: rotation 10s infinite linear;
}
#pause h3 {
font-family: "IMFellDWPicaSC-Regular", serif;
@ -444,12 +442,16 @@ ul.no-bullets {
.bol .inc-dec-btns {
color: #4b4a44;
}
.summmary-number {
padding-left: 4rem;
}
/* Items List */
.items-list {
list-style: none;
margin: 7px 0;
padding: 0;
overflow-y: auto;
overflow-y:hidden;
/*overflow-y: auto;*/
}
.items-list .item-header {
font-family: 'Signika', sans-serif;
@ -520,6 +522,18 @@ ul.no-bullets {
.items-list .item .item-control {
color: #4b4a44;
}
.items-list .item-name-fixed-medium {
min-width: 8rem;
width: 8rem;
}
.items-list .item-field-fixed-short {
max-width: 3rem;
min-width: 3rem;
width: 3rem;
}
.bougette-dice-img {
color:rgba(150, 44, 44, 0.70);
}
/* ----------------------------------------- */
/* Premade colors */
@ -1054,4 +1068,10 @@ body.system-bol img#logo {
.bol-margin-tb-2 {
margin-top: 2px;
margin-bottom: 2px;
}
}
.character-summary-container {
  opacity: 0.95;
}
.character-summary-rollable {
text-decoration: underline;
}

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 372 KiB

View File

@ -33,6 +33,7 @@
"BOL.ui.tab.description": "Description",
"BOL.ui.tab.details": "Details",
"BOL.ui.tab.spellalchemy": "Spells & Alchemy",
"BOL.ui.tab.astrologer": "Astrologer",
"BOL.ui.properties": "Properties",
"BOL.ui.description": "Description",
@ -115,6 +116,7 @@
"BOL.ui.isSorcerer": "Is Sorcerer ?",
"BOL.ui.isAlchemist": "Is Alchemist ?",
"BOL.ui.isPriest": "Is Priest/Druid ?",
"BOL.ui.isAstrologer": "Is Astrologer?",
"BOL.ui.circle": "Circle",
"BOL.ui.spells": "Spells",
"BOL.ui.focusSpell": "Cast a spell",

View File

@ -28,7 +28,9 @@
"BOL.resources.power": "Pouvoir",
"BOL.resources.villainy": "Vilénie",
"BOL.resources.alchemypoints": "Points de Creation",
"BOL.resources.astrologypoints": "Points d'Astrologie",
"BOL.traits.xp": "Expérience",
"BOL.ui.tab.stats": "Attributs",
"BOL.ui.tab.combat": "Combat",
"BOL.ui.tab.actions": "Actions",
@ -36,7 +38,19 @@
"BOL.ui.tab.equipment": "Equipement",
"BOL.ui.tab.description": "Description",
"BOL.ui.tab.details": "Details",
"BOL.ui.tab.spellalchemy": "Sorts&Alchimie",
"BOL.ui.tab.spellalchemy": "Mystères",
"BOL.ui.astrologerPoints": "Points d'Astrologie",
"BOL.ui.astrologerPointsLabel": "Points d'Astrologie actuels",
"BOL.ui.ishoroscopemajor": "Horoscope Majeur (ie de groupe) ?",
"BOL.ui.answer": "Réponse",
"BOL.ui.horoscopefavorable": "Favorable (1dB)",
"BOL.ui.horoscopeunfavorable": "Défavorable (1dM)",
"BOL.ui.horoscopes": "Horoscopes",
"BOL.ui.horoscopesBonus": "Horoscopes (Bonus)",
"BOL.ui.horoscopesMalus": "Horoscopes (Malus)",
"BOL.ui.groupHoroscope": "Horoscrope de Groupe de ",
"BOL.ui.properties": "Propriétés",
"BOL.ui.description": "Description",
"BOL.ui.actions": "Actions",
@ -117,9 +131,11 @@
"BOL.ui.spellkeep": "Prolongation",
"BOL.ui.concentrate": "Concentration",
"BOL.ui.registerInit": "Enregistrer comme Init. de combat",
"BOL.ui.isSorcerer": "Carrière de Sorcier ?",
"BOL.ui.isAlchemist": "Carrière d'Alchimiste ?",
"BOL.ui.isPriest": "Carrière de Prêtre/Druide ?",
"BOL.ui.isAstrologer": "Carrière d'Astrologue?",
"BOL.ui.circle": "Cercle",
"BOL.ui.spells": "Sorts",
"BOL.ui.focusSpell": "Lance un sort",
@ -137,6 +153,21 @@
"BOL.ui.alchemyCostTotal": "Points de Création nécessaires pour la Préparation",
"BOL.ui.alchemyInvest": "Points de Création investis",
"BOL.ui.alchemyCurrent": "Points de Création actuel dans la Préparation",
"BOL.ui.astrology": "Astrologie et Horoscopes",
"BOL.ui.astrologyMinor": "Etablir un Horoscope Mineur",
"BOL.ui.astrologyMajor": "Etablir un Horoscope Majeur",
"BOL.ui.astrologyMajorGroup": "Etablir un Horoscope Majeur de Groupe",
"BOL.ui.makeHoroscope": "Etablir un Horoscope",
"BOL.ui.astrologerRank": "Rang de l'Astrologue",
"BOL.ui.horoscopeCost": "Cout en Points d'Astrologie",
"BOL.ui.minor": "Mineur",
"BOL.ui.major": "Majeur",
"BOL.ui.majorgroup": "Majeur de Groupe",
"BOL.ui.horoscopeGroup": "Horoscopes de Groupe",
"BOL.ui.horoscopeDiceRemaining": "Dés restants",
"BOL.ui.horoscopeDiceMax": "Dés Max",
"BOL.ui.astrologyNoPoints": "Vous n'avez pas assez de Points d'Astrologie!",
"BOL.ui.advance": "Avancement",
"BOL.ui.isbonusdice": "Fourni un dé bonus?",
"BOL.ui.ismalusdice": "Fourni un dé malus?",
@ -166,7 +197,25 @@
"BOL.ui.rabble": "Piétaille",
"BOL.ui.tough": "Coriace",
"BOL.ui.villain": "Rival",
"BOL.ui.attributaptitude": "Attribut ou Aptitude",
"BOL.ui.always": "Tout les jets (ie toujours)",
"BOL.ui.effectbonusmalus": "Bonus ou Malus à appliquer",
"BOL.ui.boleffects": "Effets (automatiques)",
"BOL.ui.modifier": "Modificateur",
"BOL.ui.effects": "Effets en cours",
"BOL.ui.pcname": "PJs",
"BOL.ui.npcname": "PNJs",
"BOL.ui.pclistbutton": "Vue compacte",
"BOL.ui.noactorfound": "PNJ inconnu, le PNJ doit être présent dans le monde pour s'afficher ici.",
"BOL.ui.deletetitle": "Suppression",
"BOL.ui.confirmdelete": "Vous êtes sûr de vouloir supprimer cet item ?",
"BOL.ui.nomorealchemypoints": "Plus assez de Points de Création !",
"BOL.ui.armornoformula": "L'armure {protect.name} n'a pas de formule pour la protection !",
"BOL.ui.selectactor": "Selectionnez votre personnage pour utiliser la macro",
"BOL.ui.itemnotfound": "Impossible de trouver l'objet de cette macro",
"BOL.ui.noinit": "Pas d'initiative trouvée, veuillez en enregistrer une.",
"BOL.ui.warninitiative": "Votre initiative n'est pas disponible. Effectuez un jet d'Initiative pour ce combat.",
"BOL.featureCategory.origins": "Origines",
"BOL.featureCategory.races": "Races",
"BOL.featureCategory.careers": "Carrières",
@ -179,6 +228,7 @@
"BOL.bougette.easylife": "A l'aise",
"BOL.bougette.luxury": "Luxe&Volupté",
"BOL.bougette.rich": "Richissime",
"BOL.featureSubtypes.origin": "Origine",
"BOL.featureSubtypes.race": "Race",
"BOL.featureSubtypes.career": "Carrière",
@ -187,6 +237,11 @@
"BOL.featureSubtypes.language": "Langue",
"BOL.featureSubtypes.gods": "Dieux & Foi",
"BOL.featureSubtypes.fightOption": "Option de Combat",
"BOL.featureSubtypes.effect": "Effet",
"BOL.featureSubtypes.effects": "Effets",
"BOL.featureSubtypes.boleffect": "Effet",
"BOL.featureSubtypes.horoscope": "Horoscope",
"BOL.fightOptionTypes.armor": "Attaque au défaut d'armure",
"BOL.fightOptionTypes.intrepid": "Attaque intrépide",
"BOL.fightOptionTypes.twoweaponsdef": "Combat à 2 armes (Défense)",
@ -194,6 +249,7 @@
"BOL.fightOptionTypes.fulldefense": "Défense totale",
"BOL.fightOptionTypes.defense": "Posture défensive",
"BOL.fightOptionTypes.attack": "Posture offensive",
"BOL.itemCategory.object": "Objet",
"BOL.itemCategory.equipment": "Équipement",
"BOL.itemCategory.consumable": "Consommable",
@ -203,12 +259,14 @@
"BOL.itemCategory.capacity": "Capacité",
"BOL.itemCategory.alchemy": "Préparation Alchimique",
"BOL.itemCategory.vehicleweapon": "Armes de Véhicule",
"BOL.combatCategory.protections": "Protections",
"BOL.combatCategory.shields": "Boucliers",
"BOL.combatCategory.melee": "Armes de contact",
"BOL.combatCategory.ranged": "Armes à distance",
"BOL.combatCategory.fightOptions": "Options de combat",
"BOL.combatCategory.natural": "Armes Naturelless",
"BOL.equipmentCategory.weapon": "Arme",
"BOL.equipmentCategory.armor": "Armure",
"BOL.equipmentCategory.protection": "Protection",
@ -220,21 +278,26 @@
"BOL.equipmentCategory.container": "Conteneur",
"BOL.equipmentCategory.currency": "Monnaie",
"BOL.equipmentCategory.other": "Autre",
"BOL.protectionCategory.armor": "Armure",
"BOL.protectionCategory.shield": "Bouclier",
"BOL.protectionCategory.helm": "Casque",
"BOL.protectionCategory.other": "Autre",
"BOL.spellItem.charm": "Charme",
"BOL.spellItem.circle1": "Premier Cercle",
"BOL.spellItem.circle2": "Second Cercle",
"BOL.spellItem.circle3": "Troisième Cercle",
"BOL.alchemyItem.common": "Courante",
"BOL.alchemyItem.scarce": "Rare",
"BOL.alchemyItem.legend": "Légendaire",
"BOL.alchemyItem.mythic": "Mythique",
"BOL.weaponCategory.melee": "Arme de mêlée",
"BOL.weaponCategory.ranged": "Arme de tir",
"BOL.weaponCategory.other": "Autre",
"BOL.itemProperty.damageMultiplier": "Multiplicateur de dommages",
"BOL.itemProperty.attackBonusDice": "Dé de Bonus d'attaque",
"BOL.itemProperty.equipable": "Équipable",
@ -298,6 +361,7 @@
"BOL.itemProperty.isboarding": "Abordage",
"BOL.itemProperty.isspur": "Eperonnage",
"BOL.itemProperty.isbreakrow": "Briser les rames",
"BOL.itemStat.quantity": "Quantité",
"BOL.itemStat.weight": "Poids",
"BOL.itemStat.price": "Prix",
@ -307,21 +371,26 @@
"BOL.itemStat.soak": "Valeur de protection",
"BOL.itemStat.blocking": "Bloquage",
"BOL.itemStat.modifiers": "Modificateurs",
"BOL.weaponSize.unarmed": "Mains nues",
"BOL.weaponSize.improvised": "Arme improvisée",
"BOL.weaponSize.light": "Légère",
"BOL.weaponSize.medium": "Moyenne",
"BOL.weaponSize.heavy": "Lourde",
"BOL.itemModifiers.init": "Malus (Initiative)",
"BOL.itemModifiers.social": "Malus (Social)",
"BOL.itemModifiers.agility": "Malus (Agilité)",
"BOL.itemModifiers.powercost": "Malus (Coût supplémentaire en PP)",
"BOL.itemBlocking.malus": "Social",
"BOL.itemBlocking.nbAttacksPerRound": "Agilité",
"BOL.soakFormula.none": "-",
"BOL.soakFormula.light": "Légère (Annule d6-3 dégâts subis)",
"BOL.soakFormula.medium": "Moyenne (Annule d6-2 dégâts subis)",
"BOL.soakFormula.heavy": "Lourde (Annule d6-1 dégâts subis)",
"BOL.armorQuality.none": "-",
"BOL.armorQuality.light": "Légère",
"BOL.armorQuality.lightQ": "Légère de qualité",
@ -335,6 +404,7 @@
"BOL.armorQuality.heavyQ": "Lourde de qualité",
"BOL.armorQuality.heavySup": "Lourde Supérieure",
"BOL.armorQuality.heavyLeg": "Lourde Légendaire",
"BOL.equipmentSlots.none": "-",
"BOL.equipmentSlots.head": "Tête",
"BOL.equipmentSlots.neck": "Cou",
@ -351,10 +421,12 @@
"BOL.equipmentSlots.feet": "Pieds",
"BOL.equipmentSlots.finder": "Doigt",
"BOL.equipmentSlots.ear": "Oreille",
"BOL.vehicleCategory.mount": "Monture terrestre",
"BOL.vehicleCategory.flying": "Monture volante",
"BOL.vehicleCategory.boat": "Bateau",
"BOL.vehicleCategory.other": "Autre",
"BOL.range.PointBlank": "Bout portant",
"BOL.range.Short": "Courte",
"BOL.range.Medium": "Moyenne",
@ -362,6 +434,7 @@
"BOL.range.VeryLong": "Très longue",
"BOL.range.Extreme": "Extrême",
"BOL.range.Maximum": "Maximale",
"BOL.notification.MacroMultipleTokensSelected": "Vous avez sélectionné plusieurs tokens",
"BOL.notification.MacroNoActorAvailable": "Aucun acteur n'a pu être ciblé",
"BOL.notification.MacroNoTokenSelected": "Vous devez sélectionner un token",
@ -435,7 +508,21 @@
"BOL.chat.rangenotvisible": "La ligne de vue est bloquée entre les protagonistes.",
"BOL.chat.rangetitle": "Information MJ",
"BOL.chat.weaponreroll1": "Pour information, cette arme relance les 1 sur ses dégâts.",
"BOL.chat.rollbougette": "Jet de Bougette",
"BOL.chat.bougettesuccess": "Votre bougette reste inchangée !",
"BOL.chat.bougettefailure": "Vous avez trop dépensé, votre bougette s'est réduite...",
"BOL.chat.initiative": "Rang d'intiative (10 à 1)",
"BOL.chat.horoscope": "Horoscope",
"BOL.chat.horoscopepoints": "Coût : {points} Points d'Astrologie",
"BOL.chat.horoscopeminorsuccess": "Votre horoscope mineur est un succès : éditez le nom de l'horoscope sur votre fiche. Vous bénéficiez d'1 dé Bonus pour cette situation.",
"BOL.chat.horoscopeminorfailure": "Votre horoscope mineur est un échec : éditez le nom de l'horoscope sur votre fiche. Vous souffrez d'1 dé Malus pour cette situation.",
"BOL.chat.horoscopemajorsuccess": "Votre horoscope majeur est un succès : vous bénéficiez d'1 point d'Héroisme pour cette aventure. Ce point a été ajouté automatiquement.",
"BOL.chat.horoscopemajorfailure": "Votre horoscope majeur est un échec : vous perdez 1 point d'Héroisme pour cette aventure. Ce point a été enlevé automatiquement.",
"BOL.chat.horoscopemajorgroupsuccess": "Votre horoscope majeur de groupe est un succès. Vous et vos amis bénéficiez de {careerBonus} dés bonus pendant cette aventure.",
"BOL.chat.horoscopemajorgroupfailure": "Votre horoscope majeur de groupe est un échec. Vous et vos amis souffrez de {careerBonus} dés malus pendant cette aventure.",
"BOL.chat.usedhoroscope": "Horoscope utilisé",
"BOL.chat.horoscopedeleted": "Le(s) Horoscopes utilisé(s) a/ont été supprimé(s) automatiquement.",
"BOL.dialog.soeasy": "Inmanquable (+4)",
"BOL.dialog.veryeasy": "Trés Facile (+2)",
"BOL.dialog.easy": "Facile (+1)",
@ -470,9 +557,10 @@
"BOL.ui.bionotes": "Notes",
"BOL.chat.welcome1": "Bienvenue dans Barbarians of Lemuria (Ludospherik version)",
"BOL.chat.welcome2": "Les livres nécessaires pour jouer sont disponibles sur le site de l'éditeur : http://www.ludospherik.fr/content/14-barbarians-of-lemuria",
"BOL.chat.welcome2": "Les livres nécessaires pour jouer sont disponibles sur le site de <a href='http://www.ludospherik.fr/content/14-barbarians-of-lemuria'>l'éditeur Ludospherik.</a>",
"BOL.chat.welcome3": "Les cartes intégrées au système le sont grace à l'aimable autorisation de leur auteur Guillaume Tavernier et des éditions Ludospherik. Merci à eux !.",
"BOL.chat.welcome4": "Tout le support et le suivi de ce système est disponible via le Discord Foundry FR : https://discord.gg/pPSDNJk",
"BOL.chat.welcome5": "Bon jeu en Lemurie !"
"BOL.chat.welcome4": "Tout le support et le suivi de ce système est disponible via le <a href='https://discord.gg/pPSDNJk'>Discord Foundry FR</a>.",
"BOL.chat.welcome5": "Consulter l'aide en ligne pour plus d'informations : @UUID[Compendium.bol.aides-de-jeu.97rugQOtiwt8zPfQ]{Aide du Jeu}.",
"BOL.chat.welcome6": "Bon jeu en Lemurie !"
}

View File

@ -94,8 +94,8 @@ export class BoLActorSheet extends ActorSheet {
// Delete Inventory Item
html.find('.item-delete').click(ev => {
Dialog.confirm({
title: "Suppression",
content: `Vous êtes sûr de vouloir supprimer cet item ?`,
title: game.i18n.localize("BOL.ui.deletetitle"),
content: game.i18n.localize("BOL.ui.confirmdelete"),
yes: () => {
const li = $(ev.currentTarget).parents(".item");
this.actor.deleteEmbeddedDocuments("Item", [li.data("itemId")])
@ -134,26 +134,33 @@ export class BoLActorSheet extends ActorSheet {
formData.alchemy = this.actor.alchemy
formData.containers = this.actor.containers
formData.treasure = this.actor.treasure
formData.boleffects = this.actor.boleffects
formData.alchemyrecipe = this.actor.alchemyrecipe
formData.horoscopes = this.actor.horoscopes
formData.vehicles = this.actor.vehicles
formData.fightoptions = this.actor.fightoptions
formData.ammos = this.actor.ammos
formData.misc = this.actor.misc
formData.combat = this.actor.buildCombat()
formData.initiativeRank = this.actor.getInitiativeRank()
//formData.combatCreature = this.actor.buildCombatCreature()
formData.features = this.actor.buildFeatures()
formData.isGM = game.user.isGM
formData.options = this.options
formData.owner = this.document.isOwner
formData.editScore = this.options.editScore
formData.useBougette = BoLUtility.getUseBougette()
formData.useBougette = (this.actor.type == "character" && BoLUtility.getUseBougette()) || false
formData.bougette = this.actor.getBougette()
formData.charType = this.actor.getCharType()
formData.villainy = this.actor.getVillainy()
formData.biography = await TextEditor.enrichHTML(this.object.system.details.biography, {async: true})
formData.notes = await TextEditor.enrichHTML(this.object.system.details.notes, {async: true})
formData.isSorcerer = this.actor.isSorcerer()
formData.isAlchemist = this.actor.isAlchemist()
formData.isAstrologer = this.actor.isAstrologer()
formData.isMysteries = formData.isSorcerer || formData.isAlchemist || formData.isAstrologer
formData.isPriest = this.actor.isPriest()
formData.horoscopeGroupList = game.settings.get("bol", "horoscope-group")
formData.isGM = game.user.isGM
@ -235,10 +242,22 @@ export class BoLActorSheet extends ActorSheet {
case "attributexp":
this.actor.incAttributeXP(dataset.key)
break;
case "bougette":
this.actor.rollBougette()
break;
case "careerxp":
this.actor.incCareerXP( li.data("item-id"))
break;
case "horoscope-minor":
BoLRoll.horoscopeCheck(this.actor, event, "minor")
break
case "horoscope-major":
BoLRoll.horoscopeCheck(this.actor, event, "major")
break
case "horoscope-major-group":
BoLRoll.horoscopeCheck(this.actor, event, "majorgroup")
break
default: break;
}
}

View File

@ -1,5 +1,6 @@
import { BoLDefaultRoll } from "../controllers/bol-rolls.js";
import { BoLUtility } from "../system/bol-utility.js";
import { BoLRoll } from "../controllers/bol-rolls.js";
/**
* Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system.
@ -24,10 +25,11 @@ export class BoLActor extends Actor {
/* -------------------------------------------- */
getCharType() {
if (this.type === 'character') {
return 'player'
return "player"
}
return this.system.chartype
}
/* -------------------------------------------- */
getVillainy() {
if (this.type === 'character') {
@ -36,6 +38,37 @@ export class BoLActor extends Actor {
return true
}
/* -------------------------------------------- */
getBougette() {
if ( this.type == "character") {
let b = duplicate(this.system.bougette)
b.label = game.i18n.localize( game.bol.config.bougetteState[String(this.system.bougette.value)] )
b.diceImg = "icons/dice/" + game.bol.config.bougetteDice[String(this.system.bougette.value)] + "black.svg"
return b
}
return undefined
}
/* -------------------------------------------- */
async rollBougette() {
if ( this.type == "character") {
let attribute = duplicate(this.system.attributes.vigor)
let rollData = BoLRoll.getCommonRollData(this, "bougette", attribute, undefined )
rollData.formula = game.bol.config.bougetteDice[String(this.system.bougette.value)]
let r = new BoLDefaultRoll(rollData)
r.roll()
}
}
/* -------------------------------------------- */
decBougette() {
if ( this.type == "character") {
let bougette = duplicate(this.system.bougette)
bougette.value = Math.max( Number(bougette.value) - 1, 0)
this.update( { 'system.bougette': bougette } )
}
}
/* -------------------------------------------- */
updateResourcesData() {
if (this.type == 'character') {
@ -52,7 +85,7 @@ export class BoLActor extends Actor {
/* -------------------------------------------- */
prepareDerivedData() {
if ( this.type == "vehicle") {
if (this.type == "vehicle") {
} else {
super.prepareDerivedData()
@ -102,6 +135,13 @@ export class BoLActor extends Actor {
if (fo && fo.system.properties.fightoptiontype == "attack") {
defMod += -1
}
// Apply defense effects
for (let i of this.items) {
if (i.type === "feature" && i.system.subtype === "boleffect" && i.system.properties.identifier.includes("aptitudes.def") ) {
defMod += Number(i.system.properties.modifier)
}
}
console.log("Defense : ", defMod)
return this.system.aptitudes.def.value + defMod
}
@ -206,6 +246,12 @@ export class BoLActor extends Actor {
get resources() {
return Object.values(this.system.resources)
}
get boleffects() {
return this.items.filter(i => i.type === "feature" && i.system.subtype === "boleffect")
}
get horoscopes() {
return this.items.filter(i => i.type === "feature" && i.system.subtype === "horoscope")
}
get boons() {
return duplicate(this.items.filter(i => i.type === "feature" && i.system.subtype === "boon") || []);
}
@ -213,7 +259,7 @@ export class BoLActor extends Actor {
return duplicate(this.items.filter(i => i.type === "feature" && i.system.subtype === "flaw") || []);
}
get careers() {
return duplicate( this.items.filter(i => i.type === "feature" && i.system.subtype === "career") || [])
return duplicate(this.items.filter(i => i.type === "feature" && i.system.subtype === "career") || [])
}
get origins() {
return this.items.filter(i => i.type === "feature" && i.system.subtype === "origin");
@ -237,7 +283,7 @@ export class BoLActor extends Actor {
return this.items.filter(i => i.type === "item")
}
get equipmentCreature() {
return this.items.filter(i => i.type === "item" && i.system.category === "equipment" && (( i.system.subtype === "weapon" && i.system.properties.natural === true) || (i.system.subtype === "armor")) )
return this.items.filter(i => i.type === "item" && i.system.category === "equipment" && ((i.system.subtype === "weapon" && i.system.properties.natural === true) || (i.system.subtype === "armor")))
}
get armors() {
return this.items.filter(i => i.type === "item" && i.system.category === "equipment" && i.system.subtype === "armor");
@ -249,7 +295,7 @@ export class BoLActor extends Actor {
return this.items.filter(i => i.type === "item" && i.system.category === "equipment" && i.system.subtype === "shield");
}
get vehicleWeapons() {
return this.items.filter(i => i.type === "item" && i.system.category === "vehicleweapon" )
return this.items.filter(i => i.type === "item" && i.system.category === "vehicleweapon")
}
get weapons() {
return this.items.filter(i => i.type === "item" && i.system.category === "equipment" && i.system.subtype === "weapon")
@ -295,10 +341,10 @@ export class BoLActor extends Actor {
get bonusBoons() {
let boons = this.items.filter(i => i.type === "feature" && i.system.subtype === "boon" && i.system.properties.isbonusdice)
return duplicate( boons || [])
return duplicate(boons || [])
}
get malusFlaws() {
return duplicate( this.items.filter(i => i.type === "feature" && i.system.subtype === "flaw" && i.system.properties.ismalusdice) || []);
return duplicate(this.items.filter(i => i.type === "feature" && i.system.subtype === "flaw" && i.system.properties.ismalusdice) || []);
}
isSorcerer() {
@ -311,6 +357,11 @@ export class BoLActor extends Actor {
return true
return false
}
isAstrologer() {
if (this.careers.find(item => item.system.properties.astrologer == true))
return true
return false
}
isPriest() {
if (this.careers.find(item => item.system.properties.priest == true))
return true
@ -329,6 +380,23 @@ export class BoLActor extends Actor {
return ppCostArmor
}
/*-------------------------------------------- */
getDamageAttributeValue(attrDamage) {
let attrDamageValue = 0
if (attrDamage.includes("vigor")) {
attrDamageValue = this.system.attributes.vigor.value
if (attrDamage.includes("half")) {
attrDamageValue = Math.floor(attrDamageValue / 2)
}
// Apply vigor effects
for (let i of this.items) {
if (i.type === "feature" && i.system.subtype === "boleffect" && i.system.properties.identifier.includes("vigor") ) {
attrDamageValue += Number(i.system.properties.modifier)
}
}
}
return attrDamageValue
}
/*-------------------------------------------- */
getArmorAgiMalus() {
let malusAgi = 0
for (let armor of this.protections) {
@ -364,6 +432,80 @@ export class BoLActor extends Actor {
this.updateEmbeddedDocuments('Item', [{ _id: alchemy.id, 'system.properties.pccurrent': 0 }])
}
}
/*-------------------------------------------- */
spentAstrologyPoints(points) {
let astrology = duplicate(this.system.resources.astrologypoints)
astrology.value -= points
astrology.value = Math.max(astrology.value,0)
this.update( { 'system.resources.astrologypoints': astrology} )
}
/*-------------------------------------------- */
getHoroscopesBonus() {
let astro = this.items.filter(it => it.type == "feature" && it.system.subtype == "horoscope" && !it.system.properties.ishoroscopemajor
&& it.system.properties.horoscopeanswer == "favorable")
return astro
}
/*-------------------------------------------- */
getHoroscopesMalus() {
let astro = this.items.filter(it => it.type == "feature" && it.system.subtype == "horoscope" && !it.system.properties.ishoroscopemajor
&& it.system.properties.horoscopeanswer == "unfavorable")
return astro
}
/*-------------------------------------------- */
manageHoroscope(rollData) {
//Spent points
this.spentAstrologyPoints(rollData.astrologyPointsCost)
if ( rollData.horoscopeType == "minor") {
let horoscope = { name: "SITUATION A SPECIFIER", type :"feature",
img: "icons/magic/perception/eye-ringed-glow-angry-large-red.webp",
system :{subtype: "horoscope", properties: {
ishoroscopemajor: false,
horoscopeanswer: (rollData.isSuccess) ? "favorable": "unfavorable",
rank: rollData.careerBonus
}
}
}
this.createEmbeddedDocuments('Item', [horoscope])
}
if ( rollData.horoscopeType == "major" ) {
if ( rollData.isSuccess) {
this.subHeroPoints(1)
} else {
this.addHeroPoints(1)
}
}
if ( rollData.horoscopeType == "majorgroup" ) {
let rID = randomID(16)
let horoscopes = duplicate(game.settings.get("bol", "horoscope-group"))
horoscopes[rID] = {
id: rID,
name: game.i18n.localize("BOL.ui.groupHoroscope") + this.name,
maxDice: rollData.careerBonus,
availableDice: rollData.careerBonus,
type: (rollData.isSuccess) ? "bonus": "malus"
}
game.settings.set("bol", "horoscope-group", horoscopes)
}
}
/*-------------------------------------------- */
getAstrologyPoints() {
return this.system.resources.astrologypoints.value
}
/*-------------------------------------------- */
removeHoroscopeMinor( rollData) {
let toDel = []
for(let horo of rollData.selectedHoroscope) {
toDel.push( horo._id )
}
if (toDel.length > 0) {
this.deleteEmbeddedDocuments('Item', toDel)
}
}
/*-------------------------------------------- */
async spendAlchemyPoint(alchemyId, pcCost) {
@ -377,11 +519,18 @@ export class BoLActor extends Actor {
newPC = alchemy.system.properties.pccurrent + pcCost
await this.updateEmbeddedDocuments('Item', [{ _id: alchemy.id, 'system.properties.pccurrent': newPC }])
} else {
ui.notifications.warn("Plus assez de Points de Création !")
ui.notifications.warn( game.i18n.localize("BOL.ui.nomorealchemypoints") )
}
}
}
/*-------------------------------------------- */
getAstrologerBonus() {
let astrologer = this.careers.find(item => item.system.properties.astrologer == true)
if (astrologer) {
return astrologer.system.rank
}
return 0;
}
/*-------------------------------------------- */
getAlchemistBonus() {
let sorcerer = this.careers.find(item => item.system.properties.alchemist == true)
@ -401,7 +550,7 @@ export class BoLActor extends Actor {
/*-------------------------------------------- */
heroReroll() {
if (this.villainy == 'character') {
if (this.type == 'character') {
return this.system.resources.hero.value > 0;
} else {
if (this.system.villainy == 'adversary') {
@ -471,6 +620,11 @@ export class BoLActor extends Actor {
"label": "BOL.featureSubtypes.gods",
"ranked": false,
"items": this.godsfaith
},
"boleffects": {
"label": "BOL.featureSubtypes.effects",
"ranked": false,
"items": this.boleffects
}
}
}
@ -560,39 +714,99 @@ export class BoLActor extends Actor {
async manageHealthState() {
let hpID = "lastHP" + this.id
let lastHP = await this.getFlag("world", hpID)
if (lastHP != this.system.resources.hp.value && game.user.isGM ) { // Only GM sends this
if (lastHP != this.system.resources.hp.value && game.user.isGM) { // Only GM sends this
await this.setFlag("world", hpID, this.system.resources.hp.value)
let prone = this.effects.find( ef => ef.label == "EFFECT.StatusProne")
let dead = this.effects.find( ef => ef.label == "EFFECT.StatusDead")
if (this.system.resources.hp.value <= 0) {
if ( !prone) {
await this.createEmbeddedDocuments("ActiveEffect", [
{label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg', flags: { core: { statusId: 'prone' } } }
])
}
if ( this.system.resources.hp.value < -5 && !dead) {
await this.createEmbeddedDocuments("ActiveEffect", [
{label: 'EFFECT.StatusDead', icon: 'icons/svg/skull.svg', flags: { core: { statusId: 'dead' } } }
])
}
ChatMessage.create({
alias: this.name,
whisper: BoLUtility.getWhisperRecipientsAndGMs(this.name),
content: await renderTemplate('systems/bol/templates/chat/chat-vitality-zero.hbs', { name: this.name, img: this.img, hp: this.system.resources.hp.value })
})
} else {
if ( prone ) {
await this.deleteEmbeddedDocuments("ActiveEffect", [ prone.id ] )
}
if ( dead ) {
await this.deleteEmbeddedDocuments("ActiveEffect", [ dead.id ] )
}
}
}
}
/*-------------------------------------------- */
registerInit(initScore, isCritical, isFumble) {
this.update({ 'system.combat.lastinit': initScore, 'system.combat.iscritical': isCritical, 'system.combat.isfumble': isFumble })
async registerInit(rollData) {
rollData.actor = undefined // Cleanup if present
await this.setFlag("world", "last-initiative", rollData)
}
/*-------------------------------------------- */
getLastInitData() {
return this.system.combat
clearInitiative() {
this.unsetFlag("world", "last-initiative" )
}
/*-------------------------------------------- */
getInitiativeRank(rollData = undefined, isCombat = false) {
if (!rollData) {
rollData = this.getFlag("world", "last-initiative")
}
let fvttInit = 4 // Pietaille par defaut
if (this.type == 'character' ) {
fvttInit = 5
if (!rollData) {
fvttInit = -1
if ( isCombat ) {
ui.notifications.warn(game.i18n.localize("BOL.ui.warninitiative"))
}
} else {
if (rollData.isLegendary) {
fvttInit = 10
} else if (rollData.isCritical) {
fvttInit = 9
} else if (rollData.isSuccess ) {
fvttInit = 8
} else if (rollData.isFumble) {
fvttInit = 3
}
}
}
if ( this.getCharType() == 'adversary') {
fvttInit = 7
}
if ( this.getCharType() == 'tough') {
fvttInit = 6
}
return fvttInit
}
/*-------------------------------------------- */
async subHeroPoints(nb) {
let newHeroP = this.system.resources.hero.value - nb;
newHeroP = (newHeroP < 0) ? 0 : newHeroP;
await this.update({ 'system.resources.hero.value': newHeroP });
}
/*-------------------------------------------- */
async addHeroPoints(nb) {
let newHeroP = this.system.resources.hero.value + nb;
newHeroP = (newHeroP < 0) ? 0 : newHeroP;
await this.update({ 'system.resources.hero.value': newHeroP });
}
/*-------------------------------------------- */
async sufferDamage(damage) {
let newHP = this.system.resources.hp.value - damage
await this.update({ 'system.resources.hp.value': newHP })
await this.update({ 'system.resources.hp.value': newHP })
}
/* -------------------------------------------- */
@ -605,13 +819,13 @@ export class BoLActor extends Actor {
} else if (protect.system.subtype == 'armor') {
if (BoLUtility.getRollArmor()) {
if (!protect.system.properties.soak.formula || protect.system.properties.soak.formula == "") {
ui.notifications.warn(`L'armure ${protect.name} n'a pas de formule pour la protection !`)
ui.notifications.warn( game.i18n.localize("BOL.ui.armornoformula", protect.name) )
} else {
formula += "+" + " max(" + protect.system.properties.soak.formula +",0)"
formula += "+" + " max(" + protect.system.properties.soak.formula + ",0)"
}
} else {
if (protect.system.properties.soak.value == undefined) {
ui.notifications.warn(`L'armure ${protect.name} n'a pas de valeur fixe pour la protection !`)
ui.notifications.warn( game.i18n.localize("BOL.ui.armornoformula", protect.name) )
} else {
formula += "+ " + protect.system.properties.soak.value
}
@ -626,7 +840,7 @@ export class BoLActor extends Actor {
rollProtection(itemId) {
let armor = duplicate(this.items.get(itemId))
if (armor) {
let armorFormula = "max("+armor.system.properties.soak.formula + ", 0)"
let armorFormula = "max(" + armor.system.properties.soak.formula + ", 0)"
let rollArmor = new Roll(armorFormula)
rollArmor.roll({ async: false }).toMessage()
}

View File

@ -16,6 +16,7 @@ import { BoLTokenHud } from "./system/bol-action-hud.js"
import { BoLHotbar } from "./system/bol-hotbar.js"
import { BoLAdventureGenerator } from "./system/bol-adventure-generator.js"
import { BoLCommands} from "./system/bol-commands.js"
import { BoLCharacterSummary} from "./system/bol-character-summary.js"
/* -------------------------------------------- */
Hooks.once('init', async function () {
@ -40,7 +41,7 @@ Hooks.once('init', async function () {
*/
CONFIG.Combat.initiative = {
formula: "2d6+@attributes.mind.value+@aptitudes.init.value",
decimals: 3
decimals: 2
};
// Define custom Entity classes
@ -110,13 +111,17 @@ function welcomeMessage() {
game.i18n.localize("BOL.chat.welcome2") + "<p>" +
game.i18n.localize("BOL.chat.welcome3") + "<p>" +
game.i18n.localize("BOL.chat.welcome4") + "</p>" +
game.i18n.localize("BOL.chat.welcome5") + "</p>"
game.i18n.localize("BOL.chat.welcome5") + "<br>" +
game.i18n.localize("BOL.chat.welcome6")
} )
}
/* -------------------------------------------- */
Hooks.once('ready', async function () {
BoLUtility.ready()
BoLCharacterSummary.ready()
registerUsageCount('bol')

View File

@ -16,27 +16,76 @@ export class BoLRoll {
}
/* -------------------------------------------- */
static attributeCheck(actor, key) {
static updateApplicableEffects(rollData) {
let appEffects = []
for (let effect of rollData.bolEffects) {
if (effect.system.properties.identifier == "always") {
appEffects.push(effect)
} else if (effect.system.properties.identifier.includes(rollData.attribute.key)) {
appEffects.push(effect)
} else if (rollData.aptitude && effect.system.properties.identifier.includes(rollData.aptitude.key)) {
appEffects.push(effect)
}
}
return appEffects
}
let attribute = eval(`actor.system.attributes.${key}`)
let label = (attribute.label) ? game.i18n.localize(attribute.label) : null
let description = game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label)
/* -------------------------------------------- */
static buildHoroscopeGroupList() {
let horoscopes = game.settings.get("bol", "horoscope-group")
let horoList = [ { id: -1, name: "Aucun", type: "malus", nbDice: 0 }]
for (let id in horoscopes) {
let horo = horoscopes[id]
for (let i=0; i<horo.availableDice; i++) {
horoList.push( { id: id, name: horo.name, type: horo.type, nbDice: i+1})
}
}
return horoList
}
/* -------------------------------------------- */
static getCommonRollData(actor, mode, attribute, aptitude = undefined) {
let rollData = {
mode: "attribute",
mode: mode,
actorId: actor.id,
tokenId: actor.token?.id,
img: actor.img,
attribute: attribute,
attrValue: attribute.value,
aptValue: 0,
label: label,
careerBonus: 0,
description: description,
horoscopeBonus: 0,
horoscopeMalus: 0,
selectedHoroscope: [],
armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(),
horoscopeBonusList: actor.getHoroscopesBonus(),
horoscopeMalusList: actor.getHoroscopesMalus(),
adv: "0",
mod: 0
mod: 0,
modRanged: 0,
aptValue: 0,
bolEffects: actor.boleffects,
horoscopeGroupList: this.buildHoroscopeGroupList()
}
if (aptitude) {
rollData.aptitude = aptitude
rollData.aptValue = aptitude.value
}
rollData.bolApplicableEffects = this.updateApplicableEffects(rollData)
return rollData
}
/* -------------------------------------------- */
static attributeCheck(actor, key) {
let attribute = eval(`actor.system.attributes.${key}`)
let rollData = this.getCommonRollData(actor, "attribute", attribute)
rollData.description = game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label)
rollData.label = (attribute.label) ? game.i18n.localize(attribute.label) : null
console.log(">>>>>>>>>>", rollData, actor)
return this.displayRollDialog(rollData)
}
@ -48,49 +97,36 @@ export class BoLRoll {
let attrKey = this.getDefaultAttribute(key)
let attribute = eval(`actor.system.attributes.${attrKey}`)
let label = (aptitude.label) ? game.i18n.localize(aptitude.label) : null;
let description = game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label);
return this.displayRollDialog(
{
mode: "aptitude",
actorId: actor.id,
img: actor.img,
attribute: attribute,
aptitude: aptitude,
attrValue: attribute.value,
aptValue: aptitude.value,
armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(),
label: label,
careerBonus: 0,
adv: "0",
description: description,
mod: 0
})
let rollData = this.getCommonRollData(actor, "aptitude", attribute, aptitude)
rollData.label = (aptitude.label) ? game.i18n.localize(aptitude.label) : null
rollData.description = game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label)
return this.displayRollDialog(rollData)
}
/* -------------------------------------------- */
static async detectDistance( weapon, target ) {
static async detectDistance(weapon, target) {
let visible, dist
if (weapon.system.properties.ranged || weapon.system.properties.throwing) {
if (target && (weapon.system.properties.ranged || weapon.system.properties.throwing)) {
console.log("target", target, weapon)
visible = canvas.effects.visibility.testVisibility(target.center, { object: _token })
dist = Number(canvas.grid.measureDistances([{ ray: new Ray(_token.center, target.center) }], { gridSpaces: false })).toFixed(2)
let range = Number(weapon.system.properties.range)
let rangeMsg = "BOL.chat.rangeout"
if ( dist <= range) {
if (dist <= range) {
rangeMsg = "BOL.chat.range0"
} else if (dist < range*2) {
} else if (dist < range * 2) {
rangeMsg = "BOL.chat.range1"
} else if (dist < range*3) {
} else if (dist < range * 3) {
rangeMsg = "BOL.chat.range2"
} else if (dist < range*4) {
} else if (dist < range * 4) {
rangeMsg = "BOL.chat.range3"
} else if (dist < range*5) {
} else if (dist < range * 5) {
rangeMsg = "BOL.chat.range4"
} else if (dist < range*6) {
} else if (dist < range * 6) {
rangeMsg = "BOL.chat.range5"
} else if (dist < range*7) {
} else if (dist < range * 7) {
rangeMsg = "BOL.chat.range6"
}
ChatMessage.create({
@ -104,7 +140,7 @@ export class BoLRoll {
rangeMsg: rangeMsg
})
})
}
}
}
/* -------------------------------------------- */
@ -116,8 +152,10 @@ export class BoLRoll {
let attribute = eval(`actor.system.attributes.${weaponData.properties.attackAttribute}`)
let aptitude = eval(`actor.system.aptitudes.${weaponData.properties.attackAptitude}`)
let rollData = this.getCommonRollData(actor, "weapon", attribute, aptitude)
// Compute distance
this.detectDistance( weapon, target)
this.detectDistance(weapon, target)
// Manage specific case
let fightOption = actor.getActiveFightOption()
@ -125,31 +163,19 @@ export class BoLRoll {
ui.notifications.warn(`{{actor.name}} est en Défense Totale ! Il ne peut pas attaquer ce round.`)
return
}
// Build the roll structure
let rolldata = {
mode: "weapon",
actorId: actor.id,
img: actor.img,
weapon: weapon,
isRanged: weaponData.properties.ranged || weaponData.properties.throwing,
targetId: target?.id,
fightOption: fightOption,
careerBonus: 0,
defenderId: target?.actor.id,
attribute: attribute,
aptitude: aptitude,
attrValue: attribute.value,
aptValue: aptitude.value,
armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(),
mod: 0,
modRanged: 0,
adv: "0",
label: (weapon.name) ? weapon.name : game.i18n.localize('BOL.ui.noWeaponName'),
description: game.i18n.localize('BOL.ui.weaponAttack') + " : " + weapon.name,
}
return this.displayRollDialog(rolldata)
// Update the roll structure
rollData.weapon = weapon
rollData.isRanged = weaponData.properties.ranged || weaponData.properties.throwing
rollData.targetId = target?.id
rollData.fightOption = fightOption
rollData.defenderId = target?.actor.id
rollData.label = (weapon.name) ? weapon.name : game.i18n.localize('BOL.ui.noWeaponName')
rollData.description = game.i18n.localize('BOL.ui.weaponAttack') + " : " + weapon.name
return this.displayRollDialog(rollData)
}
/* -------------------------------------------- */
static weaponCheck(actor, event) {
const li = $(event.currentTarget).parents(".item")
@ -173,55 +199,59 @@ export class BoLRoll {
alchemy = duplicate(alchemy)
let alchemyData = alchemy.system
if (alchemyData.properties.pccurrent < alchemyData.properties.pccost) {
ui.notifications.warn("Pas assez de Points de Cration investis dans la Préparation !")
ui.notifications.warn("Pas assez de Points de Création investis dans la Préparation !")
return
}
let alchemyDef = {
mode: "alchemy",
actorId: actor.id,
img: actor.img,
alchemy: alchemy,
attribute: actor.system.attributes.mind,
attrValue: actor.system.attributes.mind.value,
aptValue: 0,
adv: "0",
careerBonus: actor.getAlchemistBonus(),
pcCost: Number(alchemyData.properties.pccost),
pcCostCurrent: Number(alchemyData.properties.pccurrent),
mod: Number(alchemyData.properties.difficulty),
armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(),
label: alchemy.name,
description: game.i18n.localize('BOL.ui.makeAlchemy') + "+" + alchemy.name,
}
console.log("ALCHEMY!", alchemyDef);
return this.displayRollDialog(alchemyDef);
let rollData = this.getCommonRollData(actor, "alchemy", actor.system.attributes.mind)
rollData.alchemy = alchemy
rollData.careerBonus = actor.getAlchemistBonus()
rollData.pcCost = Number(alchemyData.properties.pccost)
rollData.pcCostCurrent = Number(alchemyData.properties.pccurrent)
rollData.mod = Number(alchemyData.properties.difficulty)
rollData.label = alchemy.name
rollData.description = game.i18n.localize('BOL.ui.makeAlchemy') + "+" + alchemy.name
console.log("ALCHEMY!", rollData);
return this.displayRollDialog(rollData);
}
/* -------------------------------------------- */
static spellCheckWithSpell( actor, spell ) {
let spellDef = {
mode: "spell",
actorId: actor.id,
img: actor.img,
spell: spell,
attribute: actor.system.attributes.mind,
attrValue: actor.system.attributes.mind.value,
aptValue: 0,
adv: "0",
ppCurrent: Number(actor.system.resources.power.value),
careerBonus: actor.getSorcererBonus(),
ppCostArmor: actor.getPPCostArmor(),
ppCost: Number(spell.system.properties.ppcost),
mod: Number(spell.system.properties.difficulty),
armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(),
label: spell.name,
description: game.i18n.localize('BOL.ui.focusSpell') + " : " + spell.name,
static horoscopeCheck(actor, event, horoscopeType) {
let cost = (horoscopeType == "minor") ? 1 : 2
if (cost > actor.getAstrologyPoints() ) {
ui.notifications.warn(game.i18n.localize("BOL.ui.astrologyNoPoints"))
return
}
let rollData = this.getCommonRollData(actor, "horoscope", actor.system.attributes.mind)
rollData.careerBonus = actor.getAstrologerBonus()
rollData.horoscopeType = horoscopeType
rollData.horoscopeTypeLabel = "BOL.ui."+horoscopeType
rollData.astrologyPointsCost = cost
rollData.label = game.i18n.localize('BOL.ui.makeHoroscope')
rollData.description = game.i18n.localize('BOL.ui.makeHoroscope') + " " + game.i18n.localize(rollData.horoscopeTypeLabel)
console.log("HOROSCOPE!", rollData);
return this.displayRollDialog(rollData);
}
/* -------------------------------------------- */
static spellCheckWithSpell(actor, spell) {
let rollData = this.getCommonRollData(actor, "spell", actor.system.attributes.mind)
rollData.spell = spell
rollData.ppCurrent = Number(actor.system.resources.power.value),
rollData.careerBonus = actor.getSorcererBonus(),
rollData.ppCostArmor = actor.getPPCostArmor(),
rollData.ppCost = Number(spell.system.properties.ppcost),
rollData.mod = Number(spell.system.properties.difficulty),
rollData.label = spell.name,
rollData.description = game.i18n.localize('BOL.ui.focusSpell') + " : " + spell.name
//console.log("SPELL!", spellDef)
return this.displayRollDialog(spellDef)
return this.displayRollDialog(rollData)
}
/* -------------------------------------------- */
@ -237,7 +267,7 @@ export class BoLRoll {
return
}
spell = duplicate(spell)
return this.spellCheckWithSpell( actor, spell)
return this.spellCheckWithSpell(actor, spell)
}
/* -------------------------------------------- */
@ -246,8 +276,35 @@ export class BoLRoll {
this.updateArmorMalus(this.rollData)
this.updatePPCost(this.rollData)
// get basic dices from boons/flaws
let effectModifier = 0
this.rollData.bmDice = this.rollData.nbBoons - this.rollData.nbFlaws + this.rollData.bDice - this.rollData.mDice
// add applicable bonus/malus dices effects
for (let effect of this.rollData.bolApplicableEffects) {
if (effect.system.properties.modifier == "1B") {
this.rollData.bmDice++;
} else if (effect.system.properties.modifier == "1B") {
this.rollData.bmDice += 2;
} else if (effect.system.properties.modifier == "1M") {
this.rollData.bmDice--;
} else if (effect.system.properties.modifier == "2M") {
this.rollData.bmDice -= 2;
} else {
effectModifier += Number(effect.system.properties.modifier)
}
}
this.rollData.bmDice += this.rollData.horoscopeBonus
this.rollData.bmDice -= this.rollData.horoscopeMalus
if ( this.rollData.selectedGroupHoroscopeIndex && this.rollData.selectedGroupHoroscopeIndex > 0) {
let horo = this.rollData.horoscopeGroupList[this.rollData.selectedGroupHoroscopeIndex]
this.rollData.bmDice += (horo.type == "malus") ? -horo.nbDice : horo.nbDice;
}
// Keep track of the final effect modifier
this.rollData.effectModifier = effectModifier
// Final number of dices
this.rollData.nbDice = 2 + Math.abs(this.rollData.bmDice)
// Bonus or Malus ?
if (this.rollData.bmDice == 0) {
$('#roll-nbdice').val("2")
} else {
@ -255,12 +312,19 @@ export class BoLRoll {
$('#roll-nbdice').val("2 + " + String(Math.abs(this.rollData.bmDice)) + letter)
}
let rollbase = this.rollData.attrValue + "+" + this.rollData.aptValue
if ( this.rollData.weapon && this.rollData.weapon.system.properties.onlymodifier ) {
if (this.rollData.weapon && this.rollData.weapon.system.properties.onlymodifier) {
rollbase = ""
}
$('#roll-modifier').val(rollbase + "+" + this.rollData.careerBonus + "+" + this.rollData.mod + "+" +
this.rollData.modRanged + "+" + this.rollData.weaponModifier + "-" + this.rollData.defence + "-" + this.rollData.modArmorMalus + "-" +
this.rollData.shieldMalus + "+" + this.rollData.attackModifier + "+" + this.rollData.appliedArmorMalus)
this.rollData.shieldMalus + "+" + this.rollData.attackModifier + "+" + this.rollData.appliedArmorMalus + "+" + effectModifier)
// Rebuild lits of applicable effects
let selectEffects = ""
for (let effect of this.rollData.bolApplicableEffects) {
selectEffects += `<option value="${effect.id}" selected>${effect.name}</option>`
}
$('#applicable-effects').html(selectEffects)
}
/* -------------------------------------------- */
@ -320,7 +384,7 @@ export class BoLRoll {
html.find('#optcond').change((event) => { // Dynamic change of PP cost of spell
let pp = BoLUtility.computeSpellCost(this.rollData.spell, event.currentTarget.selectedOptions.length)
this.rollData.ppCost = pp
this.updatePPCost( this.rollData)
this.updatePPCost(this.rollData)
})
html.find('#mod').change((event) => {
@ -334,16 +398,18 @@ export class BoLRoll {
html.find('#attr').change((event) => {
let attrKey = event.currentTarget.value
let actor = game.actors.get( this.rollData.actorId)
let actor = BoLUtility.getActorFromRollData(this.rollData)
this.rollData.attribute = duplicate(actor.system.attributes[attrKey])
this.rollData.attrValue = actor.system.attributes[attrKey].value
this.rollData.bolApplicableEffects = this.updateApplicableEffects(this.rollData)
this.updateTotalDice()
})
html.find('#apt').change((event) => {
let aptKey = event.currentTarget.value
let actor = game.actors.get( this.rollData.actorId)
let actor = BoLUtility.getActorFromRollData(this.rollData)
this.rollData.aptitude = duplicate(actor.system.aptitudes[aptKey])
this.rollData.aptValue = actor.system.aptitudes[aptKey].value
this.rollData.bolApplicableEffects = this.updateApplicableEffects(this.rollData)
this.updateTotalDice()
})
@ -380,6 +446,31 @@ export class BoLRoll {
this.rollData.mDice = Number(event.currentTarget.value)
this.updateTotalDice()
})
html.find('#horoscope-bonus-applied').change((event) => {
this.rollData.selectedHoroscope = []
for (let option of event.currentTarget.selectedOptions) {
this.rollData.selectedHoroscope.push( duplicate(this.rollData.horoscopeBonusList[Number(option.index)]) )
}
let horoscopes = $('#horoscope-bonus-applied').val()
this.rollData.horoscopeBonus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
this.updateTotalDice()
})
html.find('#horoscope-malus-applied').change((event) => {
this.rollData.selectedHoroscope = []
for (let option of event.currentTarget.selectedOptions) {
this.rollData.selectedHoroscope.push( duplicate(this.rollData.horoscopeBonusList[Number(option.index)]) )
}
let horoscopes = $('#horoscope-malus-applied').val()
this.rollData.horoscopeMalus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
this.updateTotalDice()
})
html.find('#horoscope-group-applied').change((event) => {
this.rollData.selectedGroupHoroscopeIndex = event.currentTarget.value
this.updateTotalDice()
})
}
/* -------------------------------------------- */
@ -387,7 +478,7 @@ export class BoLRoll {
if (rollData.mode == "weapon") {
rollData.weaponModifier = rollData.weapon.system.properties.attackModifiers ?? 0
rollData.attackBonusDice = rollData.weapon.system.properties.attackBonusDice
if ( rollData.attackBonusDice) {
if (rollData.attackBonusDice) {
rollData.adv = "1B"
rollData.bDice = 1
}
@ -412,9 +503,9 @@ export class BoLRoll {
// initialize default flags/values
const rollOptionTpl = `systems/bol/templates/dialogs/${rollData.mode}-roll-dialog.hbs`
let actor = game.actors.get( rollData.actorId )
let actor = BoLUtility.getActorFromRollData(rollData)
let defender
if ( rollData.targetId) {
if (rollData.targetId) {
let token = game.scenes.current.tokens.get(rollData.targetId)
defender = token.actor
}
@ -477,15 +568,15 @@ export class BoLRoll {
//console.log("ROLLMALUS", rollData)
rollData.registerInit = (rollData.aptitude && rollData.aptitude.key == 'init') ? $('#register-init').is(":checked") : false;
const isMalus = rollData.nbFlaws > rollData.nbBoons
const isMalus = (rollData.bmDice < 0)
//rollData.nbDice += (rollData.attackBonusDice) ? 1 : 0
let rollbase = rollData.attrValue + rollData.aptValue
if ( rollData.weapon && rollData.weapon.system.properties.onlymodifier ) {
if (rollData.weapon && rollData.weapon.system.properties.onlymodifier) {
rollbase = 0
}
const modifiers = rollbase + rollData.careerBonus + rollData.mod + rollData.weaponModifier - rollData.defence - rollData.modArmorMalus + rollData.shieldMalus + rollData.attackModifier + rollData.appliedArmorMalus
}
const modifiers = rollbase + rollData.careerBonus + rollData.mod + rollData.weaponModifier - rollData.defence - rollData.modArmorMalus + rollData.shieldMalus + rollData.attackModifier + rollData.appliedArmorMalus + rollData.effectModifier
const formula = (isMalus) ? rollData.nbDice + "d6kl2 + " + modifiers : rollData.nbDice + "d6kh2 + " + modifiers
rollData.formula = formula
rollData.modifiers = modifiers
@ -514,10 +605,10 @@ export class BoLDefaultRoll {
this.rollData.isFumble = false;
}
if (this.rollData.optionsId) {
BoLUtility.cleanupButtons( this.rollData.optionsId)
BoLUtility.cleanupButtons(this.rollData.optionsId)
}
if (this.rollData.applyId) {
BoLUtility.cleanupButtons( this.rollData.applyId)
BoLUtility.cleanupButtons(this.rollData.applyId)
}
this.rollData.optionsId = randomID(16)
this.rollData.applyId = randomID(16)
@ -527,7 +618,7 @@ export class BoLDefaultRoll {
async roll() {
const r = new Roll(this.rollData.formula)
// console.log("Roll formula", this.rollData.formula)
//console.log("Roll formula", this.rollData.formula)
await r.roll({ "async": false })
const activeDice = r.terms[0].results.filter(r => r.active)
const diceTotal = activeDice.map(r => r.result).reduce((a, b) => a + b)
@ -539,32 +630,46 @@ export class BoLDefaultRoll {
this.rollData.isLegendary = false
this.rollData.isFumble = (diceTotal === 2)
this.rollData.isFailure = !this.rollData.isSuccess
//this.rollData.isRealCritical = true
//this.rollData.isFumble = true
let actor = game.actors.get( this.rollData.actorId)
let actor = BoLUtility.getActorFromRollData(this.rollData)
if (this.rollData.reroll == undefined) {
this.rollData.reroll = actor.heroReroll()
}
if (this.rollData.registerInit) {
actor.registerInit(r.total, this.rollData.isCritical, this.rollData.isFumble)
actor.registerInit(this.rollData)
this.rollData.initiativeRank = actor.getInitiativeRank(this.rollData)
}
if (this.rollData.isSuccess && this.rollData.mode == "spell") { // PP cost management
this.rollData.remainingPP = actor.spendPowerPoint(this.rollData.ppCost + this.rollData.ppCostArmor)
}
if (this.rollData.mode == "alchemy") { // PP cost management
actor.resetAlchemyStatus(this.rollData.alchemy._id)
}
if (this.rollData.mode == "bougette" && this.rollData.isFailure) {
actor.decBougette()
}
await this.sendChatMessage()
if (this.rollData.mode == "horoscope") { // PP cost management
actor.manageHoroscope(this.rollData)
}
if (this.rollData.selectedHoroscope.length > 0) { // PP cost management
actor.removeHoroscopeMinor(this.rollData)
}
if (this.rollData.selectedGroupHoroscopeIndex && this.rollData.selectedGroupHoroscopeIndex > 0) { // PP cost management
BoLUtility.removeGroupHoroscope(this.rollData)
}
}
/* -------------------------------------------- */
async sendChatMessage() {
let actor = game.actors.get( this.rollData.actorId)
this._buildChatMessage(this.rollData).then( async msgFlavor => {
let actor = BoLUtility.getActorFromRollData(this.rollData)
this._buildChatMessage(this.rollData).then(async msgFlavor => {
let msg = await this.rollData.roll.toMessage({
user: game.user.id,
rollMode: game.settings.get("core", "rollMode"),
@ -602,7 +707,7 @@ export class BoLDefaultRoll {
this.rollData.reroll = false
this.sendChatMessage()
}
/* -------------------------------------------- */
setSuccess(flag) {
this.rollData.isSuccess = flag
@ -610,7 +715,7 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */
async sendDamageMessage() {
let actor = game.actors.get( this.rollData.actorId)
let actor = BoLUtility.getActorFromRollData(this.rollData)
this._buildDamageChatMessage(this.rollData).then(async msgFlavor => {
let msg = await this.rollData.damageRoll.toMessage({
user: game.user.id,
@ -625,16 +730,8 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */
getDamageAttributeValue(attrDamage, actorId = undefined) {
let attrDamageValue = 0
let actor = game.actors.get( (actorId) ? actorId: this.rollData.actorId)
if (attrDamage.includes("vigor")) {
attrDamageValue = actor.system.attributes.vigor.value
if (attrDamage.includes("half")) {
attrDamageValue = Math.floor(attrDamageValue / 2)
}
}
return attrDamageValue
let actor = BoLUtility.getActorFromRollData(this.rollData)
return actor.getDamageAttributeValue(attrDamage)
}
/* -------------------------------------------- */
@ -677,8 +774,8 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */
_buildChatMessage(rollData) {
const rollMessageTpl = 'systems/bol/templates/chat/rolls/default-roll-card.hbs';
return renderTemplate(rollMessageTpl, rollData);
const rollMessageTpl = 'systems/bol/templates/chat/rolls/default-roll-card.hbs'
return renderTemplate(rollMessageTpl, rollData)
}
}

View File

@ -40,7 +40,7 @@ export class BoLCalendar extends Application {
constructor() {
super();
// position
this.calendarPos = duplicate(game.settings.get(SYSTEM_RDD, "calendar-pos"));
this.calendarPos = duplicate(game.settings.get("bol", "calendar-pos"));
if (this.calendarPos == undefined || this.calendarPos.top == undefined) {
this.calendrierPos = BoLCalendar.createCalendarPos()
game.settings.set("bol", "calendar-pos", this.calendarPos)

View File

@ -0,0 +1,162 @@
/* -------------------------------------------- */
import { BoLUtility } from "./bol-utility.js";
import { BoLRoll } from "../controllers/bol-rolls.js";
/* -------------------------------------------- */
export class BoLCharacterSummary extends Application {
/* -------------------------------------------- */
static displayPCSummary(){
game.bol.charSummary.render(true)
}
/* -------------------------------------------- */
updatePCSummary(){
if ( this.rendered) {
this.render(true)
}
}
/* -------------------------------------------- */
static createSummaryPos() {
return { top: 200, left: 200 };
}
/* -------------------------------------------- */
static ready() {
if ( !game.user.isGM ) { // Uniquement si GM
return
}
let charSummary = new BoLCharacterSummary()
game.bol.charSummary = charSummary
}
/* -------------------------------------------- */
constructor() {
super();
//game.settings.set("world", "character-summary-data", {npcList: [], x:0, y:0})
this.settings = game.settings.get("world", "character-summary-data")
}
/* -------------------------------------------- */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
template: "systems/bol/templates/apps/character-summary-template.html",
popOut: true,
resizable: true,
dragDrop: [{ dragSelector: ".items-list .item", dropSelector: null }],
classes: ["bol", "dialog"], width: 820, height: 'fit-content'
})
}
/* -------------------------------------------- */
getData() {
let formData = super.getData();
formData.pcs = game.actors.filter( ac => ac.type == "character" && ac.hasPlayerOwner )
formData.npcs = []
let newList = []
let toUpdate = false
for( let actorId of this.settings.npcList ) {
let actor = game.actors.get(actorId)
if (actor) {
formData.npcs.push( actor )
newList.push(actorId)
} else {
toUpdate = true
}
}
formData.config = game.bol.config
formData.horoscopeGroupList = game.settings.get("bol", "horoscope-group")
if ( toUpdate ) {
this.settings.npcList = newList
//console.log("Going to update ...", this.settings)
game.settings.set("world", "character-summary-data", this.settings)
}
return formData
}
/* -------------------------------------------- */
updateNPC() {
game.settings.set("world", "character-summary-data", game.bol.charSummary.settings)
game.bol.charSummary.close()
setTimeout( function() { game.bol.charSummary.render(true)}, 500)
}
/* -------------------------------------------- */
async _onDrop(event) {
//console.log("Dragged data are : ", dragData)
let data = event.dataTransfer.getData('text/plain')
let dataItem = JSON.parse( data)
let actor = fromUuidSync(dataItem.uuid)
if (actor) {
game.bol.charSummary.settings.npcList.push( actor.id )
game.bol.charSummary.updateNPC()
} else {
ui.notifications.warn( game.i18n.localize("BOL.ui.noactorfound") )
}
}
/* -------------------------------------------- */
/** @override */
async activateListeners(html) {
super.activateListeners(html);
html.find('.actor-open').click((event) => {
const li = $(event.currentTarget).parents(".item")
const actor = game.actors.get(li.data("actor-id"))
actor.sheet.render(true)
})
html.find('.summary-roll').click((event) => {
const li = $(event.currentTarget).parents(".item")
const actor = game.actors.get(li.data("actor-id"))
let type = $(event.currentTarget).data("type")
let key = $(event.currentTarget).data("key")
if ( type == "attribute") {
BoLRoll.attributeCheck(actor, key, event)
} else if (type == "aptitude") {
BoLRoll.aptitudeCheck(actor, key, event)
}
})
html.find('.actor-delete').click(event => {
const li = $(event.currentTarget).parents(".item");
let actorId = li.data("actor-id")
let newList = game.bol.charSummary.settings.npcList.filter(id => id != actorId)
game.bol.charSummary.settings.npcList = newList
game.bol.charSummary.updateNPC()
})
html.find('#horoscope-group-edit-available').change(event => {
const horoId = $(event.currentTarget).data("horo-id")
let newValue = event.currentTarget.value
let horoscopes = duplicate(game.settings.get("bol", "horoscope-group"))
if ( horoId && horoscopes[horoId]) {
horoscopes[horoId].availableDice = Number(newValue)
if (newValue <= 0) {
horoscopes[horoId] = undefined
}
game.settings.set("bol", "horoscope-group", horoscopes)
setTimeout(function() { BoLUtility.updateSheets()}, 800 )
}
})
html.find('#horoscope-group-edit-max').change(event => {
const horoId = $(event.currentTarget).data("horo-id")
let newValue = event.currentTarget.value
let horoscopes = duplicate(game.settings.get("bol", "horoscope-group"))
if ( horoId && horoscopes[horoId]) {
horoscopes[horoId].maxDice = Number(newValue)
if (newValue <= 0) {
horoscopes[horoId] = undefined
}
game.settings.set("bol", "horoscope-group", horoscopes)
setTimeout(function() { BoLUtility.updateSheets()}, 800 )
}
})
}
}

View File

@ -10,6 +10,8 @@ Init order =
3 - Echec critique
*/
import { BoLUtility } from "../system/bol-utility.js";
export class BoLCombatManager extends Combat {
@ -18,35 +20,12 @@ export class BoLCombatManager extends Combat {
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions);
// Structure input data
ids = typeof ids === "string" ? [ids] : ids;
const currentId = this.combatant._id;
//const currentId = this.combatant.id;
// calculate initiative
for (let cId = 0; cId < ids.length; cId++) {
const combatant = this.combatants.get(ids[cId]);
let fvttInit = 5
//console.log("TYPE", combatant.actor.type)
if (combatant.actor.type == 'character') {
let initData = combatant.actor.getLastInitData()
console.log("Init data !!!", initData)
if (initData.isLegendary) {
fvttInit = 10
} else if (initData.isCritical) {
fvttInit = 9
} else if (initData.lastinit >= 9) {
fvttInit = 8
} else if (initData.isFumble) {
fvttInit = 3
}
} else {
fvttInit = 4 // Pietaille par defautco
//console.log("ACTOR", combatant.actor.getCharType())
if ( combatant.actor.getCharType() == 'adversary') {
fvttInit = 7
}
if ( combatant.actor.getCharType() == 'tough') {
fvttInit = 6
}
}
const combatant = this.combatants.get(ids[cId])
let fvttInit = combatant.actor.getInitiativeRank(false, true)
fvttInit += (cId / 100)
await this.updateEmbeddedDocuments("Combatant", [{ _id: ids[cId], initiative: fvttInit }]);
}
@ -61,7 +40,16 @@ export class BoLCombatManager extends Combat {
}
super.nextRound()
}
/************************************************************************************/
_onDelete() {
let combatants = this.combatants.contents
for (let c of combatants) {
let actor = game.actors.get(c.data.actorId)
actor.clearInitiative()
}
super._onDelete()
}
}

View File

@ -1,5 +1,6 @@
/* -------------------------------------------- */
import { BoLAdventureGenerator } from "./bol-adventure-generator.js"
import { BoLCharacterSummary } from "./bol-character-summary.js"
/* -------------------------------------------- */
export class BoLCommands {
@ -8,6 +9,7 @@ export class BoLCommands {
if (!game.bol.commands) {
const bolCommands = new BoLCommands()
bolCommands.registerCommand({ path: ["/adventure"], func: (content, msg, params) => BoLAdventureGenerator.createAdventure(), descr: "Nouvelle idée d'aventure!" });
bolCommands.registerCommand({ path: ["/pcview"], func: (content, msg, params) => BoLCharacterSummary.displayPCSummary(), descr: "Affiche la liste des PJs!" });
game.bol.commands = bolCommands
}

View File

@ -48,12 +48,12 @@ export class BoLHotbar {
if (speaker.token) actor = game.actors.tokens[speaker.token]
if (!actor) actor = game.actors.get(speaker.actor)
if (!actor) {
return ui.notifications.warn(`Selectionnez votre personnage pour utiliser la macro`)
return ui.notifications.warn( game.i18n.localize("BOL.ui.selectactor") )
}
let item = actor.items.find(it => it.name === itemName && it.type == itemType)
if (!item ) {
return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`)
return ui.notifications.warn( game.i18n.localize("BOL.ui.itemnotfound") )
}
// Trigger the item roll
if (item.system.category === "equipment" && item.system.subtype === "weapon") {

View File

@ -28,6 +28,13 @@ export class BoLUtility {
type: Boolean,
onChange: lang => window.location.reload()
})
game.settings.register("world", "character-summary-data", {
name: "character-summary-data",
scope: "world",
config: false,
default: { npcList: [], x: 200, y: 200 },
type: Object
})
game.settings.register("bol", "logoActorSheet", {
name: "Chemin du logo des fiches de perso",
hint: "Vous pouvez changer le logo BoL des fiches de perso, pour jouer dans un autre univers (idéalement 346 x 200, défaut : /systems/bol/ui/logo.webp)",
@ -46,6 +53,13 @@ export class BoLUtility {
type: String,
onChange: lang => window.location.reload()
})
game.settings.register("bol", "horoscope-group", {
name: "horoscope-group",
scope: "world",
config: false,
default: {},
type: Object
})
this.rollArmor = game.settings.get("bol", "rollArmor") // Roll armor or not
this.useBougette = game.settings.get("bol", "useBougette") // Use optionnal bougette rules
@ -69,11 +83,24 @@ export class BoLUtility {
static getLogoTopLeft() {
return this.logoTopLeft
}
/* -------------------------------------------- */
static getActorFromRollData(rollData) {
let actor = game.actors.get(rollData.actorId)
if (rollData.tokenId) {
let token = canvas.tokens.placeables.find(t => t.id == rollData.tokenId)
if (token) {
actor = token.actor
}
}
return actor
}
/* -------------------------------------------- */
static async ready() {
//$("#logo").attr("src", this.getLogoTopLeft() )
$("#logo").css("content",`url(${this.getLogoTopLeft()})`)
$("#logo").css("content", `url(${this.getLogoTopLeft()})`)
CONFIG.statusEffects = duplicate(game.bol.config.statusEffects)
}
/* -------------------------------------------- */
@ -271,7 +298,7 @@ export class BoLUtility {
let attackId = event.currentTarget.attributes['data-attack-id'].value
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
let weaponId = (event.currentTarget.attributes['data-weapon-id']) ? event.currentTarget.attributes['data-weapon-id'].value : -1
// Remove message for all
let msgId = BoLUtility.findChatMessageId(event.currentTarget)
if (game.user.isGM) {
@ -287,7 +314,7 @@ export class BoLUtility {
if (!game.user.isGM) {
return
}
BoLUtility.removeChatMessageId( msgId )
BoLUtility.removeChatMessageId(msgId)
console.log("Damage Handling", attackId, defenseMode, weaponId)
// Only GM process this
let attackDef = this.attackStore[attackId]
@ -334,10 +361,10 @@ export class BoLUtility {
let defenderUser
for (let user of game.users) {
if ( user.character && user.character.id == defender.id ) {
if (user.character && user.character.id == defender.id) {
defenderUser = user
}
}
}
let damageResults = {
attackId: attackDef.id,
attacker: attackDef.attacker,
@ -534,31 +561,53 @@ export class BoLUtility {
}
/* -------------------------------------------- */
static async confirmDelete(actorSheet, li) {
let itemId = li.data("item-id");
let msgTxt = "<p>Are you sure to remove this Item ?";
let buttons = {
delete: {
icon: '<i class="fas fa-check"></i>',
label: "Yes, remove it",
callback: () => {
actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]);
li.slideUp(200, () => actorSheet.render(false));
}
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel"
}
}
msgTxt += "</p>";
let d = new Dialog({
title: "Confirm removal",
content: msgTxt,
buttons: buttons,
default: "cancel"
});
d.render(true);
static async loadCompendiumData(compendium) {
const pack = game.packs.get(compendium);
return await pack?.getDocuments() ?? [];
}
/* -------------------------------------------- */
static async loadCompendium(compendium, filter = item => true) {
let compendiumData = await this.loadCompendiumData(compendium);
return compendiumData.filter(filter);
}
/* -------------------------------------------- */
static async searchItem(dataItem) {
let item
if (dataItem.pack) {
let id = dataItem.id || dataItem._id
let items = await this.loadCompendium(dataItem.pack, item => item.id == id)
item = items[0] || undefined
} else {
item = game.items.get(dataItem.id)
}
return item
}
/* -------------------------------------------- */
static updateSheets() {
// Then force opened actor refresh if needed
for (let actor of game.actors) {
if (actor.sheet.rendered) {
actor.sheet.render()
}
}
game.bol.charSummary.updatePCSummary() // Refresh if needed
}
/* -------------------------------------------- */
static removeGroupHoroscope(rollData) {
let horo = rollData.horoscopeGroupList[rollData.selectedGroupHoroscopeIndex]
let horoscopes = duplicate(game.settings.get("bol", "horoscope-group"))
let toChange = duplicate(horoscopes[horo.id])
toChange.availableDice -= horo.nbDice // Remove the dice
if (toChange.availableDice <= 0) {
horoscopes[horo.id] = undefined
} else {
horoscopes[horo.id] = toChange
}
game.settings.set("bol", "horoscope-group", horoscopes)
this.updateSheets()
}
}

View File

@ -115,6 +115,14 @@ BOL.aptitudes = {
"def" : "BOL.aptitudes.def"
}
BOL.resources = {
"hp" : "BOL.resources.hp",
"hero" : "BOL.resources.hero",
"faith" : "BOL.resources.faith",
"power" : "BOL.resources.power",
"alchemypoints" : "BOL.resources.alchemypoints"
}
BOL.weaponSizes = {
"unarmed" : "BOL.weaponSize.unarmed",
"improvised" : "BOL.weaponSize.improvised",
@ -260,7 +268,9 @@ BOL.featureSubtypes = {
"flaw" : "BOL.featureSubtypes.flaw",
"language" : "BOL.featureSubtypes.language",
"godsfaith" : "BOL.featureSubtypes.gods",
"fightoption" : "BOL.featureSubtypes.fightOption"
"fightoption" : "BOL.featureSubtypes.fightOption",
"boleffect": "BOL.featureSubtypes.effect",
"horoscope": "BOL.featureSubtypes.horoscope",
}
BOL.fightOptionTypes = {
@ -288,11 +298,18 @@ BOL.actorIcons = {
}
BOL.bougetteState = {
"nomoney": "BOL.bougette.nomoney",
"tolive": "BOL.bougette.tolive",
"easylife": "BOL.bougette.easylife",
"luxury": "BOL.bougette.luxury",
"rich": "BOL.bougette.rich"
"0": "BOL.bougette.nomoney",
"1": "BOL.bougette.tolive",
"2": "BOL.bougette.easylife",
"3": "BOL.bougette.luxury",
"4": "BOL.bougette.rich"
}
BOL.bougetteDice = {
"0": "0",
"1": "2d6-1",
"2": "2d6",
"3": "2d6+1",
"4": "2d6+2"
}
BOL.creatureSize = {
@ -310,4 +327,134 @@ BOL.creatureSize = {
"colossal": "BOL.size.colossal"
}
BOL.horoscopeAnswer = {
"favorable": "BOL.ui.horoscopefavorable",
"unfavorable": "BOL.ui.horoscopeunfavorable",
}
BOL.bolEffectModifier = {
"-8": "-8",
"-6": "-6",
"-4": "-4",
"-2": "-2",
"-1": "-1",
"1B": "1B",
"2B": "2B",
"1M": "1M",
"2M": "2M",
"+1": "+1",
"+2": "+2",
"+4": "+4",
"+6": "+6",
"+8": "+8",
}
BOL.statusEffects = [
{
"id": "dead",
"label": "EFFECT.StatusDead",
"icon": "icons/svg/skull.svg"
},
{
"id": "unconscious",
"label": "EFFECT.StatusUnconscious",
"icon": "icons/svg/unconscious.svg"
},
{
"id": "sleep",
"label": "EFFECT.StatusAsleep",
"icon": "icons/svg/sleep.svg"
},
{
"id": "stun",
"label": "EFFECT.StatusStunned",
"icon": "icons/svg/daze.svg"
},
{
"id": "prone",
"label": "EFFECT.StatusProne",
"icon": "icons/svg/falling.svg"
},
{
"id": "restrain",
"label": "EFFECT.StatusRestrained",
"icon": "icons/svg/net.svg"
},
{
"id": "paralysis",
"label": "EFFECT.StatusParalysis",
"icon": "icons/svg/paralysis.svg"
},
{
"id": "fly",
"label": "EFFECT.StatusFlying",
"icon": "icons/svg/wing.svg"
},
{
"id": "blind",
"label": "EFFECT.StatusBlind",
"icon": "icons/svg/blind.svg"
},
{
"id": "deaf",
"label": "EFFECT.StatusDeaf",
"icon": "icons/svg/deaf.svg"
},
{
"id": "silence",
"label": "EFFECT.StatusSilenced",
"icon": "icons/svg/silenced.svg"
},
{
"id": "fear",
"label": "EFFECT.StatusFear",
"icon": "icons/svg/terror.svg"
},
{
"id": "burning",
"label": "EFFECT.StatusBurning",
"icon": "icons/svg/fire.svg"
},
{
"id": "frozen",
"label": "EFFECT.StatusFrozen",
"icon": "icons/svg/frozen.svg"
},
{
"id": "shock",
"label": "EFFECT.StatusShocked",
"icon": "icons/svg/lightning.svg"
},
{
"id": "disease",
"label": "EFFECT.StatusDisease",
"icon": "icons/svg/biohazard.svg"
},
{
"id": "poison",
"label": "EFFECT.StatusPoison",
"icon": "icons/svg/poison.svg"
},
{
"id": "curse",
"label": "EFFECT.StatusCursed",
"icon": "icons/svg/sun.svg"
},
{
"id": "invisible",
"label": "EFFECT.StatusInvisible",
"icon": "icons/svg/invisible.svg"
},
{
"id": "target",
"label": "EFFECT.StatusTarget",
"icon": "icons/svg/target.svg"
},
{
"id": "eye",
"label": "EFFECT.StatusMarked",
"icon": "icons/svg/eye.svg"
}
]
BOL.debug = false;

View File

@ -76,6 +76,10 @@ export const registerHandlebarsHelpers = function () {
Handlebars.registerHelper('count', function (list) {
return list.length;
})
Handlebars.registerHelper('countKeys', function (obj) {
return Object.keys(obj).length;
})
Handlebars.registerHelper('isEnabled', function (configKey) {
return game.settings.get("bol", configKey);
})
@ -103,6 +107,12 @@ export const registerHandlebarsHelpers = function () {
Handlebars.registerHelper('sub', function (a, b) {
return parseInt(a) - parseInt(b);
})
Handlebars.registerHelper('abbrev2', function (a) {
return a.substring(0,2);
})
Handlebars.registerHelper('abbrev3', function (a) {
return a.substring(0,3);
})
Handlebars.registerHelper('valueAtIndex', function (arr, idx) {
return arr[idx];
})
@ -123,7 +133,14 @@ export const registerHandlebarsHelpers = function () {
}
return false
})
Handlebars.registerHelper('upperFirst', function (text) {
if (typeof text !== 'string') return text
return text.charAt(0).toUpperCase() + text.slice(1)
})
Handlebars.registerHelper('upperFirstOnly', function (text) {
if (typeof text !== 'string') return text
return text.charAt(0).toUpperCase()
})
}

View File

@ -75,4 +75,18 @@ export default function registerHooks() {
}
return false;
});
/********************************************************************************** */
Hooks.on("renderActorDirectory", (app, html, data) => {
if (game.user.isGM) {
const button = document.createElement('button');
button.style.width = '95%';
button.innerHTML = game.i18n.localize("BOL.ui.pclistbutton")
button.addEventListener('click', () => {
game.bol.charSummary.render(true)
})
html.find('.header-actions').after(button)
}
})
}

View File

@ -16,6 +16,7 @@ export const preloadHandlebarsTemplates = async function () {
"systems/bol/templates/actor/parts/tabs/actor-equipment.hbs",
"systems/bol/templates/actor/parts/tabs/actor-spellalchemy.hbs",
"systems/bol/templates/actor/parts/tabs/actor-biodata.hbs",
"systems/bol/templates/actor/parts/tabs/actor-horoscope-group.hbs",
"systems/bol/templates/actor/parts/tabs/creature-stats.hbs",
"systems/bol/templates/actor/parts/tabs/creature-actions.hbs",
"systems/bol/templates/actor/parts/tabs/vehicle-stats.hbs",
@ -36,24 +37,30 @@ export const preloadHandlebarsTemplates = async function () {
"systems/bol/templates/item/parts/properties/feature/career-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/boon-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/flaw-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/effect-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/origin-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/race-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/fightoption-properties.hbs",
"systems/bol/templates/item/parts/properties/item/weapon-vehicle-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/horoscope-properties.hbs",
// DIALOGS
"systems/bol/templates/chat/rolls/attack-damage-card.hbs",
"systems/bol/templates/chat/rolls/spell-roll-card.hbs",
"systems/bol/templates/chat/rolls/alchemy-roll-card.hbs",
"systems/bol/templates/chat/rolls/selected-horoscope-roll-card.hbs",
"systems/bol/templates/chat/rolls/horoscope-roll-card.hbs",
"systems/bol/templates/dialogs/aptitude-roll-part.hbs",
"systems/bol/templates/dialogs/attribute-roll-part.hbs",
"systems/bol/templates/dialogs/mod-roll-part.hbs",
"systems/bol/templates/dialogs/adv-roll-part.hbs",
"systems/bol/templates/dialogs/career-roll-part.hbs",
"systems/bol/templates/dialogs/effect-roll-part.hbs",
"systems/bol/templates/dialogs/boons-roll-part.hbs",
"systems/bol/templates/dialogs/flaws-roll-part.hbs",
"systems/bol/templates/dialogs/total-roll-part.hbs",
"systems/bol/templates/dialogs/fightoptions-roll-part.hbs",
"systems/bol/templates/dialogs/horoscope-roll-part.hbs"
];
// Load the template parts

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
packs/effets-exemples.db Normal file
View File

@ -0,0 +1,4 @@
{"name":"Vigueur -1","type":"feature","img":"icons/consumables/potions/bottle-conical-corked-labeled-skull-poison-green.webp","system":{"category":null,"subtype":"boleffect","description":"","properties":{"ismalusdice":false,"bonusmalus":-2,"identifier":"system.attributes.vigor","modifier":"-1"},"rank":0},"effects":[],"flags":{"core":{"sourceId":"Item.6fTZ6hOKR4pWbWOe"}},"_stats":{"systemId":"bol","systemVersion":"10.3.3","coreVersion":"10.290","createdTime":1669218607632,"modifiedTime":1669234720255,"lastModifiedBy":"kQghu0tL1dft5xLu"},"_id":"6fTZ6hOKR4pWbWOe","folder":null,"sort":0,"ownership":{"default":0,"kQghu0tL1dft5xLu":3}}
{"name":"Esprit -1","type":"feature","img":"icons/consumables/potions/bottle-conical-corked-labeled-skull-poison-green.webp","system":{"category":null,"subtype":"boleffect","description":"","properties":{"ismalusdice":false,"bonusmalus":-2,"identifier":"system.attributes.mind","modifier":"-1"},"rank":0},"effects":[],"flags":{"core":{"sourceId":"Item.6fTZ6hOKR4pWbWOe"}},"_stats":{"systemId":"bol","systemVersion":"10.3.3","coreVersion":"10.290","createdTime":1669218607632,"modifiedTime":1669234720255,"lastModifiedBy":"kQghu0tL1dft5xLu"},"_id":"V2geomwPtTBnBeQW","folder":null,"sort":0,"ownership":{"default":0,"kQghu0tL1dft5xLu":3}}
{"name":"Agilité -1","type":"feature","img":"icons/consumables/potions/bottle-conical-corked-labeled-skull-poison-green.webp","system":{"category":null,"subtype":"boleffect","description":"","properties":{"ismalusdice":false,"bonusmalus":-2,"identifier":"system.attributes.agility","modifier":"-1"},"rank":0},"effects":[],"flags":{"core":{"sourceId":"Item.6fTZ6hOKR4pWbWOe"}},"_stats":{"systemId":"bol","systemVersion":"10.3.3","coreVersion":"10.290","createdTime":1669218607632,"modifiedTime":1669234720255,"lastModifiedBy":"kQghu0tL1dft5xLu"},"_id":"eXPNwGQiwnIiGYaK","folder":null,"sort":0,"ownership":{"default":0,"kQghu0tL1dft5xLu":3}}
{"name":"Aura -1","type":"feature","img":"icons/consumables/potions/bottle-conical-corked-labeled-skull-poison-green.webp","system":{"category":null,"subtype":"boleffect","description":"","properties":{"ismalusdice":false,"bonusmalus":-2,"identifier":"system.attributes.appeal","modifier":"-1"},"rank":0},"effects":[],"flags":{"core":{"sourceId":"Item.6fTZ6hOKR4pWbWOe"}},"_stats":{"systemId":"bol","systemVersion":"10.3.3","coreVersion":"10.290","createdTime":1669218607632,"modifiedTime":1669234720256,"lastModifiedBy":"kQghu0tL1dft5xLu"},"_id":"zwSNMO9HpiqUCMt8","folder":null,"sort":0,"ownership":{"default":0,"kQghu0tL1dft5xLu":3}}

View File

@ -14,7 +14,7 @@
],
"url": "https://www.uberwald.me/gitea/public/bol",
"license": "LICENSE.txt",
"version": "10.3.3",
"version": "10.5.0",
"compatibility": {
"minimum": "10",
"verified": "10",
@ -182,6 +182,15 @@
"private": false,
"flags": {}
},
{
"label": "Effets - Exemples",
"type": "Item",
"name": "effets-exemples",
"path": "packs/effets-exemples.db",
"system": "bol",
"private": false,
"flags": {}
},
{
"label": "Créatures",
"type": "Actor",
@ -194,8 +203,8 @@
],
"socket": true,
"manifest": "https://www.uberwald.me/gitea/public/bol/raw/v10/system.json",
"download": "https://www.uberwald.me/gitea/public/bol/archive/bol-v10.3.3.zip",
"background": "systems/images/map_lemurie.webp",
"download": "https://www.uberwald.me/gitea/public/bol/archive/bol-v10.5.0.zip",
"background": "systems/bol/ui/page_accueil.webp",
"gridDistance": 1.5,
"gridUnits": "m",
"primaryTokenAttribute": "resources.hp",

View File

@ -102,26 +102,30 @@
"hp": {
"key": "hp",
"label": "BOL.resources.hp",
"base": 0,
"value": 0,
"ismain": true,
"base": 1,
"value": 1,
"bonus": 0,
"max": 0
"max": 1
},
"hero": {
"key": "hero",
"label": "BOL.resources.hero",
"ismain": true,
"value": 5,
"max": 5
},
"faith": {
"key": "faith",
"label": "BOL.resources.faith",
"ismain": true,
"value": 0,
"max": 0
},
"power": {
"key": "power",
"label": "BOL.resources.power",
"ismain": true,
"value": 0,
"bonus": 0,
"max": 0
@ -129,6 +133,15 @@
"alchemypoints": {
"key": "alchemypoints",
"label": "BOL.resources.alchemypoints",
"ismain": false,
"value": 0,
"bonus": 0,
"max": 0
},
"astrologypoints": {
"key": "astrologypoints",
"label": "BOL.resources.astrologypoints",
"ismain": false,
"value": 0,
"bonus": 0,
"max": 0
@ -141,7 +154,8 @@
"chartype": "player",
"villainy": false,
"bougette": {
"state": "nomoney"
"state": "nomoney",
"value": 0
},
"xp": {
"key": "xp",

View File

@ -7,6 +7,23 @@
<div class="sidebar flex0 bol-actor-sidebar">
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100"
style="border:1px outset lightgray; box-shadow: 5px 5px 5px gray" />
<div></div>
{{#if (count boleffects)}}
<ol class="items-list">
<li class="item flexrow item-header">
<div class="item-name flex2">{{localize "BOL.ui.effects"}}</div>
</li>
{{#each boleffects as |effect keyEffect|}}
<li class="item flexrow" data-item-id="{{effect.id}}">
<div class="item-image"><img src="{{effect.img}}" title="{{effect.name}}"/></div>
<h4 class="item-name flex2"><a class="item-edit">{{effect.name}}</a></h4>
</li>
{{/each}}
</ol>
{{/if}}
</div>
<div class="main flex1">
@ -20,7 +37,7 @@
<a class="item" data-tab="actions">{{localize "BOL.ui.tab.actions"}}</a>
<a class="item" data-tab="features">{{localize "BOL.ui.tab.features"}}</a>
<a class="item" data-tab="equipment">{{localize "BOL.ui.tab.equipment"}}</a>
{{#if (or isSorcerer isAlchemist)}}
{{#if isMysteries}}
<a class="item" data-tab="spellalchemy">{{localize "BOL.ui.tab.spellalchemy"}}</a>
{{/if}}
{{/if}}
@ -49,7 +66,7 @@
{{> "systems/bol/templates/actor/parts/tabs/actor-features.hbs"}}
</div>
{{#if (or isSorcerer isAlchemist)}}
{{#if isMysteries}}
<div class="tab features" data-group="primary" data-tab="spellalchemy">
{{> "systems/bol/templates/actor/parts/tabs/actor-spellalchemy.hbs"}}
</div>

View File

@ -1,52 +1,124 @@
<ol class="items-list">
{{#if (ne charType "creature")}}
<li class="item flexrow item-header">
<div class="item-name left">{{localize "BOL.ui.biosize"}}</div>
<div class="item-field flex2 left"><input type="text" name="system.details.height" value="{{details.height}}"></div>
<div class="item-name right">{{localize "BOL.ui.bioweight"}}</div>
<div class="item-field flex2 "><input type="text" name="system.details.weight" value="{{details.weight}}"></div>
<div class="item-name right">{{localize "BOL.ui.bioage"}} </div>
<div class="item-field flex2 "><input type="text" name="system.details.age" value="{{details.age}}"></div>
<ol class='items-list'>
{{#if (ne charType 'creature')}}
<li class='item flexrow item-header'>
<div class='item-name left'>
{{localize 'BOL.ui.biosize'}}
</div>
<div class='item-field flex2 left'>
<input
type='text'
name='system.details.height'
value="{{details.height}}"
/>
</div>
<div class='item-name right'>
{{localize 'BOL.ui.bioweight'}}
</div>
<div class='item-field flex2'>
<input
type='text'
name='system.details.weight'
value="{{details.weight}}"
/>
</div>
<div class='item-name right'>
{{localize 'BOL.ui.bioage'}}
</div>
<div class='item-field flex2'>
<input type='text' name='system.details.age' value="{{details.age}}" />
</div>
</li>
<li class="item flexrow item-header">
<div class="item-name left">{{localize "BOL.ui.biohair"}} </div>
<div class="item-field flex2 left"><input type="text" name="system.details.hait" value="{{details.hait}}"></div>
<div class="item-name right">{{localize "BOL.ui.bioeyes"}} </div>
<div class="item-field flex2 "><input type="text" name="system.details.eyes" value="{{details.eyes}}"></div>
<li class='item flexrow item-header'>
<div class='item-name left'>
{{localize 'BOL.ui.biohair'}}
</div>
<div class='item-field flex2 left'>
<input
type='text'
name='system.details.hait'
value="{{details.hait}}"
/>
</div>
<div class='item-name right'>
{{localize 'BOL.ui.bioeyes'}}
</div>
<div class='item-field flex2'>
<input
type='text'
name='system.details.eyes'
value="{{details.eyes}}"
/>
</div>
</li>
<li class="item flexrow item-header">
<div class="item-name left">{{localize "BOL.ui.biosigns"}} </div>
<div class="item-field flex2 left"><input type="text" name="system.details.signs" value="{{details.signs}}"></div>
<li class='item flexrow item-header'>
<div class='item-name left'>
{{localize 'BOL.ui.biosigns'}}
</div>
<div class='item-field flex2 left'>
<input
type='text'
name='system.details.signs'
value="{{details.signs}}"
/>
</div>
</li>
{{else}}
<li class="item flexrow item-header">
<div class="item-name left">Taille </div>
<div class="form-fields center">
<select class="field-value size" name="system.details.size" data-dtype="String">
{{#select details.size}}
{{#each config.creatureSize as |value id|}}
<option value="{{id}}">{{localize value}}</option>
{{/each}}
{{/select}}
<li class='item flexrow item-header'>
<div class='item-name left'>
Taille
</div>
<div class='form-fields center'>
<select
class='field-value size'
name='system.details.size'
data-dtype='String'
>
{{#select details.size}}
{{#each config.creatureSize as |value id|}}
<option value="{{id}}">
{{localize value}}
</option>
{{/each}}
{{/select}}
</select>
</div>
</li>
{{/if}}
</ol>
<ol class="items-list">
<li class="item flexrow item-header">
<div class="item-name flex4 left">{{localize "BOL.ui.biodescription"}}</div>
<div class="item-field flex1 right"></div>
</ol>
{{#if (and (not isAstrologer) (countKeys horoscopeGroupList))}}
{{> "systems/bol/templates/actor/parts/tabs/actor-horoscope-group.hbs"}}
{{/if}}
<ol class='items-list'>
<li class='item flexrow item-header'>
<div class='item-name flex4 left'>
{{localize 'BOL.ui.biodescription'}}
</div>
<div class='item-field flex1 right'></div>
</li>
</ol>
{{editor biography target="system.details.biography" button=true owner=owner
editable=editable}}
{{editor
biography
target='system.details.biography'
button=true
owner=owner
editable=editable
}}
<ol class="items-list">
<li class="item flexrow item-header">
<div class="item-name flex4 left">{{localize "BOL.ui.bionotes"}}</div>
<div class="item-field flex1 right"></div>
<ol class='items-list'>
<li class='item flexrow item-header'>
<div class='item-name flex4 left'>
{{localize 'BOL.ui.bionotes'}}
</div>
<div class='item-field flex1 right'></div>
</li>
</ol>
{{editor notes target="system.details.notes" button=true owner=owner editable=editable}}
{{editor
notes
target='system.details.notes'
button=true
owner=owner
editable=editable
}}

View File

@ -1,27 +1,34 @@
<!--ARMES-->
<button class="create_item">Créer un Equipement</button>
{{#if useBougette}}
<ol class="items-list">
<li class="item flexrow item-header">
<div class="item-name flex4 left">{{localize "BOL.ui.moneyTitle"}}</div>
<div class="item-name flex4 left">&nbsp;</div>
</li>
<li class="item flexrow" data-item-id="{{item._id}}">
<h4 class="item-name flex4 left">
<div class="item-image"><img src="icons/containers/bags/coinpouch-simple-leather-brown.webp" title="{{localize "BOL.ui.money"}}" /></div>
{{localize "BOL.ui.money"}}
</h4>
<select class="field-value" name="system.bougette.state" data-dtype="String">
{{#select system.bougette.state}}
{{#each config.bougetteState as |value id|}}
<option value="{{id}}">{{localize value}}</option>
{{/each}}
{{/select}}
</select>
</li>
</ol>
{{/if}}
{{#if useBougette}}
<ol class="items-list">
<li class="item flexrow item-header">
<div class="item-name flex4 left">{{localize "BOL.ui.moneyTitle"}}</div>
<div class="item-name flex4 left">&nbsp;</div>
</li>
<li class="item flexrow" data-item-id="{{item._id}}">
<h4 class="item-name flex4 left">
<div class="item-image"><img src="icons/containers/bags/coinpouch-simple-leather-brown.webp" title="{{localize "BOL.ui.money"}}" /></div>
{{localize "BOL.ui.money"}}
</h4>
<div class="item-image">
<a class="bougette-roll rollable" data-roll-type="bougette"><i class="darkgreen fas fa-dice"></i></a>
</div>
{{#if isGM}}
<select class="field-value" name="system.bougette.value" data-dtype="String">
{{#select bougette.value}}
{{#each config.bougetteState as |value id|}}
<option value="{{id}}">{{localize value}}</option>
{{/each}}
{{/select}}
</select>
{{else}}
<label class="">{{localize bougette.label}}</label></a>
{{/if}}
</li>
</ol>
{{/if}}
<ol class="items-list">
<li class="item flexrow item-header">

View File

@ -0,0 +1,26 @@
<ol class="items-list">
<li class="item flexrow item-header">
<div class="item-name flex4 left">{{localize "BOL.ui.horoscopeGroup"}}</div>
<div class="item-field flex2 center">{{localize "BOL.ui.type"}}</div>
<div class="item-field flex2 center">{{localize "BOL.ui.horoscopeDiceRemaining"}}</div>
<div class="item-field flex2 center">{{localize "BOL.ui.horoscopeDiceMax"}}</div>
<div class="item-field flex1 right"></div>
</li>
{{#each horoscopeGroupList as |horo id|}}
<li class="item flexrow" data-item-id="{{horo.id}}">
<h4 class="item-name flex4 left">
<div class="item-image"><img src="icons/magic/perception/eye-ringed-glow-angry-large-red.webp" /></div>{{horo.name}}
</h4>
<div class="item-field flex2 center">
<span class="item-field">{{upperFirst horo.type}}</span>
</div>
<div class="item-field flex2 center">
<span class="item-field">{{horo.availableDice}}</span>
</div>
<div class="item-field flex2 center">
<span class="item-field">{{horo.maxDice}}</span>
</div>
<div class="item-field flex1 right"></div>
</li>
{{/each}}
</ol>

View File

@ -21,6 +21,7 @@
</div>
<div class="item-field flex1 right">
<a class="item-control item-edit" title="{{localize "BOL.ui.edit"}}"><i class="fas fa-square"></i></a>
&nbsp;
<a class="item-control item-delete" title="{{localize "BOL.ui.delete"}}"><i class="fas fa-trash"></i></a>
</div>
</li>
@ -57,9 +58,77 @@
</div>
<div class="item-field flex1 right">
<a class="item-control item-edit" title="{{localize "BOL.ui.edit"}}"><i class="fas fa-square"></i></a>
&nbsp;
<a class="item-control item-delete" title="{{localize "BOL.ui.delete"}}"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ol>
{{/if}}
<!--ASTROLOGIE-->
{{#if isAstrologer}}
<ol class="items-list">
<li class="item flexrow item-header">
<div class="item-name flex4 left">{{localize "BOL.ui.astrologerPoints"}}</div>
<div class="item-name flex4 left">&nbsp;</div>
</li>
<li class="item flexrow" data-item-id="{{item._id}}">
<h4 class="item-name flex4 left">
<div class="item-image"><img src="icons/magic/perception/hand-eye-fire-blue.webp" /></div>
{{localize "BOL.ui.astrologerPointsLabel"}}
</h4>
<input class="field-value" type="text" name="system.resources.astrologypoints.value" value="{{resources.astrologypoints.value}}" data-dtype="Number"/>
</li>
<li class="item flexrow" data-item-id="{{item._id}}">
<h4 class="item-name flex4 left">
<div class="item-image"><img src="icons/magic/perception/eye-ringed-glow-angry-large-teal.webp" /></div>
<a class="rollable" data-roll-type="horoscope-minor">{{localize "BOL.ui.astrologyMinor"}} <i class="darkgreen fas fa-dice"></i></a>
</h4>
<h4 class="item-name flex4 left">
<div class="item-image"><img src="icons/magic/perception/eye-ringed-glow-angry-large-red.webp" /></div>
<a class="rollable" data-roll-type="horoscope-major">{{localize "BOL.ui.astrologyMajor"}} <i class="darkgreen fas fa-dice"></i></a>
</h4>
</li>
<li class="item flexrow" data-item-id="{{item._id}}">
<h4 class="item-name flex4 left">
<div class="item-image"><img src="icons/magic/perception/eye-ringed-glow-angry-large-red.webp" /></div>
<a class="rollable" data-roll-type="horoscope-major-group">{{localize "BOL.ui.astrologyMajorGroup"}} <i class="darkgreen fas fa-dice"></i></a>
</h4>
</li>
</ol>
<ol class="items-list">
<li class="item flexrow item-header">
<div class="item-name flex4 left">{{localize "BOL.ui.astrology"}}</div>
<div class="item-field flex2 center">{{localize "BOL.ui.type"}}</div>
<div class="item-field flex2 center">{{localize "BOL.ui.answer"}}</div>
<div class="item-field flex1 right"></div>
</li>
{{#each horoscopes as |item id|}}
<li class="item flexrow" data-item-id="{{item._id}}">
<h4 class="item-name flex4 left">
<div class="item-image"><img src="{{item.img}}" title="{{item.name}}"/></div>{{item.name}}
</h4>
<div class="item-field flex2 center">
{{#if item.system.properties.ishoroscopemajor}}
<span class="item-field">Majeur (de groupe)</span>
{{else}}
<span class="item-field">Mineur</span>
{{/if}}
</div>
<div class="item-field flex2 center">
<span class="item-field">{{localize (concat 'BOL.ui.horoscope' item.system.properties.horoscopeanswer)}}</span>
</div>
<div class="item-field flex1 right">
<a class="item-control item-edit" title="{{localize "BOL.ui.edit"}}"><i class="fas fa-square"></i></a>
&nbsp;
<a class="item-control item-delete" title="{{localize "BOL.ui.delete"}}"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ol>
{{> "systems/bol/templates/actor/parts/tabs/actor-horoscope-group.hbs"}}
{{/if}}

View File

@ -3,7 +3,7 @@
<div class="attribute stat flex1 flex-group-center {{key}}">
<label class="stat-label"><a class="rollable" data-roll-type="attribute" data-roll="2d6+@attributes.{{key}}.value" data-adv="0" data-key="{{key}}">{{localize label}}</a></label><br/>
<input class="stat-value rounded" type="text" name="system.attributes.{{key}}.value" value="{{numberFormat value decimals=0 sign=true}}" data-dtype="Number"/><br/>
<span class="stat-roll rollable" title="2d6" data-roll-type="attribute" data-roll="2d6+@attributes.{{key}}.value" data-adv="0" data-key="{{key}}">
<span class="stat-roll rollable" title="2d6" data-roll-type="attribute" data-roll="2d6+@attributes.{{key}}.value" data-adv="0" data-key="{{key}}">
<i class="darkgreen fas fa-dice"></i>
</span>
<span class="tooltip-container">
@ -46,34 +46,19 @@
<hr/>
<div class="resources flexrow">
{{#each resources as |resource id|}}
{{#if (eq resource.key "alchemypoints")}}
{{#if @root.isAlchemist}}
<div class="resource stat flex1 flex-group-center">
<label class="stat-label">{{localize label}}</label><br/>
<input class="stat-value resources-value" type="text" name="system.resources.{{key}}.value" value="{{numberFormat value decimals=0 sign=false}}" data-dtype="Number"/>
{{#if (eq @root.chartype 'player')}}
{{#if (exists bonus)}}
<span class="flexrow"><label class="stat-max bonus-text">Bonus</label><input class="resource-bonus resources-value" type="text" name="system.resources.{{key}}.bonus" value="{{numberFormat bonus decimals=0 sign=false}}" data-dtype="Number"/></span>
{{else}}
<span class="flexrow"><label class="stat-max resources-value">&nbsp;</label><input class="resource-bonus resources-novalue" type="text" value="" disabled></span>
{{#if resource.ismain}}
<div class="resource stat flex1 flex-group-center">
<label class="stat-label">{{localize label}}</label><br/>
<input class="stat-value resources-value" type="text" name="system.resources.{{key}}.value" value="{{numberFormat value decimals=0 sign=false}}" data-dtype="Number"/>
{{#if (eq @root.charType 'player')}}
{{#if (exists bonus)}}
<span class="flexrow"><label class="stat-max bonus-text">Bonus</label><input class="resource-bonus resources-value" type="text" name="system.resources.{{key}}.bonus" value="{{numberFormat bonus decimals=0 sign=false}}" data-dtype="Number"/></span>
{{else}}
<span class="flexrow"><label class="stat-max">&nbsp;</label><input class="resource-bonus resources-novalue" type="text" value="" disabled></span>
{{/if}}
{{/if}}
{{/if}}
<input class="resources-value" type="text" name="system.resources.{{key}}.max" value="{{numberFormat max decimals=0 sign=false}}" data-dtype="Number"/>
</div>
{{/if}}
{{else}}
<div class="resource stat flex1 flex-group-center">
<label class="stat-label">{{localize label}}</label><br/>
<input class="stat-value resources-value" type="text" name="system.resources.{{key}}.value" value="{{numberFormat value decimals=0 sign=false}}" data-dtype="Number"/>
{{#if (eq @root.chartype 'player')}}
{{#if (exists bonus)}}
<span class="flexrow"><label class="stat-max bonus-text">Bonus</label><input class="resource-bonus resources-value" type="text" name="system.resources.{{key}}.bonus" value="{{numberFormat bonus decimals=0 sign=false}}" data-dtype="Number"/></span>
{{else}}
<span class="flexrow"><label class="stat-max">&nbsp;</label><input class="resource-bonus resources-novalue" type="text" value="" disabled></span>
{{/if}}
{{/if}}
<input class="resources-value" type="text" name="system.resources.{{key}}.max" value="{{numberFormat max decimals=0 sign=false}}" data-dtype="Number"/>
</div>
<input class="resources-value" type="text" name="system.resources.{{key}}.max" value="{{numberFormat max decimals=0 sign=false}}" data-dtype="Number"/>
</div>
{{/if}}
{{/each}}
</div>

View File

@ -0,0 +1,112 @@
<form class="{{cssClass}} flexcol character-summary-container" autocomplete="off">
<ol class="items-list">
<li class="item flexrow item-header">
<div class="item-field item-name item-name-fixed-medium">{{localize "BOL.ui.pcname"}}</div>
{{#each config.attackAttributes as |attr key|}}
<div class="item-field flex2 item-field-fixed-short">{{abbrev3 (localize attr)}}</div>
{{/each}}
{{#each config.aptitudes as |apt key|}}
<div class="item-field flex2 item-field-fixed-short">{{abbrev3 (localize apt)}}</div>
{{/each}}
{{#each config.resources as |res key|}}
<div class="item-field flex2 item-field-fixed-short">{{abbrev3 (localize res)}}</div>
{{/each}}
<div class="item-field flex1 right">
</div>
</li>
{{#each pcs as |pc key|}}
<li class="item flexrow" data-actor-id="{{pc.id}}">
<div class="item-field item-name item-name-fixed-medium">
<a class="actor-open character-summary-rollable">{{pc.name}}</a>
</div>
{{#each pc.system.attributes as |attr key|}}
<div class="item-field flex2 item-field-fixed-short">
<a class="summary-roll character-summary-rollable" data-type="attribute" data-key="{{key}}">{{attr.value}}</a>
</div>
{{/each}}
{{#each pc.system.aptitudes as |apt key|}}
<div class="item-field flex item-field-fixed-short">
<a class="summary-roll character-summary-rollable" data-type="aptitude" data-key="{{key}}">{{apt.value}}</a>
</div>
{{/each}}
{{#each pc.system.resources as |res key|}}
<div class="item-field flex2 item-field-fixed-short">{{res.value}}/{{res.max}}</div>
{{/each}}
<div class="item-field flex1 right">
</div>
</li>
{{/each}}
<li class="item flexrow item-header">
<div class="item-field item-name item-name-fixed-medium">{{localize "BOL.ui.npcname"}}</div>
{{#each config.attackAttributes as |attr key|}}
<div class="item-field flex2 item-field-fixed-short">{{abbrev3 (localize attr)}}</div>
{{/each}}
{{#each config.aptitudes as |apt key|}}
<div class="item-field flex2 item-field-fixed-short">{{abbrev3 (localize apt)}}</div>
{{/each}}
{{#each config.resources as |res key|}}
<div class="item-field flex2 item-field-fixed-short">{{abbrev3 (localize res)}}</div>
{{/each}}
<div class="item-field flex1 right">
</div>
</li>
{{#each npcs as |pc key|}}
<li class="item flexrow" data-actor-id="{{pc.id}}">
<div class="item-field item-name item-name-fixed-medium">
<a class="actor-open character-summary-rollable">{{pc.name}}</a>
</div>
{{#each pc.system.attributes as |attr key|}}
<div class="item-field flex2 item-field-fixed-short">
<a class="summary-roll character-summary-rollable" data-type="attribute" data-key="{{key}}">{{attr.value}}</a>
</div>
{{/each}}
{{#each pc.system.aptitudes as |apt key|}}
<div class="item-field flex item-field-fixed-short">
<a class="summary-roll character-summary-rollable" data-type="aptitude" data-key="{{key}}">{{apt.value}}</a>
</div>
{{/each}}
{{#each pc.system.resources as |res key|}}
<div class="item-field flex2 item-field-fixed-short">{{res.value}}/{{res.max}}</div>
{{/each}}
<div class="item-field flex1 right">
<a class="item-control actor-delete" title="{{localize "BOL.ui.delete"}}"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
{{#if (countKeys horoscopeGroupList)}}
<li class="item flexrow item-header">
<div class="item-name flex4 left">{{localize "BOL.ui.horoscopeGroup"}}</div>
<div class="item-field flex2 center">{{localize "BOL.ui.type"}}</div>
<div class="item-field flex2 center">{{localize "BOL.ui.horoscopeDiceRemaining"}}</div>
<div class="item-field flex2 center">{{localize "BOL.ui.horoscopeDiceMax"}}</div>
<div class="item-field flex1 right"></div>
</li>
{{#each horoscopeGroupList as |horo id|}}
<li class="item flexrow" data-item-id="{{horo.id}}">
<h4 class="item-name flex4 left">
<div class="item-image"><img src="icons/magic/perception/eye-ringed-glow-angry-large-red.webp" /></div>{{horo.name}}
</h4>
<div class="item-field flex2 center">
<span class="item-field">{{upperFirst horo.type}}</span>
</div>
<div class="item-field flex2 center">
<input class="field-value" type="text" id="horoscope-group-edit-available" value="{{horo.availableDice}}" data-horo-id="{{id}}" data-type="Number">
</div>
<div class="item-field flex2 center">
<input class="field-value" type="text" id="horoscope-group-edit-max" value="{{horo.maxDice}}" data-horo-id="{{id}}" data-type="Number">
</div>
<div class="item-field flex1 right"></div>
</li>
{{/each}}
{{/if}}
</ol>
</form>

View File

@ -34,8 +34,27 @@
</div>
{{/if}}
{{#if initiativeRank}}
<div>
{{localize "BOL.chat.initiative"}}: {{initiativeRank}}
</div>
{{/if}}
{{#if (eq mode "bougette")}}
<div>
{{localize "BOL.chat.rollbougette"}} :
{{#if isSuccess}}
{{localize "BOL.chat.bougettesuccess"}}
{{else}}
{{localize "BOL.chat.bougettefailure"}}
{{/if}}
</div>
{{/if}}
<div id="{{optionsId}}">
{{#if isRealCritical}}
<div class="bol-margin-tb-2">
<a class="content-link" draggable="true" data-uuid="Compendium.bol.aides-de-jeu.Yl1RKQb0BjVUtilk" data-id="Yl1RKQb0BjVUtilk" data-type="JournalEntry" data-pack="bol.aides-de-jeu" data-tooltip="un journal"><i class="fas fa-book-open"></i>Succès Héroïque</a>
@ -51,7 +70,14 @@
{{#if alchemy}}
{{> "systems/bol/templates/chat/rolls/alchemy-roll-card.hbs"}}
{{/if}}
{{#if (eq mode "horoscope")}}
{{> "systems/bol/templates/chat/rolls/horoscope-roll-card.hbs"}}
{{/if}}
{{#if (count selectedHoroscope)}}
{{> "systems/bol/templates/chat/rolls/selected-horoscope-roll-card.hbs"}}
{{/if}}
{{#if reroll}}
<button class="chat-button button hero-reroll bol-margin-tb-2" data-roll-id=="{{rollId}}" data-actor-id="{{actor.id}}">{{localize "BOL.chat.reroll"}}</button>
{{/if}}

View File

@ -0,0 +1,26 @@
<h4><strong>{{localize "BOL.chat.horoscope"}} {{localize horoscopeTypeLabel}}</strong></h4>
<h4><strong>{{localize "BOL.chat.horoscopepoints" points=astrologyPointsCost}}</strong></h4>
{{#if (eq horoscopeType "minor")}}
{{#if isSuccess}}
{{localize "BOL.chat.horoscopeminorsuccess"}}
{{else}}
{{localize "BOL.chat.horoscopeminorfailure"}}
{{/if}}
{{/if}}
{{#if (eq horoscopeType "major")}}
{{#if isSuccess}}
{{localize "BOL.chat.horoscopemajorsuccess"}}
{{else}}
{{localize "BOL.chat.horoscopemajorfailure"}}
{{/if}}
{{/if}}
{{#if (eq horoscopeType "majorgroup")}}
{{#if isSuccess}}
{{localize "BOL.chat.horoscopemajorgroupsuccess" careerBonus=careerBonus}}
{{else}}
{{localize "BOL.chat.horoscopemajorgroupfailure" careerBonus=careerBonus}}
{{/if}}
{{/if}}

View File

@ -0,0 +1,8 @@
<div>
{{#each selectedHoroscope as |horo id|}}
{{localize "BOL.chat.usedhoroscope"}} : {{horo.name}}
{{/each}}
</div>
<div>{{localize "BOL.chat.horoscopedeleted"}}</div>

View File

@ -35,6 +35,10 @@
{{> "systems/bol/templates/dialogs/flaws-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/effect-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/horoscope-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/adv-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/mod-roll-part.hbs"}}

View File

@ -32,6 +32,10 @@
{{> "systems/bol/templates/dialogs/flaws-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/effect-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/horoscope-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/adv-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/mod-roll-part.hbs"}}

View File

@ -16,6 +16,10 @@
{{> "systems/bol/templates/dialogs/flaws-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/effect-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/horoscope-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/adv-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/mod-roll-part.hbs"}}

View File

@ -0,0 +1,14 @@
{{#if (count bolEffects)}}
<div class="flexrow roll-box" >
<div class="flex1 center bg-darkred">
<label for="mod">{{localize 'BOL.ui.boleffects'}}</label>
</div>
<div class="flex1 center cell">
<select disabled class="flex1" name="applicable-effects" id="applicable-effects" data-type="String" multiple>
{{#each bolApplicableEffects as |effect id|}}
<option value="{{id}}" selected >{{effect.name}} ({{effect.system.properties.modifier}})</option>
{{/each}}
</select>
</div>
</div>
{{/if}}

View File

@ -0,0 +1,39 @@
<form class="{{cssClass}}" autocomplete="off">
{{!-- Sheet Header --}}
<header class="sheet-header">
<div class="row flexrow table-header">
<div class="flex1 center">
<h3>{{localize 'BOL.ui.makeHoroscope'}} {{localize horoscopeTypeLabel}}</h3>
</div>
</div>
</header>
{{> "systems/bol/templates/dialogs/attribute-roll-part.hbs"}}
<div class="flexrow" style="margin-bottom: 1px;">
<div class="flex1 center bg-darkred">
<label for="mod">{{localize 'BOL.ui.astrologerRank'}}</label>
</div>
<div class="flex1 center cell">{{careerBonus}}</div>
</div>
<div class="flexrow" style="margin-bottom: 1px;">
<div class="flex1 center bg-darkred">
<label for="mod">{{localize 'BOL.ui.horoscopeCost'}}</label>
</div>
<div class="flex1 center cell" id="astrologyPointsCost">{{astrologyPointsCost}}</div>
</div>
{{> "systems/bol/templates/dialogs/boons-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/flaws-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/effect-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/adv-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/mod-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/total-roll-part.hbs"}}
</form>

View File

@ -0,0 +1,73 @@
{{#if (count horoscopeBonusList)}}
<div class='flexrow roll-box'>
<div class='flex1 center bg-darkred'>
<label for='mod'>
{{localize 'BOL.ui.horoscopesBonus'}}
</label>
</div>
<div class='flex1 center cell'>
<select
class='flex1'
name='horoscope-bonus-applied'
id='horoscope-bonus-applied'
data-type='String'
multiple
>
{{#each horoscopeBonusList as |horoscope id|}}
<option value="{{id}}">
{{horoscope.name}}
</option>
{{/each}}
</select>
</div>
</div>
{{/if}}
{{#if (count horoscopeMalusList)}}
<div class='flexrow roll-box'>
<div class='flex1 center bg-darkred'>
<label for='mod'>
{{localize 'BOL.ui.horoscopesMalus'}}
</label>
</div>
<div class='flex1 center cell'>
<select
class='flex1'
name='horoscope-malus-applied'
id='horoscope-malus-applied'
data-type='String'
multiple
>
{{#each horoscopeMalusList as |horoscope id|}}
<option value="{{id}}">
{{horoscope.name}}
</option>
{{/each}}
</select>
</div>
</div>
{{/if}}
{{#if (countKeys horoscopeGroupList)}}
<div class='flexrow roll-box'>
<div class='flex1 center bg-darkred'>
<label for='mod'>
{{localize 'BOL.ui.horoscopeGroup'}}
</label>
</div>
<div class='flex1 center cell'>
<select
class='flex1'
name='horoscope-group-applied'
id='horoscope-group-applied'
data-type='String'
>
{{#each horoscopeGroupList as |horoscope index|}}
<option value="{{index}}">
{{horoscope.nbDice}}d{{upperFirstOnly horoscope.type}} - {{horoscope.name}}
</option>
{{/each}}
</select>
</div>
</div>
{{/if}}

View File

@ -65,6 +65,8 @@
{{> "systems/bol/templates/dialogs/flaws-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/horoscope-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/adv-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/mod-roll-part.hbs"}}

View File

@ -56,6 +56,10 @@
{{> "systems/bol/templates/dialogs/fightoptions-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/effect-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/horoscope-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/adv-roll-part.hbs"}}
{{> "systems/bol/templates/dialogs/mod-roll-part.hbs"}}

View File

@ -24,3 +24,9 @@
{{#if (equals item.system.subtype "flaw")}}
{{> "systems/bol/templates/item/parts/properties/feature/flaw-properties.hbs"}}
{{/if}}
{{#if (equals item.system.subtype "boleffect")}}
{{> "systems/bol/templates/item/parts/properties/feature/effect-properties.hbs"}}
{{/if}}
{{#if (equals item.system.subtype "horoscope")}}
{{> "systems/bol/templates/item/parts/properties/feature/horoscope-properties.hbs"}}
{{/if}}

View File

@ -15,3 +15,7 @@
<label class="property-label">{{localize "BOL.ui.isPriest"}}</label>
<input class="field-value" type="checkbox" name="system.properties.priest" {{checked item.system.properties.priest}}>
</div>
<div class="property flexrow">
<label class="property-label">{{localize "BOL.ui.isAstrologer"}}</label>
<input class="field-value" type="checkbox" name="system.properties.astrologer" {{checked item.system.properties.astrologer}}>
</div>

View File

@ -0,0 +1,27 @@
<h3 class="form-header">{{localize 'BOL.featureSubtypes.effect'}}</h3>
<div class="property flexrow">
<label class="property-label">{{localize "BOL.ui.attributaptitude"}}</label>
<select name="system.properties.identifier" value="{{item.system.properties.identifier}}">
{{#select item.system.properties.identifier}}
<option value="always">{{localize "BOL.ui.always"}}</option>
{{#each config.attackAttributes as |value id|}}
<option value="system.attributes.{{id}}">{{localize value}}</option>
{{/each}}
{{#each config.aptitudes as |value id|}}
<option value="system.aptitudes.{{id}}">{{localize value}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="property flexrow">
<label class="property-label">{{localize "BOL.ui.modifier"}}</label>
<select name="system.properties.modifier" value="{{item.system.properties.modifier}}">
{{#select item.system.properties.modifier}}
{{#each config.bolEffectModifier as |modifier id|}}
<option value="{{id}}">{{localize modifier}}</option>
{{/each}}
{{/select}}
</select>
</div>

View File

@ -0,0 +1,17 @@
<h3 class="form-header">{{localize 'BOL.featureSubtypes.horoscope'}}</h3>
<div class="property flexrow">
<label class="property-label">{{localize "BOL.ui.answer"}}</label>
<select name="system.properties.horoscopeanswer" data-dtype="String">
{{#select item.system.properties.horoscopeanswer}}
{{#each config.horoscopeAnswer as |item id|}}
<option value="{{id}}">{{localize item}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="property flexrow">
<label class="property-label">{{localize "BOL.ui.rank"}}</label>
<input class="field-value" type="text" name="system.properties.rank" value={{item.system.properties.rank}} data-type="Number">
</div>

BIN
ui/page_accueil.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB