Track Tomes and Rituals

Fixes #107
This commit is contained in:
TheLastScrub
2024-08-02 15:48:34 -07:00
parent ef19793128
commit 7053c39d03
7 changed files with 307 additions and 4 deletions
+34
View File
@@ -1044,6 +1044,32 @@ input.item-sheet-short-input {
padding-right: 5px;
}
/*
Tome Item Sheet
*/
.tome-sheet-horizontal-grid-2col {
display: grid;
grid-template-columns: 100px auto;
align-items: center;
text-align: left;
column-gap: 10px;
row-gap: 10px;
padding-bottom: 10px;
padding-right: 5px;
}
.tome-sheet-handler-info-horizontal-grid-2col {
display: grid;
grid-template-columns: max-content auto;
align-items: left;
text-align: left;
column-gap: 10px;
row-gap: 10px;
padding-bottom: 10px;
padding-right: 5px;
}
/*
Unnatural Character Sheet Specific Classes
*/
@@ -1146,3 +1172,11 @@ input.item-sheet-short-input {
align-self: flex-start;
text-align: left;
}
.armor-piercing-chat-card-img {
border-radius: 10%;
height: 20px !important;
width: 20px !important;
margin: 0px;
vertical-align: text-bottom;
}
+6 -1
View File
@@ -287,5 +287,10 @@
"TYPES.Item.bond": "Bond",
"TYPES.Item.gear": "Gear",
"TYPES.Item.motivation": "Motivation",
"TYPES.Item.weapon": "Weapon"
"TYPES.Item.weapon": "Weapon",
"DG.Tome.Name": "Name",
"DG.ItemWindow.Tome.Description": "Description",
"DG.ItemWindow.Tome.LanguagePlaceholder": "Language",
"DG.ItemWindow.Tome.StudyTime": "Study Time"
}
+8
View File
@@ -81,6 +81,14 @@ Hooks.on("preCreateItem", (item) => {
item.updateSource({
img: "systems/deltagreen/assets/icons/person-black-bg.svg",
});
} else if (item.type === "tome") {
item.updateSource({
img: "systems/deltagreen/assets/icons/book-cover.svg",
});
} else if (item.type === "ritual") {
item.updateSource({
img: "systems/deltagreen/assets/icons/bookmarklet.svg",
});
} else {
item.updateSource({
img: "systems/deltagreen/assets/icons/swap-bag-black-bg.svg",
+126 -1
View File
@@ -1,3 +1,10 @@
import {
DGPercentileRoll,
DGLethalityRoll,
DGDamageRoll,
DGSanityDamageRoll,
} from "../roll/roll.js";
/**
* Extend the basic ItemSheet with some very simple modifications
* @extends {ItemSheet}
@@ -32,10 +39,19 @@ export default class DeltaGreenItemSheet extends ItemSheet {
/** @override */
async getData() {
const data = super.getData();
data.enrichedDescription = await TextEditor.enrichHTML(
this.object.system.description,
{ async: true },
);
if (data.item.type === "tome" || data.type === "ritual") {
data.enrichedHandlerNotes = await TextEditor.enrichHTML(
this.object.system.handlerNotes,
{ async: true },
);
}
return data;
}
@@ -60,6 +76,115 @@ export default class DeltaGreenItemSheet extends ItemSheet {
// eslint-disable-next-line no-useless-return
if (!this.options.editable) return;
// Roll handlers, click handlers, etc. would go here.
// Rollable abilities - bind to everything with the 'Rollable' class
html.find(".rollable").click(this._onRoll.bind(this));
html.find(".rollable").contextmenu(this._onRoll.bind(this)); // this is for right-click, which triggers the roll modifier dialogue for most rolls
// toggle whether information is shown to a player for a tome or not
html.find(".tome-show-hide-info").click((event) => {
event.preventDefault();
this.item.system.revealed = !this.item.system.revealed;
this.item.update({ "system.revealed": this.item.system.revealed });
});
}
/**
* Handle clickable rolls.
*
* @param {Event} event The originating click event
* @async
* @private
*/
async _onRoll(event) {
event.preventDefault();
const element = event.currentTarget;
const { dataset } = element;
if (event && event.which === 2) {
// probably don't want rolls to trigger from a middle mouse click so just kill it here
return;
}
//const item = this.actor.items.get(dataset.iid);
const rollOptions = {
rollType: dataset.rolltype,
key: dataset.key,
//actor: this,
specialTrainingName: dataset?.name || null, // Only applies to Special Training Rolls
item: this,
};
// Create a default 1d100 roll just in case.
let roll = new Roll("1d100", {});
switch (dataset.rolltype) {
case "stat":
case "skill":
case "sanity":
case "special-training":
case "weapon":
roll = new DGPercentileRoll("1D100", {}, rollOptions);
break;
case "lethality":
roll = new DGLethalityRoll("1D100", {}, rollOptions);
break;
case "damage": {
let diceFormula = item.system.damage;
const { skill } = item.system;
if (
this.actor.type === "agent" &&
(skill === "unarmed_combat" || skill === "melee_weapons")
) {
diceFormula +=
this.actor.system.statistics.str.meleeDamageBonusFormula;
}
roll = new DGDamageRoll(diceFormula, {}, rollOptions);
break;
}
case "sanity-damage": {
let combinedFormula;
if (this.item.type === "tome") {
const { successLoss, failedLoss } = this.item.system.sanity;
combinedFormula = `{${successLoss}, ${failedLoss}}`;
}
roll = new DGSanityDamageRoll(combinedFormula, {}, rollOptions);
break;
}
default:
break;
}
this.processRoll(event, roll, rollOptions);
}
/**
* Show a dialog for the roll and then send to chat.
* Broke this logic out from `_onRoll()` so that other files can call it,
* namely the macro logic.
*
* TODO: Move this logic to the roll.js.
*
* @param {Event} event The originating click event
* @param {Event} roll The roll to show a dialog for and then send to chat.
* @async
*/
async processRoll(event, roll) {
// Open dialog if user requests it (no dialog for Sanity Damage rolls)
if (
(event.shiftKey || event.which === 3) &&
!(roll instanceof DGSanityDamageRoll)
) {
const dialogData = await roll.showDialog();
if (!dialogData) return;
if (dialogData.newFormula) {
roll = new DGDamageRoll(dialogData.newFormula, {}, roll.options);
}
roll.modifier += dialogData.targetModifier;
roll.options.rollMode = dialogData.rollMode;
}
// Evaluate the roll.
await roll.evaluate();
// Send the roll to chat.
roll.toChat();
}
}
+3 -1
View File
@@ -671,7 +671,9 @@ export class DGDamageRoll extends DGRoll {
.localize("DG.Roll.Damage")
.toUpperCase()}</b> ${game.i18n.localize("DG.Roll.For")} ${
this.item.name
}`;
} (<b>${
this.item.system.armorPiercing
} </b><img class="armor-piercing-chat-card-img" src="systems/deltagreen/assets/icons/supersonic-bullet.svg" alt="armor penetration"/>)`;
} catch (ex) {
// console.log(ex);
label = `Rolling <b>DAMAGE</b> for <b>${label.toUpperCase()}</b>`;
+34 -1
View File
@@ -520,7 +520,15 @@
}
},
"Item": {
"types": ["weapon", "armor", "motivation", "bond", "gear"],
"types": [
"weapon",
"armor",
"motivation",
"bond",
"gear",
"tome",
"ritual"
],
"templates": {
"base": {
"name": "",
@@ -564,6 +572,31 @@
"templates": ["base"],
"equipped": true,
"expense": "Standard"
},
"tome": {
"templates": ["base"],
"language": "",
"studyTime": "days",
"unnaturalSkillIncrease": 5,
"occultSkillIncrease": 3,
"sanity": {
"notes": "",
"failedLoss": "1D6",
"successLoss": "1"
},
"handlerNotes": "",
"revealed": false
},
"ritual": {
"templates": ["base"],
"studyTime": "weeks",
"studySanCost": "1D10",
"studyUnnaturalIncrease": 1,
"activationSanCost": "1D10",
"activationCosts": "6 WP, 0 POW, 0 HP",
"complexity": "Simple",
"activationTime": "days",
"handlerNotes": ""
}
}
}
+96
View File
@@ -0,0 +1,96 @@
<form class="{{cssClass}} {{getCharacterSheetStyle}}" autocomplete="off">
<header class="">
<div class="gear-sheet-grid-2col">
<img class="item-img" src="{{item.img}}" data-edit="img" title="{{item.name}}"/>
<div class="tome-sheet-horizontal-grid-2col">
{{#if item.system.revealed}}
<span class="resource-label">
{{#if (playerHasGamemasterPrivileges)}}<a class="tome-show-hide-info"><i class="far fa-eye"></i></a>{{/if}}
{{localize 'DG.Tome.Name'}}:
</span>
<input name="name" type="text" value="{{item.name}}" placeholder="{{localize 'DG.ItemWindow.Tome.NamePlaceholder'}}"/>
<span class="resource-label">Language:</span>
<input name="system.language" type="text" value="{{item.system.language}}" placeholder="{{localize 'DG.ItemWindow.Tome.LanguagePlaceholder'}}"/>
<span class="resource-label">Study Time:</span>
<input name="system.studyTime" type="text" value="{{item.system.studyTime}}" placeholder="{{localize 'DG.ItemWindow.Tome.StudyTime'}}"/>
{{else}}
{{#if (playerHasGamemasterPrivileges)}}
<span class="resource-label">
{{#if (playerHasGamemasterPrivileges)}}<a class="tome-show-hide-info"><i class="far fa-eye-slash"></i></a>{{/if}}
{{localize 'DG.Tome.Name'}}:
</span>
<input name="name" type="text" value="{{item.name}}" placeholder="{{localize 'DG.ItemWindow.Tome.NamePlaceholder'}}"/>
<span class="resource-label">Language:</span>
<input name="system.language" type="text" value="{{item.system.language}}" placeholder="{{localize 'DG.ItemWindow.Tome.LanguagePlaceholder'}}"/>
<span class="resource-label">Study Time:</span>
<input name="system.studyTime" type="text" value="{{item.system.studyTime}}" placeholder="{{localize 'DG.ItemWindow.Tome.StudyTime'}}"/>
{{else}}
<span class="resource-label">
{{#if (playerHasGamemasterPrivileges)}}<a class="tome-show-hide-info"><i class="far fa-eye-slash"></i></a>{{/if}}
{{localize 'DG.Tome.Name'}}:
</span>
<span>???<span>
<span class="resource-label">Language:</span>
<span>???</span>
<span class="resource-label">Study Time:</span>
<span>???</span>
{{/if}}
{{/if}}
</div>
</div>
</div>
</header>
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="description">{{localize 'DG.ItemWindow.Tome.Description'}}</a>
{{#if (playerHasGamemasterPrivileges)}}
<a class="item" data-tab="handler">Handler Only</a>
{{/if}}
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Description Tab --}}
<div class="tab top-div-border" data-group="primary" data-tab="description">
{{editor enrichedDescription target="system.description" button=true owner=owner editable=editable}}
</div>
{{!-- Handler Notes Tab --}}
{{#if (playerHasGamemasterPrivileges)}}
<div class="tab" data-group="primary" data-tab="handler">
<div class="tome-sheet-handler-info-horizontal-grid-2col">
<span class="resource-label">Unnatural Skill Increase:</span>
<input class="item-sheet-short-input" name="system.unnaturalSkillIncrease" type="text" value="{{item.system.unnaturalSkillIncrease}}" type="integer" data-dtype="Number"/>
<span class="resource-label">Occult Skill Increase:</span>
<input class="item-sheet-short-input" name="system.occultSkillIncrease" type="text" value="{{item.system.occultSkillIncrease}}" type="integer" data-dtype="Number"/>
<span class="resource-label">Study Sanity Damage:</span>
<span>
<input class="item-sheet-short-input" name="system.sanity.successLoss" type="text" value="{{item.system.sanity.successLoss}}" type="text" data-dtype="Text"/>
/
<input class="item-sheet-short-input" name="system.sanity.failedLoss" type="text" value="{{item.system.sanity.failedLoss}}" type="text" data-dtype="Text"/>
<i class="fas fa-dice rollable" data-rolltype="sanity-damage"></i>
</span>
</div>
<span class="resource-label">Handler Notes:</span>
<div class="tab top-div-border">
{{editor enrichedHandlerNotes target="system.handlerNotes" button=true owner=owner editable=editable}}
</div>
</div>
{{/if}}
</section>
</form>