forked from public/bol
Add a PC list summary
This commit is contained in:
parent
7b4e5bcbfa
commit
e1c7304551
@ -526,6 +526,11 @@ ul.no-bullets {
|
||||
min-width: 8rem;
|
||||
width: 8rem;
|
||||
}
|
||||
.items-list .item-field-fixed-short {
|
||||
max-width: 3rem;
|
||||
min-width: 3rem;
|
||||
width: 3rem;
|
||||
}
|
||||
/* ----------------------------------------- */
|
||||
/* Premade colors */
|
||||
/* ----------------------------------------- */
|
||||
@ -1063,3 +1068,6 @@ body.system-bol img#logo {
|
||||
.character-summary-container {
|
||||
opacity: 0.95;
|
||||
}
|
||||
.character-summary-rollable {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
10
lang/fr.json
10
lang/fr.json
@ -172,6 +172,16 @@
|
||||
"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.featureCategory.origins": "Origines",
|
||||
"BOL.featureCategory.races": "Races",
|
||||
|
@ -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")])
|
||||
|
@ -343,7 +343,7 @@ export class BoLActor extends Actor {
|
||||
getDamageAttributeValue(attrDamage) {
|
||||
let attrDamageValue = 0
|
||||
if (attrDamage.includes("vigor")) {
|
||||
attrDamageValue = actor.system.attributes.vigor.value
|
||||
attrDamageValue = this.system.attributes.vigor.value
|
||||
if (attrDamage.includes("half")) {
|
||||
attrDamageValue = Math.floor(attrDamageValue / 2)
|
||||
}
|
||||
@ -405,7 +405,7 @@ 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") )
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -638,13 +638,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)"
|
||||
}
|
||||
} 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
|
||||
}
|
||||
|
@ -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 () {
|
||||
@ -117,7 +118,10 @@ function welcomeMessage() {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
Hooks.once('ready', async function () {
|
||||
|
||||
BoLUtility.ready()
|
||||
BoLCharacterSummary.ready()
|
||||
|
||||
registerUsageCount('bol')
|
||||
|
||||
|
||||
|
@ -7,8 +7,7 @@ export class BoLCharacterSummary extends Application {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static displayPCSummary(){
|
||||
let pcList = new BoLCharacterSummary()
|
||||
pcList.render(true)
|
||||
game.bol.charSummary.render(true)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -16,13 +15,20 @@ export class BoLCharacterSummary extends Application {
|
||||
return { top: 200, left: 200 };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static ready() {
|
||||
let charSummary = new BoLCharacterSummary()
|
||||
game.bol.charSummary = charSummary
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor() {
|
||||
if ( !game.user.isGM ) { // Uniquement si GM
|
||||
return;
|
||||
}
|
||||
|
||||
super();
|
||||
//game.settings.set("world", "character-summary-data", {npcList: [], x:0, y:0})
|
||||
this.settings = game.settings.get("world", "character-summary-data")
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -31,6 +37,7 @@ export class BoLCharacterSummary extends Application {
|
||||
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'
|
||||
})
|
||||
}
|
||||
@ -40,16 +47,62 @@ export class BoLCharacterSummary extends Application {
|
||||
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
|
||||
|
||||
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"))
|
||||
@ -61,6 +114,15 @@ export class BoLCharacterSummary extends Application {
|
||||
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()
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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") {
|
||||
|
@ -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)",
|
||||
@ -74,6 +81,7 @@ export class BoLUtility {
|
||||
static async ready() {
|
||||
//$("#logo").attr("src", this.getLogoTopLeft() )
|
||||
$("#logo").css("content", `url(${this.getLogoTopLeft()})`)
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -534,31 +542,29 @@ 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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
],
|
||||
"url": "https://www.uberwald.me/gitea/public/bol",
|
||||
"license": "LICENSE.txt",
|
||||
"version": "10.4.3",
|
||||
"version": "10.4.4",
|
||||
"compatibility": {
|
||||
"minimum": "10",
|
||||
"verified": "10",
|
||||
@ -203,7 +203,7 @@
|
||||
],
|
||||
"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.4.3.zip",
|
||||
"download": "https://www.uberwald.me/gitea/public/bol/archive/bol-v10.4.4.zip",
|
||||
"background": "systems/images/map_lemurie.webp",
|
||||
"gridDistance": 1.5,
|
||||
"gridUnits": "m",
|
||||
|
@ -3,30 +3,80 @@
|
||||
<ol class="items-list">
|
||||
|
||||
<li class="item flexrow item-header">
|
||||
<div class="item-field item-name item-name-fixed-medium">{{localize "BOL.ui.name"}}</div>
|
||||
<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">{{abbrev3 (localize attr)}}</div>
|
||||
<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">{{abbrev3 (localize apt)}}</div>
|
||||
<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">{{abbrev3 (localize res)}}</div>
|
||||
<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">{{pc.name}}</div>
|
||||
<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 "><a class="summary-roll" data-type="attribute" data-key="{{key}}">{{attr.value}}</a></div>
|
||||
<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 flex2 "><a class="summary-roll" data-type="aptitude" data-key="{{key}}">{{apt.value}}</a></div>
|
||||
<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 ">{{res.value}}/{{res.max}}</div>
|
||||
<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}}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user