export default class RMFRPPlayerSheet extends ActorSheet { // Override Default Options, Set CSS Classes, Set Default Sheet, Set up Sheet Tabs static get defaultOptions() { return foundry.utils.mergeObject(super.defaultOptions, { width: 860, height: 780, template: "systems/fvtt-rolemaster-frp/templates/sheets/actors/rmfrp-character-sheet.html", classes: ["rmfrp", "sheet", "actor"], tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "features" }] }); } // Make the data available to the sheet template async getData() { const context = super.getData(); // Use a safe clone of the actor data for further operations. const actorData = this.actor.toObject(false); let enrichedDescription = await TextEditor.enrichHTML(this.actor.system.description, {async: true}); // Add the actor's data to context.data for easier access, as well as flags. context.system = actorData.system; context.flags = actorData.flags; context.enrichedDescription = enrichedDescription; // Prepare character data and items. if (actorData.type === "character") { this._prepareItems(context); this._prepareCharacterData(context); } // Prepare NPC data and items. if (actorData.type === "npc") { this._prepareItems(context); } return context; } // Override this method to check for duplicates when things are dragged to the sheet // We don't want duplicate skills and skill categories. async _onDropItem(event, data) { // Reconstruct the item from the event const newitem = await Item.implementation.fromDropData(data); const itemData = newitem.toObject(); // To Do: Seperate Skills and Skill Categories. Increment Counts for items if (itemData.type === "skill_category") { // Get the already owned Items from the actor and push into an array const owneditems = this.object.getOwnedItemsByType("skill_category"); let ownedskillcatlist = Object.values(owneditems); // Check if the dragged item is not in the array and not owned if (!ownedskillcatlist.includes(itemData.name)) { console.log("Not Owned!"); super._onDropItem(event, data); } } else if ( itemData.type === "skill") { // Get the already owned Items from the actor and push into an array const owneditems = this.object.getOwnedItemsByType("skill"); let ownedskilllist = Object.values(owneditems); // Check if the dragged item is not in the array and not owned if (!ownedskilllist.includes(itemData.name)) { console.log("Not Owned!"); super._onDropItem(event, data); } } else { super._onDropItem(event, data); } } _prepareCharacterData(context) { // Calculate Power Point Exhaustion let powerpointPercentage = (Number(context.system.attributes.power_points.current) / Number(context.system.attributes.power_points.max)) * 100; console.log(true); switch (true) { case (powerpointPercentage < 25): context.system.attributes.power_points.modifier = "PP Exhaustion Penalty: -30 "; break; case (powerpointPercentage < 50): context.system.attributes.power_points.modifier = "PP Exhaustion Penalty: -20 "; break; case (powerpointPercentage < 75): //console.log("Less than 75"); context.system.attributes.power_points.modifier = "PP Exhaustion Penalty: -10 "; break; default: //console.log("Setting Default"); context.system.attributes.power_points.modifier = "PP Exhaustion Penalty: 0 "; } // Calculate Exhaustion Point Penalty let exhaustionPercentage = (Number(context.system.attributes.exhaustion_points.current) / Number(context.system.attributes.exhaustion_points.max)) * 100; console.log(true); switch (true) { case (exhaustionPercentage < 1): context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -100 "; break; case (exhaustionPercentage < 10): context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -60 "; break; case (exhaustionPercentage < 25): context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -30 "; break; case (exhaustionPercentage < 50): context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -15 "; break; case (exhaustionPercentage < 75): //console.log("Less than 75"); context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -5 "; break; default: //console.log("Setting Default"); context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: 0 "; } } _prepareItems(context) { console.log(`rmfrp | rmfrp_player_sheet.js | Preparing items for: ${this.name}`); // Initialize containers. const gear = []; const playerskill= []; const skillcat = []; const weapons = []; const armor = []; const herbs = []; const spells = []; const equipables = []; // Iterate through items, allocating to containers for (let i of context.items) { i.img = i.img || DEFAULT_TOKEN; // Append to gear. if (i.type === "item") { gear.push(i); } else if (i.type === "weapon") { weapons.push(i); } else if (i.type === "herb_or_poison") { herbs.push(i); } // Append to skill categories. else if (i.type === "skill_category") { skillcat.push(i); } // Append to playerskill else if (i.type === "skill") { playerskill.push(i); } else if (i.type === "armor") { armor.push(i); } else if (i.type === "spell") { spells.push(i); } } // Parse skill categories and re+levant skills for (let s of skillcat) { s.skills = []; for (let sk of playerskill) { if (sk.system.category.toLowerCase() === s.name.toLowerCase()) { s.skills.push(sk); } } // Sort skills with localcompare s.skills.sort((a, b) => a.name.localeCompare(b.name)); } // Sort all items skillcat.sort((a, b) => a.name.localeCompare(b.name)); gear.sort((a, b) => a.name.localeCompare(b.name)); weapons.sort((a, b) => a.name.localeCompare(b.name)); armor.sort((a, b) => a.name.localeCompare(b.name)); herbs.sort((a, b) => a.name.localeCompare(b.name)); spells.sort((a, b) => a.name.localeCompare(b.name)); // Assign and return context.gear = gear; context.skillcat = skillcat; context.playerskill = playerskill; context.weapons = weapons; context.armor = armor; context.herbs = herbs; context.spells = spells; // Dump context to console console.log("ACTOR CONTEXT", context); } async renderCharacterSettings(data) { console.log(data); const configSheet = await renderTemplate("systems/fvtt-rolemaster-frp/templates/sheets/actors/dialogs/app_skill_category_importer.html", data); return (configSheet); } activateListeners(html) { super.activateListeners(html); // Render the item sheet for viewing/editing prior to the editable check. html.find(".item-edit").click(ev => { const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); item.sheet.render(true); }); html.find(".item-roll").click(ev => { const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); new game.rmfrp.applications.RMFRPToolsDiceRoller(item, this.actor).render(true); }); // ------------------------------------------------------------- // Everything below here is only needed if the sheet is editable if (!this.isEditable) return; // Add Item html.find(".item-create").click(this._onItemCreate.bind(this)); // Delete Item html.find(".item-delete").click(ev => { console.log(ev.currentTarget.getAttribute("data-item-id")); const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); item.delete(); }); // Show Skill Category Importer html.find(".import-skillcats").click(async ev => { let selectOptions = {}; for (const pack of game.packs) { if (pack.metadata.type === "Item") { selectOptions[pack.metadata.id] = pack.metadata.label; } } new game.rmfrp.applications.RMFRPToolsSCImporter(selectOptions, this.actor).render(true); }); // Check/Uncheck Favorite Skill html.find(".skill-favorite").click(ev => { const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); console.log(item); console.log(`Before change: ${item.system.favorite}`); if (item.system.favorite === true) { console.log("Setting False"); item.update({system: {favorite: false}}); } else { console.log("Setting True"); item.update({system: {favorite: true}}); } console.log(`After change: ${item.system.favorite}`); }); // Check/Uncheck Favorite Spell html.find(".spell-favorite").click(ev => { const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); console.log(item); console.log(`Before change: ${item.system.favorite}`); if (item.system.favorite === true) { console.log("Setting False"); item.update({system: {favorite: false}}); } else { console.log("Setting True"); item.update({system: {favorite: true}}); } console.log(`After change: ${item.system.favorite}`); }); // Equip/Unequip Weapon/Armor html.find(".equippable").click(ev => { const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); console.log(item); console.log(`Before change: ${item.system.equipped}`); if (item.system.equipped === true) { console.log("Setting False"); item.update({system: {equipped: false}}); } else { console.log("Setting True"); item.update({system: {equipped: true}}); } console.log(`After change: ${item.system.equipped}`); }); // Wear/Remove Item html.find(".wearable").click(ev => { const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); console.log(item); console.log(`Before change: ${item.system.equipped}`); if (item.system.worn === true) { console.log("Setting False"); item.update({system: {worn: false}}); } else { console.log("Setting True"); item.update({system: {worn: true}}); } console.log(`After change: ${item.system.equipped}`); }); // Change New Ranks value when clicked in player sheet. From 0-3. html.find(".skill-newrank").click(ev => { const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); console.log("Firing in the Player Sheet"); console.log(ev.currentTarget.getAttribute("value")); console.log(ev.currentTarget.getAttribute("data-item-id")); switch (ev.currentTarget.getAttribute("value")) { case "0": console.log("Skill NewRanks is 0 setting to 1"); item.update({system: {new_ranks: { value: 1 }}}); break; case "1": console.log("Skill NewRanks is 1 setting to 2"); item.update({system: {new_ranks: { value: 2 }}}); break; case "2": console.log("Skill NewRanks is 2 setting to 3"); item.update({system: {new_ranks: { value: 3 }}}); break; case "3": console.log("Skill NewRanks is 3 setting to 0"); item.update({system: {new_ranks: { value: 0 }}}); break; } }); // Change New Ranks value when clicked in player sheet. From 0-3. html.find(".skillcategory-newrank").click(ev => { const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); console.log("Firing in the Player Sheet"); console.log(ev.currentTarget.getAttribute("value")); console.log(ev.currentTarget.getAttribute("data-item-id")); switch (ev.currentTarget.getAttribute("value")) { case "0": console.log("Skill Category NewRanks is 0 setting to 1"); item.update({system: {new_ranks: { value: 1 }}}); break; case "1": console.log("Skill Category NewRanks is 1 setting to 2"); item.update({system: {new_ranks: { value: 2 }}}); break; case "2": console.log("Skill Category NewRanks is 2 setting to 3"); item.update({system: {new_ranks: { value: 3 }}}); break; case "3": console.log("Skill Category NewRanks is 3 setting to 0"); item.update({system: {new_ranks: { value: 0 }}}); break; } }); } async _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()}`; // Prepare the item object. const itemData = { name: name, type: type, data: data }; // Remove the type from the dataset since it's in the itemData.type prop. delete itemData.data.type; // Finally, create the item! return await Item.create(itemData, {parent: this.actor}); } }