Compare commits
9 Commits
main
...
feature/at
| Author | SHA1 | Date |
|---|---|---|
|
|
d461b1287b | |
|
|
f05a263406 | |
|
|
6c1c5a9c52 | |
|
|
6133cc2237 | |
|
|
ced57dbbcb | |
|
|
03ff37ab5a | |
|
|
571b59f0d2 | |
|
|
52082e4e38 | |
|
|
d84aec7ffa |
|
|
@ -1,3 +1,5 @@
|
|||
import {rollAttributeForActor} from "../utils/rolls/rollEngine.mjs";
|
||||
|
||||
import {PlayerCharacterDataModel} from "../data/character.mjs";
|
||||
import {ActionManager} from "./actions/action-manager.mjs";
|
||||
import {LiturgyData} from "../data/miracle/liturgydata.mjs";
|
||||
|
|
@ -563,19 +565,33 @@ export class CharacterSheet extends ActorSheet {
|
|||
}
|
||||
}
|
||||
|
||||
_onAttributeRoll(event) {
|
||||
async _onAttributeRoll(event) {
|
||||
event.preventDefault();
|
||||
const dataset = event.currentTarget.dataset;
|
||||
if (dataset.roll) {
|
||||
let label = dataset.label ? `[Attribut] ${dataset.label}` : '';
|
||||
let roll = new Roll(dataset.roll, this.actor.getRollData());
|
||||
roll.toMessage({
|
||||
speaker: ChatMessage.getSpeaker({actor: this.actor}),
|
||||
flavor: label,
|
||||
rollMode: game.settings.get('core', 'rollMode'),
|
||||
});
|
||||
return roll;
|
||||
let actor = this.actor
|
||||
let dataset = event.currentTarget.dataset
|
||||
let data = await this.getData()
|
||||
let attribute = data.attributes.find(item => item.name === dataset.label)
|
||||
|
||||
let content = await foundry.applications.handlebars.renderTemplate("templates/dialog/attribute-roll.hbs", {
|
||||
attribute: attribute.tooltip,
|
||||
mod: 0,
|
||||
})
|
||||
|
||||
let d = new Dialog({
|
||||
title: `${attribute.tooltip}-Probe`,
|
||||
content: content,
|
||||
buttons: {
|
||||
one: {
|
||||
label: "Würfeln",
|
||||
callback: (html) => {
|
||||
let mod = html.find('#mod-input').val()
|
||||
rollAttributeForActor(actor, attribute, mod > 0 ? `+${mod}` : mod)
|
||||
}
|
||||
},
|
||||
},
|
||||
default: "two",
|
||||
});
|
||||
d.render(true);
|
||||
}
|
||||
|
||||
openEmbeddedDocument(documentId) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Rolls an attribute Check
|
||||
* @param actor the actor that performs the roll
|
||||
* @param attribute the attribute to check against
|
||||
* @param modifier the modifier that is applied to the check in good old-fashioned DSA-Notation (+X for more difficulty, -X to make it easier)
|
||||
* @param mode the mode as described in [foundry.CONFIG.Dice.rollModes]
|
||||
*/
|
||||
export async function rollAttributeForActor(actor, attribute, modifier, mode = foundry.CONFIG.Dice.rollModes.publicroll) {
|
||||
let result = await rollDice("1d20", mode)
|
||||
let resultRoll = result.results[0]
|
||||
let mod = parseInt(modifier)
|
||||
let success = attribute.wert >= resultRoll + mod
|
||||
|
||||
let message = await foundry.applications.handlebars.renderTemplate("templates/chat-messages/attribute-check.hbs", {
|
||||
attribute: attribute.name,
|
||||
target: attribute.wert - mod,
|
||||
mod: modifier,
|
||||
result: resultRoll,
|
||||
success: success,
|
||||
rest: attribute.wert - (resultRoll + mod),
|
||||
})
|
||||
|
||||
let chatData = {
|
||||
speaker: ChatMessage.getSpeaker({actor: actor}),
|
||||
content: message
|
||||
}
|
||||
ChatMessage.create(chatData, {})
|
||||
}
|
||||
|
||||
async function rollDice(check, mode = foundry.CONFIG.Dice.rollModes.publicroll) {
|
||||
let roll = new Roll(check)
|
||||
|
||||
// This is used to roll via Dice so Nice without writing any specific code
|
||||
// and to prevent the ugly total rolled section in the message from appearing
|
||||
let message = await roll.toMessage({}, {rollMode: mode, create: true})
|
||||
message.delete()
|
||||
|
||||
let results = []
|
||||
for (let term in roll.terms) {
|
||||
term = roll.terms[term]
|
||||
for (let value in term.results) {
|
||||
value = term.results[value]
|
||||
results.push(value.result)
|
||||
}
|
||||
}
|
||||
return new RollResult(
|
||||
check,
|
||||
results
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the check and the results for the check
|
||||
* @param check the chack that has been rolled
|
||||
* @param result the results for the check as an array
|
||||
*/
|
||||
class RollResult {
|
||||
constructor(check, results) {
|
||||
this.check = check;
|
||||
this.results = results;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"seite": "11",
|
||||
"name": "ABVENENUM REINE SPEISE",
|
||||
"probe": [
|
||||
"KL",
|
||||
"KL",
|
||||
"FF"
|
||||
],
|
||||
"probenMod": "+Mod.",
|
||||
"technik": "Der Elf spricht bha’sama venya bha’za yalza über die zu reinigende Nahrung.",
|
||||
"zauberdauer": "mindestens 15 Aktionen",
|
||||
"wirkung": "Der Zauber reinigt Nahrungsmittel und Ge tränke von sämtlichen Giften und Krankheitskeimen; verdorbene Nahr ung wird frisch und genießbar. Die Zauberprobe ist um die doppelte Stufe des Giftes oder der beim Verzehr zu befürchtenden Krankheit erschwert. Verdorbene Nahrung kann je nach Zustand einen Zuschlag von 2 bis 12 Punkten auf die Probe bedeuten. Dieser Zauber versetzt Nahrung in einen Zustand, die dem Spruchanwender nicht gefährlich werden kann. Da es aber von dem Entwickler des Spruches abhängt, in welchem Zustand Nahrung als gefährlich angesehen werden muss und in welchem nicht, variiert die genaue Wirkung je nach Repräsentation recht erheblich. So wandelt die elfische Repräsentation selbst Wein in Traubensaft um, während die Achazform des Spruches manche für Menschen und Elfen giftige Mahlzeiten unverändert lässt. Gift, das sich nicht in Nahrung befindet, wird von dem Zauber nicht als solches erkannt, weswegen das Gift auf der Klinge eines Meuchlers oder in der Phiole eines Alchimisten nicht verändert wird. Wenn allerdings zum Beispiel in einer Pilzpfanne giftige Pilze enthalten sind, dann wirkt der Zauber sehr wohl.",
|
||||
"kosten": "4 AsP pro Mahlzeit, die für etwa 10 Personen reicht (Sch: 3 AsP)",
|
||||
"zielobjekt": "Nahrungsmenge (mehrere Objekte) nach AsP-Aufwand",
|
||||
"reichweite": "1 Schritt",
|
||||
"wirkungsdauer": "augenblicklich",
|
||||
"modifikationen": "Zauberdauer, Reichweite",
|
||||
"varianten": {
|
||||
"Schutz vor Übelkeit": {
|
||||
"description": "Nahrung, die an sich nicht giftig ist, deren Genuss aber heftige Übelkeit erzeugt, wird in einen Zustand versetzt, der als harmlos gelten kann. So ist es zum Beispiel möglich, auch Meerwasser in Trinkwasser zu verwandeln. Horasische Sahnetorten werden jedoch nur von den wenigsten Repräsentationen in Mitleidenschaft gezogen.",
|
||||
"mod": "+5",
|
||||
"limit": ""
|
||||
},
|
||||
"Schutz vor Vergiftung": {
|
||||
"description": "Bewahrt die Nahrung für die nächsten ZfP* Stunden vor jeglicher in diesem Zeitraum geschehener Vergiftung und jedem Verschimmeln oder Verderben. Der Zaubernde muss sich hierbei selbst einen Aufschlag auf die Zauberprobe auferlegen, und zwar in Höhe der Stufe der Krankheit/des Giftes, gegen die der Schutz höchstens wirksam sein soll. Eine bereits vergiftete Speise wird dabei entgiftet.Vereinzelt existieren eingeschränkte Variationen dieses Spruches, die (bei geringerem Probenaufschlag und AsP-Aufwand) nur gegen gewisse Giftgruppen (Schlangengifte) oder gar nur gegen einzelne Gifte und Krankheiten wirken.",
|
||||
"mod": "+5",
|
||||
"limit": ""
|
||||
}
|
||||
},
|
||||
"reversalis": "bewirkt das schlagartige Verfaulen und Verschimmeln von L ebensmitteln.",
|
||||
"antimagie": "kann in einer Zone des OBJEKT ENTZAUBERN nur erschwert gesprochen wer den; lässt sich wegen der Wirkungsdauer augenblicklich nicht mittels Antimagie widerrufen.",
|
||||
"merkmal": "Objekt",
|
||||
"komplexität": "C",
|
||||
"repräsentation": "Dru, Elf, Hex, Mag je 6; Geo5; Ach, Sch je 4",
|
||||
"info": "Dieser ursprünglich von den Waldelfen stammende Spruch ist bei fast allen Zauberkundigen weit verbreitet. An allen Orten, an denen die lokalen Potentaten in ständiger Furcht vor Meuchlern und Giftmischern leben, werden Meisterinnen und Meister des ABVENENUM mit Kusshand in den Hofstaat aufgenommen (wenn sie nach einem Demonstrationszaubern den Genuss der vorher präparierten Narung überlebt haben)."
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
@use "chat-messages/attribute-check-message";
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
.attribute-check-message {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto auto auto 1fr;
|
||||
|
||||
div {
|
||||
text-align: center;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.headline {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.result {
|
||||
grid-row: 2;
|
||||
grid-column: 1;
|
||||
background-color: rgb(255 255 255 / 35%);
|
||||
padding: 10px 0;
|
||||
|
||||
.success {
|
||||
color: #008800;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.failure {
|
||||
color: #880000;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.result-message {
|
||||
grid-row: 3;
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.roll-result {
|
||||
grid-row: 4;
|
||||
grid-column: 1;
|
||||
display: grid;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
|
||||
.roll {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.attribute-value {
|
||||
grid-row: 1;
|
||||
grid-column: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
@use "dialogs/attribute-roll";
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
.attribute-roll-dialog-content {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 30px 1fr 30px 2fr;
|
||||
grid-template-rows: auto auto 30px minmax(10px, 1fr);
|
||||
align-items: center;
|
||||
|
||||
.headline {
|
||||
grid-row: 1;
|
||||
grid-column: 1 / span 5;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#mod-type {
|
||||
grid-row: 2;
|
||||
grid-column: 1 / span 5;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.subtract-button {
|
||||
grid-row: 3;
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
#mod-input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mod-display {
|
||||
grid-row: 3;
|
||||
grid-column: 3;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.add-button {
|
||||
grid-row: 3;
|
||||
grid-column: 4;
|
||||
}
|
||||
}
|
||||
|
|
@ -14,3 +14,6 @@
|
|||
@use "_talent-sheet";
|
||||
@use "_active-effect-sheet";
|
||||
@use "_advantage-sheet";
|
||||
|
||||
@use "chat-messages";
|
||||
@use "dialogs";
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<div class="attribute-check-message">
|
||||
<div class="headline">
|
||||
<h2>{{attribute}}-Probe ({{mod}})</h2>
|
||||
</div>
|
||||
<div class="result {{#if success}}success{{else}}failure{{/if}}">
|
||||
{{#if success}}
|
||||
<h2 class="success">Gelungen</h2>
|
||||
{{else}}
|
||||
<h2 class="failure">Misslungen</h2>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="result-message">
|
||||
{{#if success}}
|
||||
<span>Es sind noch {{rest}} Punkte übrig</span>
|
||||
{{else}}
|
||||
<span>Es fehlen {{rest}} Punkte</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="roll-result">
|
||||
<div class="roll">
|
||||
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}
|
||||
<span class="center">{{result}}</span>
|
||||
</div>
|
||||
<div class="attribute-value">{{target}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<script>
|
||||
function raiseMod() {
|
||||
let input = $('#mod-input')
|
||||
let mod = parseInt(input.val())
|
||||
mod++;
|
||||
input.val(mod)
|
||||
adaptModType()
|
||||
adaptMod()
|
||||
}
|
||||
|
||||
function lowerMod() {
|
||||
let input = $('#mod-input')
|
||||
let mod = parseInt(input.val())
|
||||
mod--;
|
||||
input.val(mod)
|
||||
adaptModType()
|
||||
adaptMod()
|
||||
}
|
||||
|
||||
function adaptModType() {
|
||||
let input = $('#mod-input')
|
||||
let mod = parseInt(input.val())
|
||||
if (mod > 0) {
|
||||
document.getElementById('mod-type').innerHTML = "Erschwernis"
|
||||
} else if (mod < 0) {
|
||||
document.getElementById('mod-type').innerHTML = "Erleichterung"
|
||||
} else {
|
||||
document.getElementById('mod-type').innerHTML = "Keine Änderung"
|
||||
}
|
||||
}
|
||||
|
||||
function adaptMod() {
|
||||
let input = $('#mod-input')
|
||||
let mod = parseInt(input.val())
|
||||
document.getElementById('mod-display').innerHTML = mod >= 0 ? `+${mod}` : mod
|
||||
}
|
||||
</script>
|
||||
<div class="attribute-roll-dialog-content">
|
||||
<h2 class="headline">{{attribute}}</h2>
|
||||
<h3 id="mod-type">
|
||||
{{#if (gt mod 0)}}
|
||||
Erschwernis
|
||||
{{else if (lt mod 0)}}
|
||||
Erleichterung
|
||||
{{else}}
|
||||
Keine Anpassung
|
||||
{{/if}}
|
||||
</h3>
|
||||
<button class="subtract-button" onclick="lowerMod()">-</button>
|
||||
<span id="mod-display">{{mod}}</span>
|
||||
<button class="add-button" onclick="raiseMod()">+</button>
|
||||
<input type="number" id="mod-input" value="{{mod}}">
|
||||
</div>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<form class="flexcol" autocomplete="off">
|
||||
<header class="sheet-header">
|
||||
<div class="header-fields">
|
||||
<h1 class="charname">{{actor.name}}</h1>
|
||||
</div>
|
||||
</header>
|
||||
<section class="sheet-body">
|
||||
<textarea readonly>{{formatCharacter actor}}</textarea>
|
||||
</section>
|
||||
</form>
|
||||
Loading…
Reference in New Issue