implements last standalone tab

pull/65/head
macniel 2025-11-16 16:56:54 +01:00
parent 182aeb2dc6
commit 02f0ecc9dd
4 changed files with 392 additions and 0 deletions

View File

@ -0,0 +1,111 @@
const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
const {ActorSheetV2} = foundry.applications.sheets
export class StandaloneHealth extends HandlebarsApplicationMixin(ActorSheetV2) {
/** @inheritDoc */
static DEFAULT_OPTIONS = {
position: {width: 520, height: 716},
classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'health'],
tag: 'form',
actions: {
openEmbeddedDocument: StandaloneHealth.#openEmbeddedDocument,
setWounds: StandaloneHealth.#setWounds,
}
}
/** @inheritDoc */
static PARTS = {
form: {
template: `systems/DSA_4-1/templates/actor/character/standalone/health.hbs`
}
}
_actor = null
constructor(actor) {
super(actor)
this._actor = actor
this.render(true)
}
static async #openEmbeddedDocument(event, target) {
this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target)
}
static async #setWounds(event, target) {
this._actor?.sheet.options.actions.setWounds.bind(this)(event, target)
}
_configureRenderOptions(options) {
super._configureRenderOptions(options)
options.window.title = `${this.document.name}: Gesundheit`
return options
}
async _prepareContext(context, options, object) {
const actorData = this.document
context.system = actorData.system
context.flags = actorData.flags
context.derived = this.document.system
context.originalName = actorData.name
context.name = context.derived.name ?? actorData.name
context.effects = actorData.effects ?? []
const findEquipmentOnSlot = (slot, setNumber, object) => {
return object.items.get(object.system.heldenausruestung[setNumber]?.[slot])
}
context.inidice = actorData.system.ini.wuerfel
context.inivalue = actorData.system.ini.aktuell
context.inimod = actorData.system.ini.mod
context.zonenruestung = game.settings.get("DSA_4-1", "optional_ruestungzonen")
context.trefferzonen = game.settings.get("DSA_4-1", "optional_trefferzonen")
context.ausdauer = game.settings.get("DSA_4-1", "optional_ausdauer")
context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice')
context.aupper = Math.min((actorData.system.aup.aktuell / actorData.system.aup.max) * 100, 100)
context.lepper = Math.min((actorData.system.lep.aktuell / actorData.system.lep.max) * 100, 100)
context.keper = Math.min((actorData.system.kap.aktuell / actorData.system.kap.max) * 100, 100)
context.aspper = Math.min((actorData.system.asp.aktuell / actorData.system.asp.max) * 100, 100)
context.lepcurrent = actorData.system.lep.aktuell ?? 0
context.aupcurrent = actorData.system.aup.aktuell ?? 0
context.aspcurrent = actorData.system.asp.aktuell ?? 0
context.kapcurrent = actorData.system.kap.aktuell ?? 0
context.maxWounds = actorData.system.wunden.max ?? 3
context.wounds = actorData.system.wunden.aktuell ?? 0
context.woundsFilled = []
for (let i = 1; i <= context.maxWounds; i++) {
context.woundsFilled[i] = i <= context.wounds
}
context.withErschoepfung = game.settings.get("DSA_4-1", "optional_erschoepfung")
context.ueberanstrengung = actorData.system.ueberanstrengung
context.erschoepfung = actorData.system.erschoepfung.aktuell
context.maxErschoepfung = actorData.system.erschoepfung.max
context.erschoepfungFilled = []
for (let i = 1; i <= context.maxErschoepfung; i++) {
context.erschoepfungFilled[i] = i <= context.erschoepfung
}
context.effects = []
for (let i = 0; i < actorData.appliedEffects.length; i++) {
const item = actorData.appliedEffects[i]
context.effects.push(item.name)
}
return context
}
_onRender(context, options) {
}
}

View File

@ -21,6 +21,7 @@ import {StandaloneSkills} from "./character-standalone/skills.mjs";
import {Bagpack} from "./character-standalone/bagpack.mjs";
import {StandaloneSpells} from "./character-standalone/spells.mjs";
import {StandaloneLiturgies} from "./character-standalone/liturgies.mjs";
import {StandaloneHealth} from "./character-standalone/health.mjs";
const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
const {ActorSheetV2} = foundry.applications.sheets
@ -67,6 +68,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
openBagpack: CharacterSheet.#openBagpack,
openStandaloneSpells: CharacterSheet.#openStandaloneSpells,
openStandaloneLiturgies: CharacterSheet.#openStandaloneLiturgies,
openStandaloneHealth: CharacterSheet.#openStandaloneHealth,
setWounds: CharacterSheet.#setWounds,
}

View File

@ -255,3 +255,144 @@
}
}
.mini-health {
@include tab;
display: flex;
flex-direction: column;
padding: 0;
input {
height: 26px !important;
text-align: center !important;
padding: 0 !important;
margin: 0 !important;
width: 28px !important;
}
.side-by-side {
display: flex;
> * {
flex: 1;
}
}
.paperdoll {
div {
position: relative;
.wound {
position: absolute;
width: 32px;
height: 32px;
border-radius: 16px;
border: 1px solid black;
background-color: rgba(0, 0, 0, 0.5);
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
line-height: 32px;
vertical-align: middle;
text-align: center;
color: red;
&.armlinks {
top: 146px;
left: 210px;
}
&.armrechts {
top: 146px;
left: 60px;
}
&.beinlinks {
top: 346px;
left: 210px;
}
&.beinrechts {
top: 346px;
left: 60px;
}
&.bauch {
top: 166px;
left: 136px;
}
&.kopf {
top: 6px;
left: 136px
}
&.brust {
top: 86px;
left: 110px;
}
&.ruecken {
top: 86px;
left: 160px;
}
}
.armor {
position: absolute;
width: 32px;
height: 32px;
border-radius: 0 0 16px 16px;
line-height: 32px;
vertical-align: middle;
text-align: center;
border: 1px solid silver;
background-color: rgba(0, 0, 0, 0.5);
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
color: silver;
&.armlinks {
top: 180px;
left: 210px;
}
&.armrechts {
top: 180px;
left: 60px;
}
&.beinlinks {
top: 380px;
left: 210px;
}
&.beinrechts {
top: 380px;
left: 60px;
}
&.bauch {
top: 200px;
left: 136px;
}
&.kopf {
top: 40px;
left: 136px
}
&.ruecken {
top: 120px;
left: 160px;
}
&.brust {
top: 120px;
left: 110px;
}
}
}
}
}

View File

@ -0,0 +1,138 @@
<div class="mini-health">
<div class="combatline">
<div class="initiaitve" data-tooltip="{{fieldTooltip "ini" actorId}}">
<label>Ini:</label>
<input type="number" name="system.attribute.ini.wuerfel" value="{{this.inidice}}"/>
<span class="inline">w6</span>
<input type="number" name="system.attribute.ini.aktuell" value="{{this.inivalue}}"/>
</div>
<div class="lebensenergie" data-tooltip="{{fieldTooltip "lep" actorId}}">
<label>LeP:</label>
<input type="number" name="system.lep.aktuell" value="{{this.system.lep.aktuell}}"/>
<span class="inline">von</span>
<input type="number" disabled value="{{this.system.lep.max}}"/>
</div>
{{#if ausdauer}}
<div class="ausdauer" data-tooltip="{{fieldTooltip "aus" actorId}}">
<label>AuP:</label>
<input type="number" name="system.aup.aktuell" value="{{this.system.aup.aktuell}}"/>
<span class="inline">von</span>
<input type="number" disabled value="{{this.system.aup.max}}"/>
</div>
{{/if}}
{{#if (not zonenruestung)}}
<div class="armor">
<label>RS:</label>
{{derived.rs}}
</div>
{{/if}}
<div class="handicap">
<label>BE:</label>
{{derived.be}}
</div>
<div class="speed">
<label>GS:</label>
{{derived.gs.aktuell}}
</div>
</div>
{{#if (not trefferzonen)}}
<div class="wounds">
<label data-action="setWounds" data-value="0">Wunden: {{this.wounds}} / {{this.maxWounds}}</label>
{{#each this.woundsFilled}}
{{#if this}}
<div class="filled-segment" data-action="setWounds"
data-value="{{@index}}">{{@index}}</div>
{{else}}
<div class="empty-segment" data-action="setWounds" data-value="{{@index}}">{{@index}}</div>
{{/if}}
{{/each}}
</div>
{{/if}}
{{#if withErschoepfung}}
<div class="fatigue">
<label><span>Erschöpfung</span>
<input type="number" name="system.erschoepfung.aktuell" value="{{system.erschoepfung.aktuell}}"/>
</label>
{{#each this.erschoepfungFilled}}
{{#if this}}
<div class="filled-segment {{#if (gt ../ueberanstrengung 0)}}danger{{/if}}" {{#if
(gt ../ueberanstrengung 0)}}data-tooltip="Überanstrengt<hr/>Zusätzliche BE: {{../ueberanstrengung}}"
{{else}}data-tooltip="Erschöpft<br/>{{../system.erschoepfung.aktuell}} von maximal {{../system.erschoepfung.max}}"{{/if}}>{{@index}}</div>
{{else}}
<div class="empty-segment {{#if (gt ../ueberanstrengung 0)}}danger{{/if}}" {{#if
(gt ../ueberanstrengung 0)}}data-tooltip="Überanstrengt<hr/>Zusätzliche BE: {{../ueberanstrengung}}"
{{else}}data-tooltip="Erschöpft<br/>{{../system.erschoepfung.aktuell}} von maximal {{../system.erschoepfung.max}}"{{/if}}>{{@index}}</div>
{{/if}}
{{/each}}
{{#if (gt this.ueberanstrengung 0)}}
<div class="filled-segment {{#if (gt ueberanstrengung 0)}}danger{{/if}}" {{#if
(gt ueberanstrengung 0)}}data-tooltip="Überanstrengt<hr/>Zusätzliche BE: {{ueberanstrengung}}"
{{else}}data-tooltip="Erschöpft<br/>{{../system.erschoepfung.aktuell}} von maximal {{../system.erschoepfung.max}}"{{/if}}>{{system.erschoepfung.aktuell}}</div>
{{else}}
<div class="empty-segment {{#if (gt ueberanstrengung 0)}}danger{{/if}}" {{#if
(gt ueberanstrengung 0)}}data-tooltip="Überanstrengt<hr/>Zusätzliche BE: {{ueberanstrengung}}"
{{else}}data-tooltip="Erschöpft<br/>{{../system.erschoepfung.aktuell}} von maximal {{../system.erschoepfung.max}}"{{/if}}></div>
{{/if}}
</div>
{{/if}}
{{#if (or trefferzonen zonenruestung)}}
<div class="side-by-side">
{{/if}}
<div class="effects">
<label>Einflüsse</label>
<ul>
{{#each effects}}
<li>{{this}}</li>
{{/each}}
</ul>
</div>
{{#if (or trefferzonen zonenruestung)}}
<div class="paperdoll">
<h3>{{#if (and trefferzonen zonenruestung)}}Trefferzonen{{/if}}{{#if
(and trefferzonen (not zonenruestung))}}Wunden{{/if}}{{#if
(and (not trefferzonen) zonenruestung)}}Rüstung{{/if}}</h3>
<div>
<svg
width="280"
height="530"
viewBox="0 0 70 140"
xmlns="http://www.w3.org/2000/svg">
<path class="paperdoll-image"
d="m 22.868053,0.6591628 0.658626,-0.52687462 6.270125,4.42573652 3.97809,0.5795595 0.605938,-4.58379633 11.828915,2.02846193 0.07905,2.3182421 3.556578,-0.9220267 6.691636,3.7671414 2.292014,3.7671454 -4.030787,0.05268 0.89573,3.951549 -1.106491,2.23921 -3.345818,-0.632247 0.869387,4.241332 v 2.476303 l 1.422627,-0.02634 0.500563,1.343527 h 3.29312 l 1.975878,3.424677 0.05267,2.818774 2.371046,6.243447 6.665292,14.72611 1.949534,0.658592 0.34249,4.794545 -0.289802,1.606966 0.922074,1.765023 -0.395167,2.897805 2.002222,6.743979 1.027449,1.949433 -0.737657,5.031644 -3.925413,4.399394 -0.922074,-0.553222 0.579595,-1.844054 -1.896847,1.264499 -0.526897,-0.790314 1.475315,-1.369869 -1.36994,-5.690236 -0.974762,4.083275 -1.053803,-0.342473 -0.790345,-3.108552 0.579584,-2.370933 0.526907,-0.658592 -0.263459,-0.500527 0.289803,-1.554277 0.948418,-2.739737 -0.447865,-2.212876 -1.106492,-0.974715 -1.554356,-1.501588 -2.423744,-4.030581 0.711314,-1.264496 -3.793683,-5.532171 -0.02638,-1.554275 -1.475326,-1.554276 -1.185522,-3.213929 -0.869387,-0.763967 -3.029682,4.820892 -1.159179,0.447843 0.447865,0.974716 -0.790345,0.974716 -0.21076,2.002118 0.368823,1.343527 -0.289792,1.923087 1.71243,2.397274 0.02638,1.791371 1.23821,1.975774 2.950651,13.013779 -0.421522,0.684934 2.713536,14.278264 7.113157,18.150786 1.132835,0.0791 3.767339,9.19394 -2.344701,0.73762 1.92318,7.42891 -1.738774,3.87253 1.001116,3.79348 2.687192,4.10961 -0.68497,2.44996 -10.643392,0.079 -0.684969,-8.42997 1.106491,-1.42257 -1.659742,-1.47524 0.07905,-2.00211 -1.949535,-2.18653 -0.55325,-3.84617 -1.422628,0.15805 -0.500553,-7.71869 1.02745,-1.05374 -2.133941,-4.21499 0.421521,-2.42362 -4.32059,-6.322483 -1.317252,-4.056921 -9.247098,-17.702946 -0.395178,0.210749 -3.609266,18.783038 -1.975878,3.635422 -0.289802,10.721871 0.764011,-0.0264 2.397389,7.71869 -4.663069,0.97472 -0.737658,6.74398 -2.212983,1.92309 1.422638,6.74397 -1.896847,3.10855 -4.504997,0.34248 -0.105385,-0.86934 -3.714641,1.2118 -8.140618,0.21075 -0.131729,-2.00212 8.483107,-5.47948 0.711314,-1.89674 -0.316146,-2.18653 0.869386,-0.71128 -1.027449,-1.36986 1.659732,-6.55958 -2.502775,-0.76396 1.317252,-3.42469 -0.289792,-1.2645 2.397389,-3.05585 2.107608,-12.592278 -0.948419,-7.349881 0.316136,-13.90946 -1.554356,-1.159119 4.504996,-21.153968 0.316147,-4.557454 0.948418,-3.345646 -2.160295,2.924147 -4.847487,4.135956 1.264565,1.080091 -3.42485,2.397275 -3.29313,2.766082 -0.68497,1.923087 -1.791461,-0.57956 -1.001116,1.633307 0.07905,4.87358 L 9.168636,68.889233 4.2948053,70.180074 1.5812697,67.466679 0.13228831,66.070468 2.9775532,60.801731 6.5868297,58.825953 6.692205,57.245334 8.0884885,56.059869 v -1.923064 l 2.9769935,-7.824067 2.897953,0.553216 7.323918,-8.166536 v -0.500531 l 3.872714,-4.689172 -0.263448,-2.028463 2.766234,-5.1897 5.163622,-1.448903 0.158063,-1.844055 -0.922074,-2.291899 0.948428,-5.95367 -0.658626,-4.294017 -4.926518,-3.9515498 z"/>
</svg>
{{#if trefferzonen}}
<span class="wound kopf">{{derived.wunden.kopf}}</span>
<span class="wound brust">{{derived.wunden.brust}}</span>
<span class="wound armlinks">{{derived.wunden.armlinks}}</span>
<span class="wound armrechts">{{derived.wunden.armrechts}}</span>
<span class="wound ruecken">{{derived.wunden.ruecken}}</span>
<span class="wound bauch">{{derived.wunden.bauch}}</span>
<span class="wound beinlinks">{{derived.wunden.beinlinks}}</span>
<span class="wound beinrechts">{{derived.wunden.beinrechts}}</span>
{{/if}}
{{#if zonenruestung}}
<span class="armor kopf">{{derived.rs.kopf}}</span>
<span class="armor brust">{{derived.rs.brust}}</span>
<span class="armor armlinks">{{derived.rs.armlinks}}</span>
<span class="armor armrechts">{{derived.rs.armrechts}}</span>
<span class="armor ruecken">{{derived.rs.ruecken}}</span>
<span class="armor bauch">{{derived.rs.bauch}}</span>
<span class="armor beinlinks">{{derived.rs.beinlinks}}</span>
<span class="armor beinrechts">{{derived.rs.beinrechts}}</span>
{{/if}}
</div>
</div>
{{/if}}
{{#if (or trefferzonen zonenruestung)}}
</div>
{{/if}}
</div>