Ajour lancer de sort

This commit is contained in:
sladecraven 2020-07-23 22:09:40 +02:00
parent 47b2a55bea
commit 2cb51e7999
10 changed files with 116 additions and 28 deletions

View File

@ -159,7 +159,7 @@ export class RdDActorSheet extends ActorSheet {
// Roll spell
html.find('.sort-label a').click((event) => {
let sortID = event.currentTarget.attributes['data-id'].value;
this.actor.rollSort( sortID);
this.actor.displayTMR( sortID);
});
// On carac change

View File

@ -88,13 +88,11 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async performRoll( rollData ) {
let myroll = new Roll("d100");
myroll.roll();
let result = new Roll("d100").roll().total;
let quality = "Echec";
let xpmsg = "";
let tache = 0;
//console.log(">>> ROLL", rollData.selectedCarac.label, rollData.rollTarget.score, myroll.total );
let result = myroll.total;
if (result <= rollData.rollTarget.part) {
quality = "Réussite Particulière!";
if ( rollData.finalLevel < 0 ) {
@ -195,9 +193,15 @@ export class RdDActor extends Actor {
await this.setFlag( "foundryvtt-reve-de-dragon", "rollData", undefined );
await this.setFlag( "foundryvtt-reve-de-dragon", "rollData", rollData );
let lvl = (rollData.competence) ? rollData.competence.name : rollData.bmValue;
let lvl = ""
if ( rollData.selectedSort) {
lvl = rollData.selectedDraconic.name +"/"+ rollData.selectedSort.name;
specialStr = "";
} else {
lvl = (rollData.competence) ? rollData.competence.name : rollData.bmValue;
}
let chatOptions = { content: "<strong>Test : " + rollData.selectedCarac.label + " / " + lvl + "</strong><br>Jet : " +
rollData.selectedCarac.value + " / " + rollData.finalLevelStr + " -> " + rollData.rollTarget.score + "%<br><strong>Résutat : </strong>" + myroll.total + "<br>" +
rollData.selectedCarac.value + " / " + rollData.finalLevelStr + " -> " + rollData.rollTarget.score + "%<br><strong>Résutat : </strong>" + result + "<br>" +
"<strong>" + quality + "</strong>" + specialStr + xpmsg,
user: game.user._id,
title: "Résultat du test"
@ -432,6 +436,27 @@ export class RdDActor extends Actor {
}
}
/* -------------------------------------------- */
async rollUnSort( coord ) {
console.log("Lancer de sort !!!!!");
let draconicList = this.getDraconicList();
let sortList = this.getSortList();
let rollData = {
"selectedCarac": this.data.data.carac.reve,
"etat": this.data.data.compteurs.etat.value,
"draconicList": draconicList,
"sortList": sortList,
"selectedDraconic": draconicList[0],
"selectedSort": sortList[0],
"coord": coord,
"finalLevel": 0,
"bmValue": 0
}
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html', rollData);
new RdDRollDialog("sort", html, rollData, this ).render(true);
}
/* -------------------------------------------- */
async rollCarac( caracName )
{
@ -468,9 +493,9 @@ export class RdDActor extends Actor {
}
/* -------------------------------------------- */
async rollSort( sortID )
async displayTMR( sortID )
{
if (this.data.data.carac.reve.value <= 1 ) {
if (this.data.data.reve.reve.value <= 1 ) {
ChatMessage.create( { title: "Montée impossible !", content: "Vous n'avez plus assez de Points de Reve pour monter dans les Terres Médianes",
whisper: ChatMessage.getWhisperRecipients(game.user.name) } );
return;

View File

@ -36,6 +36,10 @@ export class RdDRollDialog extends Dialog {
dialogConf.title = "Test de caractéristique",
dialogOptions.width = 600;
dialogOptions.height = 320;
} else if (mode == "sort") {
dialogConf.title = "Lancer un sort",
dialogOptions.width = 600;
dialogOptions.height = 360;
}
super(dialogConf, dialogOptions);
@ -60,7 +64,9 @@ export class RdDRollDialog extends Dialog {
function updateRollResult( rollData ) {
if ( rollData.competence )
rollData.finalLevel = parseInt(rollData.competence.data.niveau) + parseInt(rollData.bmValue) + parseInt(rollData.etat);
else
else if ( rollData.draconicList )
rollData.finalLevel = parseInt(rollData.selectedDraconic.data.niveau) + parseInt(rollData.selectedSort.data.difficulte) + parseInt(rollData.etat);
else
rollData.finalLevel = parseInt(rollData.bmValue) + parseInt(rollData.etat);
rollData.finalLevelStr = (rollData.finalLevel >= 0 ) ? "+" + rollData.finalLevel : rollData.finalLevel;
@ -72,6 +78,8 @@ export class RdDRollDialog extends Dialog {
if ( rollData.competence ) {
niveauStr = (rollData.competence.data.niveau >= 0) ? "+" + rollData.competence.data.niveau : rollData.competence.data.niveau;
$("#compdialogTitle").text( rollData.selectedCarac.label + "/" + rollData.competence.name + armeTitle + " " + niveauStr );
} else if ( rollData.draconicList) {
$("#compdialogTitle").text( rollData.selectedDraconic.name + " - " + rollData.selectedSort.name );
} else {
$("#compdialogTitle").text( rollData.selectedCarac.label );
}
@ -104,6 +112,18 @@ export class RdDRollDialog extends Dialog {
//console.log("CARAC CLICKED !!!", rollData.selectedCarac, rollData.competence.data.niveau, rollData.bmValue);
updateRollResult(rollData);
});
html.find('#draconic').click((event) => {
let draconicKey = event.currentTarget.value;
rollData.selectedDraconic = rollData.draconicList[draconicKey]; // Update the selectedCarac
//console.log("CARAC CLICKED !!!", rollData.selectedCarac, rollData.competence.data.niveau, rollData.bmValue);
updateRollResult(rollData);
});
html.find('#sort').click((event) => {
let sortKey = event.currentTarget.value;
rollData.selectedSort = rollData.sortList[sortKey]; // Update the selectedCarac
//console.log("CARAC CLICKED !!!", rollData.selectedCarac, rollData.competence.data.niveau, rollData.bmValue);
updateRollResult(rollData);
});
}
}

View File

@ -282,8 +282,8 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
lancerSort () {
console.log("Lancer de sort !!!!!");
lancerSort() {
this.actor.rollUnSort(this.actor.data.data.reve.tmrpos.coord);
}
/* -------------------------------------------- */

View File

@ -101,6 +101,7 @@ export class RdDUtility {
// Dialogs
'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html'
];

View File

@ -1,16 +1,16 @@
{"name":"Mauvaise rencontre en perspective","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Tirer la prochaine rencontre dans les TMR sur la @RollTable[52ymSWISvXPUhRyQ]{Table spéciale de rencontres}</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"0jrEZ62Q2Jz4kBGf"}
{"name":"Souvenir obsessionnel de l'archétype","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Les prochains points dexpérience dus au stress doivent être mis dans une compétence déterminée aléatoirement. TABLE ALÉATOIRE À CRÉER</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"1gGVlZM0UyifL6RK"}
{"name":"Coup de foudre fatal","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>On devient immédiatement amoureux fou de la première personne inconnue de sexe opposé et de même espèce rencontrée. Tant que satisfaction nest pas obtenue, traiter comme un désir lancinant.&nbsp;</p>","refoulement":2},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"32LbwxxokC9Tn370"}
{"name":"Montée laborieuse","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Pendant un jour, monter en TMR coûte 2 points de rêve au lieu dun, et 3 points en déplacement accéléré.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"5knw1NcnBsLIjHpr"}
{"name":"Inertie draconique","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Pendant un jour, la fatigue en TMR est doublée. Chaque case ou round coûte 2 points au lieu dun.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"EUrxQGd7FuW628NS"}
{"name":"Idée fixe","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Tirer 1d20 sur la table des @RollTable[FKXqN9FOJQHQXZ2L]{Idées fixes}. Les idées fixes prennent e!et immédiatement et durent jusquà lextrême $n de lheure du Château Dormant du lendemain. Si passé ce délai, loccasion de les manifester ne sest pas présentée, la queue prend $n néanmoins. Si elles entrent en contradiction avec une autre queue de Dragon, retirer.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"J3XtcVuQo846U1OT"}
{"name":"Désir lancinant","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Tirer 1d20 sur la table des@RollTable[wysZQFqioBqPijZM]{Désirs lancinants}. Les désirs lancinants durent jusquà ce quils soient satisfaits ou refoulés. Tant que satisfaction nest pas obtenue, aucun point dexpérience ne peut plus être gagné par lexercice en cas de particulière et dajustement final négatif. Les points dexpérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"Ltgqj86rYQr8D8LW"}
{"name":"Pélerinage","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement. Un Passeur peut ly téléporter, mais un Messager ne peut sy rendre à sa place. Dès que la case est atteinte, le pèlerinage est accompli.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"NF4E7jTty1QGjaNj"}
{"name":"Urgence draconique","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Le haut-rêvant est pris du besoin irrésistible de déclencher immédiatement son plus proche sort en réserve. À équidistance, prendre dans le sens des aiguilles dune montre en commençant par le haut. En cas de rencontre dans les TMR, se dérober équivaut à refouler la queue de Dragon. Si aucun sort nest en réserve, ou si il y a impossibilité de pratiquer la magie à cause dune autre queue ou dun souffle, tirer à la place une idée fixe.</p>","refoulement":2},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"OSV2b7bVWv2SCfUY"}
{"name":"Coup de barre","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Prise immédiate de 3d6 points de fatigue.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"Qgj5eSMpQ0IDHwZX"}
{"name":"Masque de Narcos","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Pendant 1d7 jours à compter du lendemain, la caractéristique APPARENCE baisse de 1d6 points, de même que la Beauté.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"TmEeikWOQt6NZGVY"}
{"name":"Réinsertion aléatoire","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Comme apr&egrave;s une sortie de la carte, le gardien des r&ecirc;ves r&eacute;introduit secr&egrave;tement le demi-r&ecirc;ve du haut-r&ecirc;vant dans les TMR.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"iHuLw0I1Gc5mIucG"}
{"_id":"0jrEZ62Q2Jz4kBGf","name":"Mauvaise rencontre en perspective","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Tirer la prochaine rencontre dans les TMR sur la @RollTable[52ymSWISvXPUhRyQ]{Table spéciale de rencontres}</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"1gGVlZM0UyifL6RK","name":"Souvenir obsessionnel de l'archétype","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Les prochains points dexpérience dus au stress doivent être mis dans une compétence déterminée aléatoirement par la table de @Compendium[foundryvtt-reve-de-dragon.tables-diverses.E0WLgjn6LA9WsvKJ]{Détermination aléatoire de compétence}.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"32LbwxxokC9Tn370","name":"Coup de foudre fatal","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>On devient immédiatement amoureux fou de la première personne inconnue de sexe opposé et de même espèce rencontrée. Tant que satisfaction nest pas obtenue, traiter comme un désir lancinant.&nbsp;</p>","refoulement":2},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"5knw1NcnBsLIjHpr","name":"Montée laborieuse","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Pendant un jour, monter en TMR coûte 2 points de rêve au lieu dun, et 3 points en déplacement accéléré.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"EUrxQGd7FuW628NS","name":"Inertie draconique","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Pendant un jour, la fatigue en TMR est doublée. Chaque case ou round coûte 2 points au lieu dun.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"J3XtcVuQo846U1OT","name":"Idée fixe","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Tirer 1d20 sur la table des @RollTable[FKXqN9FOJQHQXZ2L]{Idées fixes}. Les idées fixes prennent e!et immédiatement et durent jusquà lextrême $n de lheure du Château Dormant du lendemain. Si passé ce délai, loccasion de les manifester ne sest pas présentée, la queue prend $n néanmoins. Si elles entrent en contradiction avec une autre queue de Dragon, retirer.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"Ltgqj86rYQr8D8LW","name":"Désir lancinant","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Tirer 1d20 sur la table des @RollTable[wysZQFqioBqPijZM]{Désirs lancinants}. Les désirs lancinants durent jusquà ce quils soient satisfaits ou refoulés. Tant que satisfaction nest pas obtenue, aucun point dexpérience ne peut plus être gagné par lexercice en cas de particulière et dajustement final négatif. Les points dexpérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"NF4E7jTty1QGjaNj","name":"Pélerinage","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement. Un Passeur peut ly téléporter, mais un Messager ne peut sy rendre à sa place. Dès que la case est atteinte, le pèlerinage est accompli.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"OSV2b7bVWv2SCfUY","name":"Urgence draconique","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Le haut-rêvant est pris du besoin irrésistible de déclencher immédiatement son plus proche sort en réserve. À équidistance, prendre dans le sens des aiguilles dune montre en commençant par le haut. En cas de rencontre dans les TMR, se dérober équivaut à refouler la queue de Dragon. Si aucun sort nest en réserve, ou si il y a impossibilité de pratiquer la magie à cause dune autre queue ou dun souffle, tirer à la place une idée fixe.</p>","refoulement":2},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"Qgj5eSMpQ0IDHwZX","name":"Coup de barre","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Prise immédiate de 3d6 points de fatigue.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"TmEeikWOQt6NZGVY","name":"Masque de Narcos","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Pendant 1d7 jours à compter du lendemain, la caractéristique APPARENCE baisse de 1d6 points, de même que la Beauté.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"iHuLw0I1Gc5mIucG","name":"Réinsertion aléatoire","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Comme apr&egrave;s une sortie de la carte, le gardien des r&ecirc;ves r&eacute;introduit secr&egrave;tement le demi-r&ecirc;ve du haut-r&ecirc;vant dans les TMR.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"iJw6j7kuP1eAHIck","name":"Amnésie sélective","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Pendant un jour, perte totale dune compétence, à lexclusion du Draconic. Déterminer aléatoirement la compétence visée qui, pratiquement, retourne au niveau de base. Si elle est déjà au niveau de base, en choisir une autre.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"name":"Insomnie","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Impossibilité totale de dormir, et donc de rêver, pendant un jour.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"kHWwwxA0alcpDYpf"}
{"name":"Conquête","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Avant de pouvoir &agrave; nouveau faire usage du haut-r&ecirc;ve, y compris d&eacute;clencher volontairement un sort mis en r&eacute;serve, le haut-r&ecirc;vant doit se rendre dans une certaine case des TMR d&eacute;termin&eacute;e al&eacute;atoirement et la&nbsp;<em>ma&icirc;triser</em>, difficult&eacute; -7. Ce peut &ecirc;tre n&rsquo;importe quelle case, sauf une case humide. En cas d&rsquo;&eacute;chec, la concentration est rompue ; il n&rsquo;y a pas de souffle de Dragon en cas d&rsquo;&eacute;chec total.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"lBkO8FvFqXoKNhvk"}
{"name":"Dépouillement","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Faire don de toute la monnaie actuellement possédée à la première personne inconnue rencontrée. En attendant, se garder daucune dépense.</p>","refoulement":2},"flags":{},"img":"icons/svg/mystery-man.svg","_id":"vft88ioHpGxMzdML"}
{"_id":"kHWwwxA0alcpDYpf","name":"Insomnie","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Impossibilité totale de dormir, et donc de rêver, pendant un jour.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"lBkO8FvFqXoKNhvk","name":"Conquête","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Avant de pouvoir &agrave; nouveau faire usage du haut-r&ecirc;ve, y compris d&eacute;clencher volontairement un sort mis en r&eacute;serve, le haut-r&ecirc;vant doit se rendre dans une certaine case des TMR d&eacute;termin&eacute;e al&eacute;atoirement et la&nbsp;<em>ma&icirc;triser</em>, difficult&eacute; -7. Ce peut &ecirc;tre n&rsquo;importe quelle case, sauf une case humide. En cas d&rsquo;&eacute;chec, la concentration est rompue ; il n&rsquo;y a pas de souffle de Dragon en cas d&rsquo;&eacute;chec total.</p>","refoulement":1},"flags":{},"img":"icons/svg/mystery-man.svg"}
{"_id":"vft88ioHpGxMzdML","name":"Dépouillement","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Faire don de toute la monnaie actuellement possédée à la première personne inconnue rencontrée. En attendant, se garder daucune dépense.</p>","refoulement":2},"flags":{},"img":"icons/svg/mystery-man.svg"}

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
"name": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"description": "L'implémentation de Rêve de Dragon pour FoundryVTT",
"version": "0.7.20",
"version": "0.7.21",
"minimumCoreVersion": "0.6.0",
"compatibleCoreVersion": "0.6.2",
"templateVersion": 20,

View File

@ -0,0 +1,41 @@
<form class="dialog-roll-sort">
<h2 class="compdialog" id="sort-dialog"></h2>
<div class="form-group">
<label for="categorie">Rêve : {{selectedCarac.value}}
</div>
<div class="form-group">
<label for="categorie">Draconic </label>
<select name="draconic" id="draconic" data-dtype="String">
{{#select draconic}}
{{#each draconicList as |draconic key|}}
<option value={{key}}>{{draconic.name}} : {{draconic.data.niveau}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="form-group">
<label for="categorie">Sort </label>
<select name="sort" id="sort" data-dtype="String">
{{#select sort}}
{{#each sortList as |sort key|}}
<option value={{key}}>{{sort.name}} : {{sort.data.niveau}} - {{sort.data.difficulte}} - {{sort.data.caseTMR}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="form-group">
<label for="categorie">Etat général</label><label>{{numberFormat etat decimals=0 sign=true}}</label>
</div>
<div class="form-group">
<label>Ajustement final : </label><label id="roll-param">10 / 0</label>
</div>
<div id="resolutionTable">
</div>
</form>
<script>
</script>

View File

@ -52,7 +52,7 @@
</div>
<div class="flex-group-center">
<button id="lancer-sort">Lancer un Sort</button>
<a id="lancer-sort">Lancer un Sort</a>
</div>
</td>