feat: implement streamlined single-page NPC actor sheet v0.6.12

This commit is contained in:
2026-05-28 00:05:31 +01:00
parent b931d0634b
commit acf2c8ef07
5 changed files with 856 additions and 2 deletions
+586
View File
@@ -5654,4 +5654,590 @@ p {
margin-bottom: 8px !important;
}
/* ==========================================================================
STREAMLINED NPC (CREATURE) SHEET DASHBOARD STYLES
========================================================================== */
.mosh.npc-sheet {
background: #080808 !important;
color: #e0e0e0 !important;
font-family: "Barlow Condensed", "Montserrat", sans-serif !important;
}
.mosh.npc-sheet .window-content {
background: #080808 !important;
color: #e0e0e0 !important;
padding: 12px !important;
overflow-y: auto !important;
}
/* NPC Header Styles */
.mosh .npc-header-container {
background: rgba(10, 10, 10, 0.9);
border: 1px solid rgba(0, 255, 100, 0.15);
border-radius: 6px;
padding: 12px;
margin-bottom: 12px;
box-shadow: 0 0 10px rgba(0, 255, 100, 0.05);
}
.mosh .npc-name-input {
font-family: "Montserrat", "Arial Black", sans-serif;
font-size: 1.8rem;
font-weight: 900;
color: #ffffff;
background: transparent;
border: none;
border-bottom: 2px solid rgba(0, 255, 100, 0.2);
width: 100%;
text-transform: uppercase;
letter-spacing: 1px;
padding-bottom: 4px;
margin-bottom: 8px;
transition: all 0.2s ease;
}
.mosh .npc-name-input:focus {
border-bottom-color: #00ff66;
box-shadow: 0 4px 10px rgba(0, 255, 100, 0.1);
outline: none;
}
.mosh .npc-meta-row {
display: flex;
gap: 15px;
}
.mosh .npc-meta-item {
flex: 1;
display: flex;
flex-direction: column;
}
.mosh .npc-meta-item label {
font-size: 0.75rem;
font-weight: bold;
text-transform: uppercase;
color: #00ff66;
margin-bottom: 2px;
letter-spacing: 0.5px;
}
.mosh .npc-meta-item input {
background: rgba(0, 0, 0, 0.4);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 4px;
color: #fff;
padding: 4px 8px;
font-size: 0.9rem;
transition: border-color 0.15s ease;
}
.mosh .npc-meta-item input:focus {
border-color: #00ff66;
outline: none;
}
/* Dashboard Layout */
.mosh .npc-sheet-dashboard {
display: grid;
grid-template-columns: 1.1fr 0.9fr;
gap: 15px;
align-items: start;
}
.mosh .npc-column-left,
.mosh .npc-column-right {
display: flex;
flex-direction: column;
gap: 12px;
}
/* Vitals Cards */
.mosh .npc-vitals-block {
display: flex;
gap: 12px;
}
.mosh .npc-vital-card {
flex: 1;
background: rgba(0, 0, 0, 0.5);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 5px;
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.8);
}
.mosh .npc-vital-card.health {
border-color: rgba(0, 229, 255, 0.2);
}
.mosh .npc-vital-card.wounds {
border-color: rgba(255, 50, 50, 0.2);
}
.mosh .npc-vital-label {
font-size: 0.8rem;
font-weight: bold;
text-transform: uppercase;
color: #aaa;
margin-bottom: 6px;
letter-spacing: 0.5px;
}
.mosh .npc-vital-card.health .npc-vital-label {
color: #00e5ff;
text-shadow: 0 0 5px rgba(0, 229, 255, 0.2);
}
.mosh .npc-vital-card.wounds .npc-vital-label {
color: #ff3232;
text-shadow: 0 0 5px rgba(255, 50, 50, 0.2);
}
.mosh .npc-vital-inputs {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.mosh .npc-vital-inputs input {
background: transparent;
border: none;
color: #fff;
font-size: 1.4rem;
font-weight: bold;
width: 45px;
text-align: center;
}
.mosh .npc-vital-inputs input:focus {
outline: none;
background: rgba(255, 255, 255, 0.05);
border-radius: 3px;
}
.mosh .npc-vital-inputs .divider {
color: #666;
font-size: 1.2rem;
font-weight: light;
}
/* Glowing Action Buttons */
.mosh .npc-action-buttons {
display: flex;
gap: 12px;
}
.mosh .npc-action-btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 12px;
font-family: "Barlow Condensed", sans-serif;
font-size: 1.05rem;
font-weight: 800;
border-radius: 5px;
cursor: pointer;
color: white;
border: 1px solid transparent;
text-transform: uppercase;
letter-spacing: 0.5px;
transition: all 0.2s ease;
}
.mosh .npc-wound-roll {
background: linear-gradient(135deg, #440a0a 0%, #7e1212 100%) !important;
border-color: #9c1d1d !important;
box-shadow: 0 0 10px rgba(126, 18, 18, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
}
.mosh .npc-wound-roll:hover {
background: linear-gradient(135deg, #580d0d 0%, #9e1717 100%) !important;
box-shadow: 0 0 16px rgba(220, 20, 20, 0.75), inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
transform: translateY(-1px);
}
.mosh .npc-panic-roll {
background: linear-gradient(135deg, #0a361c 0%, #155e32 100%) !important;
border-color: #1c8747 !important;
box-shadow: 0 0 10px rgba(21, 94, 50, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.1) !important;
}
.mosh .npc-panic-roll:hover {
background: linear-gradient(135deg, #0e4c27 0%, #1c7e43 100%) !important;
box-shadow: 0 0 16px rgba(30, 215, 96, 0.75), inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
transform: translateY(-1px);
}
/* Sections Block */
.mosh .npc-section-block {
background: rgba(12, 12, 12, 0.75);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 6px;
padding: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}
.mosh .npc-section-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid rgba(0, 255, 100, 0.2);
padding-bottom: 6px;
margin-bottom: 10px;
color: #00ff66;
font-family: "Barlow Condensed", sans-serif;
font-size: 1.15rem;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.mosh .npc-add-btn {
font-size: 0.8rem !important;
color: #00ff66 !important;
cursor: pointer;
transition: all 0.15s ease;
font-family: "Barlow Condensed", sans-serif;
font-weight: bold;
}
.mosh .npc-add-btn:hover {
color: #ffffff !important;
text-shadow: 0 0 8px #00ff66;
}
/* Attributes Grid */
.mosh .npc-stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.mosh .npc-stat-box {
background: rgba(0, 0, 0, 0.4);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 4px;
padding: 8px 4px;
display: flex;
flex-direction: column;
align-items: center;
transition: all 0.2s ease;
}
.mosh .npc-stat-box:hover {
border-color: rgba(0, 255, 100, 0.25);
box-shadow: 0 0 10px rgba(0, 255, 100, 0.12);
background: rgba(0, 0, 0, 0.6);
}
.mosh .npc-stat-label {
font-size: 0.75rem;
font-weight: bold;
letter-spacing: 0.5px;
color: #888;
margin-bottom: 4px;
text-align: center;
}
.mosh .npc-stat-label.clickable {
cursor: pointer;
}
.mosh .npc-stat-label.clickable:hover {
color: #00ff66;
text-shadow: 0 0 6px rgba(0, 255, 100, 0.6);
}
.mosh .npc-stat-box input {
background: transparent;
border: none;
color: #ffffff;
font-size: 1.2rem;
font-weight: 800;
text-align: center;
width: 100%;
}
.mosh .npc-stat-box input:focus {
outline: none;
background: rgba(255, 255, 255, 0.04);
border-radius: 3px;
}
/* Skills List */
.mosh .npc-skills-list {
display: flex;
flex-direction: column;
gap: 6px;
}
.mosh .npc-skill-item {
display: flex;
align-items: center;
background: rgba(0, 0, 0, 0.3);
border: 1px solid rgba(255, 255, 255, 0.04);
border-left: 3px solid #00ff66;
border-radius: 0 4px 4px 0;
padding: 6px 10px;
justify-content: space-between;
transition: all 0.15s ease;
}
.mosh .npc-skill-item:hover {
background: rgba(0, 255, 100, 0.04);
border-color: rgba(0, 255, 100, 0.15);
}
.mosh .npc-skill-item .skill-name {
font-weight: 700;
color: #eee;
flex-grow: 1;
}
.mosh .npc-skill-item .skill-name.clickable {
cursor: pointer;
}
.mosh .npc-skill-item .skill-name.clickable:hover {
color: #00ff66;
text-shadow: 0 0 6px rgba(0, 255, 100, 0.4);
}
.mosh .npc-skill-item .skill-bonus {
color: #00ff66;
font-weight: 800;
margin-right: 12px;
}
.mosh .npc-skill-item .skill-controls,
.mosh .npc-weapon-item .weapon-controls,
.mosh .npc-ability-item .ability-controls {
display: flex;
gap: 8px;
}
.mosh .npc-skill-item .skill-controls a,
.mosh .npc-weapon-item .weapon-controls a,
.mosh .npc-ability-item .ability-controls a {
color: #555 !important;
font-size: 0.8rem;
transition: color 0.15s ease;
}
.mosh .npc-skill-item .skill-controls a:hover,
.mosh .npc-weapon-item .weapon-controls a:hover,
.mosh .npc-ability-item .ability-controls a:hover {
color: #fff !important;
}
/* Profile Wrapper */
.mosh .npc-profile-wrapper {
background: rgba(0, 0, 0, 0.4);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 6px;
padding: 6px;
display: flex;
justify-content: center;
align-items: center;
height: 160px;
overflow: hidden;
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.8);
}
.mosh .npc-profile-img {
max-height: 100%;
max-width: 100%;
object-fit: cover;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
cursor: pointer;
transition: all 0.2s ease;
}
.mosh .npc-profile-img:hover {
border-color: #00ff66 !important;
box-shadow: 0 0 10px rgba(0, 255, 100, 0.25);
}
/* Weapons List */
.mosh .npc-weapons-list {
display: flex;
flex-direction: column;
gap: 6px;
}
.mosh .npc-weapon-item {
background: rgba(0, 0, 0, 0.3);
border: 1px solid rgba(255, 255, 255, 0.04);
border-left: 3px solid #ff3232;
border-radius: 0 4px 4px 0;
padding: 6px 10px;
transition: all 0.15s ease;
}
.mosh .npc-weapon-item:hover {
background: rgba(255, 50, 50, 0.04);
border-color: rgba(255, 50, 50, 0.15);
}
.mosh .npc-weapon-item .weapon-main {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.mosh .npc-weapon-item .weapon-name {
font-weight: 700;
color: #eee;
flex-grow: 1;
}
.mosh .npc-weapon-item .weapon-name.clickable {
cursor: pointer;
}
.mosh .npc-weapon-item .weapon-name.clickable:hover {
color: #ff3232;
text-shadow: 0 0 6px rgba(255, 50, 50, 0.4);
}
.mosh .npc-weapon-item .weapon-damage {
color: #ff3232;
font-weight: 800;
margin-right: 12px;
}
.mosh .npc-weapon-item .weapon-damage.clickable {
cursor: pointer;
}
.mosh .npc-weapon-item .weapon-damage.clickable:hover {
text-shadow: 0 0 6px rgba(255, 50, 50, 0.5);
}
.mosh .npc-weapon-item .weapon-ammo-count {
font-size: 0.75rem;
color: #aaa;
background: rgba(255, 255, 255, 0.06);
padding: 2px 6px;
border-radius: 3px;
margin-right: 12px;
border: 1px solid rgba(255, 255, 255, 0.05);
}
.mosh .npc-weapon-item .weapon-ammo-count.clickable {
cursor: pointer;
}
.mosh .npc-weapon-item .weapon-ammo-count.clickable:hover {
color: #fff;
border-color: rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.12);
}
/* Protection values */
.mosh .npc-armor-grid {
display: flex;
gap: 12px;
}
.mosh .npc-armor-field {
flex: 1;
display: flex;
flex-direction: column;
}
.mosh .npc-armor-field label {
font-size: 0.75rem;
font-weight: bold;
text-transform: uppercase;
color: #888;
margin-bottom: 4px;
letter-spacing: 0.5px;
}
.mosh .npc-armor-field input {
background: rgba(0, 0, 0, 0.4);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 4px;
color: #fff;
padding: 6px;
font-size: 1rem;
font-weight: 800;
text-align: center;
transition: all 0.15s ease;
}
.mosh .npc-armor-field input:focus {
border-color: #00ff66;
outline: none;
background: rgba(0, 0, 0, 0.6);
}
/* Ebon Capabilities */
.mosh .npc-abilities-list {
display: flex;
flex-direction: column;
gap: 6px;
}
.mosh .npc-ability-item {
background: rgba(0, 0, 0, 0.3);
border: 1px solid rgba(255, 255, 255, 0.04);
border-left: 3px solid #00e5ff;
border-radius: 0 4px 4px 0;
padding: 6px 10px;
}
.mosh .npc-ability-item .ability-main {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.mosh .npc-ability-item .ability-name {
font-weight: 700;
color: #00e5ff;
flex-grow: 1;
text-shadow: 0 0 4px rgba(0, 229, 255, 0.1);
}
.mosh .npc-ability-item .ability-name.clickable {
cursor: pointer;
}
.mosh .npc-ability-item .ability-name.clickable:hover {
color: #ffffff;
text-shadow: 0 0 8px #00e5ff;
}
.mosh .npc-ability-item .ability-description {
font-size: 0.8rem;
color: #bbb;
margin-top: 4px;
padding-top: 4px;
border-top: 1px solid rgba(255, 255, 255, 0.04);
line-height: 1.3;
}
/* Helper empty text */
.mosh .npc-empty-text {
font-size: 0.8rem;
color: #555;
font-style: italic;
text-align: center;
padding: 8px;
}
+57
View File
@@ -0,0 +1,57 @@
import { MothershipCreatureSheet } from "./creature-sheet.js";
/**
* Extend MothershipCreatureSheet for the streamlined NPC (creature) actor sheet.
* Displays a single-page, tab-free dashboard with core stats and equipment.
* @extends {MothershipCreatureSheet}
*/
export class MothershipNpcSheet extends MothershipCreatureSheet {
/** @override */
static get defaultOptions() {
const options = {
classes: ["mosh", "sheet", "actor", "creature", "npc-sheet"],
template: "systems/sla-mothership/templates/actor/npc-sheet.html",
width: 720,
height: 680,
tabs: [], // Disable tabs
submitOnChange: true
};
return foundry.utils.mergeObject(super.defaultOptions, options);
}
/** @override */
async getData() {
const data = await super.getData();
// Limit the displayed skills to a maximum of 5
if (data.skills) {
data.skills = data.skills.slice(0, 5);
}
// Flag to show/hide the "Add Skill" button based on 5-skill constraint
data.showAddSkill = (!data.skills || data.skills.length < 5);
return data;
}
/** @override */
activateListeners(html) {
super.activateListeners(html);
if (!this.options.editable) return;
// Custom Wound Roll Button Click
html.find('.npc-wound-roll').click(async ev => {
ev.preventDefault();
await this.actor.chooseSlaWoundTable();
});
// Custom Panic Roll Button Click
html.find('.npc-panic-roll').click(async ev => {
ev.preventDefault();
await this.actor.rollTable("panicCheck", null, null, null, null, null, null);
});
}
}
+3 -1
View File
@@ -2,6 +2,7 @@
import { MothershipActor } from "./actor/actor.js";
import { MothershipActorSheet, MothershipActorSheetDossier } from "./actor/actor-sheet.js";
import { MothershipCreatureSheet } from "./actor/creature-sheet.js";
import { MothershipNpcSheet } from "./actor/npc-sheet.js";
import { MothershipShipSheet } from "./actor/ship-sheet.js";
import { MothershipShipSheetSBT } from "./actor/ship-sheet-sbt.js";
@@ -81,7 +82,8 @@ Hooks.once('init', async function () {
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
foundry.documents.collections.Actors.registerSheet("sla-mothership", MothershipActorSheet, {types: ['character'], makeDefault: true});
foundry.documents.collections.Actors.registerSheet("sla-mothership", MothershipActorSheetDossier, {types: ['character'], makeDefault: false, label: "SLA Dossier"});
foundry.documents.collections.Actors.registerSheet("sla-mothership", MothershipCreatureSheet, {types: ['creature'], makeDefault: false});
foundry.documents.collections.Actors.registerSheet("sla-mothership", MothershipNpcSheet, {types: ['creature'], makeDefault: true, label: "SLA Streamlined NPC Sheet"});
foundry.documents.collections.Actors.registerSheet("sla-mothership", MothershipCreatureSheet, {types: ['creature'], makeDefault: false, label: "SLA Standard Creature Sheet"});
foundry.documents.collections.Actors.registerSheet("sla-mothership", MothershipShipSheetSBT, {types: ['ship'], makeDefault: true});
foundry.documents.collections.Actors.registerSheet("sla-mothership", MothershipShipSheet, {types: ['ship'], makeDefault: false});
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
+1 -1
View File
@@ -2,7 +2,7 @@
"id": "sla-mothership",
"title": "SLA Mothership",
"description": "An SLA Industries conversion built on the unofficial Mothership system for Foundry VTT, preserving Mothership's core mechanics while adding SLA flux, Ebb, BPN, and equipment support.",
"version": "0.6.11",
"version": "0.6.12",
"esmodules": [
"module/mosh.js"
],
+209
View File
@@ -0,0 +1,209 @@
<form class="{{cssClass}} npc-sheet-form" autocomplete="off">
{{!-- NPC Header --}}
<header class="npc-header-container">
<div class="npc-header-title-row">
<input name="name" class="noborder npc-name-input" type="text" value="{{name}}" placeholder="NPC / Creature Name" />
</div>
<div class="npc-meta-row">
<div class="npc-meta-item">
<label>Species</label>
<input type="text" name="system.slaNpc.species.value" value="{{system.slaNpc.species.value}}" placeholder="Unknown" />
</div>
<div class="npc-meta-item">
<label>Role</label>
<input type="text" name="system.slaNpc.role.value" value="{{system.slaNpc.role.value}}" placeholder="None" />
</div>
<div class="npc-meta-item">
<label>Threat</label>
<input type="text" name="system.slaNpc.threat.value" value="{{system.slaNpc.threat.value}}" placeholder="Low" />
</div>
</div>
</header>
{{!-- Main NPC Dashboard --}}
<div class="npc-sheet-dashboard">
{{!-- Left Column: Vitals, Actions, Stats, and Skills --}}
<div class="npc-column-left">
{{!-- Vitals --}}
<div class="npc-vitals-block">
<div class="npc-vital-card health">
<span class="npc-vital-label">{{ localize 'Mosh.Health' }}</span>
<div class="npc-vital-inputs">
<input type="text" name="system.health.value" value="{{system.health.value}}" data-dtype="Number" />
<span class="divider">/</span>
<input type="text" name="system.health.max" value="{{system.health.max}}" data-dtype="Number" />
</div>
</div>
<div class="npc-vital-card wounds">
<span class="npc-vital-label">
{{#if system.settings.firstEdition}}{{ localize 'Mosh.Wounds' }}{{else}}{{ localize 'Mosh.Hits' }}{{/if}}
</span>
<div class="npc-vital-inputs">
<input type="text" name="system.hits.value" value="{{system.hits.value}}" data-dtype="Number" />
<span class="divider">/</span>
<input type="text" name="system.hits.max" value="{{system.hits.max}}" data-dtype="Number" />
</div>
</div>
</div>
{{!-- Glowing Quick Roll Buttons --}}
<div class="npc-action-buttons">
<button type="button" class="npc-action-btn npc-wound-roll" title="Roll Wound Table">
<i class="fas fa-skull"></i> 💀 WOUND ROLL
</button>
<button type="button" class="npc-action-btn npc-panic-roll" title="Roll Panic Check">
<i class="fas fa-brain"></i> 🧠 PANIC ROLL
</button>
</div>
{{!-- Stats Grid --}}
<div class="npc-section-block">
<div class="npc-section-header">
<span><i class="fas fa-chart-bar"></i> Attributes</span>
</div>
<div class="npc-stats-grid">
<!-- Combat -->
<div class="npc-stat-box">
<span class="npc-stat-label stat-roll clickable" data-key="combat" data-roll="d100" data-label="Combat">COMBAT</span>
<input type="text" name="system.stats.combat.value" value="{{system.stats.combat.value}}" data-dtype="Number" />
</div>
<!-- Instinct -->
<div class="npc-stat-box">
<span class="npc-stat-label stat-roll clickable" data-key="instinct" data-roll="d100" data-label="Instinct">INSTINCT</span>
<input type="text" name="system.stats.instinct.value" value="{{system.stats.instinct.value}}" data-dtype="Number" />
</div>
<!-- Speed -->
<div class="npc-stat-box">
<span class="npc-stat-label stat-roll clickable" data-key="speed" data-roll="d100" data-label="Speed">SPEED</span>
<input type="text" name="system.stats.speed.value" value="{{system.stats.speed.value}}" data-dtype="Number" />
</div>
<!-- Loyalty -->
<div class="npc-stat-box">
<span class="npc-stat-label stat-roll clickable" data-key="loyalty" data-roll="d100" data-label="Loyalty">LOYALTY</span>
<input type="text" name="system.stats.loyalty.value" value="{{system.stats.loyalty.value}}" data-dtype="Number" />
</div>
<!-- Armor -->
<div class="npc-stat-box">
<span class="npc-stat-label stat-roll clickable" data-key="armor" data-roll="d100" data-label="Armor Save">ARMOR</span>
<input type="text" name="system.stats.armor.value" value="{{system.stats.armor.value}}" data-dtype="Number" />
</div>
<!-- Sanity -->
<div class="npc-stat-box">
<span class="npc-stat-label stat-roll clickable" data-key="sanity" data-roll="d100" data-label="Sanity">SANITY</span>
<input type="text" name="system.stats.sanity.value" value="{{system.stats.sanity.value}}" data-dtype="Number" />
</div>
</div>
</div>
{{!-- Skills (Max 5) --}}
<div class="npc-section-block">
<div class="npc-section-header">
<span><i class="fas fa-graduation-cap"></i> Skills (Max 5)</span>
{{#if showAddSkill}}
<a class="item-control skill-create npc-add-btn" title="Create Skill" data-type="skill"><i class="fas fa-plus"></i> Add Skill</a>
{{/if}}
</div>
<div class="npc-skills-list">
{{#each skills as |skill id|}}
<div class="npc-skill-item item" data-item-id="{{skill._id}}">
<span class="skill-name skill-roll clickable" title="Roll Skill Check">{{skill.name}}</span>
<span class="skill-bonus">+{{skill.system.bonus}}%</span>
<div class="skill-controls">
<a class="item-control skill-edit" title="Edit Skill"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Skill"><i class="fas fa-trash"></i></a>
</div>
</div>
{{else}}
<div class="npc-empty-text">No skills added yet. Click 'Add Skill' to add one.</div>
{{/each}}
</div>
</div>
</div>
{{!-- Right Column: Image, Weapons, Armor Values, and Ebon Capabilities --}}
<div class="npc-column-right">
{{!-- Profile Image --}}
<div class="npc-profile-wrapper">
<img class="img profile noborder npc-profile-img" src="{{img}}" data-edit="img" title="{{name}}" />
</div>
{{!-- Weapons --}}
<div class="npc-section-block">
<div class="npc-section-header">
<span><i class="fas fa-crosshairs"></i> Weapons</span>
<a class="item-control weapon-create npc-add-btn" title="Create Weapon" data-type="weapon"><i class="fas fa-plus"></i> Add Weapon</a>
</div>
<div class="npc-weapons-list">
{{#each weapons as |weapon id|}}
<div class="npc-weapon-item item" data-item-id="{{weapon._id}}">
<div class="weapon-main">
<span class="weapon-name weapon-roll clickable" title="Roll Attack Check">{{weapon.name}}</span>
<span class="weapon-damage dmg-roll clickable" title="Roll Damage">{{weapon.system.damage}}</span>
{{#if weapon.system.useAmmo}}
<span class="weapon-ammo-count weapon-ammo clickable" title="Right/Left click to adjust ammo">{{weapon.system.ammo}} rnds</span>
{{/if}}
<div class="weapon-controls">
<a class="item-control weapon-edit" title="Edit Weapon"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Weapon"><i class="fas fa-trash"></i></a>
</div>
</div>
</div>
{{else}}
<div class="npc-empty-text">No weapons added yet.</div>
{{/each}}
</div>
</div>
{{!-- Armor AP & DR --}}
<div class="npc-section-block">
<div class="npc-section-header">
<span><i class="fas fa-shield-alt"></i> Protection Values</span>
</div>
<div class="npc-armor-grid">
<div class="npc-armor-field">
<label>Armor Points (AP)</label>
<input type="text" name="system.stats.armor.mod" value="{{system.stats.armor.mod}}" data-dtype="Number" />
</div>
<div class="npc-armor-field">
<label>Damage Reduction (DR)</label>
<input type="text" name="system.stats.armor.damageReduction" value="{{system.stats.armor.damageReduction}}" data-dtype="Number" />
</div>
</div>
</div>
{{!-- Ebon (Ebb) Capabilities --}}
<div class="npc-section-block">
<div class="npc-section-header">
<span><i class="fas fa-magic"></i> Ebon Capabilities</span>
<a class="item-control weapon-create npc-add-btn" title="Create Ability" data-type="ability"><i class="fas fa-plus"></i> Add Ebb</a>
</div>
<div class="npc-abilities-list">
{{#each abilities as |ability id|}}
<div class="npc-ability-item item" data-item-id="{{ability._id}}">
<div class="ability-main">
<span class="ability-name description-roll clickable" title="Click to post description to chat">{{ability.name}}</span>
<div class="ability-controls">
<a class="item-control item-edit" title="Edit Ability"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Ability"><i class="fas fa-trash"></i></a>
</div>
</div>
{{#if ability.system.description}}
<div class="ability-description">{{{ability.system.description}}}</div>
{{/if}}
</div>
{{else}}
<div class="npc-empty-text">No Ebon abilities.</div>
{{/each}}
</div>
</div>
</div>
</div>
</form>