From e36f30a7872e31a2d66e41b1e927202613e306d0 Mon Sep 17 00:00:00 2001
From: Johannes Loher <johannes.loher@fg4f.de>
Date: Wed, 13 Jan 2021 17:20:25 +0100
Subject: [PATCH] Add special abilities to creature sheet

---
 src/lang/de.json                              |  1 +
 src/lang/en.json                              |  1 +
 src/module/actor/actor.ts                     |  4 +-
 src/module/actor/{ => sheets}/actor-sheet.ts  | 10 ++-
 src/module/actor/sheets/character-sheet.ts    | 11 ++++
 src/module/actor/sheets/creature-sheet.ts     | 11 ++++
 src/module/ds4.ts                             |  9 ++-
 src/templates/actor/creature-sheet.hbs        |  6 +-
 .../actor/partials/items-overview.hbs         |  2 +-
 .../special-creature-abilites-overview.hbs    | 61 +++++++++++++++++++
 .../actor/partials/spells-overview.hbs        |  2 +-
 .../actor/partials/talents-overview.hbs       |  4 +-
 12 files changed, 107 insertions(+), 15 deletions(-)
 rename src/module/actor/{ => sheets}/actor-sheet.ts (96%)
 create mode 100644 src/module/actor/sheets/character-sheet.ts
 create mode 100644 src/module/actor/sheets/creature-sheet.ts
 create mode 100644 src/templates/actor/partials/special-creature-abilites-overview.hbs

diff --git a/src/lang/de.json b/src/lang/de.json
index ba6d5569..aafc8506 100644
--- a/src/lang/de.json
+++ b/src/lang/de.json
@@ -11,6 +11,7 @@
     "DS4.HeadingTalents": "Talente & Fähigkeiten",
     "DS4.HeadingSpells": "Zaubersprüche",
     "DS4.HeadingDescription": "Beschreibung",
+    "DS4.HeadingSpecialCreatureAbilites": "Besondere Fähigkeiten",
     "DS4.AttackType": "Angriffs Typ",
     "DS4.AttackTypeAbbr": "AT",
     "DS4.WeaponBonus": "Waffen Bonus",
diff --git a/src/lang/en.json b/src/lang/en.json
index 3e6fdc93..2c74d9d9 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -11,6 +11,7 @@
     "DS4.HeadingTalents": "Talents & Abilities",
     "DS4.HeadingSpells": "Spells",
     "DS4.HeadingDescription": "Description",
+    "DS4.HeadingSpecialCreatureAbilites": "Special Abilites",
     "DS4.AttackType": "Attack Type",
     "DS4.AttackTypeAbbr": "AT",
     "DS4.WeaponBonus": "Weapon Bonus",
diff --git a/src/module/actor/actor.ts b/src/module/actor/actor.ts
index 9d4ac8e0..29d80199 100644
--- a/src/module/actor/actor.ts
+++ b/src/module/actor/actor.ts
@@ -33,16 +33,16 @@ export class DS4Actor extends Actor<DS4ActorDataType, DS4ItemDataType, DS4Item>
                     "weapon",
                     "armor",
                     "shield",
-                    "spell",
                     "trinket",
                     "equipment",
+                    "spell",
                     "talent",
                     "racialAbility",
                     "language",
                     "alphabet",
                 ];
             case "creature":
-                return ["weapon", "armor", "spell", "specialCreatureAbility"];
+                return ["weapon", "armor", "shield", "trinket", "equipment", "spell", "specialCreatureAbility"];
             default:
                 [];
         }
diff --git a/src/module/actor/actor-sheet.ts b/src/module/actor/sheets/actor-sheet.ts
similarity index 96%
rename from src/module/actor/actor-sheet.ts
rename to src/module/actor/sheets/actor-sheet.ts
index d8a3b6dc..bfb58b01 100644
--- a/src/module/actor/actor-sheet.ts
+++ b/src/module/actor/sheets/actor-sheet.ts
@@ -1,7 +1,7 @@
-import { DS4Item } from "../item/item";
-import { DS4ItemDataType, ItemType } from "../item/item-data";
-import { DS4Actor } from "./actor";
-import { DS4ActorDataType } from "./actor-data";
+import { DS4Item } from "../../item/item";
+import { DS4ItemDataType, ItemType } from "../../item/item-data";
+import { DS4Actor } from "../actor";
+import { DS4ActorDataType } from "../actor-data";
 
 /**
  * Extend the basic ActorSheet with some very simple modifications
@@ -14,7 +14,6 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
             classes: ["ds4", "sheet", "actor"],
             width: 745,
             height: 600,
-            tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "inventory" }],
         });
     }
 
@@ -40,7 +39,6 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
             // Add the items explicitly sorted by type to the data:
             itemsByType: this.actor.itemTypes,
         };
-        console.log("Data:", data);
         return data;
     }
 
diff --git a/src/module/actor/sheets/character-sheet.ts b/src/module/actor/sheets/character-sheet.ts
new file mode 100644
index 00000000..a7f9d15e
--- /dev/null
+++ b/src/module/actor/sheets/character-sheet.ts
@@ -0,0 +1,11 @@
+import { DS4ActorSheet } from "./actor-sheet";
+
+export class DS4CharacterActorSheet extends DS4ActorSheet {
+    /** @override */
+    static get defaultOptions(): FormApplicationOptions {
+        return mergeObject(super.defaultOptions, {
+            classes: ["ds4", "sheet", "actor", "character"],
+            tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "inventory" }],
+        });
+    }
+}
diff --git a/src/module/actor/sheets/creature-sheet.ts b/src/module/actor/sheets/creature-sheet.ts
new file mode 100644
index 00000000..a9103391
--- /dev/null
+++ b/src/module/actor/sheets/creature-sheet.ts
@@ -0,0 +1,11 @@
+import { DS4ActorSheet } from "./actor-sheet";
+
+export class DS4CreatureActorSheet extends DS4ActorSheet {
+    /** @override */
+    static get defaultOptions(): FormApplicationOptions {
+        return mergeObject(super.defaultOptions, {
+            classes: ["ds4", "sheet", "actor", "creature"],
+            tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "items" }],
+        });
+    }
+}
diff --git a/src/module/ds4.ts b/src/module/ds4.ts
index 8bd9ea53..e0e2a892 100644
--- a/src/module/ds4.ts
+++ b/src/module/ds4.ts
@@ -1,10 +1,11 @@
 // Import Modules
 import { DS4Actor } from "./actor/actor";
-import { DS4ActorSheet } from "./actor/actor-sheet";
 import { DS4Item } from "./item/item";
 import { DS4ItemSheet } from "./item/item-sheet";
 import { DS4 } from "./config";
 import { DS4Check } from "./rolls/check";
+import { DS4CharacterActorSheet } from "./actor/sheets/character-sheet";
+import { DS4CreatureActorSheet } from "./actor/sheets/creature-sheet";
 
 Hooks.once("init", async function () {
     console.log(`DS4 | Initializing the DS4 Game System\n${DS4.ASCII}`);
@@ -36,7 +37,8 @@ Hooks.once("init", async function () {
 
     // Register sheet application classes
     Actors.unregisterSheet("core", ActorSheet);
-    Actors.registerSheet("ds4", DS4ActorSheet, { makeDefault: true });
+    Actors.registerSheet("ds4", DS4CharacterActorSheet, { types: ["character"], makeDefault: true });
+    Actors.registerSheet("ds4", DS4CreatureActorSheet, { types: ["creature"], makeDefault: true });
     Items.unregisterSheet("core", ItemSheet);
     Items.registerSheet("ds4", DS4ItemSheet, { makeDefault: true });
 
@@ -59,6 +61,7 @@ async function registerHandlebarsPartials() {
         "systems/ds4/templates/actor/partials/combat-values.hbs",
         "systems/ds4/templates/actor/partials/profile.hbs",
         "systems/ds4/templates/actor/partials/character-progression.hbs",
+        "systems/ds4/templates/actor/partials/special-creature-abilites-overview.hbs",
     ];
     return loadTemplates(templatePaths);
 }
@@ -100,7 +103,7 @@ Hooks.once("setup", function () {
     ];
 
     // Exclude some from sorting where the default order matters
-    const noSort = ["attributes", "traits", "combatValues"];
+    const noSort = ["attributes", "traits", "combatValues", "creatureSizeCategories"];
 
     // Localize and sort CONFIG objects
     for (const o of toLocalize) {
diff --git a/src/templates/actor/creature-sheet.hbs b/src/templates/actor/creature-sheet.hbs
index 40d5eaf4..2ebf5977 100644
--- a/src/templates/actor/creature-sheet.hbs
+++ b/src/templates/actor/creature-sheet.hbs
@@ -53,8 +53,9 @@
     {{!-- Sheet Tab Navigation --}}
     <nav class="sheet-tabs tabs" data-group="primary">
         <a class="item" data-tab="inventory">{{localize 'DS4.HeadingInventory'}}</a>
-        <a class="item" data-tab="description">{{localize 'DS4.HeadingDescription'}}</a>
+        <a class="item" data-tab="special-creature-abilites">{{localize 'DS4.HeadingSpecialCreatureAbilites'}}</a>
         <a class="item" data-tab="spells">{{localize 'DS4.HeadingSpells'}}</a>
+        <a class="item" data-tab="description">{{localize 'DS4.HeadingDescription'}}</a>
     </nav>
 
     {{!-- Sheet Body --}}
@@ -62,6 +63,9 @@
         {{!-- Items Tab --}}
         {{> systems/ds4/templates/actor/partials/items-overview.hbs}}
 
+        {{!-- Special Creature Abilities Tab --}}
+        {{> systems/ds4/templates/actor/partials/special-creature-abilites-overview.hbs}}
+
         {{!-- Spells Tab --}}
         {{> systems/ds4/templates/actor/partials/spells-overview.hbs}}
 
diff --git a/src/templates/actor/partials/items-overview.hbs b/src/templates/actor/partials/items-overview.hbs
index 4dbd269b..a76c714e 100644
--- a/src/templates/actor/partials/items-overview.hbs
+++ b/src/templates/actor/partials/items-overview.hbs
@@ -1,5 +1,5 @@
 {{!-- TODO: For items list: only show header, if list is not empty --}}
-
+{{!-- TODO: Refactor to avoid code duplication with special-creature-abilites-overview and talents-overview --}}
 
 {{!-- ======================================================================== --}}
 {{!-- INLINE PARTIAL DEFINITIONS --}}
diff --git a/src/templates/actor/partials/special-creature-abilites-overview.hbs b/src/templates/actor/partials/special-creature-abilites-overview.hbs
new file mode 100644
index 00000000..28637149
--- /dev/null
+++ b/src/templates/actor/partials/special-creature-abilites-overview.hbs
@@ -0,0 +1,61 @@
+{{!-- TODO: Refactor to avoid code duplication with items-overview and talents-overview --}}
+
+{{!-- ======================================================================== --}}
+{{!-- INLINE PARTIAL DEFINITIONS --}}
+{{!-- ======================================================================== --}}
+
+{{!--
+!-- Render a list row for a base item from a given item.
+!-- Base item means it just has an image, a description, and a name (and effects).
+!-- It is a flexbox with a child for each item value of interest.
+!-- The partial assumes a variable item to be given in the context.
+!--
+!-- @param item: hand over the item to the partial as hash parameter
+--}}
+{{#*inline "baseItemListEntry"}}
+<li class="item flexrow" data-item-id="{{item._id}}">
+    {{!-- image --}}
+    <div class="flex05 item-image">
+        <img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
+    </div>
+    {{!-- name --}}
+    <input class="flex1 item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
+        data-property="name" title="{{localize 'DS4.ItemName'}}">
+    {{!-- description --}}
+    <div class="flex3 item-description">{{{item.data.data.description}}}</div>
+    {{!-- control buttons --}}
+    {{> systems/ds4/templates/actor/partials/overview-control-buttons.hbs }}
+</li>
+{{/inline}}
+
+{{!--
+!-- Render a list header for a base item list entries from a given item.
+!-- The partial assumes a variable dataType to be given in the context.
+!--
+!-- @param dataType: the string item type for the list
+--}}
+{{#*inline "baseItemListHeader"}}
+<li class="item flexrow item-header">
+    {{!-- image --}}
+    <div class="flex05 item-image"></div>
+    {{!-- name --}}
+    <div class="flex1 item-name">{{localize 'DS4.ItemName'}}</div>
+    {{!-- description --}}
+    <div class="flex3">{{localize 'DS4.Description'}}</div>
+    {{!-- add button --}}
+    {{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType=dataType }}
+</li>
+{{/inline}}
+
+
+{{!-- ======================================================================== --}}
+
+
+<div class="tab special-creature-abilites" data-group="primary" data-tab="special-creature-abilites">
+    <ol class="items-list">
+        {{> baseItemListHeader dataType='specialCreatureAbility' }}
+        {{#each itemsByType.specialCreatureAbility as |item id|}}
+        {{> baseItemListEntry item=item}}
+        {{/each}}
+    </ol>
+</div>
\ No newline at end of file
diff --git a/src/templates/actor/partials/spells-overview.hbs b/src/templates/actor/partials/spells-overview.hbs
index 5338955c..f72af894 100644
--- a/src/templates/actor/partials/spells-overview.hbs
+++ b/src/templates/actor/partials/spells-overview.hbs
@@ -27,7 +27,7 @@
 {{!-- ======================================================================== --}}
 
 
-<div class="tab items" data-group="primary" data-tab="spells">
+<div class="tab spells" data-group="primary" data-tab="spells">
     <ol class="items-list">
         <li class="item flexrow item-header">
             {{!-- equipped --}}
diff --git a/src/templates/actor/partials/talents-overview.hbs b/src/templates/actor/partials/talents-overview.hbs
index 8ef93113..96974d04 100644
--- a/src/templates/actor/partials/talents-overview.hbs
+++ b/src/templates/actor/partials/talents-overview.hbs
@@ -1,3 +1,5 @@
+{{!-- TODO: Refactor to avoid code duplication with creature-special-abilities-overview and talents-overview --}}
+
 {{!-- ======================================================================== --}}
 {{!-- INLINE PARTIAL DEFINITIONS --}}
 {{!-- ======================================================================== --}}
@@ -118,7 +120,7 @@
 {{!-- ======================================================================== --}}
 
 
-<div class="tab items" data-group="primary" data-tab="talents">
+<div class="tab talents" data-group="primary" data-tab="talents">
     <h4 class="items-list-title">{{localize 'DS4.ItemTypeTalentPlural'}}</h4>
     {{#> ifHasItemOfType itemsArray=itemsByType.talent dataType='talent' }}
     <ol class="items-list">