Item Macros + Reload Popup 0.1.0

-You can now drag items and weapons on your sheet.
-If you drag an item/weapon/skill to your macro bar it will create a rollable macro.

Reloading Changes
-When you try to fire a weapon that is either out of shots, or out of ammo, it will popup saying you need to reload.
This commit is contained in:
Martin Jencka
2020-11-23 10:27:43 -07:00
parent b62457712d
commit 417acacfe4
9 changed files with 206 additions and 25 deletions
+13
View File
@@ -170,6 +170,7 @@ export class MothershipActorSheet extends ActorSheet {
// Rollable Weapon
html.find('.weapon-roll').click(ev => {
const li = ev.currentTarget.closest(".item");
this.actor.rollWeapon(li.dataset.itemId, {
event: ev
});
@@ -243,6 +244,18 @@ export class MothershipActorSheet extends ActorSheet {
attribute.label = "Stress";
this.actor.rollStress(attribute);
});
// Drag events for macros.
if (this.actor.owner) {
let handler = ev => this._onDragStart(ev);
html.find('li.dropitem').each((i, li) => {
if (li.classList.contains("inventory-header")) return;
li.setAttribute("draggable", true);
li.addEventListener("dragstart", handler, false);
});
}
}
/* -------------------------------------------- */
+80 -6
View File
@@ -91,7 +91,7 @@ export class MothershipActor extends Actor {
rollStress(attribute) {
//this.rollAttribute(attribute, "none");
let rollOver = true;
if(attribute.label == "Calm")
if (attribute.label == "Calm")
rollOver = false;
let attLabel = attribute.label?.charAt(0).toUpperCase() + attribute.label?.toLowerCase().slice(1);
@@ -130,16 +130,71 @@ export class MothershipActor extends Actor {
item.data.ammo -= 1;
this.updateEmbeddedEntity('OwnedItem', item);
} else {
//Select the stat of the roll.
let t = new Dialog({
title: "Reload",
content: "<h2>Out of Ammo</h2><br/>",
buttons: {
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
t.render(true);
return;
}
} else {
if (item.data.curShots > 0) {
let subAmount = Math.max(item.data.shotsPerFire, 1);
item.data.curShots = Math.max(item.data.curShots-subAmount, 0);
item.data.curShots = Math.max(item.data.curShots - subAmount, 0);
console.log("Unloading Shots");
this.updateEmbeddedEntity('OwnedItem', item);
}
else {
if (item.data.ammo > 0 || !item.data.useAmmo) {
//Select the stat of the roll.
let t = new Dialog({
title: "Reload",
content: "<h2> Reload? </h2><br/>",
buttons: {
roll: {
icon: '<i class="fas fa-check"></i>',
label: "Reload",
callback: (html) => this.reloadWeapon(itemId)
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
t.render(true);
} else {
//Select the stat of the roll.
let t = new Dialog({
title: "Reload",
content: "<h2>Out of Ammo</h2><br/>",
buttons: {
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
callback: () => { }
}
},
default: "roll",
close: () => { }
});
t.render(true);
}
// let actor = this;
// let speaker = ChatMessage.getSpeaker({ actor });
// ChatMessage.create({
@@ -178,6 +233,25 @@ export class MothershipActor extends Actor {
t.render(true);
}
reloadWeapon(itemId, options = { event: null }) {
let item = duplicate(this.getEmbeddedEntity("OwnedItem", itemId));
if (event.button == 0) {
if (!item.data.useAmmo) {
item.data.curShots = item.data.shots;
} else {
item.data.ammo += item.data.curShots;
let reloadAmount = Math.min(item.data.ammo, item.data.shots);
item.data.curShots = reloadAmount;
item.data.ammo -= reloadAmount;
}
}
this.updateEmbeddedEntity('OwnedItem', item);
}
printDescription(itemId, options = { event: null }) {
let item = duplicate(this.getEmbeddedEntity("OwnedItem", itemId));
this.chatDesc(item);
@@ -247,12 +321,12 @@ export class MothershipActor extends Actor {
let a = new Roll(diceformular, {});
a.roll();
if(a._total == 100){
if (a._total == 100) {
r.results[0] = 0;
r._total = 0;
}
if(a._total == 100){
if (a._total == 100) {
r.results[0] = 0;
a._total = 0;
}
@@ -274,7 +348,7 @@ export class MothershipActor extends Actor {
//Here's where we handle the result text.
let resultText = (r._total < targetValue ? "Success" : "Failure");
if(rollOver == true)
if (rollOver == true)
resultText = (r._total > targetValue ? "Success" : "Failure");
console.log(attribute.value + attribute.mod);
@@ -412,7 +486,7 @@ export class MothershipActor extends Actor {
chatDesc(item) {
let itemName = item.name?.charAt(0).toUpperCase() + item.name?.toLowerCase().slice(1);
if (!item.name && isNaN(itemName))
itemName = item.charAt(0)?.toUpperCase() + item.toLowerCase().slice(1);
itemName = item.charAt(0)?.toUpperCase() + item.toLowerCase().slice(1);
var templateData = {
actor: this,
+11
View File
@@ -211,6 +211,17 @@ export class MothershipCreatureSheet extends ActorSheet {
});
});
// Drag events for macros.
if (this.actor.owner) {
let handler = ev => this._onDragStart(ev);
html.find('li.dropitem').each((i, li) => {
if (li.classList.contains("inventory-header")) return;
li.setAttribute("draggable", true);
li.addEventListener("dragstart", handler, false);
});
}
}
/* -------------------------------------------- */
+15 -4
View File
@@ -103,8 +103,8 @@ export class MothershipShipSheet extends ActorSheet {
const item = this.actor.getOwnedItem(li.data("itemId"));
item.sheet.render(true);
if(item.type == "module"){
item.data.totalHull = amount*item.data.hull;
if (item.type == "module") {
item.data.totalHull = amount * item.data.hull;
}
});
@@ -120,8 +120,8 @@ export class MothershipShipSheet extends ActorSheet {
item.data.quantity = Number(amount) - 1;
}
if(item.type == "module"){
item.data.totalHull = item.data.quantity*item.data.hull;
if (item.type == "module") {
item.data.totalHull = item.data.quantity * item.data.hull;
}
this.actor.updateEmbeddedEntity('OwnedItem', item);
@@ -198,6 +198,17 @@ export class MothershipShipSheet extends ActorSheet {
});
});
// Drag events for macros.
if (this.actor.owner) {
let handler = ev => this._onDragStart(ev);
html.find('li.dropitem').each((i, li) => {
if (li.classList.contains("inventory-header")) return;
li.setAttribute("draggable", true);
li.addEventListener("dragstart", handler, false);
});
}
}
/* -------------------------------------------- */
+74 -2
View File
@@ -13,7 +13,8 @@ Hooks.once('init', async function () {
game.mosh = {
MothershipActor,
MothershipItem
MothershipItem,
rollItemMacro
};
/**
@@ -75,4 +76,75 @@ Hooks.once('init', async function () {
Handlebars.registerHelper('toLowerCase', function (str) {
return str.toLowerCase();
});
});
});
Hooks.once("ready", async function () {
// Wait to register hotbar drop hook on ready so that modules could register earlier if they want to
Hooks.on("hotbarDrop", (bar, data, slot) => createMothershipMacro(data, slot));
});
/* -------------------------------------------- */
/* Hotbar Macros */
/* -------------------------------------------- */
/**
* Create a Macro from an Item drop.
* Get an existing item macro if one exists, otherwise create a new one.
* @param {Object} data The dropped data
* @param {number} slot The hotbar slot to use
* @returns {Promise}
*/
async function createMothershipMacro(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;
console.log(item);
// Create the macro command
let command = `game.mosh.rollItemMacro("${item.name}");`;
let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command));
if (!macro) {
macro = await Macro.create({
name: item.name,
type: "script",
img: item.img,
command: command,
flags: {
"mosh.itemMacro": true
}
});
}
game.user.assignHotbarMacro(macro, slot);
return false;
}
/**
* Roll Macro from a Weapon.
* @param {string} itemName
* @return {Promise}
*/
function rollItemMacro(itemName) {
const speaker = ChatMessage.getSpeaker();
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
if (!actor) actor = game.actors.get(speaker.actor);
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 with the id ${itemId}`);
console.log();
if(item.type == "weapon"){
return actor.rollWeapon(item.id);
} else if(item.type == "item" || item.type == "armor" || item.type == "ability"){
return actor.printDescription(item.id);
} else if(item.type == "skill"){
return actor.rollSkill(item.id);
}
console.error("No item type found: " + item);
}
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "mosh",
"title": "Mothership",
"description": "The unofficial Mothership system for FoundryVTT",
"version": "0.0.9",
"version": "0.1.0",
"minimumCoreVersion": "0.5.5",
"compatibleCoreVersion": "0.5.5",
"templateVersion": 2,
+5 -5
View File
@@ -308,7 +308,7 @@
</div>
</li>
{{#each actor.armors as |armor id|}}
<li class="item flexrow" data-item-id="{{armor._id}}">
<li class="item flexrow dropitem" data-item-id="{{armor._id}}">
<div class="item-image"><img src="{{armor.img}}" title="{{armor.name}}" width="24" height="24" /></div>
<h4 class="skill-name list-roll description-roll">{{armor.name}}</h4>
<div class="skill-stat">{{armor.data.bonus}}</div>
@@ -340,7 +340,7 @@
</li>
{{#if actor.data.settings.hideWeight}}
{{#each actor.gear as |item id|}}
<li class="item flexrow" data-item-id="{{item._id}}">
<li class="item flexrow dropitem" data-item-id="{{item._id}}">
<div class="item-image"><img src="{{item.img}}" title="{{item.name}}" width="24" height="24" /></div>
<h4 class="skill-name list-roll description-roll">{{item.name}}</h4>
<div class="skill-stat list-roll item-quantity">{{item.data.quantity}}</div>
@@ -353,7 +353,7 @@
{{/each}}
{{else}}
{{#each actor.gear as |item id|}}
<li class="item flexrow" data-item-id="{{item._id}}">
<li class="item flexrow dropitem" data-item-id="{{item._id}}">
<div class="item-image"><img src="{{item.img}}" title="{{item.name}}" width="24" height="24" /></div>
<h4 class="skill-name list-roll description-roll">{{item.name}}</h4>
<div class="skill-stat list-roll item-quantity">{{item.data.quantity}}</div>
@@ -384,7 +384,7 @@
</div>
</li>
{{#each actor.skills as |skill id|}}
<li class="item flexrow" data-item-id="{{skill._id}}">
<li class="item flexrow dropitem" data-item-id="{{skill._id}}">
<!-- <div class="item-image"><img src="{{skill.img}}" title="{{skill.name}}" width="24" height="24"/></div> -->
<div class="skill-name skill-roll list-roll">{{skill.name}}</div>
<div class="skill-stat">{{skill.data.rank}}</div>
@@ -414,7 +414,7 @@
</div>
</li>
{{#each actor.weapons as |weapon id|}}
<li class="item flexrow" data-item-id="{{weapon._id}}">
<li class="item flexrow dropitem" data-item-id="{{weapon._id}}">
<!-- <div class="item-image"><img src="{{skill.img}}" title="{{skill.name}}" width="24" height="24"/></div> -->
<div class="item-image"><img src="{{weapon.img}}" title="{{weapon.name}}" width="24" height="24" /></div>
<div class="skill-name weapon-roll list-roll">{{weapon.name}}</div>
+3 -3
View File
@@ -131,14 +131,14 @@
<div class="creature-ability-container creature-ability-title">Special Abilities</div>
<div class="whiteline"></div>
{{#each actor.abilities as |ability id|}}
<div class="creature-ability-container item" data-item-id="{{ability._id}}">
<li style="margin-top: -12px" class="creature-ability-container item dropitem" data-item-id="{{ability._id}}">
<div class="creature-ability-title list-roll description-roll">{{ability.name}}</div>
<div class="creature-ability-text itemtext">{{{ability.data.description}}}</div>
<div class="item-controls" style="margin-left: 3px; font-size: 0.7rem;">
<a class="item-control item-edit darkgrey" title="Edit Ability"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete darkgrey" title="Delete Ability"><i class="fas fa-trash"></i></a>
</div>
</div>
</li>
{{/each}}
<a class="item-control weapon-create darkgrey " style="margin-left: 5px;" title="Create Ability"
@@ -177,7 +177,7 @@
</div>
</li>
{{#each actor.weapons as |weapon id|}}
<li class="item flexrow" data-item-id="{{weapon._id}}">
<li class="item flexrow dropitem" data-item-id="{{weapon._id}}">
<!-- <div class="item-image"><img src="{{skill.img}}" title="{{skill.name}}" width="24" height="24"/></div> -->
<div class="item-image"><img src="{{weapon.img}}" title="{{weapon.name}}" width="24" height="24" /></div>
<div class="skill-name weapon-roll list-roll">{{weapon.name}}</div>
+4 -4
View File
@@ -159,7 +159,7 @@
</div>
<div class="creature-abilities" style="height: 300px;">
<div class="creature-ability-container creature-ability-title">Special Abilities</div>
<div class="creature-ability-container creature-ability-title">Notes</div>
<div class="whiteline"></div>
{{#each actor.abilities as |ability id|}}
<div class="creature-ability-container item" data-item-id="{{ability._id}}">
@@ -217,7 +217,7 @@
</div>
</li>
{{#each actor.weapons as |weapon id|}}
<li class="item flexrow" data-item-id="{{weapon._id}}">
<li class="item flexrow dropitem" data-item-id="{{weapon._id}}">
<!-- <div class="item-image"><img src="{{skill.img}}" title="{{skill.name}}" width="24" height="24"/></div> -->
<div class="item-image"><img src="{{weapon.img}}" title="{{weapon.name}}" width="24" height="24" /></div>
<div class="skill-name weapon-roll list-roll">{{weapon.name}}</div>
@@ -264,7 +264,7 @@
</div>
</li>
{{#each actor.modules as |module id|}}
<li class="item flexrow" data-item-id="{{module._id}}">
<li class="item flexrow dropitem" data-item-id="{{module._id}}">
<div class="item-image"><img src="{{module.img}}" title="{{module.name}}" width="24" height="24" />
</div>
<h4 class="skill-name list-roll description-roll">{{module.name}}</h4>
@@ -295,7 +295,7 @@
</div>
</li>
{{#each actor.cargo as |item id|}}
<li class="item flexrow" data-item-id="{{item._id}}">
<li class="item flexrow dropitem" data-item-id="{{item._id}}">
<div class="item-image"><img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
</div>
<h4 class="skill-name list-roll description-roll">{{item.name}}</h4>