diff --git a/CHANGELOG.md b/CHANGELOG.md
index 922abf0..ace33b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
## Release/Patch Notes
+### Version 1.0.7 - ??? [BREAKING CHANGE: THIS VERSION FORWARD COMPATIBLE WITH FOUNDRY V10 OR HIGHER ONLY!]
+
+* Enhancement - Update to new data model for Foundry V10. This breaks compatibility with older versions, but leaves the system in a better place for future updates. Thanks to Jailensailen for help with this effort.
+* Enhancement [GitHub 39] - Jailensailen added a way to toggle lethality directly on the actor sheet without editing the item. There is now a toggle button beside the damage formula/lethality percentage.
+* Enhancement [GitHub #56] - Added an actor sheet for Vehicles
+* Fix [GitHub #66] - Dragging item macros to hot bar, as well as executing them seemed to be broken.
+* Fix [GitHub #62] - Fixed issue with how weapon skill rolls are displayed in chat cards (incorrectly appended 'x5' to rolls that were not x5 rolls).
+* Enhancement [GitHub #58] - Did not completely overhaul Agent sheet per request, but did implement some of the requested changes to make the Agent/NPC sheets shorter, so that they require less scrolling when on smaller screens. Thanks to wush3 for providing some of the CSS for this.
+* Enhancement - Made a few improvements to improvements to layout for a few of the item and NPC sheets.
+
### Version 1.0.6 - 2022-05-26
* Enhancement - IgorAK25 has submitted a Portuguese translation for the system.
diff --git a/css/deltagreen.css b/css/deltagreen.css
index fc8da49..068a020 100644
--- a/css/deltagreen.css
+++ b/css/deltagreen.css
@@ -4,7 +4,7 @@
@font-face {
font-family: 'atwriter';
src: url('../assets/font/another-typewriter/atwriter.ttf') format('truetype'); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */
-}
+}
@font-face {
font-family: TypeWriterCondensed;
@@ -26,7 +26,7 @@
@font-face {
font-family: 'SpecialElite';
src: url('../assets/font/special_elite/SpecialElite-Regular.ttf') format('truetype'); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */
-}
+}
/* Global styles */
@@ -80,10 +80,14 @@ section.window-content{
color: #999999;
}
+.dg-red{
+ color:rgb(117, 0, 0);
+}
+
.grid-1col{
display: grid;
grid-column: span 1 / span 1;
- gap: 10px;
+ gap: 3px;
}
.grid,
@@ -91,7 +95,7 @@ section.window-content{
display: grid;
grid-column: span 2 / span 2;
grid-template-columns: repeat(2, minmax(0, 1fr));
- gap: 10px;
+ gap: 3px;
margin: 0px 0;
padding: 0;
}
@@ -156,7 +160,7 @@ section.window-content{
-ms-flex-align: center;
align-items: center;
text-align: center;
- padding: 5px;
+ padding: 2px;
border: 1px solid #999;
}
@@ -191,7 +195,7 @@ section.window-content{
}
.horizontal-flex-column{
- display: flex;
+ display: flex;
flex-direction: column;
}
@@ -226,11 +230,11 @@ section.window-content{
-ms-flex: 0 0 100px;
flex: 0 0 100px;
height: 100px;
- margin-right: 10px;
+ margin-right: 5px;
}
.profile-img{
- margin-bottom: 10px;
+ margin-bottom: 5px;
}
.deltagreen .sheet-header .header-fields {
@@ -240,7 +244,7 @@ section.window-content{
}
.deltagreen .sheet-header h1.charname {
- height: 50px;
+ height: 55px;
padding: 0px;
border-bottom: 0;
}
@@ -280,7 +284,7 @@ section.window-content{
font-weight: bold;
vertical-align: middle !important;
line-height: inherit;
- padding: 10px 15px 5px 15px;
+ padding: 5px 10px 0px 10px;
border-radius: 5px 5px 0px 0px;
border-color: #000;
}
@@ -361,7 +365,7 @@ a.btn-tiny{
span.left-aligned-label{
justify-content: left;
- margin-left: 10px;
+ margin-left: 5px;
}
span.max-attribute-value-label{
@@ -375,12 +379,12 @@ span.max-attribute-value-label{
}
.deltagreen .skill-label{
- margin: 5px;
+ margin: 2px;
align-content: flex-start;
}
.deltagreen .skill-type-label{
- margin: 5px;
+ margin: 2px;
}
.typed-skill-flexrow{
@@ -390,11 +394,17 @@ span.max-attribute-value-label{
}
input.percentile-skill-input{
- width: 50px;
+ flex: 0 0 40px;
margin-right: 5px;
margin-left: 5px;
}
+input.checkbox-skill-input{
+ /*flex: 0 0 10px;*/
+ width: 15px;
+ height: 15px;
+}
+
.deltagreen .sheet-header h2.profession{
border-bottom: 0px;
margin-top: 5px;
@@ -403,7 +413,7 @@ input.percentile-skill-input{
.deltagreen .sheet-header h2.profession input {
width: 100%;
- height: 35px;
+ height: 40px;
margin: 0;
}
@@ -429,7 +439,7 @@ div span.bio-grid-label{
align-items: center;
padding-bottom: 10px;
row-gap: 10px;
-}
+}
.bio-grid-top-border{
border-top: 1px solid #AAA;
@@ -441,14 +451,14 @@ div span.bio-grid-label{
grid-template-columns: 100px 100px 20px 120px auto;
align-items: center;
padding-bottom: 10px;
-}
+}
.bonds-grid-3col{
display: grid;
grid-template-columns: auto 50px max-content;
align-items: center;
padding-bottom: 10px;
-}
+}
.centered-input-value{
text-align: center !important;
@@ -621,7 +631,7 @@ div.motivation-editor-container div.editor{
}
.deltagreen .editor-host .editor {
- min-height: 35px;
+ min-height: 50px;
}
.deltagreen .editor-host .tox {
@@ -843,8 +853,9 @@ input.item-sheet-short-input{
text-align: left;
}
+
.skill-util-buttons{
- margin: 10px;
+ margin: 5px;
}
.apply-skill-improvements{
@@ -881,7 +892,7 @@ input.item-sheet-short-input{
grid-template-columns: max-content 5px max-content max-content 20px max-content max-content 10px 35px;
align-items: center;
padding-bottom: 10px;
-}
+}
.yellow-king-grid-5col{
display: grid;
@@ -901,4 +912,11 @@ input.item-sheet-short-input{
.yellow-king textarea:focus, .yellow-king input:focus{
color: #a0912f;
+}
+
+.top-div-border{
+ border-top: 1px solid #AAA;
+ margin-bottom: 10px;
+ padding-bottom: 10px;
+ padding-top: 10px;
}
\ No newline at end of file
diff --git a/lang/ca.json b/lang/ca.json
index 2daa3a5..6f604c1 100644
--- a/lang/ca.json
+++ b/lang/ca.json
@@ -238,5 +238,10 @@
"DG.ImpossibleLanscapes.CorruptionFirstHalf": "Corrup",
"DG.ImpossibleLanscapes.CorruptionSecondHalf": "tion",
"DG.ImpossibleLanscapes.Gift": "Gift",
- "DG.ImpossibleLanscapes.Insight": "Insight"
+ "DG.ImpossibleLanscapes.Insight": "Insight",
+
+ "DG.VehicleSheet.NotesTabName": "Notes",
+ "DG.VehicleSheet.GearTabName": "Gear",
+ "DG.VehicleSheet.NotesLabel": "NOTES",
+ "DG.VehicleSheet.DescriptionPlaceHolder": "Vehicle Description"
}
diff --git a/lang/en.json b/lang/en.json
index 01310ba..e1392e0 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -244,5 +244,10 @@
"DG.ImpossibleLanscapes.CorruptionFirstHalf": "Corrup",
"DG.ImpossibleLanscapes.CorruptionSecondHalf": "tion",
"DG.ImpossibleLanscapes.Gift": "Gift",
- "DG.ImpossibleLanscapes.Insight": "Insight"
+ "DG.ImpossibleLanscapes.Insight": "Insight",
+
+ "DG.VehicleSheet.NotesTabName": "Notes",
+ "DG.VehicleSheet.GearTabName": "Gear",
+ "DG.VehicleSheet.NotesLabel": "NOTES",
+ "DG.VehicleSheet.DescriptionPlaceHolder": "Vehicle Description"
}
\ No newline at end of file
diff --git a/lang/es.json b/lang/es.json
index 680b330..5e273ae 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -238,5 +238,10 @@
"DG.ImpossibleLanscapes.CorruptionFirstHalf": "Corrup",
"DG.ImpossibleLanscapes.CorruptionSecondHalf": "tion",
"DG.ImpossibleLanscapes.Gift": "Gift",
- "DG.ImpossibleLanscapes.Insight": "Insight"
+ "DG.ImpossibleLanscapes.Insight": "Insight",
+
+ "DG.VehicleSheet.NotesTabName": "Notes",
+ "DG.VehicleSheet.GearTabName": "Gear",
+ "DG.VehicleSheet.NotesLabel": "NOTES",
+ "DG.VehicleSheet.DescriptionPlaceHolder": "Vehicle Description"
}
\ No newline at end of file
diff --git a/lang/ja.json b/lang/ja.json
index eba25f3..9d4d8be 100644
--- a/lang/ja.json
+++ b/lang/ja.json
@@ -238,5 +238,10 @@
"DG.ImpossibleLanscapes.CorruptionFirstHalf": "腐",
"DG.ImpossibleLanscapes.CorruptionSecondHalf": "敗",
"DG.ImpossibleLanscapes.Gift": "ギフト",
- "DG.ImpossibleLanscapes.Insight": "インサイト"
+ "DG.ImpossibleLanscapes.Insight": "インサイト",
+
+ "DG.VehicleSheet.NotesTabName": "ノート",
+ "DG.VehicleSheet.GearTabName": "装備",
+ "DG.VehicleSheet.NotesLabel": "ノート",
+ "DG.VehicleSheet.DescriptionPlaceHolder": ""
}
\ No newline at end of file
diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js
index b826037..0fe0deb 100644
--- a/module/actor/actor-sheet.js
+++ b/module/actor/actor-sheet.js
@@ -22,7 +22,7 @@ export class DeltaGreenActorSheet extends ActorSheet {
get template() {
if(this.actor !== null){
- if(this.actor.data.type === 'agent'){
+ if(this.actor.type === 'agent'){
if ( !game.user.isGM && this.actor.limited ) {
return "systems/deltagreen/templates/actor/limited-sheet.html";
}
@@ -31,12 +31,15 @@ export class DeltaGreenActorSheet extends ActorSheet {
return `systems/deltagreen/templates/actor/actor-sheet.html`;
}
}
- else if(this.actor.data.type === 'unnatural'){
+ else if(this.actor.type === 'unnatural'){
return `systems/deltagreen/templates/actor/unnatural-sheet.html`;
}
- else if(this.actor.data.type === 'npc'){
+ else if(this.actor.type === 'npc'){
return `systems/deltagreen/templates/actor/npc-sheet.html`;
}
+ else if(this.actor.type === 'vehicle'){
+ return `systems/deltagreen/templates/actor/vehicle-sheet.html`;
+ }
else{
return "systems/deltagreen/templates/actor/limited-sheet.html";
}
@@ -47,13 +50,27 @@ export class DeltaGreenActorSheet extends ActorSheet {
}
/** @override */
- getData() {
+ async getData() {
const data = super.getData();
// Prepare items.
- if (this.actor.data.type == 'agent') {
+ if (this.actor.type == 'agent') {
this._prepareCharacterItems(data);
}
+
+ switch (this.actor.type) {
+ case "agent":
+ data.enrichedDescription = await TextEditor.enrichHTML(this.object.system.physicalDescription, {async: true});
+ break;
+ case "vehicle":
+ data.enrichedDescription = await TextEditor.enrichHTML(this.object.system.description, {async: true});
+ break;
+ case "npc":
+ case "unnatural":
+ data.enrichedDescription = await TextEditor.enrichHTML(this.object.system.notes, {async: true});
+ break;
+ default:
+ }
return data;
}
@@ -75,7 +92,7 @@ export class DeltaGreenActorSheet extends ActorSheet {
// Iterate through items, allocating to containers
// let totalWeight = 0;
for (let i of sheetData.items) {
- let item = i.data;
+ let item = i;
i.img = i.img || DEFAULT_TOKEN;
// Append to armor.
if (i.type === 'armor') {
@@ -208,9 +225,9 @@ export class DeltaGreenActorSheet extends ActorSheet {
event.preventDefault();
let currentBreakingPoint = 0;
- currentBreakingPoint = this.actor.data.data.sanity.value - this.actor.data.data.statistics.pow.value;
+ currentBreakingPoint = this.actor.system.sanity.value - this.actor.system.statistics.pow.value;
- let updatedData = duplicate(this.actor.data.data);
+ let updatedData = duplicate(this.actor.system);
updatedData.sanity.currentBreakingPoint = currentBreakingPoint;
this.actor.update({"data": updatedData});
});
@@ -227,8 +244,8 @@ export class DeltaGreenActorSheet extends ActorSheet {
event.preventDefault();
let targetskill = event.target.getAttribute("data-typedskill");
- let existingLabel = this.actor.data.data.typedSkills[targetskill].label;
- let existingGroup = this.actor.data.data.typedSkills[targetskill].group;
+ let existingLabel = this.actor.system.typedSkills[targetskill].label;
+ let existingGroup = this.actor.system.typedSkills[targetskill].group;
//this.actor.update({[`data.typedSkills.${targetskill}.label`]: 'test'});
@@ -242,7 +259,7 @@ export class DeltaGreenActorSheet extends ActorSheet {
let targetskill = event.target.getAttribute("data-typedskill");
// many bothans died to bring us this information on how to delete a property on an entity
- this.actor.update({[`data.typedSkills.-=${targetskill}`]: null});
+ this.actor.update({[`system.typedSkills.-=${targetskill}`]: null});
});
@@ -250,30 +267,34 @@ export class DeltaGreenActorSheet extends ActorSheet {
event.preventDefault();
- const failures = Object.entries(this.actor.data.data.skills).filter((skill) => skill[1].failure);
- if (failures.length === 0) {
+ const failedSkills = Object.entries(this.actor.system.skills).filter((skill) => skill[1].failure);
+ const failedTypedSkills = Object.entries(this.actor.system.typedSkills).filter((skill) => skill[1].failure);
+ if (failedSkills.length === 0 && failedTypedSkills.length === 0) {
ui.notifications.warn('No Skills to Increase')
return;
}
let htmlContent = "";
let failedSkillNames = "";
- failures.forEach(([skill], value) => {
+ failedSkills.forEach(([skill], value) => {
if (value === 0) {
failedSkillNames += (game.i18n.localize("DG.Skills." + skill));
} else {
failedSkillNames += `, ${(game.i18n.localize("DG.Skills." + skill))}`;
}
})
+ failedTypedSkills.forEach(([skillName, skillData], value) => {
+ if (value === 0 && failedSkillNames === "") {
+ failedSkillNames += `${game.i18n.localize("DG.TypeSkills." + skillData.group.split(" ").join(""))} (${skillData.label})`;
+ } else {
+ failedSkillNames += `, ${game.i18n.localize("DG.TypeSkills." + skillData.group.split(" ").join(""))} (${skillData.label})`;
+ }
+ })
+
+ const baseRollFormula = game.settings.get("deltagreen", "skillImprovementFormula");
htmlContent += `
`;
- htmlContent += ` ${game.i18n.localize("DG.Skills.ApplySkillImprovementsDialogLabel")} `;
- htmlContent += ` `;
- htmlContent += ` Flat +1% `;
- htmlContent += ` +1D3% `;
- htmlContent += ` +1D4% `;
- htmlContent += ` +1D4-1% `;
- htmlContent += ` `;
+ htmlContent += ` ${game.i18n.localize("DG.Skills.ApplySkillImprovementsDialogLabel")} +${baseRollFormula}% `;
htmlContent += `
`;
htmlContent += ` ${game.i18n.localize("DG.Skills.ApplySkillImprovementsDialogEffectsFollowing")} ${failedSkillNames} `;
htmlContent += ``;
@@ -286,8 +307,7 @@ export class DeltaGreenActorSheet extends ActorSheet {
apply:{
label: game.i18n.translations.DG?.Skills?.Apply ?? "Apply",
callback: btn =>{
- const baseRollForumla = btn.find("[name='roll-formula']").val();
- this._applySkillImprovements(baseRollForumla, failures);
+ this._applySkillImprovements(baseRollFormula, failedSkills, failedTypedSkills);
},
}
}
@@ -321,9 +341,21 @@ export class DeltaGreenActorSheet extends ActorSheet {
html.find('.gear-browse').click(ev => {
//game.packs.find(k=>k.collection==="deltagreen.firearms").render(true);
});
+
+ html.find('.toggle-lethality').click(event => {
+ this._toggleLethality(event);
+ });
}
+ _toggleLethality(event) {
+ const itemId = event.target.getAttribute("item-id");
+ const isLethal = event.target.getAttribute("is-lethal") === "true";
+ const item = this.actor.items.find((i) => i.id === itemId);
+ item.update({"data.isLethal": !isLethal});
+
+ }
+
_showNewEditTypeSkillDialog(targetSkill, currentLabel, currentGroup){
// TO DO: BUILD DIALOG TO CAPTURE UPDATED DATA
@@ -445,7 +477,7 @@ export class DeltaGreenActorSheet extends ActorSheet {
}
_addNewTypedSkill(newSkillLabel, newSkillGroup){
- let updatedData = duplicate(this.actor.data.data);
+ let updatedData = duplicate(this.actor.system);
let typedSkills = updatedData.typedSkills;
let d = new Date();
@@ -462,7 +494,7 @@ export class DeltaGreenActorSheet extends ActorSheet {
_updateTypedSkill(targetSkill, newSkillLabel, newSkillGroup){
if(newSkillLabel !== null && newSkillLabel !== "" && newSkillGroup !== null & newSkillGroup !== ""){
- let updatedData = duplicate(this.actor.data.data);
+ let updatedData = duplicate(this.actor.system);
updatedData.typedSkills[targetSkill].label = newSkillLabel;
updatedData.typedSkills[targetSkill].group = newSkillGroup;
@@ -478,40 +510,39 @@ export class DeltaGreenActorSheet extends ActorSheet {
* @private
*/
_onItemCreate(event) {
+
event.preventDefault();
+
const header = event.currentTarget;
+
// Get the type of item to create.
const type = header.dataset.type;
- // Grab any data associated with this control.
- const data = duplicate(header.dataset);
+
// Initialize a default name.
//const name = `New ${type.capitalize()}`;
const name = game.i18n.localize("DG.ItemTypes.NewPrefix") + game.i18n.localize("DG.ItemTypes." + type)
+
// Prepare the item object.
const itemData = {
name: name,
type: type,
- data: data
+ system: {}
};
- // Remove the type from the dataset since it's in the itemData.type prop.
- delete itemData.data["type"];
-
if(type == "weapon"){
- itemData.data.skill = "firearms"; //default skill to firearms, since that will be most common
- itemData.data.expense = "Standard";
+ itemData.system.skill = "firearms"; //default skill to firearms, since that will be most common
+ itemData.system.expense = "Standard";
}
else if(type == "armor"){
- itemData.data.armor = 3;
- itemData.data.expense = "Standard";
+ itemData.system.armor = 3;
+ itemData.system.expense = "Standard";
}
else if(type == "bond"){
- itemData.data.score = this.object.data.data.statistics.cha.value; // Can vary, but at character creation starting bond score is usually agent's charisma
+ itemData.system.score = this.object.system.statistics.cha.value; // Can vary, but at character creation starting bond score is usually agent's charisma
itemData.img = "icons/svg/mystery-man.svg"
}
- // Finally, create the item!
- //return this.actor.createOwnedItem(itemData);
+ // create the item
return this.actor.createEmbeddedDocuments("Item", [itemData]);
}
@@ -555,40 +586,40 @@ export class DeltaGreenActorSheet extends ActorSheet {
// otherwise roll a regular skill test
if(targetVal === "dex"){
label = game.i18n.localize("DG.Attributes.dex").toUpperCase() + "x5";
- targetVal = this.actor.data.data.statistics.dex.x5;
+ targetVal = this.actor.system.statistics.dex.x5;
}
else if(targetVal === "int"){
label = game.i18n.localize("DG.Attributes.int").toUpperCase() + "x5";
- targetVal = this.actor.data.data.statistics.int.x5;
+ targetVal = this.actor.system.statistics.int.x5;
}
else if(targetVal === "str"){
label = game.i18n.localize("DG.Attributes.str").toUpperCase() + "x5";
- targetVal = this.actor.data.data.statistics.str.x5;
+ targetVal = this.actor.system.statistics.str.x5;
}
else if(targetVal === "con"){
label = game.i18n.localize("DG.Attributes.con").toUpperCase() + "x5";
- targetVal = this.actor.data.data.statistics.con.x5;
+ targetVal = this.actor.system.statistics.con.x5;
}
else if(targetVal === "pow"){
label = game.i18n.localize("DG.Attributes.pow").toUpperCase() + "x5";
- targetVal = this.actor.data.data.statistics.pow.x5;
+ targetVal = this.actor.system.statistics.pow.x5;
}
else if(targetVal === "cha"){
label = game.i18n.localize("DG.Attributes.cha").toUpperCase() + "x5";
- targetVal = this.actor.data.data.statistics.cha.x5;
+ targetVal = this.actor.system.statistics.cha.x5;
}
else{
- label = game.i18n.localize("DG.Skills." + targetVal).toUpperCase() + "x5";
- targetVal = this.actor.data.data.skills[targetVal].proficiency;
+ label = game.i18n.localize("DG.Skills." + targetVal).toUpperCase();
+ targetVal = this.actor.system.skills[targetVal].proficiency;
}
}
else if(dataset.target === "statistic.x5"){
- let stat = this.actor.data.data.statistics[key];
+ let stat = this.actor.system.statistics[key];
targetVal = stat.x5;
- label = game.i18n.localize("DG.Attributes." + key).toUpperCase();
+ label = game.i18n.localize("DG.Attributes." + key).toUpperCase() + "x5";
}
else if(rollType === "sanity"){
- targetVal = this.actor.data.data.sanity.value;
+ targetVal = this.actor.system.sanity.value;
label = game.i18n.localize("DG.Attributes.SAN").toUpperCase();
}
else if(rollType === "damage"){
@@ -608,7 +639,7 @@ export class DeltaGreenActorSheet extends ActorSheet {
let skillType = dataset.skill ? dataset.skill : '';
if(this.actor.type === 'agent' && (skillType === 'unarmed_combat' || skillType === 'melee_weapons')){
- diceFormula += this.actor.data.data.statistics.str.meleeDamageBonusFormula;
+ diceFormula += this.actor.system.statistics.str.meleeDamageBonusFormula;
}
if(requestedModifyRoll){
@@ -640,13 +671,13 @@ export class DeltaGreenActorSheet extends ActorSheet {
let currentBreakingPoint = 0;
- currentBreakingPoint = this.actor.data.data.sanity.value - this.actor.data.data.statistics.pow.value;
+ currentBreakingPoint = this.actor.system.sanity.value - this.actor.system.statistics.pow.value;
if(currentBreakingPoint < 0){
currentBreakingPoint = 0;
}
- let updatedData = duplicate(this.actor.data.data);
+ let updatedData = duplicate(this.actor.system);
updatedData.sanity.currentBreakingPoint = currentBreakingPoint;
@@ -661,7 +692,7 @@ export class DeltaGreenActorSheet extends ActorSheet {
try{
//const item = this.actor.getOwnedItem(dataset.id);
const item = this.actor.items.get(dataset.id);
- var isEquipped = item.data.data.equipped;
+ var isEquipped = item.system.equipped;
isEquipped = !isEquipped;
item.update({data:{equipped: isEquipped}});
}
@@ -670,21 +701,22 @@ export class DeltaGreenActorSheet extends ActorSheet {
}
}
- _applySkillImprovements(baseRollFormula, failures) {
- const actorData = this.actor.data.data;
+ _applySkillImprovements(baseRollFormula, failedSkills, failedTypedSkills) {
+ const actorData = this.actor.system;
const resultList = [];
let rollFormula;
+ // Define the amount of dice being rolled, if any.
switch (baseRollFormula) {
case "1":
rollFormula = 1;
break;
case "1d3":
- rollFormula = `${failures.length}d3`;
+ rollFormula = `${failedSkills.length + failedTypedSkills.length}d3`;
break;
case "1d4":
case "1d4-1":
- rollFormula = `${failures.length}d4`;
+ rollFormula = `${failedSkills.length + failedTypedSkills.length}d4`;
break;
default:
}
@@ -693,38 +725,64 @@ export class DeltaGreenActorSheet extends ActorSheet {
if (rollFormula !== 1) {
roll = new Roll(rollFormula, actorData);
roll.evaluate({async: true});
+ // Put the results into a list.
roll.terms[0].results.forEach((result) => resultList.push(baseRollFormula === "1d4-1" ? result.result - 1 : result.result));
}
- let updatedSkills = "";
+ // This will be end up being a list of skills and how much each were improved by. It gets modified in the following loops.
+ let improvedSkillList = "";
- failures.forEach(([skill], value) => {
+ failedSkills.forEach(([skill], value) => {
const updatedData = duplicate(actorData);
- updatedData.skills[skill].proficiency += resultList[value] ?? 1;
+ updatedData.skills[skill].proficiency += resultList[value] ?? 1; // Increase proficiency by die result or by 1 if there is no dice roll.
updatedData.skills[skill].failure = false;
- this.actor.update({"data": updatedData});
+ this.actor.update({"system": updatedData});
- // So we can record the skills and how much they were increased by in chat.
- if (updatedSkills === "") {
- updatedSkills += `${game.i18n.localize("DG.Skills." + skill)}: +${resultList[value] ?? 1}%`;
+ // So we can record the regular skills improved and how much they were increased by in chat.
+ // The if statement tells us whether to add a comma before the term or not.
+ if (value === 0) {
+ improvedSkillList += `${game.i18n.localize("DG.Skills." + skill)}: +${resultList[value] ?? 1}% `;
} else {
- updatedSkills += `, ${game.i18n.localize("DG.Skills." + skill)}: +${resultList[value] ?? 1}%`;
+ improvedSkillList += `, ${game.i18n.localize("DG.Skills." + skill)}: +${resultList[value] ?? 1}% `;
}
})
+ failedTypedSkills.forEach(([skillName, skillData], value) => {
+ const updatedData = duplicate(actorData);
+ // We must increase value in the following line by the length of failedSkills, so that we index the entire resultList.
+ // Otherwise we would be adding the same die results to regular skills and typed skills.
+ updatedData.typedSkills[skillName].proficiency += resultList[value + failedSkills.length] ?? 1;
+ updatedData.typedSkills[skillName].failure = false;
+ this.actor.update({"system": updatedData});
+
+ // So we can record the typed skills improved and how much they were increased by in chat.
+ // The if statement tells us whether to add a comma before the term or not.
+ if (value === 0 && improvedSkillList === "") {
+ improvedSkillList += `${game.i18n.localize("DG.TypeSkills." + skillData.group.split(" ").join(""))} (${skillData.label}): +${resultList[value + failedSkills.length] ?? 1}% `;
+ } else {
+ improvedSkillList += `, ${game.i18n.localize("DG.TypeSkills." + skillData.group.split(" ").join(""))} (${skillData.label}): +${resultList[value + failedSkills.length] ?? 1}% `;
+ }
+ })
+
+ let html;
+ html = ``
+ html += `
${improvedSkillList}
`
+ html += `
`
+
const chatData = {
- speaker: ChatMessage.getSpeaker({actor: this.actor, token: this.token, alias: this.actor.data.name}),
- content: updatedSkills,
- flavor: `${game.i18n.localize("DG.Skills.ApplySkillImprovementsChatFlavor")} +${baseRollFormula}%:`,
+ speaker: ChatMessage.getSpeaker({actor: this.actor, token: this.token, alias: this.actor.name}),
+ content: html,
+ flavor: `${game.i18n.localize("DG.Skills.ApplySkillImprovementsChatFlavor")} +${baseRollFormula}% :`,
type: baseRollFormula === "1" ? 0 : 5, // 0 = CHAT_MESSAGE_TYPES.OTHER, 5 = CHAT_MESSAGE_TYPES.ROLL
- roll: baseRollFormula === "1" ? null : roll, // If adding flat +1, there is no roll.
+ rolls: baseRollFormula === "1" ? [] : [roll], // If adding flat +1, there is no roll.
rollMode: game.settings.get("core", "rollMode")
};
-
- // play the dice rolling sound, like a regular in-chat roll
- if (roll) AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true);
-
- ChatMessage.create(chatData, {});
+
+ // play the dice rolling sound, like a regular in-chat roll
+ if (roll) AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true);
+
+ ChatMessage.create(chatData, {});
+
}
_onDragStart(event) {
@@ -732,7 +790,7 @@ export class DeltaGreenActorSheet extends ActorSheet {
if ( event.target.classList.contains("entity-link") ) return;
// Create drag data
- const dragData = {
+ let dragData = {
actorId: this.actor.id,
sceneId: this.actor.isToken ? canvas.scene?.id : null,
tokenId: this.actor.isToken ? this.actor.token.id : null
@@ -742,14 +800,14 @@ export class DeltaGreenActorSheet extends ActorSheet {
if ( li.dataset.itemId ) {
const item = this.actor.items.get(li.dataset.itemId);
dragData.type = "Item";
- dragData.data = item.data;
+ dragData = item;
}
// Active Effect
if ( li.dataset.effectId ) {
const effect = this.actor.effects.get(li.dataset.effectId);
dragData.type = "ActiveEffect";
- dragData.data = effect.data;
+ dragData = effect;
}
// Set data transfer
diff --git a/module/actor/actor.js b/module/actor/actor.js
index 4f240ff..72dacd6 100644
--- a/module/actor/actor.js
+++ b/module/actor/actor.js
@@ -10,8 +10,8 @@ export class DeltaGreenActor extends Actor {
prepareData() {
super.prepareData();
- const actorData = this.data;
- const data = actorData.data;
+ const actorData = this;
+ const system = actorData.system;
const flags = actorData.flags;
//console.log('actor.js prepareData');
@@ -28,55 +28,76 @@ export class DeltaGreenActor extends Actor {
else if(actorData.type === 'npc'){
this._prepareNpcData(this);
}
+ else if(actorData.type === 'vehicle'){
+ this._prepareVehicleData(this);
+ }
}
/**
*
* @param {*} agent
*/
+
+ _prepareVehicleData(actor){
+ let actorData = actor;
+
+ // calculate total armor rating
+ let protection = 0;
+ for (let i of actor.items) {
+ if (i.type === 'armor') {
+ if(i.system.equipped === true){
+ protection += i.system.protection;
+ }
+ }
+ }
+
+ actorData.system.health.protection = protection;
+
+ console.log(actor);
+ }
+
_prepareNpcData(actor){
- let actorData = actor.data;
- const data = actorData.data;
+ const { system } = actor;
// Loop through ability scores, and add their modifiers to our sheet output.
- for (let [key, statistic] of Object.entries(data.statistics)) {
+ for (let [key, statistic] of Object.entries(system.statistics)) {
// the x5 is just whatever the raw statistic is x 5 to turn it into a d100 percentile
statistic.x5 = statistic.value * 5;
}
// initialize sanity, don't set these afterwards, as they need to be manually edited
- if(actorData.data.sanity.value >= 100){
- actorData.data.sanity.value = actorData.data.statistics.pow.x5
- actorData.data.sanity.currentBreakingPoint = actorData.data.sanity.value - actorData.data.statistics.pow.value;
+ if(system.sanity.value >= 100){
+ system.sanity.value = system.statistics.pow.x5
+ system.sanity.currentBreakingPoint = system.sanity.value - system.statistics.pow.value;
};
- actorData.data.sanity.max = 99 - actorData.data.skills.unnatural.proficiency;
+ system.sanity.max = 99 - system.skills.unnatural.proficiency;
- actorData.data.skills.ritual = {
+ system.skills.ritual = {
label: "Ritual",
- proficiency: 99 - actorData.data.sanity.value,
+ proficiency: 99 - system.sanity.value,
cannotBeImprovedByFailure: true,
failure: false
};
- if(actorData.data.skills.ritual.proficiency > 99){
- actorData.data.skills.ritual.proficiency = 99
+ if(system.skills.ritual.proficiency > 99){
+ system.skills.ritual.proficiency = 99
}
- else if(actorData.data.skills.ritual.proficiency < 1){
- actorData.data.skills.ritual.proficiency = 1
+ else if(system.skills.ritual.proficiency < 1){
+ system.skills.ritual.proficiency = 1
}
// calculate total armor rating
let protection = 0;
for (let i of actor.items) {
if (i.type === 'armor') {
- if(i.data.data.equipped === true){
- protection += i.data.data.protection;
+ if(i.system.equipped === true){
+ protection += i.system.protection;
}
}
}
- actorData.data.health.protection = protection;
+ system.health.protection = protection;
console.log(actor);
}
@@ -86,11 +107,10 @@ export class DeltaGreenActor extends Actor {
* @param {*} agent
*/
_prepareUnnaturalData(actor){
- let actorData = actor.data;
- const data = actorData.data;
+ const { system } = actor;
// Loop through ability scores, and add their modifiers to our sheet output.
- for (let [key, statistic] of Object.entries(data.statistics)) {
+ for (let [key, statistic] of Object.entries(system.statistics)) {
// the x5 is just whatever the raw statistic is x 5 to turn it into a d100 percentile
statistic.x5 = statistic.value * 5;
}
@@ -99,13 +119,13 @@ export class DeltaGreenActor extends Actor {
let protection = 0;
for (let i of actor.items) {
if (i.type === 'armor') {
- if(i.data.data.equipped === true){
- protection += i.data.data.protection;
+ if(i.system.equipped === true){
+ protection += i.system.protection;
}
}
}
- actorData.data.health.protection = protection;
+ system.health.protection = protection;
console.log(actor);
}
@@ -115,37 +135,36 @@ export class DeltaGreenActor extends Actor {
*/
_prepareAgentData(agent) {
- let actorData = agent.data;
- const data = actorData.data;
+ const { system } = agent;
// Make modifications to data here. For example:
// Loop through ability scores, and add their modifiers to our sheet output.
- for (let [key, statistic] of Object.entries(data.statistics)) {
+ for (let [key, statistic] of Object.entries(system.statistics)) {
// the x5 is just whatever the raw statistic is x 5 to turn it into a d100 percentile
statistic.x5 = statistic.value * 5;
}
// The ritual skill is from the Handler's Guide, it is for activating a ritual and is always equal to 99 - current sanity.
// The rules can be found on page 166, under 'Ritual Activation'.
- actorData.data.skills.ritual = {
+ system.skills.ritual = {
label: "Ritual",
- proficiency: 99 - actorData.data.sanity.value,
+ proficiency: 99 - system.sanity.value,
cannotBeImprovedByFailure: true,
failure: false
};
- if(actorData.data.skills.ritual.proficiency > 99){
- actorData.data.skills.ritual.proficiency = 99
+ if(system.skills.ritual.proficiency > 99){
+ system.skills.ritual.proficiency = 99
}
- else if(actorData.data.skills.ritual.proficiency < 1){
- actorData.data.skills.ritual.proficiency = 1
+ else if(system.skills.ritual.proficiency < 1){
+ system.skills.ritual.proficiency = 1
}
// The unnatural skill is sort of special
// It cannot be improved via failure, so add in a special property to reflect this
// Mostly to make it easy to deactivate the failure checkbox in the GUI
- for (let [key, skill] of Object.entries(data.skills)){
+ for (let [key, skill] of Object.entries(system.skills)){
if(key === 'unnatural'){
skill.cannotBeImprovedByFailure = true;
}
@@ -168,52 +187,52 @@ export class DeltaGreenActor extends Actor {
}
}
- actorData.data.wp.max = actorData.data.statistics.pow.value;
+ system.wp.max = system.statistics.pow.value;
- actorData.data.health.max = Math.ceil((actorData.data.statistics.con.value + actorData.data.statistics.str.value) / 2);
+ system.health.max = Math.ceil((system.statistics.con.value + system.statistics.str.value) / 2);
// initialize sanity, don't set these afterwards, as they need to be manually edited
- if(actorData.data.sanity.value >= 100){
- actorData.data.sanity.value = actorData.data.statistics.pow.x5
- actorData.data.sanity.currentBreakingPoint = actorData.data.sanity.value - actorData.data.statistics.pow.value;
+ if(system.sanity.value >= 100){
+ system.sanity.value = system.statistics.pow.x5
+ system.sanity.currentBreakingPoint = system.sanity.value - system.statistics.pow.value;
};
- actorData.data.sanity.max = 99 - actorData.data.skills.unnatural.proficiency;
+ system.sanity.max = 99 - system.skills.unnatural.proficiency;
// Sanity Loss Adaptations Logic
- let adaptations = actorData.data.sanity.adaptations;
+ let adaptations = system.sanity.adaptations;
if (adaptations.violence.incident1 && adaptations.violence.incident2 && adaptations.violence.incident3){
- actorData.data.sanity.adaptations.violence.isAdapted = true;
+ system.sanity.adaptations.violence.isAdapted = true;
}
else{
- actorData.data.sanity.adaptations.violence.isAdapted = false;
+ system.sanity.adaptations.violence.isAdapted = false;
}
if (adaptations.helplessness.incident1 && adaptations.helplessness.incident2 && adaptations.helplessness.incident3){
- actorData.data.sanity.adaptations.helplessness.isAdapted = true;
+ system.sanity.adaptations.helplessness.isAdapted = true;
}
else{
- actorData.data.sanity.adaptations.helplessness.isAdapted = false;
+ system.sanity.adaptations.helplessness.isAdapted = false;
}
// calculate total armor rating
let protection = 0;
for (let i of agent.items) {
if (i.type === 'armor') {
- if(i.data.data.equipped === true){
- protection += i.data.data.protection;
+ if(i.system.equipped === true){
+ protection += i.system.protection;
}
}
}
- actorData.data.health.protection = protection;
+ system.health.protection = protection;
// Damage Bonus/Malus From Strength in Hand-to-hand Combat (melee/unarmed)
let bonus = 0;
let sbonus = "";
- let strength = actorData.data.statistics.str;
+ let strength = system.statistics.str;
if(strength.value < 5){
sbonus = "-2";
@@ -232,17 +251,17 @@ export class DeltaGreenActor extends Actor {
bonus = 2;
}
- actorData.data.statistics.str.meleeDamageBonus = bonus;
- actorData.data.statistics.str.meleeDamageBonusFormula = sbonus;
+ system.statistics.str.meleeDamageBonus = bonus;
+ system.statistics.str.meleeDamageBonusFormula = sbonus;
console.log(agent);
}
/** @override */
static async create(data, options={}) {
- data.token = data.token || {};
+ data.prototypeToken = data.prototypeToken || {};
if ( data.type === "agent" ) {
- mergeObject(data.token, {
+ mergeObject(data.prototypeToken, {
actorLink: true // this will make the 'Link Actor Data' option for a token is checked by default. So changes to the token sheet will reflect to the actor sheet.
}, {overwrite: false});
}
@@ -254,7 +273,7 @@ export class DeltaGreenActor extends Actor {
let alreadyAdded = false;
- for(let item of this.data.items){
+ for(let item of this.items){
let flag = await item.getFlag('deltagreen', 'SystemName');
@@ -275,7 +294,7 @@ export class DeltaGreenActor extends Actor {
let _temp = await handToHandPack.getDocument(idx._id);
if(_temp.name === 'Unarmed Attack'){
- toAdd.push(_temp.data);
+ toAdd.push(_temp);
}
}
@@ -293,6 +312,41 @@ export class DeltaGreenActor extends Actor {
console.log('Error adding unarmed strike item to Actor.')
console.log(ex);
}
- }
+ }
+
+ async AddBaseVehicleItemsIfMissing(){
+ try{
+ let flag = await this.getFlag('deltagreen', 'DefaultVehicleArmorAdded');
+
+ if(flag !== null && flag !== undefined && flag !== true){
+ console.log('found a flag');
+ console.log(flag);
+ }
+ else{
+ // mark the actor so that we don't accidently do this again later, or if we want to fix/change something on it in the future
+ this.setFlag('deltagreen', 'DefaultVehicleArmorAdded', true);
+
+ let toAdd = []; // createEmbeddedDocument expects an array
+
+ let armor = await Item.create({type:"armor", name:"Vehicle Frame"});
+
+ // this is the current default, but set it anyways in case it gets changed later.
+ armor.system.protection = 3;
+
+ toAdd.push(armor);
+
+ // create the item on the actor
+ let newItems = await this.createEmbeddedDocuments("Item", toAdd);
+
+ for(let item of newItems){
+ await item.setFlag('deltagreen','AutoAdded', true);
+ }
+
+ }
+ }
+ catch(ex){
+ console.log(ex);
+ }
+ }
}
\ No newline at end of file
diff --git a/module/deltagreen.js b/module/deltagreen.js
index cc67251..11eb963 100644
--- a/module/deltagreen.js
+++ b/module/deltagreen.js
@@ -103,6 +103,8 @@ Hooks.once('init', async function() {
}
});
+
+ // Is this used anywhere?
Handlebars.registerHelper('getActorSkillProp', function(actorData, skillName, prop) {
try{
if(skillName != "" && prop != ""){
@@ -295,24 +297,31 @@ Hooks.on('createActor', async function(actor, options, userId){
// can put logic specific to a particular user session below
if (userId != game.user.id) { return; };
- if(actor != null && actor.data != null && actor.data.type === 'agent'){
- // update the default type skill of Art - Painting's labels to try to be localized
- // since I really backed myself into a corner on this with my implementation of it...
- console.log('createActor Hook');
+ if(actor != null){
- let artLabel = game.i18n.translations.DG?.TypeSkills?.Art ?? "Art";
- let paintingLabel = game.i18n.translations.DG?.TypeSkills?.Subskills?.Painting ?? "Painting";
+ if(actor.type === 'agent'){
+ // update the default type skill of Art - Painting's labels to try to be localized
+ // since I really backed myself into a corner on this with my implementation of it...
+ console.log('createActor Hook');
- let updatedData = duplicate(actor.data.data);
- updatedData.typedSkills.tskill_01.group = artLabel;
- updatedData.typedSkills.tskill_01.label = paintingLabel;
+ let artLabel = game.i18n.translations.DG?.TypeSkills?.Art ?? "Art";
+ let paintingLabel = game.i18n.translations.DG?.TypeSkills?.Subskills?.Painting ?? "Painting";
+
+ let updatedData = duplicate(actor.system);
+ updatedData.typedSkills.tskill_01.group = artLabel;
+ updatedData.typedSkills.tskill_01.label = paintingLabel;
+
+ actor.update({"data": updatedData});
+
+ // throw on an unarmed strike item for convenience
+ actor.AddUnarmedAttackItemIfMissing();
+ }
+ else if(actor.type === 'unnatural'){
- actor.update({"data": updatedData});
-
- // throw on an unarmed strike item for convenience
- actor.AddUnarmedAttackItemIfMissing();
- }
- else if(actor.data.type === 'unnatural'){
+ }
+ else if(actor.type === 'vehicle'){
+ actor.AddBaseVehicleItemsIfMissing();
+ }
}
@@ -334,25 +343,25 @@ Hooks.on('createActor', async function(actor, options, userId){
* @returns {Promise}
*/
async function createDeltaGreenMacro(data, slot) {
- if (data.type !== "Item") return;
- if (!("data" in data)) return ui.notifications.warn("You can only create macro buttons for owned Items");
- const item = data.data;
+ if (data.type !== "weapon") return;
+ //if (!("data" in data)) return ui.notifications.warn("You can only create macro buttons for owned Items");
+ const item = data.system;
// Create the macro command
let command = '// Uncomment line below to also roll skill check if desired.'
- command += '\n' + `//game.deltagreen.rollItemSkillCheckMacro("${item.name}");`;
- command += '\n' + `game.deltagreen.rollItemMacro("${item.name}");`;
+ command += '\n' + `//game.deltagreen.rollItemSkillCheckMacro("${data._id}");`;
+ command += '\n' + `game.deltagreen.rollItemMacro("${data._id}");`;
- let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command));
- if (!macro) {
- macro = await Macro.create({
- name: item.name,
+ //let macro = game.macros.entities.find(m => (m.name === data.name) && (m.command === command));
+ //if (!macro) {
+ let macro = await Macro.create({
+ name: data.name,
type: "script",
- img: item.img,
+ img: data.img,
command: command,
flags: { "deltagreen.itemMacro": true }
});
- }
+ //}
game.user.assignHotbarMacro(macro, slot);
return false;
@@ -364,7 +373,7 @@ async function createDeltaGreenMacro(data, slot) {
* @param {string} itemName
* @return {Promise}
*/
-function rollItemMacro(itemName) {
+async function rollItemMacro(itemId) {
const speaker = ChatMessage.getSpeaker();
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
@@ -372,14 +381,22 @@ function rollItemMacro(itemName) {
if(!actor) return ui.notifications.warn('Must have an Actor selected first.');
- const item = actor ? actor.items.find(i => i.name === itemName) : null;
- if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemName}`);
+ let item = actor ? actor.items.find(i => i._id === itemId) : null;
+
+ // for backwards compatibility with older macros, where I unwisely set it to use name instead of id
+ if(!item){
+ item = actor ? actor.items.find(i => i.name === itemId) : null;
+ }
+
+ if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemId}`);
// Trigger the item roll
- return item.roll();
+ let r = await item.roll();
+
+ return r;
}
-function rollItemSkillCheckMacro(itemName) {
+function rollItemSkillCheckMacro(itemId) {
const speaker = ChatMessage.getSpeaker();
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
@@ -387,12 +404,18 @@ function rollItemSkillCheckMacro(itemName) {
if(!actor) return ui.notifications.warn('Must have an Actor selected first.');
- const item = actor ? actor.items.find(i => i.name === itemName) : null;
- if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemName}`);
+ let item = actor ? actor.items.find(i => i._id === itemId) : null;
- let skillName = item.data.data.skill.toString();
+ // for backwards compatibility with older macros, where I unwisely set it to use name instead of id
+ if(!item){
+ item = actor ? actor.items.find(i => i.name === itemId) : null;
+ }
- let skill = actor.data.data.skills[skillName];
+ if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item '${itemName}'`);
+
+ let skillName = item.system.skill.toString();
+
+ let skill = actor.system.skills[skillName];
let translatedSkillLabel = "";
try{
@@ -413,7 +436,7 @@ function rollSkillMacro(skillName) {
if(!actor) return ui.notifications.warn('Must have an Actor selected first.');
- let skill = actor.data.data.skills[skillName];
+ let skill = actor.system.skills[skillName];
if(!skill) return ui.notifications.warn('Bad skill name passed to macro.');
diff --git a/module/item/item-sheet.js b/module/item/item-sheet.js
index 241144f..277eb31 100644
--- a/module/item/item-sheet.js
+++ b/module/item/item-sheet.js
@@ -19,14 +19,15 @@ export class DeltaGreenItemSheet extends ItemSheet {
const path = "systems/deltagreen/templates/item";
// unique item sheet by type, like `weapon-sheet.html`.
- return `${path}/item-${this.item.data.type}-sheet.html`;
+ return `${path}/item-${this.item.type}-sheet.html`;
}
/* -------------------------------------------- */
/** @override */
- getData() {
+ async getData() {
const data = super.getData();
+ data.enrichedDescription = await TextEditor.enrichHTML(this.object.system.description, {async: true});
return data;
}
diff --git a/module/item/item.js b/module/item/item.js
index f35a700..0098f18 100644
--- a/module/item/item.js
+++ b/module/item/item.js
@@ -12,9 +12,9 @@ export class DeltaGreenItem extends Item {
super.prepareData();
// Get the Item's data
- const itemData = this.data;
- const actorData = this.actor ? this.actor.data : {};
- const data = itemData.data;
+ const itemData = this;
+ const actorData = this.actor || {};
+ const system = itemData.system;
}
/**
@@ -24,22 +24,21 @@ export class DeltaGreenItem extends Item {
*/
async roll() {
// Basic template rendering data
- const token = this.actor.token;
- const item = this.data;
- const actorData = this.actor ? this.actor.data.data : {};
- const itemData = item.data;
+
+ const item = this;
+ const actorSystemData = this.actor.system || {};
- if(item.data.isLethal){
- sendLethalityTestToChat(this.actor, item.name, item.data.lethality, game.settings.get("core", "rollMode"))
+ if(item.system.isLethal){
+ sendLethalityTestToChat(this.actor, item.name, item.system.lethality, game.settings.get("core", "rollMode"))
}
else{
// regular damage roll
- let diceFormula = item.data.damage;
- let skillType = item.data.skill;
+ let diceFormula = item.system.damage;
+ let skillType = item.system.skill;
if(skillType === 'unarmed_combat' || skillType === 'melee_weapons'){
- diceFormula += this.actor.data.data.statistics.str.meleeDamageBonusFormula;
+ diceFormula += actorSystemData.statistics.str.meleeDamageBonusFormula;
}
sendDamageRollToChat(this.actor, item.name, diceFormula);
diff --git a/module/roll/roll.js b/module/roll/roll.js
index b37c37b..01e8009 100644
--- a/module/roll/roll.js
+++ b/module/roll/roll.js
@@ -2,7 +2,7 @@ import {localizeWithFallback} from "../other/utility-functions.js"
export async function sendPercentileTestToChat(actor, skill, target, rollMode){
//let roll = new Roll('1D100', actor.data.data).evaluate(false);
- let roll = new Roll('1D100', actor.data.data)
+ let roll = new Roll('1D100', actor.system)
await roll.evaluate({async: true});
@@ -140,7 +140,7 @@ export function skillCheckResultIsCritical(rollResult){
export async function sendLethalityTestToChat(actor, weaponName, target, rollMode){
//let roll = new Roll('1D100', actor.data.data).evaluate(false);
- let roll = new Roll('1D100', actor.data.data);
+ let roll = new Roll('1D100', actor.system);
await roll.evaluate({async: true});
@@ -244,7 +244,7 @@ export async function sendDamageRollToChat(actor, label, diceFormula, rollMode){
//diceFormula += actor.data.data.statistics.str.meleeDamageBonusFormula;
- let roll = new Roll(diceFormula, actor.data.data);
+ let roll = new Roll(diceFormula, actor.system);
await roll.evaluate({async: true});
diff --git a/module/templates.js b/module/templates.js
index daa5c0b..41eedf4 100644
--- a/module/templates.js
+++ b/module/templates.js
@@ -11,6 +11,7 @@ export const preloadHandlebarsTemplates = async function() {
"systems/deltagreen/templates/actor/unnatural-sheet.html",
"systems/deltagreen/templates/actor/npc-sheet.html",
"systems/deltagreen/templates/actor/cv-partial.html",
- "systems/deltagreen/templates/dialog/modify-percentile-roll.html"
+ "systems/deltagreen/templates/dialog/modify-percentile-roll.html",
+ "systems/deltagreen/templates/actor/vehicle-sheet.html"
]);
};
\ No newline at end of file
diff --git a/system.json b/system.json
index 6d829e3..7cf3997 100644
--- a/system.json
+++ b/system.json
@@ -1,16 +1,14 @@
{
- "name": "deltagreen",
+ "id": "deltagreen",
"title": "Delta Green (Unofficial)",
"description": "Fan-made Foundry VTT system for Delta Green: The Role Playing Game for Foundry VTT. Based on the rules in the Agent's Handbook (https://www.drivethrurpg.com/product/181674/Delta-Green-Agents-Handbook) [*NOT* Call of Cthulu]. Made with the permission of but neither affiliated with nor endorsed by Arc Dream Publishing or the Delta Green Partnership.",
- "author": "TheLastScrub (https://github.com/TheLastScrub)",
- "authors": [],
"url": "https://github.com/TheLastScrub/delta-green-foundry-vtt-system-unofficial",
"license": "LICENSE.txt",
- "flags": {},
- "version": "1.0.6",
- "minimumCoreVersion": "0.8.6",
- "compatibleCoreVersion": "9",
- "scripts": [],
+ "version": "1.0.7",
+ "compatibility": {
+ "minimum": "10.284",
+ "verified": "10"
+ },
"esmodules": [
"module/deltagreen.js"
],
@@ -22,27 +20,32 @@
{
"lang": "en",
"name": "English",
- "path": "lang/en.json"
+ "path": "lang/en.json",
+ "flags": {}
},
{
"lang": "ja",
"name": "日本語",
- "path": "lang/ja.json"
+ "path": "lang/ja.json",
+ "flags": {}
},
{
"lang": "es",
"name": "Español",
- "path": "lang/es.json"
+ "path": "lang/es.json",
+ "flags": {}
},
{
"lang": "ca",
"name": "Català",
- "path": "lang/ca.json"
+ "path": "lang/ca.json",
+ "flags": {}
},
{
"lang": "pt",
"name": "Português (Brasil)",
- "path": "lang/pt.json"
+ "path": "lang/pt.json",
+ "flags": {}
}
],
"packs": [
@@ -50,65 +53,61 @@
"name": "firearms",
"label": "Firearms",
"system": "deltagreen",
- "module": "deltagreen",
- "path": "./packs/firearms.db",
- "entity": "Item",
- "private": false
+ "path": "packs/firearms.db",
+ "private": false,
+ "type": "Item",
+ "flags": {}
},
{
"name": "armor",
"label": "Armor",
"system": "deltagreen",
- "module": "deltagreen",
- "path": "./packs/armor.db",
- "entity": "Item",
- "private": false
+ "path": "packs/armor.db",
+ "private": false,
+ "type": "Item",
+ "flags": {}
},
{
"name": "hand-to-hand-weapons",
"label": "Hand-to-Hand Weapons",
"system": "deltagreen",
- "module": "deltagreen",
- "path": "./packs/hand-to-hand-weapons.db",
- "entity": "Item",
- "private": false
+ "path": "packs/hand-to-hand-weapons.db",
+ "private": false,
+ "type": "Item",
+ "flags": {}
},
{
"name": "agent-pregens",
"label": "Agent Pregens",
"system": "deltagreen",
- "module": "deltagreen",
- "path": "./packs/pregens.db",
- "entity": "Actor",
- "private": false
+ "path": "packs/pregens.db",
+ "private": false,
+ "type": "Actor",
+ "flags": {}
},
{
"name": "operation-code-name-generator-tables",
"label": "Operation Code Name Generator Tables",
"system": "deltagreen",
- "module": "deltagreen",
- "path": "./packs/operation-code-name-generator.db",
- "entity": "RollTable",
- "private": false
+ "path": "packs/operation-code-name-generator.db",
+ "private": false,
+ "type": "RollTable",
+ "flags": {}
},
{
"name": "operation-code-name-generator-macro",
"label": "Operation Code Name Generator Macro",
"system": "deltagreen",
- "module": "deltagreen",
- "path": "./packs/operation-code-name-generator-macro.db",
- "entity": "Macro",
- "private": false
+ "path": "packs/operation-code-name-generator-macro.db",
+ "private": false,
+ "type": "Macro",
+ "flags": {}
}
],
- "system": [],
- "dependencies": [],
- "socket": false,
"manifest": "https://github.com/TheLastScrub/delta-green-foundry-vtt-system-unofficial/raw/master/system.json",
- "download": "https://github.com/TheLastScrub/delta-green-foundry-vtt-system-unofficial/archive/v1.0.6.zip",
- "protected": false,
+ "download": "https://github.com/TheLastScrub/delta-green-foundry-vtt-system-unofficial/archive/v1.0.7.zip",
"gridDistance": 1,
"gridUnits": "m",
"primaryTokenAttribute": "health",
"secondaryTokenAttribute": "wp"
-}
+}
\ No newline at end of file
diff --git a/template.json b/template.json
index 4ef4c83..41dc998 100644
--- a/template.json
+++ b/template.json
@@ -3,7 +3,8 @@
"types": [
"agent",
"unnatural",
- "npc"
+ "npc",
+ "vehicle"
],
"templates": {
"base": {
@@ -461,6 +462,19 @@
"shortDescription": "",
"showUntrainedSkills": true
},
+ "vehicle":{
+ "name": "",
+ "description": "",
+ "shortDescription": "",
+ "health": {
+ "value": 10,
+ "min": 0,
+ "max": 10
+ },
+ "speed": "",
+ "expense": "Standard",
+ "passengers": []
+ },
"agent": {
"templates": [
"base",
diff --git a/templates/actor/actor-sheet.html b/templates/actor/actor-sheet.html
index 60950ff..f9b3bca 100644
--- a/templates/actor/actor-sheet.html
+++ b/templates/actor/actor-sheet.html
@@ -12,8 +12,8 @@
-
@@ -22,51 +22,51 @@
{{!-- HP --}}
-
{{localize 'DG.Attributes.HP' }} ({{actor.data.data.health.protection}} )
+
{{localize 'DG.Attributes.HP' }} ({{actor.system.health.protection}} )
-
+
/
-
+
-
{{numberFormat actor.data.data.health.max decimals=0 sign=false}}
+
{{numberFormat actor.system.health.max decimals=0 sign=false}}
{{!-- WP --}}
-
{{localize 'DG.Attributes.WP' }}
+
{{localize 'DG.Attributes.WP' }}
-
+
/
-
+
-
{{numberFormat actor.data.data.wp.max decimals=0 sign=false}}
+
{{numberFormat actor.system.wp.max decimals=0 sign=false}}
{{!-- Sanity --}}
-
{{localize 'DG.Attributes.SAN' }}
{{#if (keepSanityPrivate)}}
-
+
/
-
{{numberFormat actor.data.data.sanity.max decimals=0 sign=false}}
+
{{numberFormat actor.system.sanity.max decimals=0 sign=false}}
{{/if}}
{{#unless (keepSanityPrivate)}}
-
+
/
-
{{numberFormat actor.data.data.sanity.max decimals=0 sign=false}}
+
{{numberFormat actor.system.sanity.max decimals=0 sign=false}}
{{/unless}}
@@ -94,10 +94,10 @@
- {{#each actor.data.data.skills as |skill key|}}
+ {{#each actor.system.skills as |skill key|}}
- {{#each actor.data.data.typedSkills as |skill key|}}
+ {{#each actor.system.typedSkills as |skill key|}}
{{skill.group}} ({{skill.label}})
-
-
+
+
@@ -162,16 +162,16 @@
{{!-- Physical Statistics like STR, CON, etc. --}}
{{localize 'DG.Physical.Wounds'}}
-
+
-
+
@@ -198,7 +198,7 @@
@@ -207,27 +207,27 @@
diff --git a/templates/actor/npc-sheet.html b/templates/actor/npc-sheet.html
index 02805df..2d2f7ca 100644
--- a/templates/actor/npc-sheet.html
+++ b/templates/actor/npc-sheet.html
@@ -1,5 +1,4 @@
-
+
@@ -22,33 +21,33 @@
{{!-- HP --}}
{{!-- WP --}}
{{!-- Sanity --}}
@@ -58,15 +57,15 @@
{{!-- Physical Statistics like STR, CON, etc. --}}
- {{#each actor.data.data.statistics as |statistic key|}}
+ {{#each actor.system.statistics as |statistic key|}}
{{/each}}
@@ -87,25 +86,25 @@
{{!-- Descriptions/Notes/Skills Tab --}}
-
+
{{!-- Checkbox to hide/show skills that are at zero --}}
- {{localize 'DG.UnnaturalSheet.HideUntrainedSkillsLabel'}}:
-
+ {{localize 'DG.UnnaturalSheet.HideUntrainedSkillsLabel'}}:
+
- {{#each actor.data.data.typedSkills as |skill key|}}
- {{#if (hideSkillBasedOnProficiencyAndUserChoice ../actor.data.data.showUntrainedSkills skill.proficiency)}}
+ {{#each actor.system.typedSkills as |skill key|}}
+ {{#if (hideSkillBasedOnProficiencyAndUserChoice ../actor.system.showUntrainedSkills skill.proficiency)}}
@@ -22,31 +21,31 @@
{{!-- HP --}}
{{!-- WP --}}
{{!-- Sanity Damage --}}
@@ -56,12 +55,12 @@
{{!-- Physical Statistics like STR, CON, etc. --}}
- {{#each actor.data.data.statistics as |statistic key|}}
+ {{#each actor.system.statistics as |statistic key|}}
@@ -84,25 +83,25 @@
{{!-- Descriptions/Notes/Skills Tab --}}
-
+
@@ -37,8 +37,8 @@
{{!-- Description Tab --}}
-
- {{editor content=data.data.description target="data.description" button=true owner=owner editable=editable}}
+
+ {{editor enrichedDescription target="system.description" button=true owner=owner editable=editable}}
diff --git a/templates/item/item-motivation-sheet.html b/templates/item/item-motivation-sheet.html
index 50a7956..7fd3838 100644
--- a/templates/item/item-motivation-sheet.html
+++ b/templates/item/item-motivation-sheet.html
@@ -9,11 +9,11 @@
{{!-- Sheet Body motivation-sheet-horizontal-grid-2col --}}
-
@@ -29,57 +29,57 @@
{{localize 'DG.ItemWindow.Weapons.Skill'}}:
-
- {{localize 'DG.Skills.firearms'}}
- {{localize 'DG.Skills.melee_weapons'}}
- {{localize 'DG.Skills.unarmed_combat'}}
- {{localize 'DG.Skills.heavy_weapons'}}
- {{localize 'DG.Skills.athletics'}}
- {{localize 'DG.Skills.demolitions'}}
- {{localize 'DG.Skills.artillery'}}
- {{localize 'DG.Attributes.str'}}x5
- {{localize 'DG.Attributes.con'}}x5
- {{localize 'DG.Attributes.dex'}}x5
- {{localize 'DG.Attributes.int'}}x5
- {{localize 'DG.Attributes.pow'}}x5
- {{localize 'DG.Attributes.cha'}}x5
+
+ {{localize 'DG.Skills.firearms'}}
+ {{localize 'DG.Skills.melee_weapons'}}
+ {{localize 'DG.Skills.unarmed_combat'}}
+ {{localize 'DG.Skills.heavy_weapons'}}
+ {{localize 'DG.Skills.athletics'}}
+ {{localize 'DG.Skills.demolitions'}}
+ {{localize 'DG.Skills.artillery'}}
+ {{localize 'DG.Attributes.str'}}x5
+ {{localize 'DG.Attributes.con'}}x5
+ {{localize 'DG.Attributes.dex'}}x5
+ {{localize 'DG.Attributes.int'}}x5
+ {{localize 'DG.Attributes.pow'}}x5
+ {{localize 'DG.Attributes.cha'}}x5
{{localize 'DG.ItemWindow.Weapons.IsLethality'}}:
-
{{localize 'DG.ItemWindow.Weapons.KillRadius'}}:
-
+
{{localize 'DG.ItemWindow.Weapons.Range'}}:
-
+
{{!-- If a weapon is 'Lethal', need to show the d100% Lethality input, otherwise only show the regular Damage formula (e.g. 1D6, 1D4+2, etc...) --}}
- {{#unless data.data.isLethal}}
+ {{#unless item.system.isLethal}}
{{localize 'DG.ItemWindow.Weapons.Damage'}}:
-
+
{{/unless}}
- {{#if data.data.isLethal}}
+ {{#if item.system.isLethal}}
{{localize 'DG.ItemWindow.Weapons.Lethality'}} %:
-
{{/if}}
{{localize 'DG.ItemWindow.Weapons.ArmorPiercing'}}:
-
+
@@ -87,7 +87,7 @@
{{localize 'DG.ItemWindow.Weapons.Ammo'}}:
-
+
@@ -102,8 +102,8 @@
{{!-- Description Tab --}}
-
- {{editor content=data.data.description target="data.description" button=true owner=owner editable=editable}}
+
+ {{editor enrichedDescription target="system.description" button=true owner=owner editable=editable}}