Compare commits

...

31 Commits

Author SHA1 Message Date
391b99b18f Ajout release process
All checks were successful
Release Creation / build (release) Successful in 58s
2026-01-09 17:44:47 +01:00
ff9acaab65 Ajout release process 2026-01-09 17:44:38 +01:00
60978a67b2 Appv2 + DataModel migration completed 2026-01-09 17:34:39 +01:00
5894cf043f Appv2 + DataModel migration completed 2026-01-09 17:34:39 +01:00
0fd2130fb1 Appv2 + DataModel migration completed 2026-01-09 17:34:39 +01:00
001f0cffa8 Initial data model migration 2026-01-09 17:34:39 +01:00
05ca6e1763 Proper version 2026-01-06 22:57:53 +01:00
d3f014fcca Rework title font and fix pause logo switching 2026-01-05 22:45:10 +01:00
679b3208cd Rework title font and fix pause logo switching 2026-01-05 22:43:52 +01:00
871a18a0ee Correction sur talent Dragon 2025-11-21 21:21:45 +01:00
264c49eb06 Fix release mess 2025-11-07 00:30:31 +01:00
9349c54966 Enhance CSS+fonts 2025-10-26 21:39:25 +01:00
274efac2b5 Enhance CSS+fonts 2025-10-26 15:39:08 +01:00
7a7398f8ca Correction sur styles CSS 2025-10-20 22:30:15 +02:00
93600f7e13 Correction sur styles CSS 2025-10-20 22:29:22 +02:00
a6fa3afbee Double adversités 2025-08-24 17:00:06 +02:00
1051349dd0 Correction sur usage BA sur un jet impair au D20 2025-06-24 21:04:58 +02:00
a245b0e87c Corrections sur couleur des pages dans les journaux 2025-06-03 13:32:11 +02:00
c9ce3367ed Corrections sur couleur des pages dans les journaux 2025-06-03 13:31:17 +02:00
e95e068112 Fix perte de combatitivité sur action d'un joueur 2025-06-03 09:37:50 +02:00
6dd63a2c54 Hawkmoon : Foundry v13 migration 2025-04-30 23:26:24 +02:00
650e4b7449 Hawkmoon : Foundry v13 migration 2025-04-30 23:24:55 +02:00
3f27482ad9 Hawkmoon : Foundry v13 migraton 2025-04-30 23:23:32 +02:00
436b282ff5 Correction sur se désengager 2025-03-28 18:09:36 +01:00
39f8cfdbcc Correction sur 2 attaques avec ambidextrie 2025-03-28 14:56:52 +01:00
24a57a906e Fix protection pour creatures 2025-02-07 20:43:03 +01:00
667f3678fb Fix protection pour creatures 2025-02-07 20:42:14 +01:00
d5dd9e5bf7 Cleanup welcome scene 2024-08-23 13:49:57 +02:00
3403b72d1f ajout item sur cellule + augmentation bonus et difficultés 2024-08-22 14:39:42 +02:00
8a4487c833 ajout item sur cellule + augmentation bonus et difficultés 2024-08-22 14:39:30 +02:00
4eece5aaf4 Correction sur carte europe 2024-06-18 17:26:55 +02:00
212 changed files with 13565 additions and 1718 deletions

View File

@@ -0,0 +1,63 @@
name: Release Creation
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
#- uses: actions/checkout@v3
- uses: RouxAntoine/checkout@v3.5.4
# get part of the tag after the `v`
- name: Extract tag version number
id: get_version
uses: battila7/get-version-action@v2
# Substitute the Manifest and Download URLs in the system.json
- name: Substitute Manifest and Download Links For Versioned Ones
id: sub_manifest_link_version
uses: microsoft/variable-substitution@v1
with:
files: 'system.json'
env:
version: ${{steps.get_version.outputs.version-without-v}}
url: https://www.uberwald.me/gitea/${{gitea.repository}}
manifest: https://www.uberwald.me/gitea/public/fvtt-hawkmoon-cyd/releases/download/latest/system.json
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-hawkmoon-cyd.zip
# Create a zip file with all files required by the module to add to the release
- run: |
apt update -y
apt install -y zip
- run: zip -r ./fvtt-hawkmoon-cyd.zip system.json README.md LICENCE.txt assets/ lang/ modules/ packs/ styles/ templates/
- name: setup go
uses: https://github.com/actions/setup-go@v4
with:
go-version: '>=1.20.1'
- name: Use Go Action
id: use-go-action
uses: https://gitea.com/actions/release-action@main
with:
files: |-
./fvtt-hawkmoon-cyd.zip
system.json
api_key: '${{secrets.ALLOW_PUSH_RELEASE}}'
- name: Publish to Foundry server
uses: https://github.com/djlechuck/foundryvtt-publish-package-action@v1
with:
token: ${{ secrets.FOUNDRYVTT_RELEASE_TOKEN }}
id: 'fvtt-hawkmoon-cyd'
version: ${{github.event.release.tag_name}}
manifest: 'https://www.uberwald.me/gitea/public/fvtt-hawkmoon-cyd/releases/download/latest/system.json'
notes: 'https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-hawkmoon-cyd.zip'
compatibility-minimum: '13'
compatibility-verified: '13'

View File

@@ -40,7 +40,7 @@
{{selectOptions combativiteList selected=system.sante.etat valueAttr="value" nameAttr="value" labelAttr="label"}} {{selectOptions combativiteList selected=system.sante.etat valueAttr="value" nameAttr="value" labelAttr="label"}}
</select> </select>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -55,6 +55,7 @@
<a class="item" data-tab="equipement">Equipement</a> <a class="item" data-tab="equipement">Equipement</a>
<a class="item" data-tab="biodata">Bio&Notes</a> <a class="item" data-tab="biodata">Bio&Notes</a>
</nav> </nav>
<hr>
{{!-- Sheet Body --}} {{!-- Sheet Body --}}
<section class="sheet-body"> <section class="sheet-body">
@@ -63,7 +64,7 @@
<div class="tab principal" data-group="primary" data-tab="principal"> <div class="tab principal" data-group="primary" data-tab="principal">
<div class="flexcol"> <div class="flexcol">
<div class="grid grid-2col"> <div class="grid grid-2col">
<div class="sheet-box color-bg-archetype"> <div class="sheet-box color-bg-archetype">
@@ -86,7 +87,7 @@
<input type="text" class="padd-right numeric-input item-field-label-short" name="system.vitesse.value" <input type="text" class="padd-right numeric-input item-field-label-short" name="system.vitesse.value"
value="{{system.vitesse.value}}" data-dtype="Number" /> value="{{system.vitesse.value}}" data-dtype="Number" />
</li> </li>
</ul> </ul>
</div> </div>
@@ -236,17 +237,17 @@
{{#each skills as |skill key|}} {{#each skills as |skill key|}}
<li class="item flexrow " data-item-id="{{skill._id}}" data-item-type="competence"> <li class="item flexrow " data-item-id="{{skill._id}}" data-item-type="competence">
<img class="item-name-img" src="{{skill.img}}" /> <img class="item-name-img" src="{{skill.img}}" />
<div class="flexcol item-name-label"> <div class="flexcol item-name-label">
<span class="item-name-label competence-name"><a class="roll-competence item-field-label-short" <span class="item-name-label competence-name"><a class="roll-competence "
data-attr-key="tochoose">{{skill.name}}</a></span> data-attr-key="tochoose">{{skill.name}}</a></span>
<span class="predilection-text"> <span class="predilection-text">
{{#each skill.system.predilections as |pred key|}} {{#each skill.system.predilections as |pred key|}}
{{#if (and pred.acquise (not pred.used))}} {{#if (and pred.acquise (not pred.used))}}
{{pred.name}}, {{pred.name}},
{{/if}} {{/if}}
{{/each}} {{/each}}
</span> </span>
</div> </div>
@@ -410,21 +411,21 @@
<div class="tab equipement" data-group="primary" data-tab="equipement"> <div class="tab equipement" data-group="primary" data-tab="equipement">
<div class="flexcol"> <div class="flexcol">
<hr> <hr>
<div class="sheet-box color-bg-archetype"> <div class="sheet-box color-bg-archetype">
<h4> <h4>
<label class="argent-total-text"> <label class="argent-total-text">
Argent Total : {{richesse.po}} PO - {{richesse.pa}} PA - {{richesse.sc}} SC (total {{richesse.valueSC}} SC) Argent Total : {{richesse.po}} PO - {{richesse.pa}} PA - {{richesse.sc}} SC (total {{richesse.valueSC}} SC)
</label> </label>
</h4> </h4>
</div> </div>
<div class="sheet-box color-bg-archetype"> <div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list"> <ul class="item-list alternate-list">
<li class="item flexrow list-item items-title-bg"> <li class="item flexrow list-item items-title-bg">
<span class="item-name-label-header"> <span class="item-name-label-header">
<h3><label class="items-title-text">Richesses et Argent</label></h3> <h3><label class="items-title-text">Richesses et Argent</label></h3>
</span> </span>
<span class="item-field-label-short"> <span class="item-field-label-short">
<label class="short-label">Quantité</label> <label class="short-label">Quantité</label>
@@ -440,7 +441,7 @@
<li class="item flexrow " data-item-id="{{monnaie._id}}" data-item-type="monnaie"> <li class="item flexrow " data-item-id="{{monnaie._id}}" data-item-type="monnaie">
<img class="item-name-img" src="{{monnaie.img}}" /> <img class="item-name-img" src="{{monnaie.img}}" />
<span class="item-name-label competence-name">{{monnaie.name}}</span> <span class="item-name-label competence-name">{{monnaie.name}}</span>
<span class="item-name-label competence-name item-field-label-medium">{{monnaie.system.quantite}} <span class="item-name-label competence-name item-field-label-medium">{{monnaie.system.quantite}}
<a class="quantity-modify plus-minus-button" data-quantite-value="-1">-</a> <a class="quantity-modify plus-minus-button" data-quantite-value="-1">-</a>
<a class="quantity-modify plus-minus-button" data-quantite-value="+1">+</a> <a class="quantity-modify plus-minus-button" data-quantite-value="+1">+</a>
</span> </span>
@@ -460,7 +461,7 @@
<label class="argent-total-text"> <label class="argent-total-text">
Valeur Total Equipement : {{valeurEquipement.po}} PO - {{valeurEquipement.pa}} PA - {{valeurEquipement.sc}} SC (total {{valeurEquipement.valueSC}} SC) Valeur Total Equipement : {{valeurEquipement.po}} PO - {{valeurEquipement.pa}} PA - {{valeurEquipement.sc}} SC (total {{valeurEquipement.valueSC}} SC)
</label> </label>
</h4> </h4>
</div> </div>
<div class="sheet-box color-bg-archetype"> <div class="sheet-box color-bg-archetype">
@@ -627,9 +628,6 @@
<span> <span>
<h3>Description</h3> <h3>Description</h3>
</span> </span>
<div class="medium-editor item-text-long-line">
{{editor description target="system.biodata.description" button=true owner=owner editable=editable}}
</div>
</div> </div>

View File

@@ -0,0 +1,385 @@
<form class="{{cssClass}}" autocomplete="off">
{{!-- Sheet Header --}}
<header class="sheet-header">
<div class="header-fields background-sheet-header">
<div class="flexrow">
<img class="profile-img" src="{{img}}" data-edit="img" title="{{name}}" />
<div class="flexcol">
<h1 class="charname"><input name="name" type="text" value="{{name}}" placeholder="Name" /></h1>
<div class="flexrow">
<ul class="item-list alternate-list">
<li class="item flexrow">
<h4 class="item-name-label competence-name item-field-label-medium">Notoriété</h4>
<input type="text" class="padd-right status-small-label color-class-common item-field-label-short"
name="system.notoriete" value="{{system.notoriete}}" data-dtype="Number" />
<h4 class="item-name-label competence-name item-field-label-long">Résistance</h4>
<input type="text" class="padd-right status-small-label color-class-common item-field-label-short"
name="system.resistance" value="{{system.resistance}}" data-dtype="Number" />
</li>
<li class="item flexrow ">
<h4 class="item-name-label competence-name item-field-label-long">Développement</h4>
<input type="text" class="padd-right status-small-label color-class-common item-field-label-short"
name="system.developpement" value="{{system.developpement}}" data-dtype="Number" />
</li>
</ul>
</div>
</div>
</div>
</header>
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="talents">Membres&Talents</a>
<a class="item" data-tab="contacts">Contacts</a>
<a class="item" data-tab="ressources">Ressources</a>
<a class="item" data-tab="equipement">Equipement</a>
<a class="item" data-tab="biodata">Description</a>
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Talents Tab --}}
<div class="tab talents" data-group="primary" data-tab="talents">
<div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list">
<li class="item flexrow">
<span class="item-name-label-header">
<h3><label class="items-title-text">Membres</label></h3>
</span>
<div class="item-filler">&nbsp;</div>
</li>
{{#each members as |membre key|}}
<li class="item flexrow " data-actor-id="{{membre.id}}" >
<img class="item-name-img" src="{{membre.img}}" />
<span class="item-name-label competence-name">{{membre.name}}</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control actor-edit" title="Edit Actor"><i class="fas fa-edit"></i></a>
<a class="item-control actor-delete" title="Delete Actor"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</div>
<div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list">
<li class="item flexrow">
<span class="item-name-label-header">
<h3><label class="items-title-text">Talents de Cellule</label></h3>
</span>
<span class="item-field-label-short">
<label class="short-label">Résumé</label>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-add" data-type="talent" title="Ajouter un Talent"><i
class="fas fa-plus"></i></a>
</div>
</li>
{{#each talents as |talent key|}}
<li class="item flexrow " data-item-id="{{talent._id}}" data-item-type="talent">
<img class="item-name-img" src="{{talent.img}}" />
<span class="item-name-label competence-name">{{talent.name}}</span>
<span class="item-name-label item-field-label-long2">{{talent.system.resumebonus}}</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</div>
</div>
{{!-- Contacts Tab --}}
<div class="tab contacts" data-group="primary" data-tab="contacts">
<div class="flexrow">
<div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list">
<li class="item flexrow">
<span class="item-name-label-header">
<h3><label class="items-title-text">Contacts</label></h3>
</span>
<span class="item-field-label-medium">
<label class="short-label">Type</label>
</span>
<span class="item-field-label-medium">
<label class="short-label">Niveau</label>
</span>
<div class="item-filler">&nbsp;</div>
</li>
{{#each contacts as |contact key|}}
<li class="item flexrow " data-item-id="{{contact._id}}" data-item-type="competence">
<img class="item-name-img" src="{{contact.img}}" />
<span class="item-name-label competence-name">{{contact.name}}</span>
<span class="item-name-label item-field-label-medium">{{upperFirst contact.system.contacttype}}</span>
<span class="item-name-label item-field-label-medium">{{contact.system.niveau}}</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</div>
</div>
</div>
{{!-- Ressources Tab --}}
<div class="tab ressources" data-group="primary" data-tab="ressources">
<div class="flexrow">
<div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list">
<li class="item flexrow">
<span class="item-name-label-header">
<h3><label class="items-title-text">Ressources</label></h3>
</span>
<div class="item-filler">&nbsp;</div>
</li>
{{#each ressources as |ressource key|}}
<li class="item flexrow " data-item-id="{{ressource._id}}" data-item-type="competence">
<img class="item-name-img" src="{{ressource.img}}" />
<span class="item-name-label competence-name">{{ressource.name}}</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</div>
</div>
</div>
{{!-- Equipement Tab --}}
<div class="tab equipement" data-group="primary" data-tab="equipement">
<div class="flexcol">
<hr>
<div class="sheet-box color-bg-archetype">
<h4>
<label class="argent-total-text">
Argent Total : {{richesse.po}} PO - {{richesse.pa}} PA - {{richesse.sc}} SC (total {{richesse.valueSC}} SC)
</label>
</h4>
</div>
<div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list">
<li class="item flexrow list-item items-title-bg">
<span class="item-name-label-header">
<h3><label class="items-title-text">Richesses et Argent</label></h3>
</span>
<span class="item-field-label-short">
<label class="short-label">Quantité</label>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-add" data-type="monnaie" title="Ajouter une monnaie"><i
class="fas fa-plus"></i></a>
</div>
</li>
{{#each monnaies as |monnaie key|}}
<li class="item flexrow " data-item-id="{{monnaie._id}}" data-item-type="monnaie">
<img class="item-name-img" src="{{monnaie.img}}" />
<span class="item-name-label competence-name">{{monnaie.name}}</span>
<span class="item-name-label competence-name item-field-label-medium">{{monnaie.system.quantite}}
<a class="quantity-modify plus-minus-button" data-quantite-value="-1">-</a>
<a class="quantity-modify plus-minus-button" data-quantite-value="+1">+</a>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</div>
<hr>
<div class="sheet-box color-bg-archetype">
<h4>
<label class="argent-total-text">
Valeur Total Equipement : {{valeurEquipement.po}} PO - {{valeurEquipement.pa}} PA - {{valeurEquipement.sc}} SC (total {{valeurEquipement.valueSC}} SC)
</label>
</h4>
</div>
<div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list">
<li class="item flexrow list-item items-title-bg">
<span class="item-name-label-header">
<h3><label class="items-title-text">Equipements</label></h3>
</span>
<span class="item-field-label-short">
<label class="short-label">Quantité</label>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-add" data-type="equipement" title="Ajouter un équipement"><i
class="fas fa-plus"></i></a>
</div>
</li>
{{#each equipements as |equipement key|}}
<li class="item flexrow " data-item-id="{{equipement._id}}" data-item-type="equipement">
<img class="item-name-img" src="{{equipement.img}}" />
<span class="item-name-label competence-name">{{equipement.name}}</span>
<span class="item-name-label competence-name item-field-label-medium">{{equipement.system.quantite}}
<a class="quantity-modify plus-minus-button" data-quantite-value="-1">-</a>
<a class="quantity-modify plus-minus-button" data-quantite-value="+1">+</a>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</div>
<div class="flexcol">
<div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list">
<li class="item flexrow list-item items-title-bg">
<span class="item-name-label-header">
<h3><label class="items-title-text">Armes</label></h3>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-add" data-type="arme" title="Ajouter une arme"><i
class="fas fa-plus"></i></a>
</div>
</li>
{{#each armes as |arme key|}}
<li class="item flexrow " data-item-id="{{arme._id}}" data-item-type="arme">
<img class="item-name-img" src="{{arme.img}}" />
<span class="item-name-label competence-name">{{arme.name}}</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-edit" title="Editer l' Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Supprimer l'Item"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</div>
<div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list">
<li class="item flexrow list-item items-title-bg">
<span class="item-name-label-header">
<h3><label class="items-title-text">Protections</label></h3>
</span>
<span class="item-field-label-short">
<label class="short-label">Protection</label>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-add" data-type="protection" title="Ajouter une arme"><i
class="fas fa-plus"></i></a>
</div>
</li>
{{#each protections as |protection key|}}
<li class="item flexrow " data-item-id="{{protection._id}}" data-item-type="protection">
<img class="item-name-img" src="{{protection.img}}" />
<span class="item-name-label competence-name">{{protection.name}}</span>
<span class="item-field-label-short arme-defensif"><label
class="arme-defensif">{{protection.system.protection}}</label>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-edit" title="Editer l'Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Supprimer l'Item"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</div>
</div>
<div class="sheet-box color-bg-archetype">
<ul class="item-list alternate-list">
<li class="item flexrow list-item items-title-bg">
<span class="item-name-label-header">
<h3><label class="items-title-text">Artefacts</label></h3>
</span>
<span class="item-field-label-short">
<label class="short-label">Quantité</label>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-add" data-type="artefact" title="Ajouter un artefact"><i
class="fas fa-plus"></i></a>
</div>
</li>
{{#each artefacts as |artefact key|}}
<li class="item flexrow " data-item-id="{{artefact._id}}" data-item-type="artefact">
<img class="item-name-img" src="{{artefact.img}}" />
<span class="item-name-label competence-name">{{artefact.name}}</span>
<span class="item-name-label competence-name item-field-label-medium">{{artefact.system.quantite}}
<a class="quantity-modify plus-minus-button" data-quantite-value="-1">-</a>
<a class="quantity-modify plus-minus-button" data-quantite-value="+1">+</a>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ul>
</div>
</div>
</div>
{{!-- Biography Tab --}}
<div class="tab biodata" data-group="primary" data-tab="biodata">
<span>
<h3>Description</h3>
</span>
<div class="medium-editor item-text-long-line">
{{editor description target="system.description" button=true owner=owner editable=editable}}
</div>
</div>
</section>
</form>

View File

@@ -0,0 +1,254 @@
<div class="hawkmoon-chat-result">
{{!-- Header avec acteur --}}
<div class="chat-result-header">
{{#if actorImg}}
<img class="actor-icon" src="{{actorImg}}" alt="{{alias}}" />
{{/if}}
<div class="header-info">
<h4 class="actor-name">{{alias}}</h4>
{{#if competence}}
<div class="action-title">
<i class="fas fa-dice-d20"></i>
{{competence.name}}
{{#if arme}}• {{arme.name}}{{/if}}
</div>
{{else if actionImg}}
<div class="action-title">
<i class="fas fa-dice-d20"></i>
{{attr.label}}{{#if attr2}} + {{attr2.label}}{{/if}}
</div>
{{/if}}
</div>
</div>
{{!-- Résultat principal --}}
<div class="result-main">
<div class="result-display">
<div class="dice-result">
<i class="fas fa-dice"></i>
<span class="dice-value">{{diceResult}}</span>
</div>
<div class="total-result">
<span class="total-label">Total</span>
<span class="total-value">{{finalResult}}</span>
</div>
{{#if difficulte}}
<div class="difficulty">
<span class="difficulty-label">SD</span>
<span class="difficulty-value">{{difficulte}}</span>
</div>
{{/if}}
</div>
{{!-- Badge de résultat --}}
{{#if difficulte}}
<div class="result-badge-container">
{{#if isHeroique}}
<div class="result-badge heroique">
<i class="fas fa-star"></i> HÉROÏQUE !
</div>
{{else if isDramatique}}
<div class="result-badge dramatique">
<i class="fas fa-skull"></i> DRAMATIQUE !
</div>
{{else if isSuccess}}
<div class="result-badge success">
<i class="fas fa-check"></i> Succès
</div>
{{else}}
<div class="result-badge failure">
<i class="fas fa-times"></i> Échec
</div>
{{/if}}
</div>
{{/if}}
</div>
{{!-- Détails du jet --}}
<div class="result-details">
<div class="details-section">
<div class="detail-row">
<span class="detail-label">Formule:</span>
<span class="detail-value">{{diceFormula}}</span>
</div>
<div class="detail-row">
<span class="detail-label">{{attr.label}}:</span>
<span class="detail-value">{{attr.value}}</span>
</div>
{{#if attr2}}
<div class="detail-row">
<span class="detail-label">{{attr2.label}}:</span>
<span class="detail-value">{{attr2.value}}</span>
</div>
{{/if}}
{{#if competence}}
<div class="detail-row">
<span class="detail-label">{{competence.name}}:</span>
<span class="detail-value">{{competence.system.niveau}}</span>
</div>
{{/if}}
{{#if selectedMaitrise}}
<div class="detail-row">
<span class="detail-label">Maîtrise:</span>
<span class="detail-value">{{selectedMaitrise.name}}</span>
</div>
{{/if}}
{{#if arme}}
<div class="detail-row">
<span class="detail-label">Arme:</span>
<span class="detail-value">{{arme.name}} (+{{arme.system.bonusmaniementoff}})</span>
</div>
{{/if}}
{{#if bonusRoll}}
<div class="detail-row bonus">
<span class="detail-label">{{textBonus}}:</span>
<span class="detail-value">+{{bonusRoll.total}}</span>
</div>
{{/if}}
</div>
</div>
{{!-- Effets et conséquences --}}
{{#if isSuccess}}
<div class="result-effects">
{{#if attaqueDesarme}}
<div class="effect-item">
<i class="fas fa-hand-sparkles"></i>
{{#if isHeroique}}
Vous récupérez l'arme de votre adversaire dans votre main !
{{else}}
Vous désarmez votre adversaire ! Son arme tombe hors de sa portée.
{{/if}}
</div>
{{/if}}
{{#if immobiliser}}
<div class="effect-item">
<i class="fas fa-lock"></i>
{{#if isHeroique}}
Votre cible est immobilisée, et vous pouvez faire une action complexe.
{{else}}
Votre cible est immobilisée.
{{/if}}
</div>
{{/if}}
{{#if desengager}}
<div class="effect-item">
<i class="fas fa-running"></i>
Vous vous désengagez de votre adversaire.
</div>
{{/if}}
{{#if repousser}}
<div class="effect-item">
<i class="fas fa-hand-rock"></i>
{{#if isHeroique}}
Votre cible est repoussée de 3 mètres et tombe au sol.
{{else}}
Votre cible tombe au sol.
{{/if}}
</div>
{{/if}}
{{#if assomer}}
<div class="effect-item">
<i class="fas fa-dizzy"></i>
{{#if isHeroique}}
Votre cible est assomée pour [[/r 1d10+10]] minutes.
{{else}}
Votre cible est assomée pour [[/r 1d10]] minutes.
{{/if}}
</div>
{{/if}}
{{#if coupBas}}
<div class="effect-item">
<i class="fas fa-shoe-prints"></i>
La cible a reçu 2 adversités bleues et a perdu 1 niveau de combativité.
{{#if isHeroique}}
<br><strong>Et votre cible perd sa prochaine action complexe.</strong>
{{/if}}
</div>
{{/if}}
{{#if arme}}
{{#if contenir}}
<div class="effect-item">
<i class="fas fa-shield-alt"></i>
{{#if isHeroique}}
Aucun dégât, mais tous les adversaires dont le SD + 10 est atteint ne peuvent déclarer d'attaque contre vous lors de leur prochaine action complexe.
{{else}}
Aucun dégât, mais la cible ne peut pas déclarer d'attaque contre vous lors de sa prochaine action complexe.
{{/if}}
</div>
{{else}}
{{#if (eq nbCombativitePerdu "vaincu")}}
<div class="effect-item victory">
<i class="fas fa-trophy"></i>
<strong>Votre adversaire est vaincu !</strong>
</div>
{{else}}
<div class="effect-item">
<i class="fas fa-heart-broken"></i>
Votre adversaire a perdu {{nbCombativitePerdu}} État de Combativité.
</div>
{{/if}}
{{#if (not arme.system.onlevelonly)}}
<div class="damage-buttons">
<button class="chat-card-button roll-chat-degat">
<i class="fas fa-burst"></i> Dégâts de l'arme
</button>
{{#if coupDevastateur}}
<button class="chat-card-button roll-chat-degat-devastateur">
<i class="fas fa-explosion"></i> Dégâts avec Coup Dévastateur
</button>
{{/if}}
</div>
{{/if}}
{{/if}}
{{/if}}
</div>
{{/if}}
{{!-- Avertissements --}}
{{#if attaqueCharge}}
<div class="result-warning">
<i class="fas fa-exclamation-triangle"></i>
Vous avez chargé : vos adversaires bénéficient de +3 pour vous attaquer.
</div>
{{/if}}
{{#if desengager}}
{{#if (not isSuccess)}}
<div class="result-warning">
<i class="fas fa-exclamation-triangle"></i>
Vous ne parvenez pas à vous désengager, votre adversaire a un bonus de +3 pour vous attaquer.
</div>
{{/if}}
{{/if}}
{{#if isInit}}
<div class="result-info">
<i class="fas fa-flag"></i> Initiative stockée !
</div>
{{/if}}
{{!-- Prédilections --}}
{{#each predilections as |pred key|}}
{{#if (and (and pred.acquise (not pred.maitrise)) (not pred.used))}}
<div class="predilection-section">
<button class="chat-card-button predilection-reroll" data-predilection-index="{{key}}">
<i class="fas fa-redo"></i> Prédilection : {{pred.name}}
</button>
</div>
{{/if}}
{{/each}}
</div>

View File

@@ -351,7 +351,7 @@
<label class="short-label">Protection</label> <label class="short-label">Protection</label>
</span> </span>
<div class="item-filler">&nbsp;</div> <div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed"> <div class="item-controls item-controls-fixed">
<a class="item-control item-add" data-type="protection" title="Ajouter une arme"><i <a class="item-control item-add" data-type="protection" title="Ajouter une arme"><i
class="fas fa-plus"></i></a> class="fas fa-plus"></i></a>
</div> </div>
@@ -365,8 +365,10 @@
</span> </span>
<div class="item-filler">&nbsp;</div> <div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed"> <div class="item-controls item-controls-fixed">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a> <a class="item-control item-equip" title="Equipé">{{#if protection.system.equipped}}<i
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a> class="fas fa-circle"></i>{{else}}<i class="fas fa-genderless"></i>{{/if}}</a>
<a class="item-control item-edit" title="Editer l'Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Supprimer l'Item"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@@ -3,11 +3,11 @@
* @extends {ActorSheet} * @extends {ActorSheet}
*/ */
import { HawkmoonUtility } from "./hawkmoon-utility.js"; import { HawkmoonUtility } from "../modules/hawkmoon-utility.js";
import { HawkmoonAutomation } from "./hawkmoon-automation.js"; import { HawkmoonAutomation } from "../modules/hawkmoon-automation.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class HawkmoonActorSheet extends ActorSheet { export class HawkmoonActorSheet extends foundry.appv1.sheets.ActorSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
@@ -25,7 +25,7 @@ export class HawkmoonActorSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
const objectData = foundry.utils.duplicate(this.object) const objectData = foundry.utils.duplicate(this.object)
let formData = { let formData = {
title: this.title, title: this.title,
@@ -36,6 +36,7 @@ export class HawkmoonActorSheet extends ActorSheet {
editable: this.isEditable, editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked", cssClass: this.isEditable ? "editable" : "locked",
system: objectData.system, system: objectData.system,
systemFields: this.document.system.schema.fields,
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)), effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
limited: this.object.limited, limited: this.object.limited,
skills: this.actor.getSkills(), skills: this.actor.getSkills(),
@@ -47,7 +48,7 @@ export class HawkmoonActorSheet extends ActorSheet {
mutations: foundry.utils.duplicate(this.actor.getMutations() || []), mutations: foundry.utils.duplicate(this.actor.getMutations() || []),
talentsCell: this.getCelluleTalents(), talentsCell: this.getCelluleTalents(),
profils: foundry.utils.duplicate(this.actor.getProfils() || []), profils: foundry.utils.duplicate(this.actor.getProfils() || []),
combat: this.actor.getCombatValues(), combat: this.actor.getCombatValues(),
equipements: foundry.utils.duplicate(this.actor.getEquipments()), equipements: foundry.utils.duplicate(this.actor.getEquipments()),
artefacts: foundry.utils.duplicate(this.actor.getArtefacts()), artefacts: foundry.utils.duplicate(this.actor.getArtefacts()),
richesse: this.actor.computeRichesse(), richesse: this.actor.computeRichesse(),
@@ -56,8 +57,8 @@ export class HawkmoonActorSheet extends ActorSheet {
nbCombativite: this.actor.system.sante.nbcombativite, nbCombativite: this.actor.system.sante.nbcombativite,
combativiteList: HawkmoonUtility.getCombativiteList(this.actor.system.sante.nbcombativite), combativiteList: HawkmoonUtility.getCombativiteList(this.actor.system.sante.nbcombativite),
initiative: this.actor.getFlag("world", "last-initiative") || -1, initiative: this.actor.getFlag("world", "last-initiative") || -1,
description: await TextEditor.enrichHTML(this.object.system.biodata.description, {async: true}), enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.biodata.description, {async: true}),
habitat: await TextEditor.enrichHTML(this.object.system.biodata.habitat, {async: true}), habitat: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.biodata.habitat, {async: true}),
options: this.options, options: this.options,
owner: this.document.isOwner, owner: this.document.isOwner,
editScore: this.options.editScore, editScore: this.options.editScore,
@@ -66,7 +67,6 @@ export class HawkmoonActorSheet extends ActorSheet {
} }
this.formData = formData; this.formData = formData;
console.log("PC : ", formData, this.object);
return formData; return formData;
} }
@@ -91,14 +91,14 @@ export class HawkmoonActorSheet extends ActorSheet {
// Everything below here is only needed if the sheet is editable // Everything below here is only needed if the sheet is editable
if (!this.options.editable) return; if (!this.options.editable) return;
// Update Inventory Item // Update Inventory Item
html.find('.item-edit').click(ev => { html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item") const li = $(ev.currentTarget).parents(".item")
let itemId = li.data("item-id") let itemId = li.data("item-id")
const item = this.actor.items.get( itemId ) const item = this.actor.items.get( itemId )
item.sheet.render(true) item.sheet.render(true)
}) })
// Delete Inventory Item // Delete Inventory Item
html.find('.item-delete').click(ev => { html.find('.item-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
@@ -120,7 +120,7 @@ export class HawkmoonActorSheet extends ActorSheet {
let value = Number($(event.currentTarget).data("adversite-value")) let value = Number($(event.currentTarget).data("adversite-value"))
this.actor.incDecAdversite(adv, value) this.actor.incDecAdversite(adv, value)
}) })
html.find('.quantity-modify').click(event => { html.find('.quantity-modify').click(event => {
const li = $(event.currentTarget).parents(".item") const li = $(event.currentTarget).parents(".item")
const value = Number($(event.currentTarget).data("quantite-value")) const value = Number($(event.currentTarget).data("quantite-value"))
@@ -130,7 +130,7 @@ export class HawkmoonActorSheet extends ActorSheet {
html.find('.roll-initiative').click((event) => { html.find('.roll-initiative').click((event) => {
this.actor.rollAttribut("adr", true) this.actor.rollAttribut("adr", true)
}) })
html.find('.roll-attribut').click((event) => { html.find('.roll-attribut').click((event) => {
const li = $(event.currentTarget).parents(".item") const li = $(event.currentTarget).parents(".item")
let attrKey = li.data("attr-key") let attrKey = li.data("attr-key")
@@ -147,7 +147,7 @@ export class HawkmoonActorSheet extends ActorSheet {
let armeId = li.data("item-id") let armeId = li.data("item-id")
this.actor.rollArmeOffensif(armeId) this.actor.rollArmeOffensif(armeId)
}) })
html.find('.roll-assommer').click((event) => { html.find('.roll-assommer').click((event) => {
this.actor.rollAssommer() this.actor.rollAssommer()
}) })
@@ -163,30 +163,30 @@ export class HawkmoonActorSheet extends ActorSheet {
html.find('.roll-desengager').click((event) => { html.find('.roll-desengager').click((event) => {
this.actor.rollDesengager() this.actor.rollDesengager()
}) })
html.find('.roll-arme-degats').click((event) => { html.find('.roll-arme-degats').click((event) => {
const li = $(event.currentTarget).parents(".item") const li = $(event.currentTarget).parents(".item")
let armeId = li.data("item-id") let armeId = li.data("item-id")
this.actor.rollArmeDegats(armeId) this.actor.rollArmeDegats(armeId)
}) })
html.find('.item-add').click((event) => { html.find('.item-add').click((event) => {
const itemType = $(event.currentTarget).data("type") const itemType = $(event.currentTarget).data("type")
this.actor.createEmbeddedDocuments('Item', [{ name: `Nouveau ${itemType}`, type: itemType }], { renderSheet: true }) this.actor.createEmbeddedDocuments('Item', [{ name: `Nouveau ${itemType}`, type: itemType }], { renderSheet: true })
}) })
html.find('.lock-unlock-sheet').click((event) => { html.find('.lock-unlock-sheet').click((event) => {
this.options.editScore = !this.options.editScore; this.options.editScore = !this.options.editScore;
this.render(true); this.render(true);
}); });
html.find('.item-equip').click(ev => { html.find('.item-equip').click(ev => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
this.actor.equipItem( li.data("item-id") ); this.actor.equipItem( li.data("item-id") );
this.render(true); this.render(true);
}); });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
setPosition(options = {}) { setPosition(options = {}) {

View File

@@ -3,14 +3,14 @@
* @extends {ActorSheet} * @extends {ActorSheet}
*/ */
import { HawkmoonUtility } from "./hawkmoon-utility.js"; import { HawkmoonUtility } from "../modules/hawkmoon-utility.js";
import { HawkmoonAutomation } from "./hawkmoon-automation.js"; import { HawkmoonAutomation } from "../modules/hawkmoon-automation.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const __ALLOWED_ITEM_CELLULE = { "talent": 1, "ressource": 1, "contact": 1} const __ALLOWED_ITEM_CELLULE = { "talent": 1, "ressource": 1, "contact": 1, "equipement": 1, "protection": 1, "artefact": 1, "arme": 1, "monnaie": 1 }
/* -------------------------------------------- */ /* -------------------------------------------- */
export class HawkmoonCelluleSheet extends ActorSheet { export class HawkmoonCelluleSheet extends foundry.appv1.sheets.ActorSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
@@ -45,6 +45,13 @@ export class HawkmoonCelluleSheet extends ActorSheet {
ressources: foundry.utils.duplicate(this.actor.getRessources()), ressources: foundry.utils.duplicate(this.actor.getRessources()),
contacts: foundry.utils.duplicate(this.actor.getContacts()), contacts: foundry.utils.duplicate(this.actor.getContacts()),
members: this.getMembers(), members: this.getMembers(),
equipements: foundry.utils.duplicate(this.actor.getEquipments()),
artefacts: foundry.utils.duplicate(this.actor.getArtefacts()),
armes: foundry.utils.duplicate(this.actor.getWeapons()),
monnaies: foundry.utils.duplicate(this.actor.getMonnaies()),
protections: foundry.utils.duplicate(this.actor.getArmors()),
richesse: this.actor.computeRichesse(),
valeurEquipement: this.actor.computeValeurEquipement(),
description: await TextEditor.enrichHTML(this.object.system.description, { async: true }), description: await TextEditor.enrichHTML(this.object.system.description, { async: true }),
options: this.options, options: this.options,
owner: this.document.isOwner, owner: this.document.isOwner,
@@ -88,7 +95,7 @@ export class HawkmoonCelluleSheet extends ActorSheet {
let actorId = li.data("actor-id") let actorId = li.data("actor-id")
this.actor.removeMember(actorId) this.actor.removeMember(actorId)
}) })
// Update Inventory Item // Update Inventory Item
html.find('.item-edit').click(ev => { html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item") const li = $(ev.currentTarget).parents(".item")
@@ -110,15 +117,15 @@ export class HawkmoonCelluleSheet extends ActorSheet {
let value = ev.currentTarget.value let value = ev.currentTarget.value
this.actor.editItemField(itemId, itemType, itemField, dataType, value) this.actor.editItemField(itemId, itemType, itemField, dataType, value)
}) })
html.find('.quantity-modify').click(event => {
html.find('.quantity-minus').click(event => { const li = $(event.currentTarget).parents(".item")
const li = $(event.currentTarget).parents(".item"); const value = Number($(event.currentTarget).data("quantite-value"))
this.actor.incDecQuantity(li.data("item-id"), -1); this.actor.incDecQuantity( li.data("item-id"), value );
}); })
html.find('.quantity-plus').click(event => { html.find('.item-add').click((event) => {
const li = $(event.currentTarget).parents(".item"); const itemType = $(event.currentTarget).data("type")
this.actor.incDecQuantity(li.data("item-id"), +1); this.actor.createEmbeddedDocuments('Item', [{ name: `Nouveau ${itemType}`, type: itemType }], { renderSheet: true })
}); })
html.find('.lock-unlock-sheet').click((event) => { html.find('.lock-unlock-sheet').click((event) => {
this.options.editScore = !this.options.editScore; this.options.editScore = !this.options.editScore;
@@ -129,7 +136,7 @@ export class HawkmoonCelluleSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onDropActor(event, dragData) { async _onDropActor(event, dragData) {
const actor = fromUuidSync(dragData.uuid) const actor = fromUuidSync(dragData.uuid)
if (actor) { if (actor) {
this.actor.addMember(actor.id) this.actor.addMember(actor.id)
} else { } else {
ui.notifications.warn("Cet acteur n'a pas été trouvé.") ui.notifications.warn("Cet acteur n'a pas été trouvé.")
@@ -149,7 +156,7 @@ export class HawkmoonCelluleSheet extends ActorSheet {
super._onDropItem(event, dragData) super._onDropItem(event, dragData)
return return
} }
ui.notifications("Ce type d'item n'est pas autorisé sur une Cellule.") ui.notification.info("Ce type d'item n'est pas autorisé sur une Cellule.")
} }

View File

@@ -4,8 +4,8 @@
*/ */
import { HawkmoonActorSheet } from "./hawkmoon-actor-sheet.js"; import { HawkmoonActorSheet } from "./hawkmoon-actor-sheet.js";
import { HawkmoonUtility } from "./hawkmoon-utility.js"; import { HawkmoonUtility } from "../modules/hawkmoon-utility.js";
import { HawkmoonAutomation } from "./hawkmoon-automation.js"; import { HawkmoonAutomation } from "../modules/hawkmoon-automation.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class HawkmoonCreatureSheet extends HawkmoonActorSheet { export class HawkmoonCreatureSheet extends HawkmoonActorSheet {

View File

@@ -4,7 +4,7 @@ import { HawkmoonUtility } from "./hawkmoon-utility.js";
* Extend the basic ItemSheet with some very simple modifications * Extend the basic ItemSheet with some very simple modifications
* @extends {ItemSheet} * @extends {ItemSheet}
*/ */
export class HawkmoonItemSheet extends ItemSheet { export class HawkmoonItemSheet extends foundry.appv1.sheets.ItemSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
@@ -145,7 +145,7 @@ export class HawkmoonItemSheet extends ItemSheet {
pred[index].description = ev.currentTarget.value pred[index].description = ev.currentTarget.value
pred[index].id = pred[index].id || randomID(16) pred[index].id = pred[index].id || randomID(16)
this.object.update( { 'system.predilections': pred }) this.object.update( { 'system.predilections': pred })
}) })
html.find('.predilection-acquise').change(ev => { html.find('.predilection-acquise').change(ev => {
const li = $(ev.currentTarget).parents(".prediction-item") const li = $(ev.currentTarget).parents(".prediction-item")
let index = li.data("prediction-index") let index = li.data("prediction-index")
@@ -153,7 +153,7 @@ export class HawkmoonItemSheet extends ItemSheet {
pred[index].acquise = ev.currentTarget.checked pred[index].acquise = ev.currentTarget.checked
pred[index].id = pred[index].id || randomID(16) pred[index].id = pred[index].id || randomID(16)
this.object.update( { 'system.predilections': pred }) this.object.update( { 'system.predilections': pred })
}) })
html.find('.predilection-maitrise').change(ev => { html.find('.predilection-maitrise').change(ev => {
const li = $(ev.currentTarget).parents(".prediction-item") const li = $(ev.currentTarget).parents(".prediction-item")
let index = li.data("prediction-index") let index = li.data("prediction-index")
@@ -161,7 +161,7 @@ export class HawkmoonItemSheet extends ItemSheet {
pred[index].maitrise = ev.currentTarget.checked pred[index].maitrise = ev.currentTarget.checked
pred[index].id = pred[index].id || randomID(16) pred[index].id = pred[index].id || randomID(16)
this.object.update( { 'system.predilections': pred }) this.object.update( { 'system.predilections': pred })
}) })
html.find('.predilection-used').change(ev => { html.find('.predilection-used').change(ev => {
const li = $(ev.currentTarget).parents(".prediction-item") const li = $(ev.currentTarget).parents(".prediction-item")
let index = li.data("prediction-index") let index = li.data("prediction-index")
@@ -169,11 +169,11 @@ export class HawkmoonItemSheet extends ItemSheet {
pred[index].used = ev.currentTarget.checked pred[index].used = ev.currentTarget.checked
pred[index].id = pred[index].id || randomID(16) pred[index].id = pred[index].id || randomID(16)
this.object.update( { 'system.predilections': pred }) this.object.update( { 'system.predilections': pred })
}) })
html.find('#add-predilection').click(ev => { html.find('#add-predilection').click(ev => {
let pred = foundry.utils.duplicate(this.object.system.predilections) let pred = foundry.utils.duplicate(this.object.system.predilections)
pred.push( { name: "Nouvelle prédilection", id: randomID(16), used: false }) pred.push( { name: "Nouvelle prédilection", id: randomID(16), used: false })
this.object.update( { 'system.predilections': pred }) this.object.update( { 'system.predilections': pred })
}) })
html.find('.delete-prediction').click(ev => { html.find('.delete-prediction').click(ev => {
@@ -186,7 +186,7 @@ export class HawkmoonItemSheet extends ItemSheet {
html.find('#add-automation').click(ev => { html.find('#add-automation').click(ev => {
let autom = foundry.utils.duplicate(this.object.system.automations) let autom = foundry.utils.duplicate(this.object.system.automations)
autom.push( { eventtype: "on-drop", name: "Automatisation 1", bonusname: "vigueur", bonus: 0, competence: "", minLevel: 0, baCost: 0, id: randomID(16) }) autom.push( { eventtype: "on-drop", name: "Automatisation 1", bonusname: "vigueur", bonus: 0, competence: "", minLevel: 0, baCost: 0, id: randomID(16) })
this.object.update( { 'system.automations': autom }) this.object.update( { 'system.automations': autom })
}) })
html.find('.delete-automation').click(ev => { html.find('.delete-automation').click(ev => {
@@ -203,8 +203,8 @@ export class HawkmoonItemSheet extends ItemSheet {
auto[index][field] = ev.currentTarget.value auto[index][field] = ev.currentTarget.value
auto[index].id = auto[index].id || randomID(16) auto[index].id = auto[index].id || randomID(16)
this.object.update( { 'system.automations': auto }) this.object.update( { 'system.automations': auto })
}) })
// Update Inventory Item // Update Inventory Item
html.find('.item-delete').click(ev => { html.find('.item-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");

View File

@@ -1,14 +1,14 @@
import { HawkmoonUtility } from "./hawkmoon-utility.js"; import { HawkmoonUtility } from "../modules/hawkmoon-utility.js";
export class HawkmoonRollDialog extends Dialog { export class HawkmoonRollDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async create(actor, rollData ) { static async create(actor, rollData) {
let options = { classes: ["HawkmoonDialog"], width: 320, height: 'fit-content', 'z-index': 99999 }; let options = { classes: ["HawkmoonDialog"], width: 420, height: 'fit-content', 'z-index': 99999 };
let html = await renderTemplate('systems/fvtt-hawkmoon-cyd/templates/roll-dialog-generic.html', rollData); let html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-hawkmoon-cyd/templates/roll-dialog-generic.html', rollData);
return new HawkmoonRollDialog(actor, rollData, html, options ); return new HawkmoonRollDialog(actor, rollData, html, options);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -16,22 +16,23 @@ export class HawkmoonRollDialog extends Dialog {
let conf = { let conf = {
title: "Test de Capacité", title: "Test de Capacité",
content: html, content: html,
buttons: { buttons: {
rolld10: { rolld10: {
icon: '<i class="fas fa-check"></i>', icon: '<i class="fas fa-check"></i>',
label: "Lancer 1d10", label: "Lancer 1d10",
callback: () => { this.roll("d10") } callback: () => { this.roll("d10") }
}, },
rolld20: { rolld20: {
icon: '<i class="fas fa-check"></i>', icon: '<i class="fas fa-check"></i>',
label: "Lancer 1d20", label: "Lancer 1d20",
callback: () => { this.roll("d20") } callback: () => { this.roll("d20") }
}, },
cancel: { cancel: {
icon: '<i class="fas fa-times"></i>', icon: '<i class="fas fa-times"></i>',
label: "Annuler", label: "Annuler",
callback: () => { this.close() } callback: () => { this.close() }
} }, }
},
close: close close: close
} }
@@ -42,9 +43,9 @@ export class HawkmoonRollDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
roll ( dice) { roll(dice) {
this.rollData.mainDice = dice this.rollData.mainDice = dice
HawkmoonUtility.rollHawkmoon( this.rollData ) HawkmoonUtility.rollHawkmoon(this.rollData)
} }
@@ -56,87 +57,87 @@ export class HawkmoonRollDialog extends Dialog {
function onLoad() { function onLoad() {
} }
$(function () { onLoad(); }); $(function () { onLoad(); });
html.find('#modificateur').change(async (event) => { html.find('#modificateur').change(async (event) => {
this.rollData.modificateur = Number(event.currentTarget.value) this.rollData.modificateur = Number(event.currentTarget.value)
}) })
html.find('#difficulte').change( (event) => { html.find('#difficulte').change((event) => {
console.log("Difficulte: " + event.currentTarget.value) console.log("Difficulte: " + event.currentTarget.value)
this.rollData.difficulte = Number(event.currentTarget.value) this.rollData.difficulte = Number(event.currentTarget.value)
}) })
html.find('#attrKey').change(async (event) => { html.find('#attrKey').change(async (event) => {
this.rollData.attrKey = String(event.currentTarget.value) this.rollData.attrKey = String(event.currentTarget.value)
}) })
html.find('#attrKey2').change(async (event) => { html.find('#attrKey2').change(async (event) => {
this.rollData.attrKey2 = String(event.currentTarget.value) this.rollData.attrKey2 = String(event.currentTarget.value)
}) })
html.find('#select-maitrise').change(async (event) => { html.find('#select-maitrise').change(async (event) => {
this.rollData.maitriseId = String(event.currentTarget.value) this.rollData.maitriseId = String(event.currentTarget.value)
}) })
html.find('#competence-talents').change((event) => { html.find('#competence-talents').change((event) => {
this.rollData.selectedTalents = $('#competence-talents').val() this.rollData.selectedTalents = $('#competence-talents').val()
}) })
html.find('#taille-cible').change((event) => { html.find('#taille-cible').change((event) => {
this.rollData.tailleCible = String(event.currentTarget.value) this.rollData.tailleCible = String(event.currentTarget.value)
}) })
html.find('#tireur-deplacement').change((event) => { html.find('#tireur-deplacement').change((event) => {
this.rollData.tireurDeplacement = String(event.currentTarget.value) this.rollData.tireurDeplacement = String(event.currentTarget.value)
}) })
html.find('#cible-couvert').change((event) => { html.find('#cible-couvert').change((event) => {
this.rollData.cibleCouvert = String(event.currentTarget.value) this.rollData.cibleCouvert = String(event.currentTarget.value)
}) })
html.find('#distance-tir').change((event) => { html.find('#distance-tir').change((event) => {
this.rollData.distanceTir = String(event.currentTarget.value) this.rollData.distanceTir = String(event.currentTarget.value)
}) })
html.find('#bonus-malus-context').change((event) => { html.find('#bonus-malus-context').change((event) => {
this.rollData.bonusMalusContext = Number(event.currentTarget.value) this.rollData.bonusMalusContext = Number(event.currentTarget.value)
}) })
html.find('#defenseur-au-sol').change((event) => { html.find('#defenseur-au-sol').change((event) => {
this.rollData.defenseurAuSol = event.currentTarget.checked this.rollData.defenseurAuSol = event.currentTarget.checked
}) })
html.find('#ambidextre-1').change((event) => { html.find('#ambidextre-1').change((event) => {
this.rollData.ambidextre1 = event.currentTarget.checked this.rollData.ambidextre1 = event.currentTarget.checked
}) })
html.find('#ambidextre-2').change((event) => { html.find('#ambidextre-2').change((event) => {
this.rollData.ambidextre2 = event.currentTarget.checked this.rollData.ambidextre2 = event.currentTarget.checked
}) })
html.find('#attaque-monte').change((event) => { html.find('#attaque-monte').change((event) => {
this.rollData.attqueMonte = event.currentTarget.checked this.rollData.attqueMonte = event.currentTarget.checked
}) })
html.find('#defenseur-aveugle').change((event) => { html.find('#defenseur-aveugle').change((event) => {
this.rollData.defenseurAveugle = event.currentTarget.checked this.rollData.defenseurAveugle = event.currentTarget.checked
}) })
html.find('#defenseur-de-dos').change((event) => { html.find('#defenseur-de-dos').change((event) => {
this.rollData.defenseurDeDos = event.currentTarget.checked this.rollData.defenseurDeDos = event.currentTarget.checked
}) })
html.find('#defenseur-restreint').change((event) => { html.find('#defenseur-restreint').change((event) => {
this.rollData.defenseurRestreint = event.currentTarget.checked this.rollData.defenseurRestreint = event.currentTarget.checked
}) })
html.find('#defenseur-immobilise').change((event) => { html.find('#defenseur-immobilise').change((event) => {
this.rollData.defenseurImmobilise = event.currentTarget.checked this.rollData.defenseurImmobilise = event.currentTarget.checked
}) })
html.find('#attaque-charge').change((event) => { html.find('#attaque-charge').change((event) => {
this.rollData.attaqueCharge = event.currentTarget.checked this.rollData.attaqueCharge = event.currentTarget.checked
}) })
html.find('#charge-cavalerie').change((event) => { html.find('#charge-cavalerie').change((event) => {
this.rollData.chargeCavalerie = event.currentTarget.checked this.rollData.chargeCavalerie = event.currentTarget.checked
}) })
html.find('#attaquants-multiple').change((event) => { html.find('#attaquants-multiple').change((event) => {
this.rollData.attaquantsMultiples = event.currentTarget.checked this.rollData.attaquantsMultiples = event.currentTarget.checked
}) })
html.find('#soutiens').change((event) => { html.find('#soutiens').change((event) => {
this.rollData.soutiens = Number(event.currentTarget.value) this.rollData.soutiens = Number(event.currentTarget.value)
}) })
html.find('#feinte').change((event) => { html.find('#feinte').change((event) => {
this.rollData.feinte = event.currentTarget.checked this.rollData.feinte = event.currentTarget.checked
}) })
html.find('#contenir').change((event) => { html.find('#contenir').change((event) => {
this.rollData.contenir = event.currentTarget.checked this.rollData.contenir = event.currentTarget.checked
}) })
html.find('#attaque-desarme').change((event) => { html.find('#attaque-desarme').change((event) => {
this.rollData.attaqueDesarme = event.currentTarget.checked this.rollData.attaqueDesarme = event.currentTarget.checked
}) })
} }
} }

View File

@@ -0,0 +1,36 @@
<li
class="item flexrow list-item list-item-shadow"
data-item-id="{{equip._id}}"
>
<a class="item-edit item-name-img" title="Edit Item"
><img class="sheet-competence-img" src="{{equip.img}}"
/></a>
{{#if (eq level 1)}}
<span class="item-name-label">{{equip.name}}</span>
{{else}}
<span class="item-name-label-level2">{{equip.name}}</span>
{{/if}}
<span class="item-field-label-long"
><label>
{{equip.system.quantity}} (<a class="quantity-minus plus-minus-button">
-</a
>/<a class="quantity-plus plus-minus-button">+</a>)
</label>
</span>
<div class="item-filler">&nbsp;</div>
<div class="item-controls item-controls-fixed">
{{#if (eq level 1)}}
<a class="item-control item-equip" title="Worn"
>{{#if equip.system.equipped}}<i class="fas fa-circle"></i>{{else}}<i
class="fas fa-genderless"
></i
>{{/if}}</a
>
{{/if}}
<a class="item-control item-delete" title="Delete Item"
><i class="fas fa-trash"></i
></a>
</div>
</li>

View File

@@ -0,0 +1,334 @@
<form class="skill-roll-dialog">
<header class="roll-dialog-header">
{{#if img}}
<img class="actor-icon" src="{{img}}" data-edit="img" title="{{name}}" />
{{/if}}
<h1 class="dialog-roll-title roll-dialog-header">{{title}}</h1>
</header>
<div class="flexcol">
<div class="flexrow">
{{#if (eq attrKey "tochoose")}}
<span class="roll-dialog-label"><strong>Attribut</strong></span>
<select
class="status-small-label color-class-common"
id="attrKey"
type="text"
name="attrKey"
value="attrKey"
data-dtype="string"
>
{{selectOptions attributs selected=attrKey}}
</select>
{{else}}
<span class="roll-dialog-label"><strong>{{attr.label}}</strong></span>
<span class="small-label roll-dialog-label">{{attr.value}}</span>
{{/if}}
</div>
{{#if nbAdversites}}
<div class="flexrow">
<span class="roll-dialog-label"><strong>Malus d'adversités</strong></span>
<span class="small-label roll-dialog-label">- {{nbAdversites}}</span>
</div>
{{/if}} {{#if competence}}
<div class="flexrow">
<span class="roll-dialog-label"><strong>{{competence.name}}</strong></span>
<span class="small-label roll-dialog-label"><strong>{{competence.system.niveau}}</strong></span>
</div>
{{#if maitrises}}
<div class="flexrow">
<span class="roll-dialog-label"><strong>Maîtrise</strong></span>
<select
class="status-small-label color-class-common"
id="select-maitrise"
type="text"
name="select-maitrise"
value="maitriseId"
data-dtype="string"
>
{{selectOptions maitrises selected=maitriseId valueAttr="key"
nameAttr="key" labelAttr="label"}}
</select>
</div>
{{/if}} {{else}}
<div class="flexrow">
<span class="roll-dialog-label"><strong>Second Attribut</strong></span>
<select
class="status-small-label color-class-common"
id="attrKey2"
type="text"
name="attrKey2"
value="attrKey2"
data-dtype="string"
>
{{#select attrKey2}}
<option value="none">Aucun</option>
{{#each attributs as |attrLabel attrKey|}}
<option value="{{attrKey}}">{{attrLabel}}</option>
{{/each}} {{/select}}
</select>
</div>
{{/if}} {{#if (count talents)}}
<div class="flexrow">
<span class="roll-dialog-label"><strong></strong>Talents</strong></span>
<select
class="flex1"
name="competence-talents"
id="competence-talents"
data-type="String"
multiple
>
{{#each talents as |talent key|}}
<option value="{{talent._id}}">{{talent.name}}</option>
{{/each}}
</select>
</div>
{{/if}} {{#if conditionsCommunes}}
<div class="flexrow">
<span class="roll-dialog-label">En surplomb, défenseur au sol (+3)?</span>
<input type="checkbox" id="defenseur-au-sol" {{checked defenseurAuSol}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label">Défenseur aveuglé (+10)?</span>
<input
type="checkbox"
id="defenseur-aveugle"
{{checked
defenseurAveugle}}
/>
</div>
<div class="flexrow">
<span class="roll-dialog-label">Défenseur de dos (+5)?</span>
<input type="checkbox" id="defenseur-de-dos" {{checked defenseurDeDos}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label">Défenseur immobilisé (+5)?</span>
<input
type="checkbox"
id="defenseur-immobilise"
{{checked
defenseurImmobilise}}
/>
</div>
{{/if}} {{#if (or immobiliser repousser)}}
<div class="flexrow">
<span class="roll-dialog-label">Cible consciente?</span>
<input type="checkbox" id="cibleconsciente" {{checked cibleconsciente}} />
</div>
{{/if}} {{#if arme}} {{#if arme.system.isMelee}} {{#if bonusArmeNaturelle}}
<div class="flexrow">
<span class="roll-dialog-label">Arme naturelle/fortune en défense</span>
<span class="small-label roll-dialog-label">{{bonusArmeNaturelle}}</span>
</div>
{{/if}}
<div class="flexrow">
<span class="roll-dialog-label">En surplomb, défenseur au sol (+3)?</span>
<input type="checkbox" id="defenseur-au-sol" {{checked defenseurAuSol}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label"
>Attaquants multiples (après le premier) (+3)?</span
>
<input
type="checkbox"
id="attaquants-multiple"
{{checked
attaquantsMultiples}}
/>
</div>
{{#if hasAmbidextre}}
<div class="flexrow">
<span class="roll-dialog-label"
>Première attaque avec deux armes (-3)?</span
>
<input type="checkbox" id="ambidextre-1" {{checked attaqueAmbidextre1}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label"
>Seconde attaque avec deux armes (-6)?</span
>
<input type="checkbox" id="ambidextre-2" {{checked attaqueAmbidextre2}} />
</div>
{{/if}} {{#if hasFeinte}}
<div class="flexrow">
<span class="roll-dialog-label"
>Feinte (<strong>cout : 1 BA</strong>) ?</span
>
<input type="checkbox" id="feinte" {{checked feinte}} />
</div>
{{/if}}
<div class="flexrow">
<span class="roll-dialog-label"><strong></strong>Soutiens</strong></span>
<select
class="status-small-label color-class-common"
name="soutiens"
id="soutiens"
data-type="Number"
>
{{selectOptions config.optionsSoutiens selected=soutiens valueAttr="key"
nameAttr="key" labelAttr="label"}}
</select>
</div>
<div class="flexrow">
<span class="roll-dialog-label">Défenseur aveuglé (+10)?</span>
<input
type="checkbox"
id="defenseur-aveugle"
{{checked
defenseurAveugle}}
/>
</div>
<div class="flexrow">
<span class="roll-dialog-label">Défenseur de dos (+5)?</span>
<input type="checkbox" id="defenseur-de-dos" {{checked defenseurDeDos}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label"
>Défenseur dans espace restreint (+3)?</span
>
<input
type="checkbox"
id="defenseur-restreint"
{{checked
defenseurRestreint}}
/>
</div>
<div class="flexrow">
<span class="roll-dialog-label">Défenseur immobilisé (+5)?</span>
<input
type="checkbox"
id="defenseur-immobilise"
{{checked
defenseurImmobilise}}
/>
</div>
<div class="flexrow">
<span class="roll-dialog-label">Charge ?</span>
<input type="checkbox" id="attaque-charge" {{checked attaqueCharge}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label">Contenir?</span>
<input type="checkbox" id="contenir" {{checked contenir}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label">Désarmer (SD+10)?</span>
<input type="checkbox" id="attaque-desarme" {{checked attaqueDesarme}} />
</div>
{{#if isMonte}}
<div class="flexrow">
<span class="roll-dialog-label">Charge de cavalerie?</span>
<input
type="checkbox"
id="charge-cavalerie"
{{checked
chargeCavalerie}}
/>
</div>
{{/if}} {{else}}
<div class="flexrow">
<span class="roll-dialog-label">Tireur en déplacement ?</span>
<select
class="item-field-label-long"
type="text"
id="tireur-deplacement"
data-dtype="string"
>
{{selectOptions config.optionsTireurDeplacement
selected=tireurDeplacement valueAttr="key" nameAttr="key"
labelAttr="label"}}
</select>
</div>
<div class="flexrow">
<span class="roll-dialog-label">Couvert de la cible ?</span>
<select
class="item-field-label-long"
type="text"
id="cible-couvert"
data-dtype="string"
>
{{selectOptions config.optionsCouvert selected=cibleCouvert
valueAttr="key" nameAttr="key" labelAttr="label"}}
</select>
</div>
<div class="flexrow">
<span class="roll-dialog-label">Cible se déplace vite (SD+3)?</span>
<input
type="checkbox"
id="tireur-cible-deplace"
{{checked
cibleDeplace}}
/>
</div>
<div class="flexrow">
<span class="roll-dialog-label">Cible corps à corps (SD+3)?</span>
<input type="checkbox" id="tireur-cible-cac" {{checked cibleCaC}} />
</div>
<div class="flexrow">
<span class="roll-dialog-label">Taille de la cible ?</span>
<select
class="item-field-label-long"
type="text"
id="taille-cible"
data-dtype="string"
>
{{selectOptions config.optionsTailleCible selected=tailleCible
valueAttr="key" nameAttr="key" labelAttr="label"}}
</select>
</div>
{{/if}} {{/if}}
<div class="flexrow">
<span class="roll-dialog-label">Bonus/Malus </span>
<select
class="roll-dialog-label"
id="bonus-malus-context"
type="text"
value="{{bonusMalusContext}}"
data-dtype="Number"
>
{{selectOptions config.optionsBonusMalus selected=bonusMalusContext
valueAttr="key" nameAttr="key" labelAttr="label"}}
</select>
</div>
{{#if (or armeDefense arme.system.isDistance)}} {{#if
arme.system.isDistance}}
<div class="flexrow">
<span class="roll-dialog-label">SD de distance</span>
<select
class="item-field-label-long"
type="text"
id="distance-tir"
data-dtype="string"
>
{{selectOptions config.optionsDistanceTir selected=distanceTir
valueAttr="key" nameAttr="key" labelAttr="label"}}
</select>
</div>
{{else}}
<div class="flexrow">
{{#if desengager}}
<span class="roll-dialog-label">C. Offensive adversaire </span>
{{else}}
<span class="roll-dialog-label">C. Défensive adversaire</span>
{{/if}}
<span class="roll-dialog-label"><strong>{{difficulte}}</strong> </span>
</div>
{{/if}} {{else}} {{#if isInit}} {{else}}
<div class="flexrow">
<span class="roll-dialog-label">Difficulté : </span>
<select
class="roll-dialog-label"
id="difficulte"
type="text"
name="difficulte"
data-dtype="String"
>
{{selectOptions config.optionsDifficulte selected=difficulte
valueAttr="key" nameAttr="key" labelAttr="label"}}
</select>
</div>
{{/if}} {{/if}}
</div>
</form>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 KiB

35
gulpfile.js Normal file
View File

@@ -0,0 +1,35 @@
const gulp = require('gulp');
const less = require('gulp-less');
const sourcemaps = require('gulp-sourcemaps');
// Paths
const paths = {
styles: {
src: 'less/**/*.less',
dest: 'styles/'
}
};
// Compile LESS to CSS
function styles() {
return gulp.src('less/hawkmoon.less')
.pipe(sourcemaps.init())
.pipe(less())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(paths.styles.dest));
}
// Watch files
function watchFiles() {
gulp.watch(paths.styles.src, styles);
}
// Define complex tasks
const build = gulp.series(styles);
const watch = gulp.series(build, watchFiles);
// Export tasks
exports.styles = styles;
exports.build = build;
exports.watch = watch;
exports.default = build;

4
less/hawkmoon.less Normal file
View File

@@ -0,0 +1,4 @@
// Main LESS file for Hawkmoon system
// Temporarily importing the full converted simple.css while we refactor
@import "simple-converted";

2713
less/simple-converted.less Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,177 @@
import { HawkmoonUtility } from "../hawkmoon-utility.js"
import { HAWKMOON_CONFIG } from "../hawkmoon-config.js"
/**
* Dialogue de jet de dé pour Hawkmoon - Version DialogV2
*/
export class HawkmoonRollDialog {
/**
* Create and display the roll dialog
* @param {HawkmoonActor} actor - The actor making the roll
* @param {Object} rollData - Data for the roll
* @returns {Promise<HawkmoonRollDialog>}
*/
static async create(actor, rollData) {
// Préparer le contexte pour le template
const context = {
...rollData,
difficulte: String(rollData.difficulte || 0), // Convertir en string pour matcher les options du select
img: actor.img,
name: actor.name,
config: HAWKMOON_CONFIG,
}
// Si attrKey est "tochoose", préparer la liste des attributs sélectionnables
if (rollData.attrKey === "tochoose") {
context.selectableAttributes = actor.system.attributs
// Ne pas changer attrKey ni attr - l'utilisateur doit choisir
}
// Rendre le template en HTML
const content = await foundry.applications.handlebars.renderTemplate(
"systems/fvtt-hawkmoon-cyd/templates/roll-dialog-generic.hbs",
context
)
// Utiliser DialogV2.wait avec le HTML rendu
return foundry.applications.api.DialogV2.wait({
window: { title: "Test de Capacité", icon: "fa-solid fa-dice-d20" },
classes: ["hawkmoon-roll-dialog"],
position: { width: 480 },
modal: false, // Permettre l'interaction avec le canvas pour garder la cible sélectionnée
content,
buttons: [
{
action: "rolld10",
label: "Lancer 1d10",
icon: "fa-solid fa-dice-d10",
default: true,
callback: (event, button, dialog) => {
this._updateRollDataFromForm(rollData, button.form.elements, actor)
rollData.mainDice = "d10"
HawkmoonUtility.rollHawkmoon(rollData)
}
},
{
action: "rolld20",
label: "Lancer 1d20",
icon: "fa-solid fa-dice-d20",
callback: (event, button, dialog) => {
this._updateRollDataFromForm(rollData, button.form.elements, actor)
rollData.mainDice = "d20"
HawkmoonUtility.rollHawkmoon(rollData)
}
},
],
rejectClose: false,
})
}
/**
* Mettre à jour rollData avec les valeurs du formulaire
* @param {Object} rollData - L'objet rollData à mettre à jour
* @param {HTMLFormControlsCollection} formElements - Les éléments du formulaire
* @param {HawkmoonActor} actor - L'acteur pour récupérer les attributs
* @private
*/
static _updateRollDataFromForm(rollData, formElements, actor) {
// Attributs
if (formElements.attrKey) {
rollData.attrKey = formElements.attrKey.value
// Si l'attribut a changé, mettre à jour rollData.attr
if (rollData.attrKey !== "tochoose" && rollData.attrKey !== "none" && actor) {
rollData.attr = foundry.utils.duplicate(actor.system.attributs[rollData.attrKey])
rollData.actionImg = "systems/fvtt-hawkmoon-cyd/assets/icons/" + actor.system.attributs[rollData.attrKey].labelnorm + ".webp"
}
}
if (formElements.attrKey2) {
rollData.attrKey2 = formElements.attrKey2.value
}
// Modificateurs de base
if (formElements.difficulte) {
rollData.difficulte = Number(formElements.difficulte.value)
}
if (formElements.modificateur) {
rollData.modificateur = Number(formElements.modificateur.value)
}
if (formElements.soutiens) {
rollData.soutiens = Number(formElements.soutiens.value)
}
// Compétence
if (formElements.maitrise) {
rollData.maitriseId = formElements.maitrise.value
}
if (formElements.talents) {
// Récupérer toutes les options sélectionnées (select multiple)
const selectedOptions = Array.from(formElements.talents.selectedOptions)
rollData.selectedTalents = selectedOptions.map(opt => opt.value)
}
// Modificateurs de tir
if (formElements.tailleCible) {
rollData.tailleCible = formElements.tailleCible.value
}
if (formElements.tireurDeplacement) {
rollData.tireurDeplacement = formElements.tireurDeplacement.value
}
if (formElements.cibleCouvert) {
rollData.cibleCouvert = formElements.cibleCouvert.value
}
if (formElements.distanceTir) {
rollData.distanceTir = formElements.distanceTir.value
}
if (formElements.cibleDeplace) {
rollData.cibleDeplace = formElements.cibleDeplace.checked
}
if (formElements.cibleCaC) {
rollData.cibleCaC = formElements.cibleCaC.checked
}
// Modificateurs de combat (checkboxes)
if (formElements.defenseurAuSol) {
rollData.defenseurAuSol = formElements.defenseurAuSol.checked
}
if (formElements.ambidextre1) {
rollData.ambidextre1 = formElements.ambidextre1.checked
}
if (formElements.ambidextre2) {
rollData.ambidextre2 = formElements.ambidextre2.checked
}
if (formElements.attaqueMonte) {
rollData.attaqueMonte = formElements.attaqueMonte.checked
}
if (formElements.defenseurAveugle) {
rollData.defenseurAveugle = formElements.defenseurAveugle.checked
}
if (formElements.defenseurDeDos) {
rollData.defenseurDeDos = formElements.defenseurDeDos.checked
}
if (formElements.defenseurRestreint) {
rollData.defenseurRestreint = formElements.defenseurRestreint.checked
}
if (formElements.defenseurImmobilise) {
rollData.defenseurImmobilise = formElements.defenseurImmobilise.checked
}
if (formElements.attaqueCharge) {
rollData.attaqueCharge = formElements.attaqueCharge.checked
}
if (formElements.chargeCavalerie) {
rollData.chargeCavalerie = formElements.chargeCavalerie.checked
}
if (formElements.attaquantsMultiple) {
rollData.attaquantsMultiple = formElements.attaquantsMultiple.checked
}
if (formElements.feinte) {
rollData.feinte = formElements.feinte.checked
}
if (formElements.contenir) {
rollData.contenir = formElements.contenir.checked
}
if (formElements.attaqueDesarme) {
rollData.attaqueDesarme = formElements.attaqueDesarme.checked
}
}
}

View File

@@ -0,0 +1,17 @@
export { default as HawkmoonTalentSheet } from "./talent-sheet.mjs"
export { default as HawkmoonCompetenceSheet } from "./competence-sheet.mjs"
export { default as HawkmoonArmeSheet } from "./arme-sheet.mjs"
export { default as HawkmoonProtectionSheet } from "./protection-sheet.mjs"
export { default as HawkmoonHistoriqueSheet } from "./historique-sheet.mjs"
export { default as HawkmoonProfilSheet } from "./profil-sheet.mjs"
export { default as HawkmoonEquipementSheet } from "./equipement-sheet.mjs"
export { default as HawkmoonMonnaieSheet } from "./monnaie-sheet.mjs"
export { default as HawkmoonArtefactSheet } from "./artefact-sheet.mjs"
export { default as HawkmoonRessourceSheet } from "./ressource-sheet.mjs"
export { default as HawkmoonContactSheet } from "./contact-sheet.mjs"
export { default as HawkmoonMutationSheet } from "./mutation-sheet.mjs"
// Actor sheets
export { default as HawkmoonPersonnageSheet } from "./personnage-sheet.mjs"
export { default as HawkmoonCreatureSheet } from "./creature-sheet.mjs"
export { default as HawkmoonCelluleSheet } from "./cellule-sheet.mjs"

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonArmeSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["arme"],
position: {
width: 640,
},
window: {
contentClasses: ["arme-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-arme-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonArtefactSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["artefact"],
position: {
width: 620,
},
window: {
contentClasses: ["artefact-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-artefact-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,547 @@
const { HandlebarsApplicationMixin } = foundry.applications.api
import { HawkmoonUtility } from "../../hawkmoon-utility.js"
import { HawkmoonAutomation } from "../../hawkmoon-automation.js"
export default class HawkmoonActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
/**
* Different sheet modes.
* @enum {number}
*/
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
constructor(options = {}) {
super(options)
this.#dragDrop = this.#createDragDropHandlers()
this._sheetMode = this.constructor.SHEET_MODES.PLAY // Commencer en mode visualisation
}
#dragDrop
/** @override */
static DEFAULT_OPTIONS = {
classes: ["fvtt-hawkmoon-cyd", "sheet", "actor"],
position: {
width: 640,
height: 720,
},
window: {
resizable: true,
},
form: {
submitOnChange: true,
closeOnSubmit: false,
},
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: "form" }],
actions: {
editImage: HawkmoonActorSheet.#onEditImage,
toggleSheet: HawkmoonActorSheet.#onToggleSheet,
editItem: HawkmoonActorSheet.#onEditItem,
deleteItem: HawkmoonActorSheet.#onDeleteItem,
createItem: HawkmoonActorSheet.#onCreateItem,
equipItem: HawkmoonActorSheet.#onEquipItem,
modifyQuantity: HawkmoonActorSheet.#onModifyQuantity,
modifyAdversite: HawkmoonActorSheet.#onModifyAdversite,
rollInitiative: HawkmoonActorSheet.#onRollInitiative,
rollAttribut: HawkmoonActorSheet.#onRollAttribut,
rollCompetence: HawkmoonActorSheet.#onRollCompetence,
rollArmeOffensif: HawkmoonActorSheet.#onRollArmeOffensif,
rollArmeDegats: HawkmoonActorSheet.#onRollArmeDegats,
rollAssommer: HawkmoonActorSheet.#onRollAssommer,
rollCoupBas: HawkmoonActorSheet.#onRollCoupBas,
rollImmobiliser: HawkmoonActorSheet.#onRollImmobiliser,
rollRepousser: HawkmoonActorSheet.#onRollRepousser,
rollDesengager: HawkmoonActorSheet.#onRollDesengager,
},
}
/**
* Is the sheet currently in 'Play' mode?
* @type {boolean}
*/
get isPlayMode() {
// Initialize if not set
if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
}
/**
* Is the sheet currently in 'Edit' mode?
* @type {boolean}
*/
get isEditMode() {
// Initialize if not set
if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY
return this._sheetMode === this.constructor.SHEET_MODES.EDIT
}
/**
* Tab groups state
* @type {object}
*/
tabGroups = { primary: "principal" }
/** @override */
async _prepareContext() {
const actor = this.document
const context = {
actor: actor,
system: actor.system,
source: actor.toObject(),
fields: actor.schema.fields,
systemFields: actor.system.schema.fields,
isEditable: this.isEditable,
isEditMode: this.isEditMode,
isPlayMode: this.isPlayMode,
isGM: game.user.isGM,
config: CONFIG.HAWKMOON,
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.description || "", { async: true }),
enrichedHabitat: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.habitat || "", { async: true }),
}
return context
}
/** @override */
_onRender(context, options) {
super._onRender(context, options)
// Activate drag & drop handlers
this.#dragDrop.forEach(d => d.bind(this.element))
// Manual tab navigation
const html = this.element
const tabLinks = html.querySelectorAll('a.item[data-tab]')
const tabContents = html.querySelectorAll('.tab[data-tab]')
// Hide all tabs initially
tabContents.forEach(tab => {
tab.classList.remove('active')
tab.style.display = 'none'
})
// Show active tab
const activeTab = this.tabGroups.primary
const activeTabContent = html.querySelector(`.tab[data-tab="${activeTab}"]`)
if (activeTabContent) {
activeTabContent.classList.add('active')
activeTabContent.style.display = 'block'
}
// Activate the corresponding nav link
tabLinks.forEach(link => {
if (link.dataset.tab === activeTab) {
link.classList.add('active')
} else {
link.classList.remove('active')
}
})
// Tab click handler
tabLinks.forEach(link => {
link.addEventListener('click', (event) => {
event.preventDefault()
const tab = link.dataset.tab
// Update state
this.tabGroups.primary = tab
// Hide all tabs
tabContents.forEach(t => {
t.classList.remove('active')
t.style.display = 'none'
})
// Show selected tab
const selectedTab = html.querySelector(`.tab[data-tab="${tab}"]`)
if (selectedTab) {
selectedTab.classList.add('active')
selectedTab.style.display = 'block'
}
// Update nav links
tabLinks.forEach(l => {
if (l.dataset.tab === tab) {
l.classList.add('active')
} else {
l.classList.remove('active')
}
})
})
})
// Inline item editing
html.querySelectorAll('.edit-item-data').forEach(input => {
input.addEventListener('change', (event) => {
const li = event.target.closest('.item')
const itemId = li.dataset.itemId
const itemType = li.dataset.itemType
const itemField = event.target.dataset.itemField
const dataType = event.target.dataset.dtype
const value = event.target.value
this.actor.editItemField(itemId, itemType, itemField, dataType, value)
})
})
}
// #region Drag & Drop
/**
* Create drag-and-drop workflow handlers for this Application
* @returns {DragDrop[]} An array of DragDrop handlers
* @private
*/
#createDragDropHandlers() {
return this.options.dragDrop.map((d) => {
d.permissions = {
dragstart: this._canDragStart.bind(this),
drop: this._canDragDrop.bind(this),
}
d.callbacks = {
dragstart: this._onDragStart.bind(this),
drop: this._onDrop.bind(this),
}
return new foundry.applications.ux.DragDrop(d)
})
}
/**
* Define whether a user is able to begin a dragstart workflow for a given drag selector
* @param {string} selector The candidate HTML selector for dragging
* @returns {boolean} Can the current user drag this selector?
* @protected
*/
_canDragStart(selector) {
return this.isEditable
}
/**
* Define whether a user is able to conclude a drag-and-drop workflow for a given drop selector
* @param {string} selector The candidate HTML selector for the drop target
* @returns {boolean} Can the current user drop on this selector?
* @protected
*/
_canDragDrop(selector) {
return this.isEditable
}
/**
* Callback actions which occur at the beginning of a drag start workflow.
* @param {DragEvent} event The originating DragEvent
* @protected
*/
_onDragStart(event) {
const li = event.currentTarget.closest(".item")
if (!li?.dataset.itemId) return
const item = this.actor.items.get(li.dataset.itemId)
if (!item) return
const dragData = item.toDragData()
event.dataTransfer.setData("text/plain", JSON.stringify(dragData))
}
/**
* Callback actions which occur when a dragged element is dropped on a target.
* @param {DragEvent} event The originating DragEvent
* @protected
*/
async _onDrop(event) {
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
const actor = this.actor
// Handle different data types
switch (data.type) {
case "Item":
return this._onDropItem(event, data)
case "Actor":
return this._onDropActor(event, data)
case "ActiveEffect":
return this._onDropActiveEffect(event, data)
}
}
/**
* Handle dropping an Item on the actor sheet
* @param {DragEvent} event
* @param {object} data
* @private
*/
async _onDropItem(event, data) {
if (!this.actor.isOwner) return false
let item = await fromUuid(data.uuid)
if (item.pack) {
item = await HawkmoonUtility.searchItem(item)
}
const autoresult = HawkmoonAutomation.processAutomations("on-drop", item, this.actor)
if (autoresult.isValid) {
// In AppV2, we need to get the item data differently
const itemData = item.toObject ? item.toObject() : item
return this.actor.createEmbeddedDocuments("Item", [itemData])
} else {
ui.notifications.warn(autoresult.warningMessage)
return false
}
}
/**
* Handle dropping an Actor on the sheet
* @param {DragEvent} event
* @param {object} data
* @private
*/
async _onDropActor(event, data) {
// To be implemented by subclasses if needed
return false
}
/**
* Handle dropping an ActiveEffect on the sheet
* @param {DragEvent} event
* @param {object} data
* @private
*/
async _onDropActiveEffect(event, data) {
// To be implemented by subclasses if needed
return false
}
// #endregion
// #region Action Handlers
/**
* Toggle between edit and play mode
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static #onToggleSheet(event, target) {
console.log("Toggle sheet clicked", this)
const wasEditMode = this.isEditMode
console.log("Current mode:", this._sheetMode, "isEditMode:", wasEditMode, "isPlayMode:", this.isPlayMode)
this._sheetMode = wasEditMode ? this.constructor.SHEET_MODES.PLAY : this.constructor.SHEET_MODES.EDIT
console.log("New mode set to:", this._sheetMode, "(", wasEditMode ? "PLAY" : "EDIT", ")")
console.log("After change - isEditMode:", this.isEditMode, "isPlayMode:", this.isPlayMode)
this.render({ force: true })
}
/**
* Edit the actor image
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onEditImage(event, target) {
const fp = new FilePicker({
type: "image",
current: this.actor.img,
callback: (path) => {
this.actor.update({ img: path })
},
})
return fp.browse()
}
/**
* Edit an item
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onEditItem(event, target) {
const li = target.closest(".item")
const itemId = li?.dataset.itemId
if (!itemId) return
const item = this.actor.items.get(itemId)
if (item) item.sheet.render(true)
}
/**
* Delete an item
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onDeleteItem(event, target) {
const li = target.closest(".item")
await HawkmoonUtility.confirmDelete(this, li)
}
/**
* Create a new item
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onCreateItem(event, target) {
const itemType = target.dataset.type
await this.actor.createEmbeddedDocuments("Item", [{ name: `Nouveau ${itemType}`, type: itemType }], { renderSheet: true })
}
/**
* Equip/unequip an item
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onEquipItem(event, target) {
const li = target.closest(".item")
const itemId = li?.dataset.itemId
if (itemId) {
await this.actor.equipItem(itemId)
this.render()
}
}
/**
* Modify item quantity
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onModifyQuantity(event, target) {
const li = target.closest(".item")
const itemId = li?.dataset.itemId
const value = Number(target.dataset.quantiteValue)
if (itemId) {
await this.actor.incDecQuantity(itemId, value)
}
}
/**
* Modify adversité
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onModifyAdversite(event, target) {
const li = target.closest(".item")
const adv = li?.dataset.adversite
const value = Number(target.dataset.adversiteValue)
if (adv) {
await this.actor.incDecAdversite(adv, value)
}
}
/**
* Roll initiative
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollInitiative(event, target) {
await this.actor.rollAttribut("adr", true)
}
/**
* Roll attribut
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollAttribut(event, target) {
const li = target.closest(".item")
const attrKey = li?.dataset.attrKey
if (attrKey) {
await this.actor.rollAttribut(attrKey, false)
}
}
/**
* Roll competence
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollCompetence(event, target) {
const li = target.closest(".item")
const attrKey = target.dataset.attrKey
const compId = li?.dataset.itemId
if (attrKey && compId) {
await this.actor.rollCompetence(attrKey, compId)
}
}
/**
* Roll arme offensif
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollArmeOffensif(event, target) {
const li = target.closest(".item")
const armeId = li?.dataset.itemId
if (armeId) {
await this.actor.rollArmeOffensif(armeId)
}
}
/**
* Roll arme degats
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollArmeDegats(event, target) {
const li = target.closest(".item")
const armeId = li?.dataset.itemId
if (armeId) {
await this.actor.rollArmeDegats(armeId)
}
}
/**
* Roll assommer
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollAssommer(event, target) {
await this.actor.rollAssommer()
}
/**
* Roll coup bas
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollCoupBas(event, target) {
await this.actor.rollCoupBas()
}
/**
* Roll immobiliser
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollImmobiliser(event, target) {
await this.actor.rollImmobiliser()
}
/**
* Roll repousser
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollRepousser(event, target) {
await this.actor.rollRepousser()
}
/**
* Roll désengager
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onRollDesengager(event, target) {
await this.actor.rollDesengager()
}
// #endregion
}

View File

@@ -0,0 +1,342 @@
const { HandlebarsApplicationMixin } = foundry.applications.api
export default class HawkmoonItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
constructor(options = {}) {
super(options)
this.#dragDrop = this.#createDragDropHandlers()
}
#dragDrop
/** @override */
static DEFAULT_OPTIONS = {
classes: ["fvtt-hawkmoon-cyd", "item"],
position: {
width: 620,
height: 600,
},
form: {
submitOnChange: true,
},
window: {
resizable: true,
},
tabs: [
{
navSelector: 'nav[data-group="primary"]',
contentSelector: "section.sheet-body",
initial: "description",
},
],
dragDrop: [{ dragSelector: "[data-drag]", dropSelector: null }],
actions: {
editImage: HawkmoonItemSheet.#onEditImage,
postItem: HawkmoonItemSheet.#onPostItem,
addPredilection: HawkmoonItemSheet.#onAddPredilection,
deletePredilection: HawkmoonItemSheet.#onDeletePredilection,
addAutomation: HawkmoonItemSheet.#onAddAutomation,
deleteAutomation: HawkmoonItemSheet.#onDeleteAutomation,
},
}
/**
* Tab groups state
* @type {object}
*/
tabGroups = { primary: "description" }
/**
* Is the sheet currently in 'Play' mode?
* @type {boolean}
*/
/** @override */
async _prepareContext() {
const context = {
fields: this.document.schema.fields,
systemFields: this.document.system.schema.fields,
item: this.document,
system: this.document.system,
source: this.document.toObject(),
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true }),
isEditMode: true,
isEditable: this.isEditable,
isGM: game.user.isGM,
config: CONFIG.HAWKMOON,
attributs: this.#getAttributs(),
}
return context
}
/** @override */
_onRender(context, options) {
super._onRender(context, options)
this.#dragDrop.forEach((d) => d.bind(this.element))
// Activate tab navigation manually
const nav = this.element.querySelector('nav.tabs[data-group]')
if (nav) {
const group = nav.dataset.group
// Activate the current tab
const activeTab = this.tabGroups[group] || "description"
nav.querySelectorAll('[data-tab]').forEach(link => {
const tab = link.dataset.tab
link.classList.toggle('active', tab === activeTab)
link.addEventListener('click', (event) => {
event.preventDefault()
this.tabGroups[group] = tab
this.render()
})
})
// Show/hide tab content
this.element.querySelectorAll('[data-group="' + group + '"][data-tab]').forEach(content => {
content.classList.toggle('active', content.dataset.tab === activeTab)
})
}
}
// #region Drag-and-Drop Workflow
/**
* Create drag-and-drop workflow handlers for this Application
* @returns {DragDrop[]} An array of DragDrop handlers
* @private
*/
#createDragDropHandlers() {
return this.options.dragDrop.map((d) => {
d.permissions = {
dragstart: this._canDragStart.bind(this),
drop: this._canDragDrop.bind(this),
}
d.callbacks = {
dragstart: this._onDragStart.bind(this),
dragover: this._onDragOver.bind(this),
drop: this._onDrop.bind(this),
}
return new foundry.applications.ux.DragDrop.implementation(d)
})
}
/**
* Can the User start a drag workflow for a given drag selector?
* @param {string} selector The candidate HTML selector for the drag event
* @returns {boolean} Can the current user drag this selector?
* @protected
*/
_canDragStart(selector) {
return this.isEditable
}
/**
* Can the User drop an entry at a given drop selector?
* @param {string} selector The candidate HTML selector for the drop event
* @returns {boolean} Can the current user drop on this selector?
* @protected
*/
_canDragDrop(selector) {
return this.isEditable
}
/**
* Callback for dragstart events.
* @param {DragEvent} event The drag start event
* @protected
*/
_onDragStart(event) {
const target = event.currentTarget
const dragData = { type: "Item", uuid: this.document.uuid }
event.dataTransfer.setData("text/plain", JSON.stringify(dragData))
}
/**
* Callback for dragover events.
* @param {DragEvent} event The drag over event
* @protected
*/
_onDragOver(event) {
// Default behavior is fine
}
/**
* Callback for drop events.
* @param {DragEvent} event The drop event
* @protected
*/
async _onDrop(event) {
const data = TextEditor.getDragEventData(event)
const item = await fromUuid(data.uuid)
if (!item) return
// Handle drop logic here if needed
console.log("Item dropped:", item)
}
// #endregion
// #region Action Handlers
/**
* Edit the item image
* @param {Event} event The triggering event
* @param {HTMLElement} target The target element
* @private
*/
static async #onEditImage(event, target) {
const fp = new foundry.applications.ui.FilePicker({
type: "image",
current: this.document.img,
callback: (path) => {
this.document.update({ img: path })
},
})
return fp.browse()
}
/**
* Post item to chat
* @param {Event} event The triggering event
* @param {HTMLElement} target The target element
* @private
*/
static async #onPostItem(event, target) {
let chatData = foundry.utils.duplicate(this.document)
if (this.document.actor) {
chatData.actor = { id: this.document.actor.id }
}
// Don't post any image for the item if the default image is used
if (chatData.img.includes("/blank.png")) {
chatData.img = null
}
// JSON object for easy creation
chatData.jsondata = JSON.stringify({
compendium: "postedItem",
payload: chatData,
})
const html = await renderTemplate('systems/fvtt-hawkmoon-cyd/templates/post-item.hbs', chatData)
const chatOptions = {
user: game.user.id,
content: html,
}
ChatMessage.create(chatOptions)
}
/**
* Add a predilection
* @param {Event} event The triggering event
* @param {HTMLElement} target The target element
* @private
*/
static async #onAddPredilection(event, target) {
let pred = foundry.utils.duplicate(this.document.system.predilections || [])
pred.push({ name: "Nouvelle prédilection", id: foundry.utils.randomID(16), used: false, acquise: false, maitrise: false, description: "" })
await this.document.update({ 'system.predilections': pred })
}
/**
* Delete a predilection
* @param {Event} event The triggering event
* @param {HTMLElement} target The target element
* @private
*/
static async #onDeletePredilection(event, target) {
const index = parseInt(target.closest("[data-predilection-index]").dataset.predilectionIndex)
let pred = foundry.utils.duplicate(this.document.system.predilections)
pred.splice(index, 1)
await this.document.update({ 'system.predilections': pred })
}
/**
* Add an automation
* @param {Event} event The triggering event
* @param {HTMLElement} target The target element
* @private
*/
static async #onAddAutomation(event, target) {
let autom = foundry.utils.duplicate(this.document.system.automations || [])
autom.push({
eventtype: "on-drop",
name: "Automatisation 1",
bonusname: "vigueur",
bonus: 0,
competence: "",
minLevel: 0,
baCost: 0,
id: foundry.utils.randomID(16)
})
await this.document.update({ 'system.automations': autom })
}
/**
* Delete an automation
* @param {Event} event The triggering event
* @param {HTMLElement} target The target element
* @private
*/
static async #onDeleteAutomation(event, target) {
const index = parseInt(target.closest("[data-automation-index]").dataset.automationIndex)
let autom = foundry.utils.duplicate(this.document.system.automations)
autom.splice(index, 1)
await this.document.update({ 'system.automations': autom })
}
// #endregion
// #region Helper Methods
/**
* Get list of attributs
* @returns {Object}
* @private
*/
#getAttributs() {
return {
"adr": "Adresse",
"pui": "Puissance",
"cla": "Clairvoyance",
"pre": "Présence",
"tre": "Trempe"
}
}
// #endregion
/** @override */
_onChangeForm(formConfig, event) {
// Handle special form changes
const target = event.target
// Handle predilection field changes
if (target.classList.contains('edit-predilection') ||
target.classList.contains('edit-predilection-description') ||
target.classList.contains('predilection-acquise') ||
target.classList.contains('predilection-maitrise') ||
target.classList.contains('predilection-used')) {
const li = target.closest('.prediction-item')
if (li) {
const index = parseInt(li.dataset.predictionIndex)
const field = target.classList.contains('edit-predilection') ? 'name' :
target.classList.contains('edit-predilection-description') ? 'description' :
target.classList.contains('predilection-acquise') ? 'acquise' :
target.classList.contains('predilection-maitrise') ? 'maitrise' : 'used'
let pred = foundry.utils.duplicate(this.document.system.predilections)
if (target.type === 'checkbox') {
pred[index][field] = target.checked
} else {
pred[index][field] = target.value
}
pred[index].id = pred[index].id || foundry.utils.randomID(16)
this.document.update({ 'system.predilections': pred })
return
}
}
// Handle automation field changes
if (target.classList.contains('automation-edit-field')) {
const index = parseInt(target.dataset.automationIndex)
const field = target.dataset.automationField
let auto = foundry.utils.duplicate(this.document.system.automations)
auto[index][field] = target.value
auto[index].id = auto[index].id || foundry.utils.randomID(16)
this.document.update({ 'system.automations': auto })
return
}
super._onChangeForm(formConfig, event)
}
}

View File

@@ -0,0 +1,142 @@
import HawkmoonActorSheet from "./base-actor-sheet.mjs"
const __ALLOWED_ITEM_CELLULE = { talent: 1, ressource: 1, contact: 1, equipement: 1, protection: 1, artefact: 1, arme: 1, monnaie: 1 }
export default class HawkmoonCelluleSheet extends HawkmoonActorSheet {
/** @override */
static DEFAULT_OPTIONS = {
...super.DEFAULT_OPTIONS,
classes: [...super.DEFAULT_OPTIONS.classes],
window: {
...super.DEFAULT_OPTIONS.window,
title: "SHEETS.Actor.cellule",
},
actions: {
...super.DEFAULT_OPTIONS.actions,
editActor: HawkmoonCelluleSheet.#onEditActor,
deleteActor: HawkmoonCelluleSheet.#onDeleteActor,
},
}
/** @override */
static PARTS = {
sheet: {
template: "systems/fvtt-hawkmoon-cyd/templates/cellule-sheet.hbs",
},
}
/** @override */
tabGroups = { primary: "talents" }
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
const actor = this.document
// Add cellule-specific data
context.talents = foundry.utils.duplicate(actor.getTalents() || {})
context.ressources = foundry.utils.duplicate(actor.getRessources ? actor.getRessources() : [])
context.contacts = foundry.utils.duplicate(actor.getContacts ? actor.getContacts() : [])
context.members = this.#getMembers()
context.equipements = foundry.utils.duplicate(actor.getEquipments ? actor.getEquipments() : [])
context.artefacts = foundry.utils.duplicate(actor.getArtefacts ? actor.getArtefacts() : [])
context.armes = foundry.utils.duplicate(actor.getWeapons ? actor.getWeapons() : [])
context.monnaies = foundry.utils.duplicate(actor.getMonnaies ? actor.getMonnaies() : [])
context.protections = foundry.utils.duplicate(actor.getArmors ? actor.getArmors() : [])
context.richesse = actor.computeRichesse ? actor.computeRichesse() : 0
context.valeurEquipement = actor.computeValeurEquipement ? actor.computeValeurEquipement() : 0
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.description || "", { async: true })
return context
}
/**
* Get members of the cellule with full actor data
* @returns {Array}
* @private
*/
#getMembers() {
let membersFull = []
for (let memberId of this.actor.system.members) {
let actor = game.actors.get(memberId)
if (actor) {
membersFull.push({ name: actor.name, id: actor.id, img: actor.img })
}
}
return membersFull
}
/**
* Override _onDropItem to filter allowed item types for cellule
* @override
*/
async _onDropItem(event, data) {
const item = await fromUuid(data.uuid)
// Check if item type is allowed for cellule
if (!__ALLOWED_ITEM_CELLULE[item.type]) {
ui.notifications.warn(`Le type d'item ${item.type} n'est pas autorisé pour une cellule`)
return false
}
return super._onDropItem(event, data)
}
/**
* Override _onDropActor to handle adding members
* @override
*/
async _onDropActor(event, data) {
const droppedActor = await fromUuid(data.uuid)
if (droppedActor.type !== "personnage") {
ui.notifications.warn("Seuls les personnages peuvent être ajoutés à une cellule")
return false
}
// Check if already a member
const isMember = this.actor.system.members.includes(droppedActor.id)
if (isMember) {
ui.notifications.warn("Ce personnage est déjà membre de cette cellule")
return false
}
// Add member ID
const members = [...this.actor.system.members, droppedActor.id]
await this.actor.update({ "system.members": members })
return true
}
// #region Cellule-specific Actions
/**
* Edit an actor (member)
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onEditActor(event, target) {
const li = target.closest(".item")
const actorId = li?.dataset.actorId
if (!actorId) return
const actor = game.actors.get(actorId)
if (actor) actor.sheet.render(true)
}
/**
* Delete an actor (remove member)
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onDeleteActor(event, target) {
const li = target.closest(".item")
const actorId = li?.dataset.actorId
if (actorId) {
const members = this.actor.system.members.filter(id => id !== actorId)
await this.actor.update({ "system.members": members })
}
}
// #endregion
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonCompetenceSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["competence"],
position: {
width: 620,
},
window: {
contentClasses: ["competence-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-competence-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonContactSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["contact"],
position: {
width: 620,
},
window: {
contentClasses: ["contact-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-contact-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,60 @@
import HawkmoonActorSheet from "./base-actor-sheet.mjs"
import { HawkmoonUtility } from "../../hawkmoon-utility.js"
export default class HawkmoonCreatureSheet extends HawkmoonActorSheet {
/** @override */
static DEFAULT_OPTIONS = {
...super.DEFAULT_OPTIONS,
classes: [...super.DEFAULT_OPTIONS.classes],
window: {
...super.DEFAULT_OPTIONS.window,
title: "SHEETS.Actor.creature",
},
}
/** @override */
static PARTS = {
sheet: {
template: "systems/fvtt-hawkmoon-cyd/templates/creature-sheet.hbs",
},
}
/** @override */
tabGroups = { primary: "principal" }
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
const actor = this.document
// Add creature-specific data
context.skills = actor.getSkills ? actor.getSkills() : []
context.armes = foundry.utils.duplicate(actor.getWeapons ? actor.getWeapons() : [])
context.protections = foundry.utils.duplicate(actor.getArmors ? actor.getArmors() : [])
context.combat = actor.getCombatValues ? actor.getCombatValues() : {}
context.equipements = foundry.utils.duplicate(actor.getEquipments ? actor.getEquipments() : [])
context.talents = foundry.utils.duplicate(actor.getTalents ? actor.getTalents() : [])
context.talentsCell = this.#getCelluleTalents()
context.nbCombativite = actor.system.sante?.nbcombativite || 0
context.combativiteList = HawkmoonUtility.getCombativiteList(actor.system.sante?.nbcombativite || 0)
context.initiative = actor.getFlag("world", "last-initiative") || -1
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.description || "", { async: true })
context.enrichedHabitat = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.habitat || "", { async: true })
return context
}
/**
* Get talents from attached cellule
* @private
*/
#getCelluleTalents() {
const celluleId = this.actor.system?.details?.celluleid
if (!celluleId) return []
const cellule = game.actors.get(celluleId)
if (!cellule) return []
return foundry.utils.duplicate(cellule.getTalents?.() || [])
}
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonEquipementSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["equipement"],
position: {
width: 620,
},
window: {
contentClasses: ["equipement-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-equipement-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonHistoriqueSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["historique"],
position: {
width: 620,
},
window: {
contentClasses: ["historique-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-historique-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonMonnaieSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["monnaie"],
position: {
width: 620,
},
window: {
contentClasses: ["monnaie-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-monnaie-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonMutationSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["mutation"],
position: {
width: 620,
},
window: {
contentClasses: ["mutation-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-mutation-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,104 @@
import HawkmoonActorSheet from "./base-actor-sheet.mjs"
import { HawkmoonUtility } from "../../hawkmoon-utility.js"
export default class HawkmoonPersonnageSheet extends HawkmoonActorSheet {
/** @override */
static DEFAULT_OPTIONS = {
...super.DEFAULT_OPTIONS,
classes: [...super.DEFAULT_OPTIONS.classes],
window: {
...super.DEFAULT_OPTIONS.window,
title: "SHEETS.Actor.personnage",
},
actions: {
...super.DEFAULT_OPTIONS.actions,
openCellule: HawkmoonPersonnageSheet.#onOpenCellule,
},
}
/** @override */
static PARTS = {
sheet: {
template: "systems/fvtt-hawkmoon-cyd/templates/actor-sheet.hbs",
},
}
/** @override */
tabGroups = { primary: "principal" }
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
const actor = this.document
// Add personnage-specific data
context.skills = actor.getSkills()
context.armes = foundry.utils.duplicate(actor.getWeapons())
context.monnaies = foundry.utils.duplicate(actor.getMonnaies())
context.protections = foundry.utils.duplicate(actor.getArmors())
context.historiques = foundry.utils.duplicate(actor.getHistoriques() || [])
context.talents = foundry.utils.duplicate(actor.getTalents() || [])
context.mutations = foundry.utils.duplicate(actor.getMutations() || [])
context.talentsCell = this.#getCelluleTalents()
context.celluleId = this.#getCelluleId()
context.profils = foundry.utils.duplicate(actor.getProfils() || [])
context.combat = actor.getCombatValues()
context.equipements = foundry.utils.duplicate(actor.getEquipments())
context.artefacts = foundry.utils.duplicate(actor.getArtefacts())
context.richesse = actor.computeRichesse()
context.coupDevastateur = actor.items.find(it => it.type == "talent" && it.name.toLowerCase() == "coup devastateur" && !it.system.used)
context.valeurEquipement = actor.computeValeurEquipement()
context.nbCombativite = actor.system.sante.nbcombativite
context.combativiteList = HawkmoonUtility.getCombativiteList(actor.system.sante.nbcombativite)
context.initiative = actor.getFlag("world", "last-initiative") || -1
return context
}
/**
* Get talents from cellules this actor is a member of
* @returns {Array}
* @private
*/
#getCelluleTalents() {
let talents = []
for (let cellule of game.actors) {
if (cellule.type == "cellule") {
let found = cellule.system.members.includes(this.actor.id)
if (found) {
talents = talents.concat(cellule.getTalents())
}
}
}
return talents
}
/**
* Get the ID of the cellule this actor is a member of
* @returns {string|null}
* @private
*/
#getCelluleId() {
for (let cellule of game.actors) {
if (cellule.type == "cellule") {
if (cellule.system.members.includes(this.actor.id)) {
return cellule.id
}
}
}
return null
}
/**
* Open cellule sheet
* @param {Event} event
* @param {HTMLElement} target
* @private
*/
static async #onOpenCellule(event, target) {
const celluleId = target.dataset.celluleId
if (!celluleId) return
const cellule = game.actors.get(celluleId)
if (cellule) cellule.sheet.render(true)
}
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonProfilSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["profil"],
position: {
width: 620,
},
window: {
contentClasses: ["profil-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-profil-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonProtectionSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["protection"],
position: {
width: 620,
},
window: {
contentClasses: ["protection-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-protection-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,21 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonRessourceSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["ressource"],
position: {
width: 620,
},
window: {
contentClasses: ["ressource-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-ressource-sheet.hbs",
},
}
}

View File

@@ -0,0 +1,51 @@
import HawkmoonItemSheet from "./base-item-sheet.mjs"
export default class HawkmoonTalentSheet extends HawkmoonItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["talent"],
position: {
width: 620,
},
window: {
contentClasses: ["talent-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-hawkmoon-cyd/templates/item-talent-sheet.hbs",
},
}
/** @override */
tabGroups = {
primary: "description",
}
/**
* Prepare an array of form header tabs.
* @returns {Record<string, Partial<ApplicationTab>>}
*/
#getTabs() {
const tabs = {
details: { id: "details", group: "primary", label: "Détails" },
description: { id: "description", group: "primary", label: "Description" }
}
for (const v of Object.values(tabs)) {
v.active = this.tabGroups[v.group] === v.id
v.cssClass = v.active ? "active" : ""
}
return tabs
}
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.tabs = this.#getTabs()
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
return context
}
}

View File

@@ -1,6 +1,6 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
import { HawkmoonUtility } from "./hawkmoon-utility.js"; import { HawkmoonUtility } from "./hawkmoon-utility.js";
import { HawkmoonRollDialog } from "./hawkmoon-roll-dialog.js"; import { HawkmoonRollDialog } from "./applications/hawkmoon-roll-dialog.mjs";
/* -------------------------------------------- */ /* -------------------------------------------- */
const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10] const __degatsBonus = [-2, -2, -1, -1, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10]
@@ -17,8 +17,8 @@ export class HawkmoonActor extends Actor {
/** /**
* Override the create() function to provide additional SoS functionality. * Override the create() function to provide additional SoS functionality.
* *
* This overrided create() function adds initial items * This overrided create() function adds initial items
* Namely: Basic skills, money, * Namely: Basic skills, money,
* *
* @param {Object} data Barebones actor data which this function adds onto. * @param {Object} data Barebones actor data which this function adds onto.
* @param {Object} options (Unused) Additional options which customize the creation workflow. * @param {Object} options (Unused) Additional options which customize the creation workflow.
@@ -67,6 +67,10 @@ export class HawkmoonActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
prepareArme(arme) { prepareArme(arme) {
if (this.type == "cellule") {
return arme
}
arme = foundry.utils.duplicate(arme) arme = foundry.utils.duplicate(arme)
let combat = this.getCombatValues() let combat = this.getCombatValues()
if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") { if (arme.system.typearme == "contact" || arme.system.typearme == "contactjet") {
@@ -202,6 +206,20 @@ export class HawkmoonActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
getCombatValues() { getCombatValues() {
if (this.type == "cellule") {
return {
initBase: 0,
initTotal: 0,
bonusDegats: 0,
bonusDegatsTotal: 0,
vitesseBase: 0,
vitesseTotal: 0,
defenseBase: 0,
protection: 0,
defenseTotal: 0
}
}
let combat = { let combat = {
initBase: this.system.attributs.adr.value, initBase: this.system.attributs.adr.value,
initTotal: this.system.attributs.adr.value + this.system.combat.initbonus, initTotal: this.system.attributs.adr.value + this.system.combat.initbonus,
@@ -406,7 +424,7 @@ export class HawkmoonActor extends Actor {
if (sante.etat == this.system.sante.nbcombativite) { if (sante.etat == this.system.sante.nbcombativite) {
ChatMessage.create({ content: `<strong>${this.name} est vaincu !</strong>` }) ChatMessage.create({ content: `<strong>${this.name} est vaincu !</strong>` })
} }
this.processCombativite(sante) // Duplicated ! this.processCombativite(sante)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -525,6 +543,23 @@ export class HawkmoonActor extends Actor {
return init || -1 return init || -1
} }
/* -------------------------------------------- */
getBestAttackValue() {
let attackList = this.items.filter(item => (item.type == "arme" || item.type == "talent") && item.system.equipped)
let maxOff = 0
let bestArme
for (let arme of attackList) {
if (arme.type == "arme") {
arme = this.prepareArme(arme)
}
if (arme.system.totalOffensif > maxOff) {
maxOff = arme.system.totalOffensif
bestArme = foundry.utils.duplicate(arme)
}
}
return bestArme
}
/* -------------------------------------------- */ /* -------------------------------------------- */
getBestDefenseValue() { getBestDefenseValue() {
let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped) let defenseList = this.items.filter(item => (item.type == "arme") && item.system.equipped)
@@ -620,8 +655,7 @@ export class HawkmoonActor extends Actor {
let rollData = this.getCommonRollData(attrKey) let rollData = this.getCommonRollData(attrKey)
rollData.multiplier = (isInit) ? 1 : 2 rollData.multiplier = (isInit) ? 1 : 2
rollData.isInit = isInit rollData.isInit = isInit
let rollDialog = await HawkmoonRollDialog.create(this, rollData) await HawkmoonRollDialog.create(this, rollData)
rollDialog.render(true)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -629,22 +663,30 @@ export class HawkmoonActor extends Actor {
let rollData = this.getCommonRollData(attrKey, compId) let rollData = this.getCommonRollData(attrKey, compId)
rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode rollData.multiplier = 1 // Attr multiplier, always 1 in competence mode
console.log("RollDatra", rollData) console.log("RollDatra", rollData)
let rollDialog = await HawkmoonRollDialog.create(this, rollData) await HawkmoonRollDialog.create(this, rollData)
rollDialog.render(true)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollArmeOffensif(armeId) { async rollArmeOffensif(armeId) {
let arme = this.items.get(armeId) let arme = this.items.get(armeId)
if (!arme.system.equipped) {
ui.notifications.warn("Cette arme doit être équipée pour pouvoir attaquer !")
return
}
if (arme.type == "arme") { if (arme.type == "arme") {
arme = this.prepareArme(arme) arme = this.prepareArme(arme)
} }
if (!arme.system.competence) {
ui.notifications.warn("Aucune compétence trouvée pour cette arme !")
return
}
let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id) let rollData = this.getCommonRollData(arme.system.attrKey, arme.system.competence._id)
rollData.arme = arme rollData.arme = arme
rollData.isCombat = true
rollData.isTir = arme.system.isDistance || false
HawkmoonUtility.updateWithTarget(rollData) HawkmoonUtility.updateWithTarget(rollData)
console.log("ARME!", rollData) console.log("ARME!", rollData)
let rollDialog = await HawkmoonRollDialog.create(this, rollData) await HawkmoonRollDialog.create(this, rollData)
rollDialog.render(true)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollAssommer() { async rollAssommer() {
@@ -652,8 +694,7 @@ export class HawkmoonActor extends Actor {
rollData.assomer = true rollData.assomer = true
rollData.conditionsCommunes = true rollData.conditionsCommunes = true
HawkmoonUtility.updateWithTarget(rollData) HawkmoonUtility.updateWithTarget(rollData)
let rollDialog = await HawkmoonRollDialog.create(this, rollData) await HawkmoonRollDialog.create(this, rollData)
rollDialog.render(true)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollCoupBas() { async rollCoupBas() {
@@ -661,8 +702,7 @@ export class HawkmoonActor extends Actor {
rollData.coupBas = true rollData.coupBas = true
rollData.conditionsCommunes = true rollData.conditionsCommunes = true
HawkmoonUtility.updateWithTarget(rollData) HawkmoonUtility.updateWithTarget(rollData)
let rollDialog = await HawkmoonRollDialog.create(this, rollData) await HawkmoonRollDialog.create(this, rollData)
rollDialog.render(true)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollImmobiliser() { async rollImmobiliser() {
@@ -671,8 +711,7 @@ export class HawkmoonActor extends Actor {
rollData.conditionsCommunes = true rollData.conditionsCommunes = true
rollData.cibleconsciente = true rollData.cibleconsciente = true
HawkmoonUtility.updateWithTarget(rollData) HawkmoonUtility.updateWithTarget(rollData)
let rollDialog = await HawkmoonRollDialog.create(this, rollData) await HawkmoonRollDialog.create(this, rollData)
rollDialog.render(true)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollRepousser() { async rollRepousser() {
@@ -681,8 +720,7 @@ export class HawkmoonActor extends Actor {
rollData.conditionsCommunes = true rollData.conditionsCommunes = true
rollData.cibleconsciente = true rollData.cibleconsciente = true
HawkmoonUtility.updateWithTarget(rollData) HawkmoonUtility.updateWithTarget(rollData)
let rollDialog = await HawkmoonRollDialog.create(this, rollData) await HawkmoonRollDialog.create(this, rollData)
rollDialog.render(true)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollDesengager() { async rollDesengager() {
@@ -690,13 +728,16 @@ export class HawkmoonActor extends Actor {
rollData.desengager = true rollData.desengager = true
rollData.conditionsCommunes = true rollData.conditionsCommunes = true
HawkmoonUtility.updateWithTarget(rollData) HawkmoonUtility.updateWithTarget(rollData)
let rollDialog = await HawkmoonRollDialog.create(this, rollData) await HawkmoonRollDialog.create(this, rollData)
rollDialog.render(true)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) { async rollArmeDegats(armeId, targetVigueur = undefined, rollDataInput = undefined) {
let arme = this.items.get(armeId) let arme = this.items.get(armeId)
if (!arme.system.equipped) {
ui.notifications.warn("Cette arme doit être équipée pour pouvoir infliger des dégâts !")
return
}
if (arme.type == "arme") { if (arme.type == "arme") {
arme = this.prepareArme(arme) arme = this.prepareArme(arme)
} }
@@ -747,7 +788,7 @@ export class HawkmoonActor extends Actor {
nbEtatPerdus: nbEtatPerdus nbEtatPerdus: nbEtatPerdus
} }
HawkmoonUtility.createChatWithRollMode(rollData.alias, { HawkmoonUtility.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-hawkmoon-cyd/templates/chat-degats-result.html`, rollData) content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-hawkmoon-cyd/templates/chat-degats-result.hbs`, rollData)
}) })
if (rollDataInput?.defenderTokenId && nbEtatPerdus) { if (rollDataInput?.defenderTokenId && nbEtatPerdus) {

View File

@@ -1,7 +1,7 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
import { HawkmoonUtility } from "./hawkmoon-utility.js"; import { HawkmoonUtility } from "./hawkmoon-utility.js";
import { HawkmoonRollDialog } from "./hawkmoon-roll-dialog.js"; import { HawkmoonRollDialog } from "./applications/hawkmoon-roll-dialog.mjs";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class HawkmoonCommands { export class HawkmoonCommands {
@@ -106,18 +106,17 @@ export class HawkmoonCommands {
static _chatAnswer(msg, content) { static _chatAnswer(msg, content) {
msg.whisper = [game.user.id]; msg.whisper = [game.user.id];
msg.content = content; msg.content = content;
ChatMessage.create(msg); ChatMessage.create(msg);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async poolRoll( msg) { async poolRoll( msg) {
let rollData = HawkmoonUtility.getBasicRollData() let rollData = HawkmoonUtility.getBasicRollData()
rollData.alias = "Dice Pool Roll", rollData.alias = "Dice Pool Roll",
rollData.mode = "generic" rollData.mode = "generic"
rollData.title = `Dice Pool Roll`; rollData.title = `Dice Pool Roll`;
let rollDialog = await HawkmoonRollDialog.create( this, rollData); await HawkmoonRollDialog.create( this, rollData);
rollDialog.render( true );
} }
} }

View File

@@ -3,10 +3,30 @@ export const HAWKMOON_CONFIG = {
optionsDifficulte: [ optionsDifficulte: [
{ key: "0", label: "Aucune/Inconnue" }, { key: "0", label: "Aucune/Inconnue" },
{ key: "5", label: "Facile (5)" }, { key: "5", label: "Facile (5)" },
{ key: "6", label: "(6)" },
{ key: "7", label: "(7)" },
{ key: "8", label: "(8)" },
{ key: "9", label: "(9)" },
{ key: "10", label: "Moyenne (10)" }, { key: "10", label: "Moyenne (10)" },
{ key: "11", label: "(11)" },
{ key: "12", label: "(12)" },
{ key: "13", label: "(13)" },
{ key: "14", label: "(14)" },
{ key: "15", label: "Ardue (15)" }, { key: "15", label: "Ardue (15)" },
{ key: "16", label: "(16)" },
{ key: "17", label: "(17)" },
{ key: "18", label: "(18)" },
{ key: "19", label: "(19)" },
{ key: "20", label: "Hasardeuse (20)" }, { key: "20", label: "Hasardeuse (20)" },
{ key: "21", label: "(21)" },
{ key: "22", label: "(22)" },
{ key: "23", label: "(23)" },
{ key: "24", label: "(24)" },
{ key: "25", label: "Insensée (25)" }, { key: "25", label: "Insensée (25)" },
{ key: "26", label: "(26)" },
{ key: "27", label: "(27)" },
{ key: "28", label: "(28)" },
{ key: "29", label: "(29)" },
{ key: "30", label: "Pure Folie (30)" } { key: "30", label: "Pure Folie (30)" }
], ],
optionsDistanceTir: [ optionsDistanceTir: [
@@ -15,6 +35,12 @@ export const HAWKMOON_CONFIG = {
{ key: "porteelongue", label: "Longue ({protectionDefenseur}+14)" } { key: "porteelongue", label: "Longue ({protectionDefenseur}+14)" }
], ],
optionsBonusMalus: [ optionsBonusMalus: [
{ key: "-10", label: "-10" },
{ key: "-9", label: "-9" },
{ key: "-8", label: "-8" },
{ key: "-7", label: "-7" },
{ key: "-6", label: "-6" },
{ key: "-5", label: "-5" },
{ key: "-4", label: "-4" }, { key: "-4", label: "-4" },
{ key: "-3", label: "-3" }, { key: "-3", label: "-3" },
{ key: "-2", label: "-2" }, { key: "-2", label: "-2" },
@@ -23,7 +49,13 @@ export const HAWKMOON_CONFIG = {
{ key: "1", label: "+1" }, { key: "1", label: "+1" },
{ key: "2", label: "+2" }, { key: "2", label: "+2" },
{ key: "3", label: "+3" }, { key: "3", label: "+3" },
{ key: "4", label: "+4" } { key: "4", label: "+4" },
{ key: "5", label: "+5" },
{ key: "6", label: "+6" },
{ key: "7", label: "+7" },
{ key: "8", label: "+8" },
{ key: "9", label: "+9" },
{ key: "10", label: "+10" }
], ],
optionsTailleCible: [ optionsTailleCible: [
{ key: "normal", label: "Normal (SD+0)" }, { key: "normal", label: "Normal (SD+0)" },

View File

@@ -22,9 +22,9 @@ export class HawkmoonTokenHud {
const hudData = { actor: actor } const hudData = { actor: actor }
const controlIconActions = html.find('.control-icon[data-action=combat]'); const controlIconActions = $(html).find('.control-icon[data-action=combat]');
// initiative // initiative
await HawkmoonTokenHud._configureSubMenu(controlIconActions, 'systems/fvtt-hawkmoon-cyd/templates/hud-adversites.html', hudData, await HawkmoonTokenHud._configureSubMenu(controlIconActions, 'systems/fvtt-hawkmoon-cyd/templates/hud-adversites.hbs', hudData,
(event) => { (event) => {
let adversite = event.currentTarget.attributes['data-action-index'].value let adversite = event.currentTarget.attributes['data-action-index'].value
let value = Number(event.currentTarget.attributes['data-action-value'].value) let value = Number(event.currentTarget.attributes['data-action-value'].value)
@@ -34,7 +34,7 @@ export class HawkmoonTokenHud {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async addTokenHudExtensions(app, html, tokenId) { static async addTokenHudExtensions(app, html, tokenId) {
const controlIconCombat = html.find('.control-icon[data-action=combat]') const controlIconCombat = $(html).find('.control-icon[data-action=combat]')
if (controlIconCombat.length>0 ) { if (controlIconCombat.length>0 ) {
HawkmoonTokenHud.addExtensionHud(app, html, tokenId); HawkmoonTokenHud.addExtensionHud(app, html, tokenId);
} }
@@ -42,11 +42,11 @@ export class HawkmoonTokenHud {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async _configureSubMenu(insertionPoint, template, hudData, onMenuItem) { static async _configureSubMenu(insertionPoint, template, hudData, onMenuItem) {
const hud = $(await renderTemplate(template, hudData)) const hud = $(await foundry.applications.handlebars.renderTemplate(template, hudData))
const list = hud.find('div.hawkmoon-hud-list') const list = hud.find('div.hawkmoon-hud-list')
HawkmoonTokenHud._toggleHudListActive(hud, list); HawkmoonTokenHud._toggleHudListActive(hud, list);
hud.find('img.hawkmoon-hud-togglebutton').click(event => HawkmoonTokenHud._toggleHudListActive(hud, list)); hud.find('img.hawkmoon-hud-togglebutton').click(event => HawkmoonTokenHud._toggleHudListActive(hud, list));
list.find('.hawkmoon-hud-adversite').click(onMenuItem); list.find('.hawkmoon-hud-adversite').click(onMenuItem);

View File

@@ -9,10 +9,7 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
// Import Modules // Import Modules
import { HawkmoonActor } from "./hawkmoon-actor.js"; import { HawkmoonActor } from "./hawkmoon-actor.js";
import { HawkmoonItemSheet } from "./hawkmoon-item-sheet.js";
import { HawkmoonActorSheet } from "./hawkmoon-actor-sheet.js";
import { HawkmoonCreatureSheet } from "./hawkmoon-creature-sheet.js";
import { HawkmoonCelluleSheet } from "./hawkmoon-cellule-sheet.js";
import { HawkmoonUtility } from "./hawkmoon-utility.js"; import { HawkmoonUtility } from "./hawkmoon-utility.js";
import { HawkmoonCombat } from "./hawkmoon-combat.js"; import { HawkmoonCombat } from "./hawkmoon-combat.js";
import { HawkmoonItem } from "./hawkmoon-item.js"; import { HawkmoonItem } from "./hawkmoon-item.js";
@@ -20,6 +17,12 @@ import { HawkmoonAutomation } from "./hawkmoon-automation.js";
import { HawkmoonTokenHud } from "./hawkmoon-hud.js"; import { HawkmoonTokenHud } from "./hawkmoon-hud.js";
import { HAWKMOON_CONFIG } from "./hawkmoon-config.js"; import { HAWKMOON_CONFIG } from "./hawkmoon-config.js";
// Import DataModels
import * as models from "./models/index.mjs";
// Import AppV2 Item Sheets
import * as sheets from "./applications/sheets/_module.mjs";
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -33,7 +36,7 @@ Hooks.once("init", async function () {
HawkmoonUtility.preloadHandlebarsTemplates() HawkmoonUtility.preloadHandlebarsTemplates()
/* -------------------------------------------- */ /* -------------------------------------------- */
// Set an initiative formula for the system // Set an initiative formula for the system
CONFIG.Combat.initiative = { CONFIG.Combat.initiative = {
formula: "1d10", formula: "1d10",
decimals: 1 decimals: 1
@@ -48,22 +51,59 @@ Hooks.once("init", async function () {
// Define custom Entity classes // Define custom Entity classes
CONFIG.Combat.documentClass = HawkmoonCombat CONFIG.Combat.documentClass = HawkmoonCombat
CONFIG.Actor.documentClass = HawkmoonActor CONFIG.Actor.documentClass = HawkmoonActor
CONFIG.Actor.dataModels = {
personnage: models.PersonnageDataModel,
cellule: models.CelluleDataModel,
creature: models.CreatureDataModel
}
CONFIG.Item.documentClass = HawkmoonItem CONFIG.Item.documentClass = HawkmoonItem
CONFIG.Item.dataModels = {
talent: models.TalentDataModel,
historique: models.HistoriqueDataModel,
profil: models.ProfilDataModel,
competence: models.CompetenceDataModel,
arme: models.ArmeDataModel,
protection: models.ProtectionDataModel,
monnaie: models.MonnaieDataModel,
equipement: models.EquipementDataModel,
artefact: models.ArtefactDataModel,
ressource: models.RessourceDataModel,
contact: models.ContactDataModel,
mutation: models.MutationDataModel
}
CONFIG.HAWKMOON = HAWKMOON_CONFIG
game.system.hawkmoon = { game.system.hawkmoon = {
HawkmoonUtility, HawkmoonUtility,
HawkmoonAutomation, HawkmoonAutomation,
config : HAWKMOON_CONFIG config: HAWKMOON_CONFIG,
models,
sheets
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
// Register sheet application classes // Register sheet application classes
Actors.unregisterSheet("core", ActorSheet); foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
Actors.registerSheet("fvtt-hawkmoon-cyd", HawkmoonActorSheet, { types: ["personnage"], makeDefault: true }) foundry.documents.collections.Actors.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonPersonnageSheet, { types: ["personnage"], makeDefault: true })
Actors.registerSheet("fvtt-hawkmoon-cyd", HawkmoonCreatureSheet, { types: ["creature"], makeDefault: true }) foundry.documents.collections.Actors.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonCreatureSheet, { types: ["creature"], makeDefault: true })
Actors.registerSheet("fvtt-hawkmoon-cyd", HawkmoonCelluleSheet, { types: ["cellule"], makeDefault: true }); foundry.documents.collections.Actors.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonCelluleSheet, { types: ["cellule"], makeDefault: true });
Items.unregisterSheet("core", ItemSheet); // Register AppV2 Item Sheets
Items.registerSheet("fvtt-hawkmoon-cyd", HawkmoonItemSheet, { makeDefault: true }) foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonTalentSheet, { types: ["talent"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonCompetenceSheet, { types: ["competence"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonArmeSheet, { types: ["arme"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonProtectionSheet, { types: ["protection"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonHistoriqueSheet, { types: ["historique"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonProfilSheet, { types: ["profil"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonEquipementSheet, { types: ["equipement"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonMonnaieSheet, { types: ["monnaie"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonArtefactSheet, { types: ["artefact"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonRessourceSheet, { types: ["ressource"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonContactSheet, { types: ["contact"], makeDefault: true })
foundry.documents.collections.Items.registerSheet("fvtt-hawkmoon-cyd", sheets.HawkmoonMutationSheet, { types: ["mutation"], makeDefault: true })
HawkmoonUtility.init() HawkmoonUtility.init()
HawkmoonAutomation.init() HawkmoonAutomation.init()
@@ -76,12 +116,39 @@ function welcomeMessage() {
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
whisper: [game.user.id], whisper: [game.user.id],
content: `<div id="welcome-message-Hawkmoon"><span class="rdd-roll-part"> content: `
<strong>Bienvenue dans Hawkmoon et le troisième Millénaire !</strong> <div class="hawkmoon-chat-result">
<p>Les livres de Hawkmoon sont nécessaires pour jouer : https://www.titam-france.fr</p> <div class="chat-result-header">
<p>Hawkmoon est jeu de rôle publié par Titam France/Sombres projets, tout les droits leur appartiennent.</p> <img class="actor-icon" src="systems/fvtt-hawkmoon-cyd/assets/logos/hawkmoon_logo.webp" alt="Hawkmoon" />
<p>Système développé par LeRatierBretonnien, support sur le <a href="https://discord.gg/pPSDNJk">Discord FR de Foundry</a>.</p> <div class="header-info">
` }); <h4 class="actor-name">Bienvenue dans Hawkmoon !</h4>
<div class="action-title">
<i class="fas fa-book-open"></i>
Le Troisième Millénaire
</div>
</div>
</div>
<div class="result-details">
<div class="details-section">
<h5 class="section-title"><i class="fas fa-info-circle"></i> Informations importantes</h5>
<div class="description-content">
<p><strong>Les livres de Hawkmoon sont nécessaires pour jouer.</strong></p>
<p>Hawkmoon est un jeu de rôle publié par <strong>Titam France / Sombres projets</strong>, tous les droits leur appartiennent.</p>
</div>
</div>
<div class="details-section">
<h5 class="section-title"><i class="fas fa-users"></i> Support & Communauté</h5>
<div class="description-content">
<p>Système développé par <strong>LeRatierBretonnien</strong></p>
<p>Support disponible sur le <a href="https://discord.gg/pPSDNJk" target="_blank" style="color: #d4af37; text-decoration: underline;">Discord FR de Foundry VTT</a></p>
</div>
</div>
</div>
</div>
`
});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -92,7 +159,7 @@ async function importDefaultScene() {
let newDocuments = scenes.filter(i => i.name == "Accueil"); let newDocuments = scenes.filter(i => i.name == "Accueil");
if (newDocuments) { if (newDocuments) {
await game.scenes.documentClass.create(newDocuments); await game.scenes.documentClass.create(newDocuments);
game.scenes.find(i => i.name == "Accueil").activate(); game.scenes.find(i => i.name == "Accueil").activate();
} }
} }
} }
@@ -113,13 +180,13 @@ Hooks.once("ready", function () {
}); });
} }
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter=>{ import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => {
console.log("ClassCounter loaded", moduleCounter) console.log("ClassCounter loaded", moduleCounter)
moduleCounter.ClassCounter.registerUsageCount() moduleCounter.ClassCounter.registerUsageCount()
}).catch(err=> }).catch(err =>
console.log("No stats available, giving up.") console.log("No stats available, giving up.")
) )
importDefaultScene() importDefaultScene()
welcomeMessage() welcomeMessage()
@@ -138,4 +205,3 @@ Hooks.on("chatMessage", (html, content, msg) => {
} }
return true; return true;
}); });

View File

@@ -3,10 +3,10 @@ import { HawkmoonCombat } from "./hawkmoon-combat.js";
import { HawkmoonCommands } from "./hawkmoon-commands.js"; import { HawkmoonCommands } from "./hawkmoon-commands.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const __distanceDifficulte = { "porteecourte": 5, "porteemoyenne": 9, "porteelongue": 14} const __distanceDifficulte = { "porteecourte": 5, "porteemoyenne": 9, "porteelongue": 14 }
const __tireurDeplacement = { immobile: 0, lent: 3, rapide: 5} const __tireurDeplacement = { immobile: 0, lent: 3, rapide: 5 }
const __cibleCouvert = { aucun: 0, leger: 5, complet: 10} const __cibleCouvert = { aucun: 0, leger: 5, complet: 10 }
const __tailleCible = { normal: 0, main: 10, enfant: 3, maison: -10} const __tailleCible = { normal: 0, main: 10, enfant: 3, maison: -10 }
/* -------------------------------------------- */ /* -------------------------------------------- */
export class HawkmoonUtility { export class HawkmoonUtility {
@@ -15,8 +15,7 @@ export class HawkmoonUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async init() { static async init() {
Hooks.on('renderChatLog', (log, html, data) => HawkmoonUtility.chatListeners(html)) Hooks.on('renderChatLog', (log, html, data) => HawkmoonUtility.chatListeners(html))
Hooks.on("getChatLogEntryContext", (html, options) => HawkmoonUtility.chatRollMenu(html, options)) Hooks.on("getChatMessageContextOptions", (html, options) => HawkmoonUtility.chatRollMenu(html, options))
Hooks.on("getCombatTrackerEntryContext", (html, options) => { Hooks.on("getCombatTrackerEntryContext", (html, options) => {
HawkmoonUtility.pushInitiativeOptions(html, options); HawkmoonUtility.pushInitiativeOptions(html, options);
}) })
@@ -105,15 +104,33 @@ export class HawkmoonUtility {
return this.skills return this.skills
} }
/* -------------------------------------------- */
static updatePauseLogo(html) {
let logoPause = "systems/fvtt-hawkmoon-cyd/assets/logos/" + game.settings.get("fvtt-hawkmoon-cyd", "hawkmoon-pause-logo") + ".webp"
console.log("Hawkmoon | Updating pause logo to:", logoPause)
// Supprimer l'ancien style s'il existe
let oldStyle = document.getElementById('hawkmoon-pause-logo-override')
if (oldStyle) {
oldStyle.remove()
}
// Injecter une règle CSS pour override le logo
let styleSheet = document.createElement('style')
styleSheet.id = 'hawkmoon-pause-logo-override'
styleSheet.textContent = `#pause>img { content: url(${logoPause}) !important; }`
document.head.appendChild(styleSheet)
console.log("Hawkmoon | Logo CSS rule injected")
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async ready() { static async ready() {
const skills = await HawkmoonUtility.loadCompendium("fvtt-hawkmoon-cyd.skills") const skills = await HawkmoonUtility.loadCompendium("fvtt-hawkmoon-cyd.skills")
this.skills = skills.map(i => i.toObject()) this.skills = skills.map(i => i.toObject())
// Setup pause logo // Setup pause logo
let logoPause = "systems/fvtt-hawkmoon-cyd/assets/logos/" + game.settings.get("fvtt-hawkmoon-cyd", "hawkmoon-pause-logo") + ".webp" this.updatePauseLogo()
let logoImg = document.querySelector('#pause').children[0]
logoImg.setAttribute('style', `content: url(${logoPause})`)
game.system.hawkmoon.config.listeNiveauSkill = this.createDirectOptionList(0, 10) game.system.hawkmoon.config.listeNiveauSkill = this.createDirectOptionList(0, 10)
game.system.hawkmoon.config.listeNiveauCreature = this.createDirectOptionList(0, 35) game.system.hawkmoon.config.listeNiveauCreature = this.createDirectOptionList(0, 35)
@@ -131,7 +148,7 @@ export class HawkmoonUtility {
static createArrayOptionList(min, max) { static createArrayOptionList(min, max) {
let options = []; let options = [];
for (let i = min; i <= max; i++) { for (let i = min; i <= max; i++) {
options.push({key:`${i}`, label:`${i}`}); options.push({ key: `${i}`, label: `${i}` });
} }
return options; return options;
} }
@@ -155,7 +172,7 @@ export class HawkmoonUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async chatListeners(html) { static async chatListeners(html) {
html.on("click", '.predilection-reroll', async event => { $(html).on("click", '.predilection-reroll', async event => {
let predIdx = $(event.currentTarget).data("predilection-index") let predIdx = $(event.currentTarget).data("predilection-index")
let messageId = HawkmoonUtility.findChatMessageId(event.currentTarget) let messageId = HawkmoonUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId) let message = game.messages.get(messageId)
@@ -166,14 +183,14 @@ export class HawkmoonUtility {
HawkmoonUtility.rollHawkmoon(rollData) HawkmoonUtility.rollHawkmoon(rollData)
}) })
html.on("click", '.roll-chat-degat', async event => { $(html).on("click", '.roll-chat-degat', async event => {
let messageId = HawkmoonUtility.findChatMessageId(event.currentTarget) let messageId = HawkmoonUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId) let message = game.messages.get(messageId)
let rollData = message.getFlag("world", "hawkmoon-roll") let rollData = message.getFlag("world", "hawkmoon-roll")
let actor = HawkmoonUtility.getActorFromRollData(rollData) let actor = HawkmoonUtility.getActorFromRollData(rollData)
actor.rollArmeDegats(rollData.arme._id, rollData.targetVigueur, rollData) actor.rollArmeDegats(rollData.arme._id, rollData.targetVigueur, rollData)
}) })
html.on("click", '.roll-chat-degat-devastateur', async event => { $(html).on("click", '.roll-chat-degat-devastateur', async event => {
let messageId = HawkmoonUtility.findChatMessageId(event.currentTarget) let messageId = HawkmoonUtility.findChatMessageId(event.currentTarget)
let message = game.messages.get(messageId) let message = game.messages.get(messageId)
let rollData = message.getFlag("world", "hawkmoon-roll") let rollData = message.getFlag("world", "hawkmoon-roll")
@@ -181,22 +198,22 @@ export class HawkmoonUtility {
rollData.applyCoupDevastateur = true rollData.applyCoupDevastateur = true
actor.rollArmeDegats(rollData.arme._id, rollData.targetVigueur, rollData) actor.rollArmeDegats(rollData.arme._id, rollData.targetVigueur, rollData)
}) })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async preloadHandlebarsTemplates() { static async preloadHandlebarsTemplates() {
const templatePaths = [ const templatePaths = [
'systems/fvtt-hawkmoon-cyd/templates/editor-notes-gm.html', 'systems/fvtt-hawkmoon-cyd/templates/editor-notes-gm.hbs',
'systems/fvtt-hawkmoon-cyd/templates/partial-item-header.html', 'systems/fvtt-hawkmoon-cyd/templates/partial-item-header.hbs',
'systems/fvtt-hawkmoon-cyd/templates/partial-item-description.html', 'systems/fvtt-hawkmoon-cyd/templates/partial-item-description.hbs',
'systems/fvtt-hawkmoon-cyd/templates/partial-item-nav.html', 'systems/fvtt-hawkmoon-cyd/templates/partial-item-nav.hbs',
'systems/fvtt-hawkmoon-cyd/templates/partial-item-prix.html', 'systems/fvtt-hawkmoon-cyd/templates/partial-item-prix.hbs',
'systems/fvtt-hawkmoon-cyd/templates/partial-automation.html', 'systems/fvtt-hawkmoon-cyd/templates/partial-automation.hbs',
'systems/fvtt-hawkmoon-cyd/templates/hud-adversites.html', 'systems/fvtt-hawkmoon-cyd/templates/hud-adversites.hbs',
] ]
return loadTemplates(templatePaths); return foundry.applications.handlebars.loadTemplates(templatePaths);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -248,11 +265,14 @@ export class HawkmoonUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getTarget() { static getTarget() {
if (game.user.targets && game.user.targets.size == 1) { console.log("getTarget - targets size:", game.user.targets?.size)
if (game.user.targets && game.user.targets.size >= 1) {
for (let target of game.user.targets) { for (let target of game.user.targets) {
return target; console.log("getTarget - Returning target:", target.id)
return target; // Prendre la première cible si plusieurs
} }
} }
console.log("getTarget - No target found")
return undefined; return undefined;
} }
@@ -279,9 +299,13 @@ export class HawkmoonUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static onSocketMesssage(msg) { static onSocketMesssage(msg) {
if (msg.name == "msg_apply_combativite") { if (msg.msg == "msg_apply_combativite") {
let defender = game.canvas.tokens.get(rollData.defenderTokenId).actor let defender = game.canvas.tokens.get(msg.data.defenderTokenId)?.actor
defender.changeEtatCombativite(msg.data.value) if (defender) {
defender.changeEtatCombativite(msg.data.value)
} else {
console.warn("HawkmoonUtility.onSocketMesssage : Impossible de trouver le token pour appliquer la combativité", msg.defenderTokenId)
}
} }
} }
@@ -355,17 +379,22 @@ export class HawkmoonUtility {
} }
} }
//console.log("Result : ", rollData) //console.log("Result : ", rollData
this.computeResultQuality(rollData)
}
/* -------------------------------------------- */
static computeResultQuality(rollData) {
if (rollData.difficulte > 0 && !rollData.isDramatique) { if (rollData.difficulte > 0 && !rollData.isDramatique) {
rollData.isSuccess = (rollData.finalResult >= rollData.difficulte) rollData.isSuccess = (rollData.finalResult >= rollData.difficulte)
rollData.isHeroique = ((rollData.finalResult - rollData.difficulte) >= 10) rollData.isHeroique = ((rollData.finalResult - rollData.difficulte) >= 10)
rollData.isDramatique = ((rollData.finalResult - rollData.difficulte) <= -10) rollData.isDramatique = ((rollData.finalResult - rollData.difficulte) <= -10)
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static applyCombativite(rollData, value) { static applyCombativite(rollData, value) {
if (game.user.isGM) { if (game.user.isGM) {
let defender = game.canvas.tokens.get(rollData.defenderTokenId).actor let defender = game.canvas.tokens.get(rollData.defenderTokenId).actor
defender.changeEtatCombativite(value) defender.changeEtatCombativite(value)
} else { } else {
@@ -399,7 +428,7 @@ export class HawkmoonUtility {
rollData.predilections = foundry.utils.duplicate(rollData.competence.system.predilections || []) rollData.predilections = foundry.utils.duplicate(rollData.competence.system.predilections || [])
let compmod = (rollData.competence.system.niveau == 0) ? -3 : 0 let compmod = (rollData.competence.system.niveau == 0) ? -3 : 0
rollData.diceFormula += `+${rollData.attr.value}+${rollData.competence.system.niveau}+${rollData.modificateur}+${compmod}` rollData.diceFormula += `+${rollData.attr.value}+${rollData.competence.system.niveau}+${rollData.modificateur}+${compmod}`
if (rollData.selectedTalents && rollData.selectedTalents.length > 0) { if (rollData.selectedTalents && rollData.selectedTalents.length > 0) {
for (let id of rollData.selectedTalents) { for (let id of rollData.selectedTalents) {
let talent = rollData.talents.find(t => t._id == id) let talent = rollData.talents.find(t => t._id == id)
@@ -417,13 +446,12 @@ export class HawkmoonUtility {
} }
} }
} }
rollData.diceFormula += `+${rollData.bonusMalusContext}`
} else if (rollData.attr2) { } else if (rollData.attr2) {
rollData.diceFormula += `+${rollData.attr.value}+${rollData.attr2.value}+${rollData.modificateur}+${rollData.bonusMalusContext}` rollData.diceFormula += `+${rollData.attr.value}+${rollData.attr2.value}+${rollData.modificateur}`
} else { } else {
rollData.diceFormula += `+${rollData.attr.value}*${rollData.multiplier}+${rollData.modificateur}+${rollData.bonusMalusContext}` rollData.diceFormula += `+${rollData.attr.value}*${rollData.multiplier}+${rollData.modificateur}`
} }
// Bonus arme naturelle en défense // Bonus arme naturelle en défense
if (rollData.bonusArmeNaturelle) { if (rollData.bonusArmeNaturelle) {
rollData.diceFormula += `+${rollData.bonusArmeNaturelle}` rollData.diceFormula += `+${rollData.bonusArmeNaturelle}`
@@ -432,10 +460,10 @@ export class HawkmoonUtility {
rollData.diceFormula += `+3` rollData.diceFormula += `+3`
} }
if (rollData.hasAmbidextre) { if (rollData.hasAmbidextre) {
if ( rollData.attaqueAmbidextre1) { if (rollData.ambidextre1) {
rollData.diceFormula += `-3` rollData.diceFormula += `-3`
} else if ( rollData.attaqueAmbidextre2) { } else if (rollData.ambidextre2) {
rollData.diceFormula += `-5` rollData.diceFormula += `-6`
} }
} }
if (rollData.defenseurAuSol) { if (rollData.defenseurAuSol) {
@@ -454,7 +482,7 @@ export class HawkmoonUtility {
rollData.diceFormula += `+5` rollData.diceFormula += `+5`
} }
if (rollData.soutiens > 0) { // 1 soutien = +3, 2 soutiens = +4, 3 soutiens = +5 if (rollData.soutiens > 0) { // 1 soutien = +3, 2 soutiens = +4, 3 soutiens = +5
rollData.diceFormula += `+${rollData.soutiens+2}` rollData.diceFormula += `+${rollData.soutiens + 2}`
} }
if (rollData.arme?.system.isDistance) { if (rollData.arme?.system.isDistance) {
@@ -469,16 +497,16 @@ export class HawkmoonUtility {
if (rollData.attaqueDesarme) { if (rollData.attaqueDesarme) {
rollData.difficulte += 10 rollData.difficulte += 10
} }
// Ajout adversités // Ajout adversités
rollData.diceFormula += `-${rollData.nbAdversites}` rollData.diceFormula += `-${rollData.nbAdversites}`
if (rollData.arme && rollData.arme.type == "arme") { if (rollData.arme && rollData.arme.type == "arme") {
rollData.diceFormula += `+${rollData.arme.system.bonusmaniementoff}` rollData.diceFormula += `+${rollData.arme.system.bonusmaniementoff}`
} }
// Gestion de la feinte éventuelle // Gestion de la feinte éventuelle
rollData.nbCombativitePerdu = 1 rollData.nbCombativitePerdu = 1
let myRoll = await new Roll(rollData.diceFormula).roll() let myRoll = await new Roll(rollData.diceFormula).roll()
await this.showDiceSoNice(myRoll, game.settings.get("core", "rollMode")) await this.showDiceSoNice(myRoll, game.settings.get("core", "rollMode"))
@@ -492,18 +520,18 @@ export class HawkmoonUtility {
} }
if (rollData.feinte) { if (rollData.feinte) {
actor.changeBonneAventure(-1) actor.changeBonneAventure(-1)
if ( rollData.isHeroique) { if (rollData.isHeroique) {
rollData.nbCombativitePerdu = "vaincu" rollData.nbCombativitePerdu = "vaincu"
} else if ( rollData.isSuccess) { } else if (rollData.isSuccess) {
rollData.nbCombativitePerdu = 2 rollData.nbCombativitePerdu = 2
} }
} }
this.createChatWithRollMode(rollData.alias, { this.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-hawkmoon-cyd/templates/chat-generic-result.html`, rollData) content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-hawkmoon-cyd/templates/chat-generic-result.hbs`, rollData)
}, rollData) }, rollData)
if ( (rollData.coupBas || rollData.arme) && rollData.isSuccess && rollData.defenderTokenId) { if ((rollData.coupBas || rollData.arme) && rollData.isSuccess && rollData.defenderTokenId) {
this.applyCombativite(rollData, rollData.nbCombativitePerdu) this.applyCombativite(rollData, rollData.nbCombativitePerdu)
} }
if (rollData.coupBas && rollData.isSuccess && rollData.defenderTokenId) { if (rollData.coupBas && rollData.isSuccess && rollData.defenderTokenId) {
@@ -514,30 +542,35 @@ export class HawkmoonUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getCombativiteList(nbActivite) { static getCombativiteList(nbActivite) {
let list = [ { value: String(0), label: "Combatif"}] let list = [{ value: String(0), label: "Combatif" }]
for (let i = 1; i < nbActivite-2; i++) { for (let i = 1; i < nbActivite - 2; i++) {
list.push({ value: String(i), label:"Eprouvé " + i} ) list.push({ value: String(i), label: "Eprouvé " + i })
} }
list[nbActivite-2] = { value: String(nbActivite-2), label:"Affaibli"} list[nbActivite - 2] = { value: String(nbActivite - 2), label: "Affaibli" }
list[nbActivite-1] = { value: String(nbActivite-1), label:"Très Affaibli"} list[nbActivite - 1] = { value: String(nbActivite - 1), label: "Très Affaibli" }
list[nbActivite] = { value: String(nbActivite), label:"Vaincu"} list[nbActivite] = { value: String(nbActivite), label: "Vaincu" }
return list return list
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async bonusRollHawkmoon(rollData) { static async bonusRollHawkmoon(rollData) {
rollData.bonusFormula = rollData.addedBonus rollData.bonusFormula = rollData.addedBonus
console.log("Bonus Roll Hawkmoon", rollData.bonusFormula)
let bonusRoll = await new Roll(rollData.bonusFormula).roll() if (!Number(rollData.bonusFormula)) {
await this.showDiceSoNice(bonusRoll, game.settings.get("core", "rollMode")); let bonusRoll = await new Roll(rollData.bonusFormula).roll()
rollData.bonusRoll = foundry.utils.duplicate(bonusRoll) await this.showDiceSoNice(bonusRoll, game.settings.get("core", "rollMode"));
rollData.bonusRoll = foundry.utils.duplicate(bonusRoll)
rollData.finalResult += Number(rollData.bonusRoll.total)
} else {
rollData.finalResult += Number(rollData.bonusFormula)
console.log("Bonus Roll Hawkmoon 2", rollData.finalResult)
}
rollData.finalResult += rollData.bonusRoll.total this.computeResultQuality(rollData)
this.computeResult(rollData)
this.createChatWithRollMode(rollData.alias, { this.createChatWithRollMode(rollData.alias, {
content: await renderTemplate(`systems/fvtt-hawkmoon-cyd/templates/chat-generic-result.html`, rollData) content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-hawkmoon-cyd/templates/chat-generic-result.hbs`, rollData)
}, rollData) }, rollData)
} }
@@ -620,9 +653,13 @@ export class HawkmoonUtility {
break; break;
} }
chatOptions.alias = chatOptions.alias || name chatOptions.alias = chatOptions.alias || name
// Ajouter le flag directement dans les options pour éviter les problèmes de timing
if (rollData) {
chatOptions.flags = { world: { "hawkmoon-roll": rollData } }
}
let msg = await ChatMessage.create(chatOptions) let msg = await ChatMessage.create(chatOptions)
console.log("=======>", rollData)
msg.setFlag("world", "hawkmoon-roll", rollData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -633,8 +670,7 @@ export class HawkmoonUtility {
modificateursOptions: this.getModificateurOptions(), modificateursOptions: this.getModificateurOptions(),
pointAmeOptions: this.getPointAmeOptions(), pointAmeOptions: this.getPointAmeOptions(),
difficulte: 0, difficulte: 0,
modificateur: 0, modificateur: "0",
bonusMalusContext: 0,
bonusArmeNaturelle: 0, bonusArmeNaturelle: 0,
defenseurAveugle: false, defenseurAveugle: false,
defenseurDeDos: false, defenseurDeDos: false,
@@ -645,13 +681,15 @@ export class HawkmoonUtility {
tireurDeplacement: "immobile", tireurDeplacement: "immobile",
cibleCouvert: "aucun", cibleCouvert: "aucun",
distanceTir: "porteemoyenne", distanceTir: "porteemoyenne",
cibleDeplace: false,
cibleCaC: false,
attaqueCharge: false, attaqueCharge: false,
attaqueDesarme: false, attaqueDesarme: false,
attaqueAmbidextre1 : false, attaqueAmbidextre1: false,
attaqueAmbidextre2 : false, attaqueAmbidextre2: false,
chargeCavalerie : false, chargeCavalerie: false,
contenir : false, contenir: false,
soutiens : 0 soutiens: 0
} }
return rollData return rollData
} }
@@ -659,10 +697,19 @@ export class HawkmoonUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static updateWithTarget(rollData) { static updateWithTarget(rollData) {
let target = HawkmoonUtility.getTarget() let target = HawkmoonUtility.getTarget()
console.log("updateWithTarget - Current target:", target)
console.log("updateWithTarget - Existing defenderTokenId:", rollData.defenderTokenId)
if (target) { if (target) {
rollData.defenderTokenId = target.id rollData.defenderTokenId = target.id
console.log("updateWithTarget - Set defenderTokenId to:", rollData.defenderTokenId)
}
// Utiliser la cible déjà enregistrée si aucune cible n'est actuellement sélectionnée
if (rollData.defenderTokenId) {
let defender = game.canvas.tokens.get(rollData.defenderTokenId).actor let defender = game.canvas.tokens.get(rollData.defenderTokenId).actor
console.log("updateWithTarget - Defender actor:", defender.name)
rollData.armeDefense = defender.getBestDefenseValue() rollData.armeDefense = defender.getBestDefenseValue()
console.log("updateWithTarget - armeDefense:", rollData.armeDefense)
rollData.armeAttaqueDefenseur = defender.getBestAttackValue()
rollData.targetVigueur = defender.getVigueur() rollData.targetVigueur = defender.getVigueur()
rollData.protectionDefenseur = defender.getProtection() rollData.protectionDefenseur = defender.getProtection()
if (rollData.immobiliser || rollData.repousser) { if (rollData.immobiliser || rollData.repousser) {
@@ -671,18 +718,29 @@ export class HawkmoonUtility {
} else if (rollData.coupBas) { } else if (rollData.coupBas) {
let combatValues = defender.getCombatValues() let combatValues = defender.getCombatValues()
rollData.difficulte = combatValues.defenseTotal rollData.difficulte = combatValues.defenseTotal
}else if ( rollData.assomer) { } else if (rollData.assomer) {
rollData.difficulte = 3 + (defender.system.attributs.tre.value * 2) rollData.difficulte = 3 + (defender.system.attributs.tre.value * 2)
} else if (rollData.desengager) {
rollData.difficulte = rollData.armeAttaqueDefenseur?.system?.totalOffensif || 0;
} else if (rollData.armeDefense) { } else if (rollData.armeDefense) {
rollData.difficulte = rollData.armeDefense.system.totalDefensif rollData.difficulte = rollData.armeDefense.system.totalDefensif
if ( !rollData.desengager && !rollData.arme.system.armenaturelle && !rollData.arme.system.armefortune ){ console.log("updateWithTarget - Calculated difficulte from armeDefense:", rollData.difficulte)
if (rollData.arme && !rollData.desengager && !rollData.arme.system.armenaturelle && !rollData.arme.system.armefortune) {
if (rollData.armeDefense.system.armenaturelle || rollData.armeDefense.system.armefortune) { if (rollData.armeDefense.system.armenaturelle || rollData.armeDefense.system.armefortune) {
rollData.bonusArmeNaturelle = 3 rollData.bonusArmeNaturelle = 3
} }
} }
} else if (rollData.arme?.system.isDistance) {
// Pour les armes à distance, calculer la difficulté de base (protection + distance par défaut)
const distanceValues = { "porteecourte": 5, "porteemoyenne": 9, "porteelongue": 14 }
rollData.difficulte = rollData.protectionDefenseur + distanceValues[rollData.distanceTir || "porteemoyenne"]
console.log("updateWithTarget - Calculated difficulte for ranged:", rollData.difficulte, "= protection", rollData.protectionDefenseur, "+ distance", distanceValues[rollData.distanceTir || "porteemoyenne"])
} else { } else {
console.log("updateWithTarget - No armeDefense found!")
ui.notifications.warn("Aucune arme de défense équipée, difficulté manuelle à positionner.") ui.notifications.warn("Aucune arme de défense équipée, difficulté manuelle à positionner.")
} }
} else {
console.log("updateWithTarget - No defenderTokenId, skipping target calculations")
} }
} }
@@ -693,7 +751,7 @@ export class HawkmoonUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static applyBonneAventureRoll(li, changed, addedBonus) { static applyBonneAventureRoll(li, changed, addedBonus) {
let msgId = li.data("message-id") let msgId = $(li).data("message-id")
let msg = game.messages.get(msgId) let msg = game.messages.get(msgId)
if (msg) { if (msg) {
let rollData = msg.getFlag("world", "hawkmoon-roll") let rollData = msg.getFlag("world", "hawkmoon-roll")
@@ -712,7 +770,7 @@ export class HawkmoonUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static applyEclatRoll(li, changed, addedBonus) { static applyEclatRoll(li, changed, addedBonus) {
let msgId = li.data("message-id") let msgId = $(li).data("message-id")
let msg = game.messages.get(msgId) let msg = game.messages.get(msgId)
if (msg) { if (msg) {
let rollData = msg.getFlag("world", "hawkmoon-roll") let rollData = msg.getFlag("world", "hawkmoon-roll")
@@ -733,13 +791,13 @@ export class HawkmoonUtility {
static chatRollMenu(html, options) { static chatRollMenu(html, options) {
let canApply = li => canvas.tokens.controlled.length && li.find(".hawkmoon-roll").length let canApply = li => canvas.tokens.controlled.length && li.find(".hawkmoon-roll").length
let canApplyBA = function (li) { let canApplyBA = function (li) {
let message = game.messages.get(li.attr("data-message-id")) let message = game.messages.get($(li).attr("data-message-id"))
let rollData = message.getFlag("world", "hawkmoon-roll") let rollData = message.getFlag("world", "hawkmoon-roll")
let actor = HawkmoonUtility.getActorFromRollData(rollData) let actor = HawkmoonUtility.getActorFromRollData(rollData)
return (!rollData.isReroll && actor.getBonneAventure() > 0) return (!rollData.isReroll && actor.getBonneAventure() > 0)
} }
let canApplyPE = function (li) { let canApplyPE = function (li) {
let message = game.messages.get(li.attr("data-message-id")) let message = game.messages.get($(li).attr("data-message-id"))
let rollData = message.getFlag("world", "hawkmoon-roll") let rollData = message.getFlag("world", "hawkmoon-roll")
let actor = HawkmoonUtility.getActorFromRollData(rollData) let actor = HawkmoonUtility.getActorFromRollData(rollData)
return (!rollData.isReroll && actor.getEclat() > 0) return (!rollData.isReroll && actor.getEclat() > 0)
@@ -765,7 +823,7 @@ export class HawkmoonUtility {
name: "Relancer le dé (1 point d'Eclat)", name: "Relancer le dé (1 point d'Eclat)",
icon: "<i class='fas fa-user-plus'></i>", icon: "<i class='fas fa-user-plus'></i>",
condition: canApply && canApplyPE, condition: canApply && canApplyPE,
callback: li => HawkmoonUtility.applyEclatRoll(li, -3, "reroll") callback: li => HawkmoonUtility.applyEclatRoll(li, -1, "reroll")
} }
) )
return options return options
@@ -773,7 +831,7 @@ export class HawkmoonUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async confirmDelete(actorSheet, li) { static async confirmDelete(actorSheet, li) {
let itemId = li.data("item-id"); let itemId = li.dataset.itemId;
let msgTxt = "<p>Etes vous certain de vouloir supprimer cet item ?"; let msgTxt = "<p>Etes vous certain de vouloir supprimer cet item ?";
let buttons = { let buttons = {
delete: { delete: {
@@ -781,7 +839,7 @@ export class HawkmoonUtility {
label: "Oui !", label: "Oui !",
callback: () => { callback: () => {
actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]); actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]);
li.slideUp(200, () => actorSheet.render(false)); actorSheet.render(false);
} }
}, },
cancel: { cancel: {

31
modules/models/arme.mjs Normal file
View File

@@ -0,0 +1,31 @@
/**
* Data model pour les armes
*/
export default class ArmeDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
prixpo: new fields.NumberField({ initial: 0, integer: true }),
prixca: new fields.NumberField({ initial: 0, integer: true }),
prixsc: new fields.NumberField({ initial: 0, integer: true }),
rarete: new fields.NumberField({ initial: 0, integer: true }),
quantite: new fields.NumberField({ initial: 1, integer: true }),
equipped: new fields.BooleanField({ initial: false }),
typearme: new fields.StringField({ initial: "" }),
armenaturelle: new fields.BooleanField({ initial: false }),
armefortune: new fields.BooleanField({ initial: false }),
bonusmaniementoff: new fields.NumberField({ initial: 0, integer: true }),
seuildefense: new fields.NumberField({ initial: 0, integer: true }),
onlevelonly: new fields.BooleanField({ initial: false }),
degats: new fields.StringField({ initial: "" }),
deuxmains: new fields.BooleanField({ initial: false }),
percearmure: new fields.BooleanField({ initial: false }),
percearmurevalue: new fields.NumberField({ initial: 0, integer: true }),
courte: new fields.NumberField({ initial: 0, integer: true }),
moyenne: new fields.NumberField({ initial: 0, integer: true }),
longue: new fields.NumberField({ initial: 0, integer: true }),
tr: new fields.NumberField({ initial: 0, integer: true })
};
}
}

View File

@@ -0,0 +1,28 @@
/**
* Data model pour les artefacts
*/
export default class ArtefactDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
prixpo: new fields.NumberField({ initial: 0, integer: true }),
prixca: new fields.NumberField({ initial: 0, integer: true }),
prixsc: new fields.NumberField({ initial: 0, integer: true }),
rarete: new fields.NumberField({ initial: 0, integer: true }),
quantite: new fields.NumberField({ initial: 1, integer: true }),
equipped: new fields.BooleanField({ initial: false }),
complexite: new fields.NumberField({ initial: 0, integer: true }),
branche: new fields.StringField({ initial: "" }),
branche2: new fields.StringField({ initial: "none" }),
dureerealisation: new fields.StringField({ initial: "" }),
tempsroute: new fields.StringField({ initial: "" }),
effetdejeu: new fields.StringField({ initial: "" }),
defautcourant: new fields.StringField({ initial: "" }),
autrescarac: new fields.StringField({ initial: "" }),
avantagespossibles: new fields.StringField({ initial: "" }),
avantages: new fields.StringField({ initial: "" }),
competences: new fields.StringField({ initial: "" })
};
}
}

View File

@@ -0,0 +1,53 @@
/**
* Template de base pour tous les items
*/
export class BaseItemModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" })
};
}
}
/**
* Template pour les équipements de base
*/
export class BaseEquipItemModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
prixpo: new fields.NumberField({ initial: 0, integer: true }),
prixca: new fields.NumberField({ initial: 0, integer: true }),
prixsc: new fields.NumberField({ initial: 0, integer: true }),
rarete: new fields.NumberField({ initial: 0, integer: true }),
quantite: new fields.NumberField({ initial: 1, integer: true }),
equipped: new fields.BooleanField({ initial: false })
};
}
}
/**
* Template pour l'automatisation
*/
export class AutomationItemModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
isautomated: new fields.BooleanField({ initial: false }),
automations: new fields.ArrayField(
new fields.SchemaField({
id: new fields.StringField({ initial: "" }),
eventtype: new fields.StringField({ initial: "on-drop" }),
name: new fields.StringField({ initial: "" }),
bonusname: new fields.StringField({ initial: "vigueur" }),
bonus: new fields.NumberField({ initial: 0, integer: true }),
competence: new fields.StringField({ initial: "" }),
minLevel: new fields.NumberField({ initial: 0, integer: true }),
baCost: new fields.NumberField({ initial: 0, integer: true })
}),
{ initial: [] }
)
};
}
}

View File

@@ -0,0 +1,15 @@
/**
* Data model pour les cellules
*/
export default class CelluleDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
notoriete: new fields.NumberField({ initial: 0, integer: true }),
resistance: new fields.NumberField({ initial: 0, integer: true }),
developpement: new fields.NumberField({ initial: 0, integer: true }),
members: new fields.ArrayField(new fields.StringField(), { initial: [] }),
description: new fields.HTMLField({ initial: "" })
};
}
}

View File

@@ -0,0 +1,27 @@
/**
* Data model pour les compétences
*/
export default class CompetenceDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
niveau: new fields.NumberField({ initial: 0, integer: true }),
attribut1: new fields.StringField({ initial: "" }),
attribut2: new fields.StringField({ initial: "" }),
attribut3: new fields.StringField({ initial: "" }),
doublebonus: new fields.BooleanField({ initial: false }),
predilections: new fields.ArrayField(
new fields.SchemaField({
id: new fields.StringField({ initial: "" }),
name: new fields.StringField({ initial: "" }),
description: new fields.StringField({ initial: "" }),
acquise: new fields.BooleanField({ initial: false }),
maitrise: new fields.BooleanField({ initial: false }),
used: new fields.BooleanField({ initial: false })
}),
{ initial: [] }
)
};
}
}

View File

@@ -0,0 +1,14 @@
/**
* Data model pour les contacts
*/
export default class ContactDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
contacttype: new fields.StringField({ initial: "" }),
niveau: new fields.StringField({ initial: "" }),
pointdev: new fields.NumberField({ initial: 0, integer: true }),
description: new fields.HTMLField({ initial: "" })
};
}
}

View File

@@ -0,0 +1,97 @@
/**
* Data model pour les créatures
*/
export default class CreatureDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
// Template biodata
biodata: new fields.SchemaField({
name: new fields.StringField({ initial: "" }),
age: new fields.NumberField({ initial: 0, integer: true }),
poids: new fields.StringField({ initial: "" }),
taille: new fields.StringField({ initial: "" }),
cheveux: new fields.StringField({ initial: "" }),
sexe: new fields.StringField({ initial: "" }),
yeux: new fields.StringField({ initial: "" }),
description: new fields.HTMLField({ initial: "" }),
habitat: new fields.HTMLField({ initial: "" }),
notes: new fields.HTMLField({ initial: "" }),
statut: new fields.StringField({ initial: "" }),
gmnotes: new fields.HTMLField({ initial: "" }),
statutresistant: new fields.StringField({ initial: "commun" })
}),
// Template core
subactors: new fields.ArrayField(new fields.StringField(), { initial: [] }),
attributs: new fields.SchemaField({
adr: new fields.SchemaField({
label: new fields.StringField({ initial: "Adresse" }),
labelnorm: new fields.StringField({ initial: "adresse" }),
abbrev: new fields.StringField({ initial: "adr" }),
value: new fields.NumberField({ initial: 1, integer: true })
}),
pui: new fields.SchemaField({
label: new fields.StringField({ initial: "Puissance" }),
labelnorm: new fields.StringField({ initial: "puissance" }),
abbrev: new fields.StringField({ initial: "pui" }),
value: new fields.NumberField({ initial: 1, integer: true })
}),
cla: new fields.SchemaField({
label: new fields.StringField({ initial: "Clairvoyance" }),
labelnorm: new fields.StringField({ initial: "clairvoyance" }),
abbrev: new fields.StringField({ initial: "cla" }),
value: new fields.NumberField({ initial: 1, integer: true })
}),
pre: new fields.SchemaField({
label: new fields.StringField({ initial: "Présence" }),
labelnorm: new fields.StringField({ initial: "presence" }),
abbrev: new fields.StringField({ initial: "pre" }),
value: new fields.NumberField({ initial: 0, integer: true })
}),
tre: new fields.SchemaField({
label: new fields.StringField({ initial: "Trempe" }),
labelnorm: new fields.StringField({ initial: "trempe" }),
abbrev: new fields.StringField({ initial: "tre" }),
value: new fields.NumberField({ initial: 0, integer: true })
})
}),
bonneaventure: new fields.SchemaField({
base: new fields.NumberField({ initial: 0, integer: true }),
actuelle: new fields.NumberField({ initial: 0, integer: true })
}),
experience: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true })
}),
eclat: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true })
}),
sante: new fields.SchemaField({
vigueur: new fields.NumberField({ initial: 0, integer: true }),
etat: new fields.NumberField({ initial: 0, integer: true }),
vigueurmodifier: new fields.NumberField({ initial: 0, integer: true }),
nbcombativite: new fields.NumberField({ initial: 5, integer: true })
}),
adversite: new fields.SchemaField({
bleue: new fields.NumberField({ initial: 0, integer: true }),
rouge: new fields.NumberField({ initial: 0, integer: true }),
noire: new fields.NumberField({ initial: 0, integer: true })
}),
vitesse: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true })
}),
combat: new fields.SchemaField({
initbonus: new fields.NumberField({ initial: 0, integer: true }),
vitessebonus: new fields.NumberField({ initial: 0, integer: true }),
bonusdegats: new fields.NumberField({ initial: 0, integer: true }),
attaquebonus: new fields.NumberField({ initial: 0, integer: true }),
defensebonus: new fields.NumberField({ initial: 0, integer: true }),
defensetotale: new fields.BooleanField({ initial: false }),
monte: new fields.BooleanField({ initial: false })
}),
// Propriétés spécifiques aux créatures
ressources: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true })
})
};
}
}

View File

@@ -0,0 +1,17 @@
/**
* Data model pour l'équipement
*/
export default class EquipementDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
prixpo: new fields.NumberField({ initial: 0, integer: true }),
prixca: new fields.NumberField({ initial: 0, integer: true }),
prixsc: new fields.NumberField({ initial: 0, integer: true }),
rarete: new fields.NumberField({ initial: 0, integer: true }),
quantite: new fields.NumberField({ initial: 1, integer: true }),
equipped: new fields.BooleanField({ initial: false })
};
}
}

View File

@@ -0,0 +1,12 @@
/**
* Data model pour les historiques
*/
export default class HistoriqueDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
bonusmalus: new fields.StringField({ initial: "" })
};
}
}

23
modules/models/index.mjs Normal file
View File

@@ -0,0 +1,23 @@
/**
* Index des DataModels pour Hawkmoon CYD
* Ce fichier centralise tous les exports des modèles de données
*/
// Modèles d'items
export { default as TalentDataModel } from './talent.mjs';
export { default as HistoriqueDataModel } from './historique.mjs';
export { default as ProfilDataModel } from './profil.mjs';
export { default as CompetenceDataModel } from './competence.mjs';
export { default as ArmeDataModel } from './arme.mjs';
export { default as ProtectionDataModel } from './protection.mjs';
export { default as MonnaieDataModel } from './monnaie.mjs';
export { default as EquipementDataModel } from './equipement.mjs';
export { default as ArtefactDataModel } from './artefact.mjs';
export { default as RessourceDataModel } from './ressource.mjs';
export { default as ContactDataModel } from './contact.mjs';
export { default as MutationDataModel } from './mutation.mjs';
// Modèles d'acteurs
export { default as PersonnageDataModel } from './personnage.mjs';
export { default as CelluleDataModel } from './cellule.mjs';
export { default as CreatureDataModel } from './creature.mjs';

View File

@@ -0,0 +1,17 @@
/**
* Data model pour les monnaies
*/
export default class MonnaieDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
prixpo: new fields.NumberField({ initial: 0, integer: true }),
prixca: new fields.NumberField({ initial: 0, integer: true }),
prixsc: new fields.NumberField({ initial: 0, integer: true }),
rarete: new fields.NumberField({ initial: 0, integer: true }),
quantite: new fields.NumberField({ initial: 1, integer: true }),
equipped: new fields.BooleanField({ initial: false })
};
}
}

View File

@@ -0,0 +1,14 @@
/**
* Data model pour les mutations
*/
export default class MutationDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
mutationcategorie: new fields.StringField({ initial: "tares_communes" }),
hascomplexite: new fields.BooleanField({ initial: false }),
complexite: new fields.NumberField({ initial: 0, integer: true })
};
}
}

View File

@@ -0,0 +1,93 @@
/**
* Data model pour les personnages
*/
export default class PersonnageDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
// Template biodata
biodata: new fields.SchemaField({
name: new fields.StringField({ initial: "" }),
age: new fields.NumberField({ initial: 0, integer: true }),
poids: new fields.StringField({ initial: "" }),
taille: new fields.StringField({ initial: "" }),
cheveux: new fields.StringField({ initial: "" }),
sexe: new fields.StringField({ initial: "" }),
yeux: new fields.StringField({ initial: "" }),
description: new fields.HTMLField({ initial: "" }),
habitat: new fields.HTMLField({ initial: "" }),
notes: new fields.HTMLField({ initial: "" }),
statut: new fields.StringField({ initial: "" }),
gmnotes: new fields.HTMLField({ initial: "" }),
statutresistant: new fields.StringField({ initial: "commun" })
}),
// Template core
subactors: new fields.ArrayField(new fields.StringField(), { initial: [] }),
attributs: new fields.SchemaField({
adr: new fields.SchemaField({
label: new fields.StringField({ initial: "Adresse" }),
labelnorm: new fields.StringField({ initial: "adresse" }),
abbrev: new fields.StringField({ initial: "adr" }),
value: new fields.NumberField({ initial: 1, integer: true })
}),
pui: new fields.SchemaField({
label: new fields.StringField({ initial: "Puissance" }),
labelnorm: new fields.StringField({ initial: "puissance" }),
abbrev: new fields.StringField({ initial: "pui" }),
value: new fields.NumberField({ initial: 1, integer: true })
}),
cla: new fields.SchemaField({
label: new fields.StringField({ initial: "Clairvoyance" }),
labelnorm: new fields.StringField({ initial: "clairvoyance" }),
abbrev: new fields.StringField({ initial: "cla" }),
value: new fields.NumberField({ initial: 1, integer: true })
}),
pre: new fields.SchemaField({
label: new fields.StringField({ initial: "Présence" }),
labelnorm: new fields.StringField({ initial: "presence" }),
abbrev: new fields.StringField({ initial: "pre" }),
value: new fields.NumberField({ initial: 0, integer: true })
}),
tre: new fields.SchemaField({
label: new fields.StringField({ initial: "Trempe" }),
labelnorm: new fields.StringField({ initial: "trempe" }),
abbrev: new fields.StringField({ initial: "tre" }),
value: new fields.NumberField({ initial: 0, integer: true })
})
}),
bonneaventure: new fields.SchemaField({
base: new fields.NumberField({ initial: 0, integer: true }),
actuelle: new fields.NumberField({ initial: 0, integer: true })
}),
experience: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true })
}),
eclat: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true })
}),
sante: new fields.SchemaField({
vigueur: new fields.NumberField({ initial: 0, integer: true }),
etat: new fields.NumberField({ initial: 0, integer: true }),
vigueurmodifier: new fields.NumberField({ initial: 0, integer: true }),
nbcombativite: new fields.NumberField({ initial: 5, integer: true })
}),
adversite: new fields.SchemaField({
bleue: new fields.NumberField({ initial: 0, integer: true }),
rouge: new fields.NumberField({ initial: 0, integer: true }),
noire: new fields.NumberField({ initial: 0, integer: true })
}),
vitesse: new fields.SchemaField({
value: new fields.NumberField({ initial: 0, integer: true })
}),
combat: new fields.SchemaField({
initbonus: new fields.NumberField({ initial: 0, integer: true }),
vitessebonus: new fields.NumberField({ initial: 0, integer: true }),
bonusdegats: new fields.NumberField({ initial: 0, integer: true }),
attaquebonus: new fields.NumberField({ initial: 0, integer: true }),
defensebonus: new fields.NumberField({ initial: 0, integer: true }),
defensetotale: new fields.BooleanField({ initial: false }),
monte: new fields.BooleanField({ initial: false })
})
};
}
}

23
modules/models/profil.mjs Normal file
View File

@@ -0,0 +1,23 @@
/**
* Data model pour les profils
*/
export default class ProfilDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
exemples: new fields.StringField({ initial: "" }),
attribut1: new fields.StringField({ initial: "" }),
attribut2: new fields.StringField({ initial: "" }),
attribut3: new fields.StringField({ initial: "" }),
competences: new fields.StringField({ initial: "" }),
talentsinitie: new fields.StringField({ initial: "" }),
prerequisaguerri: new fields.StringField({ initial: "" }),
talentsaguerri: new fields.StringField({ initial: "" }),
prerequismaitre: new fields.StringField({ initial: "" }),
talentsmaitre: new fields.StringField({ initial: "" }),
celluleinfo: new fields.StringField({ initial: "" }),
equipement: new fields.StringField({ initial: "" })
};
}
}

View File

@@ -0,0 +1,19 @@
/**
* Data model pour les protections
*/
export default class ProtectionDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
prixpo: new fields.NumberField({ initial: 0, integer: true }),
prixca: new fields.NumberField({ initial: 0, integer: true }),
prixsc: new fields.NumberField({ initial: 0, integer: true }),
rarete: new fields.NumberField({ initial: 0, integer: true }),
quantite: new fields.NumberField({ initial: 1, integer: true }),
equipped: new fields.BooleanField({ initial: false }),
protection: new fields.NumberField({ initial: 0, integer: true }),
adversitepoids: new fields.NumberField({ initial: 0, integer: true })
};
}
}

View File

@@ -0,0 +1,12 @@
/**
* Data model pour les ressources
*/
export default class RessourceDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
pointdev: new fields.NumberField({ initial: 0, integer: true }),
description: new fields.HTMLField({ initial: "" })
};
}
}

30
modules/models/talent.mjs Normal file
View File

@@ -0,0 +1,30 @@
/**
* Data model pour les talents
*/
export default class TalentDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
description: new fields.HTMLField({ initial: "" }),
isautomated: new fields.BooleanField({ initial: false }),
automations: new fields.ArrayField(
new fields.SchemaField({
id: new fields.StringField({ initial: "" }),
eventtype: new fields.StringField({ initial: "on-drop" }),
name: new fields.StringField({ initial: "" }),
bonusname: new fields.StringField({ initial: "vigueur" }),
bonus: new fields.NumberField({ initial: 0, integer: true }),
competence: new fields.StringField({ initial: "" }),
minLevel: new fields.NumberField({ initial: 0, integer: true }),
baCost: new fields.NumberField({ initial: 0, integer: true })
}),
{ initial: [] }
),
talenttype: new fields.StringField({ initial: "" }),
utilisation: new fields.StringField({ initial: "" }),
prerequis: new fields.StringField({ initial: "" }),
resumebonus: new fields.StringField({ initial: "" }),
used: new fields.BooleanField({ initial: false })
};
}
}

View File

@@ -1 +1 @@
MANIFEST-000213 MANIFEST-000377

View File

@@ -1,8 +1,8 @@
2024/06/01-08:52:45.194842 7f28a4c006c0 Recovering log #211 2026/01/09-17:40:07.997473 7f1c563fe6c0 Recovering log #375
2024/06/01-08:52:45.205284 7f28a4c006c0 Delete type=3 #209 2026/01/09-17:40:08.091717 7f1c563fe6c0 Delete type=0 #375
2024/06/01-08:52:45.205352 7f28a4c006c0 Delete type=0 #211 2026/01/09-17:40:08.091792 7f1c563fe6c0 Delete type=3 #373
2024/06/01-09:10:33.808591 7f289f8006c0 Level-0 table #216: started 2026/01/09-17:44:28.072757 7f1c54bfb6c0 Level-0 table #380: started
2024/06/01-09:10:33.808615 7f289f8006c0 Level-0 table #216: 0 bytes OK 2026/01/09-17:44:28.072827 7f1c54bfb6c0 Level-0 table #380: 0 bytes OK
2024/06/01-09:10:33.814886 7f289f8006c0 Delete type=0 #214 2026/01/09-17:44:28.079432 7f1c54bfb6c0 Delete type=0 #378
2024/06/01-09:10:33.815181 7f289f8006c0 Manual compaction at level-0 from '!journal!MUbViCE2PkVxlzqe' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) 2026/01/09-17:44:28.105106 7f1c54bfb6c0 Manual compaction at level-0 from '!journal!MUbViCE2PkVxlzqe' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end)
2024/06/01-09:10:33.815226 7f289f8006c0 Manual compaction at level-1 from '!journal!MUbViCE2PkVxlzqe' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) 2026/01/09-17:44:28.117150 7f1c54bfb6c0 Manual compaction at level-1 from '!journal!MUbViCE2PkVxlzqe' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,8 @@
2024/05/31-23:16:45.991898 7f18090006c0 Recovering log #207 2026/01/08-08:15:08.713116 7f93ea7fc6c0 Recovering log #371
2024/05/31-23:16:46.046753 7f18090006c0 Delete type=3 #205 2026/01/08-08:15:08.722804 7f93ea7fc6c0 Delete type=3 #369
2024/05/31-23:16:46.046809 7f18090006c0 Delete type=0 #207 2026/01/08-08:15:08.722873 7f93ea7fc6c0 Delete type=0 #371
2024/05/31-23:25:37.384266 7f18020006c0 Level-0 table #212: started 2026/01/08-08:28:05.068912 7f93e9ffb6c0 Level-0 table #376: started
2024/05/31-23:25:37.384313 7f18020006c0 Level-0 table #212: 0 bytes OK 2026/01/08-08:28:05.068957 7f93e9ffb6c0 Level-0 table #376: 0 bytes OK
2024/05/31-23:25:37.390630 7f18020006c0 Delete type=0 #210 2026/01/08-08:28:05.106033 7f93e9ffb6c0 Delete type=0 #374
2024/05/31-23:25:37.403867 7f18020006c0 Manual compaction at level-0 from '!journal!MUbViCE2PkVxlzqe' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) 2026/01/08-08:28:05.217659 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!MUbViCE2PkVxlzqe' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end)
2024/05/31-23:25:37.403898 7f18020006c0 Manual compaction at level-1 from '!journal!MUbViCE2PkVxlzqe' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end) 2026/01/08-08:28:05.217719 7f93e9ffb6c0 Manual compaction at level-1 from '!journal!MUbViCE2PkVxlzqe' @ 72057594037927935 : 1 .. '!journal.pages!gVybbv17TFY8o3Y4.fQidyqfF1TbsZKHM' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
packs/armes/000275.ldb Normal file

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000213 MANIFEST-000376

View File

@@ -1,8 +1,8 @@
2024/06/01-08:52:45.038253 7f28a56006c0 Recovering log #211 2026/01/09-17:40:07.215100 7f1c563fe6c0 Recovering log #374
2024/06/01-08:52:45.049363 7f28a56006c0 Delete type=3 #209 2026/01/09-17:40:07.308808 7f1c563fe6c0 Delete type=0 #374
2024/06/01-08:52:45.049432 7f28a56006c0 Delete type=0 #211 2026/01/09-17:40:07.308890 7f1c563fe6c0 Delete type=3 #372
2024/06/01-09:10:33.725130 7f289f8006c0 Level-0 table #216: started 2026/01/09-17:44:28.036990 7f1c54bfb6c0 Level-0 table #379: started
2024/06/01-09:10:33.725172 7f289f8006c0 Level-0 table #216: 0 bytes OK 2026/01/09-17:44:28.037073 7f1c54bfb6c0 Level-0 table #379: 0 bytes OK
2024/06/01-09:10:33.731955 7f289f8006c0 Delete type=0 #214 2026/01/09-17:44:28.043547 7f1c54bfb6c0 Delete type=0 #377
2024/06/01-09:10:33.753233 7f289f8006c0 Manual compaction at level-0 from '!items!0fit7HelSjaFtXcW' @ 72057594037927935 : 1 .. '!items!wxrzP3NyiHiYnAMJ' @ 0 : 0; will stop at (end) 2026/01/09-17:44:28.043784 7f1c54bfb6c0 Manual compaction at level-0 from '!items!0fit7HelSjaFtXcW' @ 72057594037927935 : 1 .. '!items!wxrzP3NyiHiYnAMJ' @ 0 : 0; will stop at (end)
2024/06/01-09:10:33.753281 7f289f8006c0 Manual compaction at level-1 from '!items!0fit7HelSjaFtXcW' @ 72057594037927935 : 1 .. '!items!wxrzP3NyiHiYnAMJ' @ 0 : 0; will stop at (end) 2026/01/09-17:44:28.043823 7f1c54bfb6c0 Manual compaction at level-1 from '!items!0fit7HelSjaFtXcW' @ 72057594037927935 : 1 .. '!items!wxrzP3NyiHiYnAMJ' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,8 @@
2024/05/31-23:16:45.511332 7f1803e006c0 Recovering log #207 2026/01/08-08:15:08.609938 7f93eaffd6c0 Recovering log #370
2024/05/31-23:16:45.571770 7f1803e006c0 Delete type=3 #205 2026/01/08-08:15:08.619765 7f93eaffd6c0 Delete type=3 #368
2024/05/31-23:16:45.571914 7f1803e006c0 Delete type=0 #207 2026/01/08-08:15:08.619830 7f93eaffd6c0 Delete type=0 #370
2024/05/31-23:25:37.338949 7f18020006c0 Level-0 table #212: started 2026/01/08-08:28:04.844266 7f93e9ffb6c0 Level-0 table #375: started
2024/05/31-23:25:37.338972 7f18020006c0 Level-0 table #212: 0 bytes OK 2026/01/08-08:28:04.844294 7f93e9ffb6c0 Level-0 table #375: 0 bytes OK
2024/05/31-23:25:37.345723 7f18020006c0 Delete type=0 #210 2026/01/08-08:28:04.883113 7f93e9ffb6c0 Delete type=0 #373
2024/05/31-23:25:37.358156 7f18020006c0 Manual compaction at level-0 from '!items!0fit7HelSjaFtXcW' @ 72057594037927935 : 1 .. '!items!wxrzP3NyiHiYnAMJ' @ 0 : 0; will stop at (end) 2026/01/08-08:28:04.919770 7f93e9ffb6c0 Manual compaction at level-0 from '!items!0fit7HelSjaFtXcW' @ 72057594037927935 : 1 .. '!items!wxrzP3NyiHiYnAMJ' @ 0 : 0; will stop at (end)
2024/05/31-23:25:37.358188 7f18020006c0 Manual compaction at level-1 from '!items!0fit7HelSjaFtXcW' @ 72057594037927935 : 1 .. '!items!wxrzP3NyiHiYnAMJ' @ 0 : 0; will stop at (end) 2026/01/08-08:28:04.919798 7f93e9ffb6c0 Manual compaction at level-1 from '!items!0fit7HelSjaFtXcW' @ 72057594037927935 : 1 .. '!items!wxrzP3NyiHiYnAMJ' @ 0 : 0; will stop at (end)

Binary file not shown.

BIN
packs/armes/MANIFEST-000376 Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000213 MANIFEST-000376

View File

@@ -1,8 +1,8 @@
2024/06/01-08:52:45.010642 7f28a56006c0 Recovering log #211 2026/01/09-17:40:07.033899 7f1c55bfd6c0 Recovering log #374
2024/06/01-08:52:45.021246 7f28a56006c0 Delete type=3 #209 2026/01/09-17:40:07.115529 7f1c55bfd6c0 Delete type=0 #374
2024/06/01-08:52:45.021304 7f28a56006c0 Delete type=0 #211 2026/01/09-17:40:07.115669 7f1c55bfd6c0 Delete type=3 #372
2024/06/01-09:10:33.739501 7f289f8006c0 Level-0 table #216: started 2026/01/09-17:44:28.002424 7f1c54bfb6c0 Level-0 table #379: started
2024/06/01-09:10:33.739525 7f289f8006c0 Level-0 table #216: 0 bytes OK 2026/01/09-17:44:28.002453 7f1c54bfb6c0 Level-0 table #379: 0 bytes OK
2024/06/01-09:10:33.745719 7f289f8006c0 Delete type=0 #214 2026/01/09-17:44:28.008591 7f1c54bfb6c0 Delete type=0 #377
2024/06/01-09:10:33.753252 7f289f8006c0 Manual compaction at level-0 from '!items!0nhTxujlIUB63Aqt' @ 72057594037927935 : 1 .. '!items!tFU5yISK6spdNWco' @ 0 : 0; will stop at (end) 2026/01/09-17:44:28.016607 7f1c54bfb6c0 Manual compaction at level-0 from '!items!0nhTxujlIUB63Aqt' @ 72057594037927935 : 1 .. '!items!tFU5yISK6spdNWco' @ 0 : 0; will stop at (end)
2024/06/01-09:10:33.753274 7f289f8006c0 Manual compaction at level-1 from '!items!0nhTxujlIUB63Aqt' @ 72057594037927935 : 1 .. '!items!tFU5yISK6spdNWco' @ 0 : 0; will stop at (end) 2026/01/09-17:44:28.016651 7f1c54bfb6c0 Manual compaction at level-1 from '!items!0nhTxujlIUB63Aqt' @ 72057594037927935 : 1 .. '!items!tFU5yISK6spdNWco' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,8 @@
2024/05/31-23:16:45.399504 7f1803e006c0 Recovering log #207 2026/01/08-08:15:08.584392 7f93eb7fe6c0 Recovering log #370
2024/05/31-23:16:45.453251 7f1803e006c0 Delete type=3 #205 2026/01/08-08:15:08.595037 7f93eb7fe6c0 Delete type=3 #368
2024/05/31-23:16:45.453307 7f1803e006c0 Delete type=0 #207 2026/01/08-08:15:08.595129 7f93eb7fe6c0 Delete type=0 #370
2024/05/31-23:25:37.324970 7f18020006c0 Level-0 table #212: started 2026/01/08-08:28:04.658126 7f93e9ffb6c0 Level-0 table #375: started
2024/05/31-23:25:37.324998 7f18020006c0 Level-0 table #212: 0 bytes OK 2026/01/08-08:28:04.658154 7f93e9ffb6c0 Level-0 table #375: 0 bytes OK
2024/05/31-23:25:37.332256 7f18020006c0 Delete type=0 #210 2026/01/08-08:28:04.696322 7f93e9ffb6c0 Delete type=0 #373
2024/05/31-23:25:37.332486 7f18020006c0 Manual compaction at level-0 from '!items!0nhTxujlIUB63Aqt' @ 72057594037927935 : 1 .. '!items!tFU5yISK6spdNWco' @ 0 : 0; will stop at (end) 2026/01/08-08:28:04.770719 7f93e9ffb6c0 Manual compaction at level-0 from '!items!0nhTxujlIUB63Aqt' @ 72057594037927935 : 1 .. '!items!tFU5yISK6spdNWco' @ 0 : 0; will stop at (end)
2024/05/31-23:25:37.332520 7f18020006c0 Manual compaction at level-1 from '!items!0nhTxujlIUB63Aqt' @ 72057594037927935 : 1 .. '!items!tFU5yISK6spdNWco' @ 0 : 0; will stop at (end) 2026/01/08-08:28:04.770775 7f93e9ffb6c0 Manual compaction at level-1 from '!items!0nhTxujlIUB63Aqt' @ 72057594037927935 : 1 .. '!items!tFU5yISK6spdNWco' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
MANIFEST-000213 MANIFEST-000376

View File

@@ -1,8 +1,8 @@
2024/06/01-08:52:44.981269 7f28a56006c0 Recovering log #211 2026/01/09-17:40:06.860640 7f1c553fc6c0 Recovering log #374
2024/06/01-08:52:44.991052 7f28a56006c0 Delete type=3 #209 2026/01/09-17:40:06.945970 7f1c553fc6c0 Delete type=0 #374
2024/06/01-08:52:44.991117 7f28a56006c0 Delete type=0 #211 2026/01/09-17:40:06.946049 7f1c553fc6c0 Delete type=3 #372
2024/06/01-09:10:33.708570 7f289f8006c0 Level-0 table #216: started 2026/01/09-17:44:27.995662 7f1c54bfb6c0 Level-0 table #379: started
2024/06/01-09:10:33.708600 7f289f8006c0 Level-0 table #216: 0 bytes OK 2026/01/09-17:44:27.995696 7f1c54bfb6c0 Level-0 table #379: 0 bytes OK
2024/06/01-09:10:33.714914 7f289f8006c0 Delete type=0 #214 2026/01/09-17:44:28.002283 7f1c54bfb6c0 Delete type=0 #377
2024/06/01-09:10:33.724977 7f289f8006c0 Manual compaction at level-0 from '!items!15IDGG6JoZnRCQtY' @ 72057594037927935 : 1 .. '!items!yI1zY5k8mAdx9wHK' @ 0 : 0; will stop at (end) 2026/01/09-17:44:28.016595 7f1c54bfb6c0 Manual compaction at level-0 from '!items!15IDGG6JoZnRCQtY' @ 72057594037927935 : 1 .. '!items!yI1zY5k8mAdx9wHK' @ 0 : 0; will stop at (end)
2024/06/01-09:10:33.725013 7f289f8006c0 Manual compaction at level-1 from '!items!15IDGG6JoZnRCQtY' @ 72057594037927935 : 1 .. '!items!yI1zY5k8mAdx9wHK' @ 0 : 0; will stop at (end) 2026/01/09-17:44:28.016641 7f1c54bfb6c0 Manual compaction at level-1 from '!items!15IDGG6JoZnRCQtY' @ 72057594037927935 : 1 .. '!items!yI1zY5k8mAdx9wHK' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,8 @@
2024/05/31-23:16:45.284662 7f1803e006c0 Recovering log #207 2026/01/08-08:15:08.560342 7f93eaffd6c0 Recovering log #370
2024/05/31-23:16:45.346436 7f1803e006c0 Delete type=3 #205 2026/01/08-08:15:08.570307 7f93eaffd6c0 Delete type=3 #368
2024/05/31-23:16:45.346487 7f1803e006c0 Delete type=0 #207 2026/01/08-08:15:08.570398 7f93eaffd6c0 Delete type=0 #370
2024/05/31-23:25:37.311914 7f18020006c0 Level-0 table #212: started 2026/01/08-08:28:04.883258 7f93e9ffb6c0 Level-0 table #375: started
2024/05/31-23:25:37.311964 7f18020006c0 Level-0 table #212: 0 bytes OK 2026/01/08-08:28:04.883283 7f93e9ffb6c0 Level-0 table #375: 0 bytes OK
2024/05/31-23:25:37.318352 7f18020006c0 Delete type=0 #210 2026/01/08-08:28:04.919585 7f93e9ffb6c0 Delete type=0 #373
2024/05/31-23:25:37.324962 7f18020006c0 Manual compaction at level-0 from '!items!15IDGG6JoZnRCQtY' @ 72057594037927935 : 1 .. '!items!yI1zY5k8mAdx9wHK' @ 0 : 0; will stop at (end) 2026/01/08-08:28:04.919781 7f93e9ffb6c0 Manual compaction at level-0 from '!items!15IDGG6JoZnRCQtY' @ 72057594037927935 : 1 .. '!items!yI1zY5k8mAdx9wHK' @ 0 : 0; will stop at (end)
2024/05/31-23:25:37.332453 7f18020006c0 Manual compaction at level-1 from '!items!15IDGG6JoZnRCQtY' @ 72057594037927935 : 1 .. '!items!yI1zY5k8mAdx9wHK' @ 0 : 0; will stop at (end) 2026/01/08-08:28:04.919805 7f93e9ffb6c0 Manual compaction at level-1 from '!items!15IDGG6JoZnRCQtY' @ 72057594037927935 : 1 .. '!items!yI1zY5k8mAdx9wHK' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
packs/equipement/000275.ldb Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More