Adds mod management (WIP)

This commit is contained in:
mstein 2022-07-05 00:10:08 +02:00
parent 8b6bfd2efb
commit c8d59588e0
18 changed files with 1181 additions and 171 deletions

View File

@ -12,10 +12,13 @@ Link to documentation: [Midgard-Forum](https://www.midgard-forum.de/forum/articl
- character sheet (WIP) - character sheet (WIP)
- rudimentary rolltables for critical rolls - rudimentary rolltables for critical rolls
- basic world map - basic world map
- Modification of the dice roller (detection of critical rolls and practice points)
## TODO ## TODO
- Race & Class Modifiers
- Items & Mods
- GM descriptions
- Modification of the standard combat tracker to fit the Midgard specific battle round rules - Modification of the standard combat tracker to fit the Midgard specific battle round rules
- Modification of the dice roller (detection of critical rolls and practice points)
## License ## License

View File

@ -197,5 +197,27 @@
"midgard5.spell-effectTarget": "Wirkunsziel", "midgard5.spell-effectTarget": "Wirkunsziel",
"midgard5.spell-effectArea": "Wirkungsbereich", "midgard5.spell-effectArea": "Wirkungsbereich",
"midgard5.spell-effectDuration": "Wirkungsdauer", "midgard5.spell-effectDuration": "Wirkungsdauer",
"midgard5.spell-origin": "Ursprung" "midgard5.spell-origin": "Ursprung",
"midgard5.mod-operation-add100": "Addieren (max 100)",
"midgard5.mod-operation-add": "Addieren",
"midgard5.mod-operation-set": "Basiswert",
"midgard5.mod-operation-fixed": "Fester Wert",
"midgard5.mod-stat-defense": "Abwehr",
"midgard5.mod-stat-attack": "Angriff",
"midgard5.mod-stat-damage": "Schaden",
"midgard5.mod-stat-movement": "Bewegung",
"midgard5.mod-stat-resistanceMind": "Resistenz Geist",
"midgard5.mod-stat-resistanceBody": "Resistenz Körper",
"midgard5.mod-stat-spellCasting": "Zaubern",
"midgard5.mod-stat-brawl": "Raufen",
"midgard5.mod-stat-poisonResistance": "Giftresistenz",
"midgard5.mod-stat-lp": "Lebenspunkte",
"midgard5.mod-stat-ap": "Ausdauerpunkte",
"midgard5.mod-type": "Typ der Modifikation",
"midgard5.mod-id": "Was soll modifiziert werden",
"midgard5.mod-operation": "Wie soll modifiziert werden",
"midgard5.mod-value": "Wert"
} }

View File

@ -0,0 +1,469 @@
{
"name": "Val",
"type": "character",
"img": "icons/svg/mystery-man.svg",
"data": {
"lp": {
"value": 15,
"min": 0,
"max": 15
},
"ap": {
"value": 20,
"min": 0,
"max": 20
},
"attributes": {
"st": {
"value": 71,
"bonus": 0
},
"gs": {
"value": 87,
"bonus": 0
},
"gw": {
"value": 87,
"bonus": 0
},
"ko": {
"value": 80,
"bonus": 0
},
"in": {
"value": 74,
"bonus": 0
},
"zt": {
"value": 96,
"bonus": 0
},
"au": {
"value": 100,
"bonus": 0
},
"pa": {
"value": 62,
"bonus": 0
},
"wk": {
"value": 82,
"bonus": 0
}
},
"info": {
"description": "",
"class": "Ordenskrieger",
"race": "",
"magicUsing": true,
"gender": "",
"weight": "",
"height": "",
"shape": "",
"age": "",
"caste": "",
"occupation": "",
"origin": "",
"faith": ""
},
"es": 4693,
"ep": 0,
"gg": 0,
"sg": 0,
"gp": 2,
"skills": {
"general": {
"akrobatik": {
"fw": 6,
"attribute": "gw",
"initial": 8
},
"alchimie": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"anfuehren": {
"fw": 6,
"attribute": "pa",
"initial": 8
},
"athletik": {
"fw": 0,
"attribute": "st",
"initial": 8
},
"balancieren": {
"fw": 6,
"attribute": "gw",
"initial": 8
},
"beidhaendigerKampf": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"beredsamkeit": {
"fw": 3,
"attribute": "pa",
"initial": 8
},
"betaeuben": {
"fw": 6,
"attribute": "gs",
"initial": 8
},
"bootfahren": {
"fw": 3,
"attribute": "gs",
"initial": 8
},
"ersteHilfe": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"etikette": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"fallenEntdecken": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"fallenmechanik": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"faelschen": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"fechten": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"gassenwissen": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"gaukeln": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"gelaendelauf": {
"fw": 6,
"attribute": "gw",
"initial": 8
},
"geraetekunde": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"geschaeftssinn": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"gluecksspiel": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"heilkunde": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"kampfInVollruestung": {
"fw": 0,
"attribute": "st",
"initial": 8
},
"klettern": {
"fw": 6,
"attribute": "st",
"initial": 8
},
"landeskunde": {
"fw": 6,
"attribute": "in",
"initial": 8
},
"laufen": {
"fw": 0,
"attribute": "ko",
"initial": 8
},
"lesenVonZauberschrift": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"meditieren": {
"fw": 0,
"attribute": "wk",
"initial": 8
},
"menschenkenntnis": {
"fw": 3,
"attribute": "in",
"initial": 8
},
"meucheln": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"musizieren": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"naturkunde": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"pflanzenkunde": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"reiten": {
"fw": 6,
"attribute": "gw",
"initial": 8
},
"reiterkampf": {
"fw": 0,
"attribute": "gw",
"initial": 8
},
"scharfschiessen": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"schleichen": {
"fw": 3,
"attribute": "gw",
"initial": 8
},
"schloesserOeffnen": {
"fw": 0,
"attribute": "gs",
"initial": 8
},
"schwimmen": {
"fw": 3,
"attribute": "gw",
"initial": 8
},
"seilkunst": {
"fw": 3,
"attribute": "gs",
"initial": 8
},
"spurensuche": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"stehlen": {
"fw": 3,
"attribute": "gs",
"initial": 8
},
"tarnen": {
"fw": 3,
"attribute": "gw",
"initial": 8
},
"tauchen": {
"fw": 6,
"attribute": "ko",
"initial": 8
},
"tierkunde": {
"fw": 0,
"attribute": "in",
"initial": 8
},
"ueberleben": {
"fw": 6,
"attribute": "in",
"initial": 8
},
"verfuehren": {
"fw": 3,
"attribute": "pa",
"initial": 8
},
"verhoeren": {
"fw": 3,
"attribute": "pa",
"initial": 8
},
"verstellen": {
"fw": 3,
"attribute": "pa",
"initial": 8
},
"wagenlenken": {
"fw": 3,
"attribute": "gs",
"initial": 8
},
"zauberkunde": {
"fw": 0,
"attribute": "in",
"initial": 8
}
}
},
"calc": {}
},
"token": {
"name": "Val",
"img": "icons/svg/mystery-man.svg",
"displayName": 0,
"actorLink": false,
"width": 1,
"height": 1,
"scale": 1,
"mirrorX": false,
"mirrorY": false,
"lockRotation": false,
"rotation": 0,
"alpha": 1,
"vision": false,
"dimSight": 0,
"brightSight": 0,
"sightAngle": 0,
"light": {
"alpha": 0.5,
"angle": 0,
"bright": 0,
"coloration": 1,
"dim": 0,
"gradual": true,
"luminosity": 0.5,
"saturation": 0,
"contrast": 0,
"shadows": 0,
"animation": {
"speed": 5,
"intensity": 5,
"reverse": false
},
"darkness": {
"min": 0,
"max": 1
}
},
"disposition": -1,
"displayBars": 0,
"bar1": {
"attribute": "lp"
},
"bar2": {
"attribute": "ap"
},
"flags": {},
"randomImg": false
},
"items": [
{
"_id": "0c7eqO7G0q6xfleC",
"name": "Wahrnehmung",
"type": "skill",
"img": "icons/svg/item-bag.svg",
"data": {
"description": "",
"attributes": {
"st": {
"short": "midgard5.actor-st",
"long": "midgard5.actor-st-long"
},
"gs": {
"short": "midgard5.actor-gs",
"long": "midgard5.actor-gs-long"
},
"gw": {
"short": "midgard5.actor-gw",
"long": "midgard5.actor-gw-long"
},
"ko": {
"short": "midgard5.actor-ko",
"long": "midgard5.actor-ko-long"
},
"in": {
"short": "midgard5.actor-in",
"long": "midgard5.actor-in-long"
},
"zt": {
"short": "midgard5.actor-zt",
"long": "midgard5.actor-zt-long"
},
"au": {
"short": "midgard5.actor-au",
"long": "midgard5.actor-au-long"
},
"pa": {
"short": "midgard5.actor-pa",
"long": "midgard5.actor-pa-long"
},
"wk": {
"short": "midgard5.actor-wk",
"long": "midgard5.actor-wk-long"
}
},
"fw": 6,
"attribute": "",
"skill": "",
"type": "innate",
"rolls": {
"formulas": {
"0": {
"formula": "1d20 + @i.fw + @i.calc.bonus",
"type": "ew",
"label": "EW"
}
},
"output": ""
},
"calc": {}
},
"effects": [],
"folder": null,
"sort": 0,
"permission": {
"default": 0,
"XD0IpWT6bN4AJiYQ": 3
},
"flags": {}
}
],
"effects": [],
"folder": null,
"sort": 0,
"permission": {
"default": 0,
"XD0IpWT6bN4AJiYQ": 3
},
"flags": {
"core": {
"sourceId": "Actor.wpOCjtgirIyBM6jH"
}
},
"_id": "fuXWE1rW4QIsywAk"
}

View File

@ -65,10 +65,5 @@
"default": 0, "default": 0,
"XD0IpWT6bN4AJiYQ": 3 "XD0IpWT6bN4AJiYQ": 3
}, },
"flags": {
"core": {
"sourceId": "Item.ieQ6JMEyOoF7n0qy"
}
},
"_id": "nkMkMFNDSdvlP1Jt" "_id": "nkMkMFNDSdvlP1Jt"
} }

View File

@ -0,0 +1,46 @@
{
"name": "Rüstung",
"type": "armor",
"img": "icons/svg/item-bag.svg",
"data": {
"description": "",
"stats": {
"damageBonus": 0,
"attackBonus": 0,
"defenseBonus": 0,
"movementBonus": 0,
"resistanceMind": 0,
"resistanceBody": 0,
"spellBonus": 0
},
"equippable": false,
"equipped": true,
"attributeMod": {
"st": 0,
"gs": 0,
"gw": 0,
"ko": 0,
"in": 0,
"zt": 0,
"au": 0,
"pa": 0,
"wk": 0
},
"magic": false,
"lpProtection": 0,
"apProtection": 0,
"rolls": {
"formulas": {},
"output": ""
},
"calc": {}
},
"effects": [],
"folder": null,
"sort": 0,
"permission": {
"default": 0,
"XD0IpWT6bN4AJiYQ": 3
},
"_id": "pV1hNavlQGJ9UaEf"
}

View File

@ -0,0 +1,67 @@
{
"name": "Zauber",
"type": "spell",
"img": "icons/svg/item-bag.svg",
"data": {
"description": "",
"spellProcessSelection": {
"none": "midgard5.spell-process-none",
"beherrschen": "midgard5.spell-process-beherrschen",
"bewegen": "midgard5.spell-process-bewegen",
"erkennen": "midgard5.spell-process-erkennen",
"erschaffen": "midgard5.spell-process-erschaffen",
"formen": "midgard5.spell-process-formen",
"veraendern": "midgard5.spell-process-veraendern",
"zerstoeren": "midgard5.spell-process-zerstoeren",
"wundertat": "midgard5.spell-process-wundertat",
"dweomer": "midgard5.spell-process-dweomer",
"zauberlied": "midgard5.spell-process-zauberlied",
"salz": "midgard5.spell-process-salz",
"thaumagraphie": "midgard5.spell-process-thaumagraphie",
"beschwoeren": "midgard5.spell-process-beschwoeren",
"nekromantie": "midgard5.spell-process-nekromantie",
"thaumatherapie": "midgard5.spell-process-thaumatherapie",
"zaubermittel": "midgard5.spell-process-zaubermittel",
"zauberschutz": "midgard5.spell-process-zauberschutz"
},
"spellTypeSelection": {
"gedanke": "midgard5.spell-type-gedanke",
"geste": "midgard5.spell-type-geste",
"wort": "midgard5.spell-type-wort"
},
"spellTargetSelection": {
"umgebung": "midgard5.spell-target-umgebung",
"geist": "midgard5.spell-target-geist",
"koerper": "midgard5.spell-target-koerper"
},
"bonus": 0,
"type": "gedanke",
"process": "none",
"ap": 0,
"castDuration": "",
"range": "",
"effectTarget": "umgebung",
"effectArea": "",
"effectDuration": "",
"origin": "",
"rolls": {
"formulas": {
"0": {
"formula": "1d20 + @c.calc.stats.spellCasting + @i.bonus",
"type": "ew",
"label": "Zaubern"
}
},
"output": ""
},
"calc": {}
},
"effects": [],
"folder": null,
"sort": 0,
"permission": {
"default": 0,
"XD0IpWT6bN4AJiYQ": 3
},
"_id": "HQ469FvZkwKfzFfu"
}

View File

@ -1,4 +1,48 @@
export interface M5CharacterCalculatedData {
level: number
attributes: {
st: { value: number, bonus: number }
gs: { value: number, bonus: number }
gw: { value: number, bonus: number }
ko: { value: number, bonus: number }
in: { value: number, bonus: number }
zt: { value: number, bonus: number }
au: { value: number, bonus: number }
pa: { value: number, bonus: number }
wk: { value: number, bonus: number }
}
stats: {
armor: number
defense: number
damageBonus: number
attackBonus: number
defenseBonus: number
movementBonus: number
resistanceMind: number
resistanceBody: number
spellCasting: number
brawl: number
brawlEw: number
poisonResistance: number
enduranceBonus: number
}
skills: {
innate: {}
general: {}
combat: {}
language: {}
custom: {}
}
gear: {
weapons: {}
defensiveWeapons: {}
armor: {}
items: {}
}
spells: {}
}
export interface M5Skill { export interface M5Skill {
fw: number fw: number
attribute: string attribute: string
@ -13,6 +57,11 @@ export interface M5SkillLearned extends M5Skill {
type: string type: string
} }
export interface M5SkillCalculated extends M5Skill {
label: string,
calc: any
}
export interface M5Attribute { export interface M5Attribute {
value: number value: number
bonus: number bonus: number
@ -47,4 +96,54 @@ export enum M5EwResult {
HIGH = "roll-ew-result-high", HIGH = "roll-ew-result-high",
FAIL = "roll-ew-result-fail", FAIL = "roll-ew-result-fail",
PASS = "roll-ew-result-pass" PASS = "roll-ew-result-pass"
} }
export enum M5Attributes {
ST = "st",
GW = "gw",
GS = "gs",
KO = "ko",
IN = "in",
ZT = "zt",
AU = "au",
PA = "pa",
WK = "wk"
}
export enum M5Stats {
DEFENSE = "defense",
ATTACK = "attack",
DAMAGE = "damage",
MOVEMENT = "movement",
RESISTANCE_MIND = "resistanceMind",
RESISTANCE_BODY = "resistanceBody",
SPELL_CASTING = "spellCasting",
BRAWL = "brawl",
POISON_RESISTANCE = "poisonResistance",
LP = "lp",
AP = "ap"
}
export enum M5ModType {
ATTRIBUTE = "attribute",
STAT = "stat",
SKILL = "skill"
}
export enum M5ModOperation {
ADD_100 = "add100",
ADD = "add",
SET = "set",
FIXED = "fixed"
}
export interface M5ItemMod {
type: M5ModType
id: string
operation: M5ModOperation
value: number
}
export function enumKeys<O extends object, K extends keyof O = keyof O>(obj: O): K[] {
return Object.keys(obj).filter(k => Number.isNaN(+k)) as K[]
}

View File

@ -1,49 +1,5 @@
import { M5Item } from "../items/M5Item" import { M5Item } from "../items/M5Item"
import { M5Attribute, M5RollData, M5Skill, M5SkillLearned } from "../M5Base" import { M5Attribute, M5CharacterCalculatedData, M5RollData, M5Skill, M5SkillCalculated, M5SkillLearned } from "../M5Base"
export interface M5CharacterCalculatedData {
level: number
attributes: {
st: { value: number, bonus: number }
gs: { value: number, bonus: number }
gw: { value: number, bonus: number }
ko: { value: number, bonus: number }
in: { value: number, bonus: number }
zt: { value: number, bonus: number }
au: { value: number, bonus: number }
pa: { value: number, bonus: number }
wk: { value: number, bonus: number }
}
stats: {
armor: number
defense: number
damageBonus: number
attackBonus: number
defenseBonus: number
movementBonus: number
resistanceMind: number
resistanceBody: number
spellCasting: number
brawl: number
brawlEw: number
poisonResistance: number
enduranceBonus: number
}
skills: {
innate: {}
general: {}
combat: {}
language: {}
custom: {}
}
gear: {
weapons: {}
defensiveWeapons: {}
armor: {}
items: {}
}
spells: {}
}
export class M5Character extends Actor { export class M5Character extends Actor {
@ -118,7 +74,13 @@ export class M5Character extends Actor {
} as M5CharacterCalculatedData } as M5CharacterCalculatedData
const context = (this as any).data const context = (this as any).data
if (!context)
return null
const data = context.data const data = context.data
if (!data)
return null
ret.level = M5Character.levelFromExp(data.es) ret.level = M5Character.levelFromExp(data.es)
ret.attributes.st.value = M5Character.attributeMinMax(data.attributes.st) // TODO item effects ret.attributes.st.value = M5Character.attributeMinMax(data.attributes.st) // TODO item effects
@ -155,6 +117,23 @@ export class M5Character extends Actor {
ret.stats.poisonResistance = 30 + Math.floor(ret.attributes.ko.value / 2) ret.stats.poisonResistance = 30 + Math.floor(ret.attributes.ko.value / 2)
ret.stats.enduranceBonus = Math.floor(ret.attributes.ko.value/10) + Math.floor(ret.attributes.st.value/20) ret.stats.enduranceBonus = Math.floor(ret.attributes.ko.value/10) + Math.floor(ret.attributes.st.value/20)
if (!skip.items) {
context.items?.filter(item => item.data.type === "item").forEach(item => {
item.prepareDerivedData()
let label = item.data.name
if (item.data.data.magic) {
label += "*"
}
ret.gear.items[item.data._id] = {
label: label,
magic: item.data.data.magic,
calc: item.data.data.calc
}
})
}
if (!skip.skills) { if (!skip.skills) {
context.items?.filter(item => item.data.type === "skill").forEach(item => { context.items?.filter(item => item.data.type === "skill").forEach(item => {
item.prepareDerivedData() item.prepareDerivedData()
@ -164,7 +143,7 @@ export class M5Character extends Actor {
fw: item.data.data.fw, fw: item.data.data.fw,
attribute: item.data.data.attribute, attribute: item.data.data.attribute,
calc: item.data.data.calc calc: item.data.data.calc
} } as M5SkillCalculated
}) })
} }
@ -227,23 +206,6 @@ export class M5Character extends Actor {
}) })
} }
if (!skip.items) {
context.items?.filter(item => item.data.type === "item").forEach(item => {
item.prepareDerivedData()
let label = item.data.name
if (item.data.data.magic) {
label += "*"
}
ret.gear.items[item.data._id] = {
label: label,
magic: item.data.data.magic,
calc: item.data.data.calc
}
})
}
if (!skip.spells) { if (!skip.spells) {
context.items?.filter(item => item.data.type === "spell").forEach(item => { context.items?.filter(item => item.data.type === "spell").forEach(item => {
item.prepareDerivedData() item.prepareDerivedData()
@ -323,7 +285,7 @@ export class M5Character extends Actor {
attribute(name: string): M5Attribute { attribute(name: string): M5Attribute {
const context = (this as any).data const context = (this as any).data
return context.data.attributes[name] return context?.data?.attributes[name]
} }
createSkill(skillName: string): Promise<M5Item> { createSkill(skillName: string): Promise<M5Item> {
@ -334,12 +296,14 @@ export class M5Character extends Actor {
return (this as any).createEmbeddedDocuments("Item", [itemData]).then(docs => { return (this as any).createEmbeddedDocuments("Item", [itemData]).then(docs => {
const item = docs[0] const item = docs[0]
return item as M5Item return item
}) })
} }
getSkill(skillId: string): M5Skill { getItem(itemId: string): any {
return (this as any).getEmbeddedDocument("Item", skillId) as M5Skill if (!(this as any).data?.items)
return null
return (this as any).getEmbeddedDocument("Item", itemId)
} }
} }

View File

@ -1,5 +1,7 @@
import { ItemData } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/module.mjs"
import { ConstructorDataType } from "@league-of-foundry-developers/foundry-vtt-types/src/types/helperTypes"
import { M5Character } from "../actors/M5Character" import { M5Character } from "../actors/M5Character"
import { M5RollData, M5RollResult, M5Skill } from "../M5Base" import { enumKeys, M5Attributes, M5ItemMod, M5ModType, M5RollData, M5RollResult, M5Skill, M5Stats } from "../M5Base"
import { M5Roll } from "../rolls/M5Roll" import { M5Roll } from "../rolls/M5Roll"
export class M5Item extends Item { export class M5Item extends Item {
@ -16,7 +18,8 @@ export class M5Item extends Item {
if (context.data?.attribute && context.data?.attribute !== "" && character) { if (context.data?.attribute && context.data?.attribute !== "" && character) {
const attribute = character.attribute(context.data.attribute) const attribute = character.attribute(context.data.attribute)
calc.bonus += M5Character.attributeBonus(attribute) if (attribute)
calc.bonus += M5Character.attributeBonus(attribute)
} }
calc.ew = context.data.fw + calc.bonus calc.ew = context.data.fw + calc.bonus
@ -29,9 +32,12 @@ export class M5Item extends Item {
if (actor) { if (actor) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true }) const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true })
calc.ew += actorCalc.stats.attackBonus if (actorCalc) {
calc.ew += actorCalc.stats.attackBonus
calc.combatSkills = actorCalc.skills.combat
}
const skill = character.getSkill(context.data.skillId) as any const skill = character.getItem(context.data.skillId)
//console.log("M5Item.prepareDerivedData:weapon", context.data, skill?.data?.data) //console.log("M5Item.prepareDerivedData:weapon", context.data, skill?.data?.data)
if (skill) { if (skill) {
skill.prepareDerivedData() skill.prepareDerivedData()
@ -40,8 +46,6 @@ export class M5Item extends Item {
calc.bonus += skillData.calc.bonus calc.bonus += skillData.calc.bonus
calc.fw += skillData.fw calc.fw += skillData.fw
} }
calc.combatSkills = actorCalc.skills.combat
} }
} else if (context.type === "defensiveWeapon") { } else if (context.type === "defensiveWeapon") {
calc.fw = 0 calc.fw = 0
@ -52,9 +56,12 @@ export class M5Item extends Item {
if (actor) { if (actor) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true }) const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true })
calc.ew += actorCalc.stats.defense + actorCalc.stats.defenseBonus if (actorCalc) {
calc.ew += actorCalc.stats.defense + actorCalc.stats.defenseBonus
calc.combatSkills = actorCalc.skills.combat
}
const skill = character.getSkill(context.data.skillId) as any const skill = character.getItem(context.data.skillId)
//console.log("M5Item.prepareDerivedData:weapon", context.data, skill?.data?.data) //console.log("M5Item.prepareDerivedData:weapon", context.data, skill?.data?.data)
if (skill) { if (skill) {
skill.prepareDerivedData() skill.prepareDerivedData()
@ -63,15 +70,90 @@ export class M5Item extends Item {
calc.bonus += skillData.calc.bonus calc.bonus += skillData.calc.bonus
calc.fw += skillData.fw calc.fw += skillData.fw
} }
calc.combatSkills = actorCalc.skills.combat
} }
} else if (context.type === "spell") { } else if (context.type === "spell") {
calc.ew = context.data.bonus calc.ew = context.data.bonus
if (actor) { if (actor) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true }) const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true })
calc.ew += actorCalc.stats.spellCasting if (actorCalc) {
calc.ew += actorCalc.stats.spellCasting
}
} }
} else if (context.type === "mod") {
const parent = (this as any).parent
const actor = parent?.actor
const character = actor as M5Character
calc.ids = {}
switch (context.data.type as M5ModType) {
case M5ModType.ATTRIBUTE: {
for (const key of enumKeys(M5Attributes)) {
const val = M5Attributes[key]
calc.ids[key] = (game as Game).i18n.localize(`midgard5.actor-${val}-long`)
}
break
}
case M5ModType.STAT: {
for (const key of enumKeys(M5Stats)) {
const val = M5Stats[key]
calc.ids[key] = (game as Game).i18n.localize(`midgard5.mod-stat-${val}`)
}
break
}
case M5ModType.SKILL: {
if (character) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true })
if (actorCalc) {
let category = (game as Game).i18n.localize("midgard5.innate-ability")
Object.keys(actorCalc.skills.innate).forEach(skillId => {
const skill = character.getItem(skillId)
if (skill)
calc.ids[skillId] = `${category}: ${skill.data.name}`
})
}
}
break
}
}
} else if (context.type === "item") {
calc.mods = {}
Object.keys(context.data?.mods).forEach(key => {
const mod = context.data.mods[key]
const modCalc = {}
switch (mod.type) {
case M5ModType.ATTRIBUTE: {
for (const key of enumKeys(M5Attributes)) {
const val = M5Attributes[key]
modCalc[key] = (game as Game).i18n.localize(`midgard5.actor-${val}-long`)
}
break
}
case M5ModType.STAT: {
for (const key of enumKeys(M5Stats)) {
const val = M5Stats[key]
modCalc[key] = (game as Game).i18n.localize(`midgard5.mod-stat-${val}`)
}
break
}
case M5ModType.SKILL: {
if (character) {
const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true })
if (actorCalc) {
let category = (game as Game).i18n.localize("midgard5.innate-ability")
Object.keys(actorCalc.skills.innate).forEach(skillId => {
const skill = character.getItem(skillId)
if (skill)
modCalc[skillId] = `${category}: ${skill.data.name}`
})
}
}
break
}
}
calc.mods[key] = modCalc
})
} }
} }
@ -128,6 +210,10 @@ export class M5Item extends Item {
}) })
return null return null
} }
} }
getItem(itemId: string): any {
return (this as any).getEmbeddedDocument("Item", itemId)
}
} }

View File

@ -57,9 +57,26 @@ export default class M5CharacterSheet extends ActorSheet {
const context = this.actor.data const context = this.actor.data
const item = context.items.get(itemId) const item = context.items.get(itemId)
console.log("edit-item", item)
item.sheet.render(true) item.sheet.render(true)
}) })
html.find(".item-delete").on("click", async (event) => {
let row = event.target.parentElement
let itemId = row.dataset["item"]
while (!itemId) {
row = row.parentElement
if (!row)
return
itemId = row.dataset["item"]
}
const context = this.actor.data
const item = context.items.get(itemId)
item.delete()
this.render(false)
})
html.find(".roll-learned-button").on("click", async (event) => { html.find(".roll-learned-button").on("click", async (event) => {
const row = event.target.parentElement.parentElement const row = event.target.parentElement.parentElement
let skillId = row.dataset["item"] let skillId = row.dataset["item"]
@ -193,7 +210,6 @@ export default class M5CharacterSheet extends ActorSheet {
if (!data.data) if (!data.data)
return false return false
if (data.actorId === this.actor.id) if (data.actorId === this.actor.id)
return false return false

View File

@ -1,4 +1,5 @@
import { M5Item } from "../items/M5Item" import { M5Item } from "../items/M5Item"
import { M5Attributes, M5ItemMod, M5ModOperation, M5ModType } from "../M5Base"
export class M5ItemSheet extends ItemSheet { export class M5ItemSheet extends ItemSheet {
@ -41,4 +42,108 @@ export class M5ItemSheet extends ItemSheet {
}) })
} }
override activateListeners(html: JQuery) {
super.activateListeners(html)
html.find(".add-mod").on("click", async (event) => {
const context = this.object.data
const mods = context.data.mods
const modIndex = Object.keys(mods).length
mods[modIndex.toString()] = {
type: M5ModType.ATTRIBUTE,
id: M5Attributes.ST,
operation: M5ModOperation.ADD,
value: 0
} as M5ItemMod
this.object.update({
data: {
mods: mods
}
})
})
html.find(".item-delete").on("click", async (event) => {
let row = event.target.parentElement
let itemId = row.dataset["item"]
while (!itemId) {
row = row.parentElement
if (!row)
return
itemId = row.dataset["item"]
}
const context = this.item.data
const item = context.items.get(itemId)
item.delete()
this.render(false)
})
// Drag & Drop
if (["item"].includes(this.object.data?.type)) {
const itemToItemAssociation = new DragDrop({
dragSelector: ".item",
dropSelector: null,
permissions: { dragstart: this._canDragStart.bind(this), drop: this._canDragDrop.bind(this) },
callbacks: { drop: this._onDropItem.bind(this) },
})
itemToItemAssociation.bind(html[0])
}
}
_canDragStart(selector) {
console.log("M5ItemSheet._canDragStart", selector)
return this.options.editable && this.object.isOwner
}
_canDragDrop(selector) {
console.log("M5ItemSheet._canDragDrop", selector)
return true
}
async _onDropItem(event) {
let data
const obj = this.object
const li = event.currentTarget
try {
data = JSON.parse(event.dataTransfer.getData("text/plain"))
if (data.type !== "Item")
return false
} catch (err) {
return false
}
// Case 1 - Import from a Compendium pack
let itemObject
if (data.pack) {
const compendiumObject = await (this as any).importItemFromCollection(data.pack, data.id)
itemObject = compendiumObject.data
}
// Case 2 - Import from World entity
else {
const originalItem = await (game as Game).items.get(data.id)
itemObject = duplicate(originalItem)
if (!itemObject)
return
}
if ((itemObject.type === "mod")) {
let mods = obj?.data?.data?.mods
if (!mods)
mods = []
itemObject.id = randomID()
console.log("M5ItemSheet._onDropItem", itemObject)
mods.push(itemObject)
obj.update({
data: {
mods: mods
}
})
}
}
async _onDragItemStart(event) { }
} }

View File

@ -47,6 +47,11 @@
&.center { &.center {
text-align: center; text-align: center;
} }
&.fixed-value {
width: 3rem;
text-align: center;
}
} }
input.skill { input.skill {

View File

@ -1,6 +1,6 @@
{ {
"Actor": { "Actor": {
"types": ["npc", "character"], "types": ["character"],
"templates": { "templates": {
"characterDescription": { "characterDescription": {
"info": { "info": {
@ -118,7 +118,7 @@
} }
}, },
"Item": { "Item": {
"types": ["skill", "item", "weapon", "defensiveWeapon", "armor", "spell"], "types": ["skill", "weapon", "defensiveWeapon", "armor", "spell", "item"],
"templates": { "templates": {
"itemDescription": { "itemDescription": {
"description": "" "description": ""
@ -170,6 +170,10 @@
"equippable": false, "equippable": false,
"equipped": true "equipped": true
}, },
"physical": {
"value": 0,
"magic": false
},
"spellSelection": { "spellSelection": {
"spellProcessSelection": { "spellProcessSelection": {
"none": "midgard5.spell-process-none", "none": "midgard5.spell-process-none",
@ -214,31 +218,33 @@
"0": { "0": {
"formula": "1d20 + @i.fw + @i.calc.bonus", "formula": "1d20 + @i.fw + @i.calc.bonus",
"type": "ew", "type": "ew",
"label": "EW" "label": "EW",
"enabled": true
} }
}, },
"output": "" "output": ""
}, },
"calc": {} "calc": {}
}, },
"item": { "mod": {
"templates": ["itemDescription", "stats", "equippable"], "type": "",
"quantity": 1, "id": "",
"operation": "",
"value": 0, "value": 0,
"magic": false, "calc": {}
"onbody": false, },
"attributes": {}, "item": {
"groups": {}, "templates": ["itemDescription", "equippable", "physical"],
"rolls": { "rolls": {
"formulas": {}, "formulas": {},
"output": "" "output": ""
}, },
"mods": {},
"calc": {} "calc": {}
}, },
"weapon": { "weapon": {
"templates": ["itemDescription", "stats", "equippable"], "templates": ["itemDescription", "stats", "equippable", "physical"],
"special": false, "special": false,
"magic": false,
"ranged": false, "ranged": false,
"skillId": "", "skillId": "",
"damageBase": "1d6", "damageBase": "1d6",
@ -247,12 +253,14 @@
"0": { "0": {
"formula": "1d20 + @i.calc.fw + @i.calc.bonus + @i.calc.special + @c.calc.stats.attackBonus + @i.stats.attackBonus", "formula": "1d20 + @i.calc.fw + @i.calc.bonus + @i.calc.special + @c.calc.stats.attackBonus + @i.stats.attackBonus",
"type": "ew", "type": "ew",
"label": "Angriff" "label": "Angriff",
"enabled": true
}, },
"1": { "1": {
"formula": "@i.damageBase + @i.stats.damageBonus + @c.calc.stats.damageBonus", "formula": "@i.damageBase + @i.stats.damageBonus + @c.calc.stats.damageBonus",
"type": "dmg", "type": "dmg",
"label": "Schaden" "label": "Schaden",
"enabled": true
} }
}, },
"output": "" "output": ""
@ -260,16 +268,16 @@
"calc": {} "calc": {}
}, },
"defensiveWeapon": { "defensiveWeapon": {
"templates": ["itemDescription", "stats", "equippable"], "templates": ["itemDescription", "stats", "equippable", "physical"],
"special": false, "special": false,
"magic": false,
"skillId": "", "skillId": "",
"rolls": { "rolls": {
"formulas": { "formulas": {
"0": { "0": {
"formula": "1d20 + @i.calc.fw + @i.calc.bonus + @i.calc.special + @c.calc.stats.defense + @c.calc.stats.defenseBonus + @i.stats.defenseBonus", "formula": "1d20 + @i.calc.fw + @i.calc.bonus + @i.calc.special + @c.calc.stats.defense + @c.calc.stats.defenseBonus + @i.stats.defenseBonus",
"type": "ew", "type": "ew",
"label": "Abwehr" "label": "Abwehr",
"enabled": true
} }
}, },
"output": "" "output": ""
@ -277,8 +285,7 @@
"calc": {} "calc": {}
}, },
"armor": { "armor": {
"templates": ["itemDescription", "stats", "equippable", "attributeMod"], "templates": ["itemDescription", "stats", "equippable", "attributeMod", "physical"],
"magic": false,
"lpProtection": 0, "lpProtection": 0,
"apProtection": 0, "apProtection": 0,
"rolls": { "rolls": {
@ -304,7 +311,8 @@
"0": { "0": {
"formula": "1d20 + @c.calc.stats.spellCasting + @i.bonus", "formula": "1d20 + @c.calc.stats.spellCasting + @i.bonus",
"type": "ew", "type": "ew",
"label": "Zaubern" "label": "Zaubern",
"enabled": true
} }
}, },
"output": "" "output": ""

View File

@ -4,21 +4,24 @@
<th>{{localize "ITEM.TypeWeapon"}}</th> <th>{{localize "ITEM.TypeWeapon"}}</th>
<th>{{localize "midgard5.ew"}}</th> <th>{{localize "midgard5.ew"}}</th>
<th></th> <th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{#each data.calc.gear.weapons as |item itemId|}} {{#each data.calc.gear.weapons as |item itemId|}}
<tr data-item="{{itemId}}"> <tr data-item="{{itemId}}">
<td class="padding edit-item">{{item.label}}</td> <td class="padding edit-item">{{item.label}}</td>
<td class="center">{{item.calc.ew}}</td> <td class="fixed-value">{{item.calc.ew}}</td>
<td><button class="roll-weapon-button">{{localize "midgard5.roll"}}</button></td> <td class="fixed-value"><button class="roll-button roll-weapon-button"></button></td>
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
</tr> </tr>
{{/each}} {{/each}}
<tr data-item="{{itemId}}"> <tr data-item="{{itemId}}">
<td class="padding edit-item">{{localize "midgard5.brawl"}}</td> <td class="padding edit-item">{{localize "midgard5.brawl"}}</td>
<td class="center">{{data.calc.stats.brawlEw}}</td> <td class="center">{{data.calc.stats.brawlEw}}</td>
<td><button class="roll-brawl-button">{{localize "midgard5.roll"}}</button></td> <td class="fixed-value"><button class="roll-button roll-brawl-button"></button></td>
<td class="fixed-value"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -29,14 +32,16 @@
<th>{{localize "ITEM.TypeDefensiveWeapon"}}</th> <th>{{localize "ITEM.TypeDefensiveWeapon"}}</th>
<th>{{localize "midgard5.ew"}}</th> <th>{{localize "midgard5.ew"}}</th>
<th></th> <th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{#each data.calc.gear.defensiveWeapons as |item itemId|}} {{#each data.calc.gear.defensiveWeapons as |item itemId|}}
<tr data-item="{{itemId}}"> <tr data-item="{{itemId}}">
<td class="padding edit-item">{{item.label}}</td> <td class="padding edit-item">{{item.label}}</td>
<td class="center">{{item.calc.ew}}</td> <td class="fixed-value">{{item.calc.ew}}</td>
<td><button class="roll-weapon-button">{{localize "midgard5.roll"}}</button></td> <td class="fixed-value"><button class="roll-button roll-weapon-button"></button></td>
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>
@ -52,18 +57,20 @@
<th>{{localize "midgard5.defenseBonus-short"}}</th> <th>{{localize "midgard5.defenseBonus-short"}}</th>
<th>B</th> <th>B</th>
<th>Gw</th> <th>Gw</th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{#each data.calc.gear.armor as |item itemId|}} {{#each data.calc.gear.armor as |item itemId|}}
<tr data-item="{{itemId}}"> <tr data-item="{{itemId}}">
<td class="padding edit-item">{{item.label}}</td> <td class="padding edit-item">{{item.label}}</td>
<td class="center">{{actorItemValue ../actor._id itemId "lpProtection"}}</td> <td class="fixed-value">{{actorItemValue ../actor._id itemId "lpProtection"}}</td>
<td class="center">{{actorItemValue ../actor._id itemId "apProtection"}}</td> <td class="fixed-value">{{actorItemValue ../actor._id itemId "apProtection"}}</td>
<td class="center">{{actorItemValue ../actor._id itemId "stats.attackBonus"}}</td> <td class="fixed-value">{{actorItemValue ../actor._id itemId "stats.attackBonus"}}</td>
<td class="center">{{actorItemValue ../actor._id itemId "stats.defenseBonus"}}</td> <td class="fixed-value">{{actorItemValue ../actor._id itemId "stats.defenseBonus"}}</td>
<td class="center">{{actorItemValue ../actor._id itemId "stats.movementBonus"}}</td> <td class="fixed-value">{{actorItemValue ../actor._id itemId "stats.movementBonus"}}</td>
<td class="center">{{actorItemValue ../actor._id itemId "attributeMod.gw"}}</td> <td class="fixed-value">{{actorItemValue ../actor._id itemId "attributeMod.gw"}}</td>
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>

View File

@ -6,16 +6,18 @@
<th>{{localize "midgard5.bonus"}}</th> <th>{{localize "midgard5.bonus"}}</th>
<th>{{localize "midgard5.ew"}}</th> <th>{{localize "midgard5.ew"}}</th>
<th></th> <th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{#each data.calc.skills.general as |skill skillId|}} {{#each data.calc.skills.general as |skill skillId|}}
<tr data-item="{{skillId}}"> <tr data-item="{{skillId}}">
<td class="padding edit-item">{{skill.label}}</td> <td class="padding edit-item">{{skill.label}}</td>
<td class="center">{{skill.fw}}</td> <td class="fixed-value">{{skill.fw}}</td>
<td class="center">{{skill.calc.bonus}}</td> <td class="fixed-value">{{skill.calc.bonus}}</td>
<td class="center">{{skill.calc.ew}}</td> <td class="fixed-value">{{skill.calc.ew}}</td>
<td><button class="roll-learned-button">{{localize "midgard5.roll"}}</button></td> <td class="fixed-value"><button class="roll-button roll-learned-button"></button></td>
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>
@ -29,16 +31,18 @@
<th>{{localize "midgard5.bonus"}}</th> <th>{{localize "midgard5.bonus"}}</th>
<th>{{localize "midgard5.ew"}}</th> <th>{{localize "midgard5.ew"}}</th>
<th></th> <th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{#each data.calc.skills.language as |skill skillId|}} {{#each data.calc.skills.language as |skill skillId|}}
<tr data-item="{{skillId}}"> <tr data-item="{{skillId}}">
<td class="padding edit-item">{{skill.label}}</td> <td class="padding edit-item">{{skill.label}}</td>
<td class="center">{{skill.fw}}</td> <td class="fixed-value">{{skill.fw}}</td>
<td class="center">{{skill.calc.bonus}}</td> <td class="fixed-value">{{skill.calc.bonus}}</td>
<td class="center">{{skill.calc.ew}}</td> <td class="fixed-value">{{skill.calc.ew}}</td>
<td><button class="roll-learned-button">{{localize "midgard5.roll"}}</button></td> <td class="fixed-value"><button class="roll-button roll-learned-button"></button></td>
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>
@ -52,16 +56,18 @@
<th>{{localize "midgard5.bonus"}}</th> <th>{{localize "midgard5.bonus"}}</th>
<th>{{localize "midgard5.ew"}}</th> <th>{{localize "midgard5.ew"}}</th>
<th></th> <th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{#each data.calc.skills.innate as |skill skillId|}} {{#each data.calc.skills.innate as |skill skillId|}}
<tr data-item="{{skillId}}"> <tr data-item="{{skillId}}">
<td class="padding edit-item">{{skill.label}}</td> <td class="padding edit-item">{{skill.label}}</td>
<td class="center">{{skill.fw}}</td> <td class="fixed-value">{{skill.fw}}</td>
<td class="center">{{skill.calc.bonus}}</td> <td class="fixed-value">{{skill.calc.bonus}}</td>
<td class="center">{{skill.calc.ew}}</td> <td class="fixed-value">{{skill.calc.ew}}</td>
<td><button class="roll-learned-button">{{localize "midgard5.roll"}}</button></td> <td class="fixed-value"><button class="roll-button roll-learned-button"></button></td>
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>
@ -75,16 +81,18 @@
<th>{{localize "midgard5.bonus"}}</th> <th>{{localize "midgard5.bonus"}}</th>
<th>{{localize "midgard5.ew"}}</th> <th>{{localize "midgard5.ew"}}</th>
<th></th> <th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{#each data.calc.skills.combat as |skill skillId|}} {{#each data.calc.skills.combat as |skill skillId|}}
<tr data-item="{{skillId}}"> <tr data-item="{{skillId}}">
<td class="padding edit-item">{{skill.label}}</td> <td class="padding edit-item">{{skill.label}}</td>
<td class="center">{{skill.fw}}</td> <td class="fixed-value">{{skill.fw}}</td>
<td class="center">{{skill.calc.bonus}}</td> <td class="fixed-value">{{skill.calc.bonus}}</td>
<td class="center">{{skill.calc.ew}}</td> <td class="fixed-value">{{skill.calc.ew}}</td>
<td><button class="roll-learned-button">{{localize "midgard5.roll"}}</button></td> <td class="fixed-value"><button class="roll-button roll-learned-button"></button></td>
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>
@ -99,6 +107,7 @@
<th>{{localize "midgard5.bonus"}}</th> <th>{{localize "midgard5.bonus"}}</th>
<th>{{localize "midgard5.ew"}}</th> <th>{{localize "midgard5.ew"}}</th>
<th></th> <th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -106,10 +115,11 @@
<tr data-skill="{{key}}"> <tr data-skill="{{key}}">
<td><button class="learn-button">{{localize "midgard5.learn"}}</button></td> <td><button class="learn-button">{{localize "midgard5.learn"}}</button></td>
<td class="padding">{{localizeMidgard key}}</td> <td class="padding">{{localizeMidgard key}}</td>
<td class="center">{{skill.fw}}</td> <td class="fixed-value">{{skill.fw}}</td>
<td class="center">{{skillBonus ../actor._id skill}}</td> <td class="fixed-value">{{skillBonus ../actor._id skill}}</td>
<td class="center">{{skillEw ../actor._id skill}}</td> <td class="fixed-value">{{skillEw ../actor._id skill}}</td>
<td><button class="roll-general-button">{{localize "midgard5.roll"}}</button></td> <td class="fixed-value"><button class="roll-button roll-general-button"></button></td>
<td class="fixed-value"></td>
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>

View File

@ -4,6 +4,7 @@
<th>{{localize "ITEM.TypeSpell"}}</th> <th>{{localize "ITEM.TypeSpell"}}</th>
<th>{{localize "midgard5.ew"}}</th> <th>{{localize "midgard5.ew"}}</th>
<th></th> <th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -13,8 +14,9 @@
<span>{{item.label}}</span> <span>{{item.label}}</span>
<span class="spell-process">{{localize item.process}}</span> <span class="spell-process">{{localize item.process}}</span>
</td> </td>
<td class="center">{{item.calc.ew}}</td> <td class="fixed-value">{{item.calc.ew}}</td>
<td><button class="roll-weapon-button">{{localize "midgard5.roll"}}</button></td> <td class="fixed-value"><button class="roll-button roll-weapon-button" /></td>
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>

View File

@ -1,31 +1,77 @@
<form class="{{cssClass}}" autocomplete="off"> <form class="{{cssClass}} m5item-item" autocomplete="off">
<header class="sheet-header"> <header class="sheet-header">
<img class="item-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" /> <img class="item-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
<h1><input name="name" type="text" value="{{item.name}}" placeholder="Name" /></h1> <h1><input name="name" type="text" value="{{item.name}}" placeholder="Name" /></h1>
</header> </header>
<div class="sheet-content"> <div class="sheet-content">
<table> <table>
<tr> <tr>
<th>{{localize "midgard5.item-quantity"}}</th> <td>
<th>{{localize "midgard5.item-value"}}</th> <input id="data.magic" type="checkbox" name="data.magic" {{checked data.magic}}>
<th>{{localize "midgard5.item-onbody"}}</th> <label for="data.magic">{{localize "midgard5.magic"}}</label>
<th>{{localize "midgard5.item-ismagic"}}</th> </td>
</tr> <td>
<tr> <div class="flexrow">
<td> <span>{{localize "midgard5.item-value"}}</span>
<input name="data.quantity" type="text" value="{{data.quantity}}" data-dtype="Number" /> <input name="data.value" type="text" value="{{data.value}}" data-dtype="Number" />
</td> </div>
<td> </td>
<input name="data.value" type="text" value="{{data.value}}" data-dtype="Number" /> </tr>
</td> </table>
<td>
<input name="data.onbody" type="checkbox" {{checked data.onbody}} /> <table>
</td> <thead>
<td> <tr>
<input name="data.magic" type="checkbox" {{checked data.magic}} /> <th>Mods</th>
</td> <th></th>
</tr> <th></th>
</table> <th><button class="add-mod">+</button></th>
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}} </tr>
</div> </thead>
<tbody>
{{#each data.mods as |mod modId|}}
<tr>
<td>
<select class="select-mod-type" name="data.mods.{{modId}}.type" data-type="String">
{{#select mod.type}}
<option value="attribute">{{localize "midgard5.attribute"}}</option>
<option value="stat">{{localize "midgard5.bonus"}}</option>
<option value="skill">{{localize "midgard5.skill"}}</option>
{{/select}}
</select>
</td>
<td>
<select class="select-id" name="data.mods.{{modId}}.id" data-type="String">
{{#select mod.id}}
{{#each (lookup ../data.calc.mods modId) as |name key|}}
<option value="{{key}}">{{name}}</option>
{{/each}}
{{/select}}
</select>
</td>
<td>
<select class="select-mod-operation" name="data.mods.{{modId}}.operation" data-type="String">
{{#select mod.operation}}
{{#if (eq mod.type "attribute")}}
<option value="add100">{{localize "midgard5.mod-operation-add100"}}</option>
{{/if}}
<option value="add">{{localize "midgard5.mod-operation-add"}}</option>
<option value="set">{{localize "midgard5.mod-operation-set"}}</option>
<option value="fixed">{{localize "midgard5.mod-operation-fixed"}}</option>
{{/select}}
</select>
</td>
<td>
<input name="data.mods.{{modId}}.value" type="text" value="{{mod.value}}" data-dtype="Number" />
</td>
</tr>
{{/each}}
</tbody>
</table>
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
</div>
</form> </form>

View File

@ -0,0 +1,60 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="item-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
<h1><input name="name" type="text" value="{{item.name}}" placeholder="Name" /></h1>
</header>
<div class="sheet-content">
<table>
<tbody>
<tr>
<td>{{localize "midgard5.mod-type"}}</td>
<td>
<select class="select-mod-type" name="data.type" data-type="String">
{{#select data.type}}
<option value="attribute">{{localize "midgard5.attribute"}}</option>
<option value="stat">{{localize "midgard5.bonus"}}</option>
<option value="skill">{{localize "midgard5.skill"}}</option>
{{/select}}
</select>
</td>
</tr>
<tr>
<td>{{localize "midgard5.mod-id"}}</td>
<td>
<select class="select-id" name="data.id" data-type="String">
{{#select data.id}}
{{#each data.calc.ids as |name key|}}
<option value="{{key}}">{{name}}</option>
{{/each}}
{{/select}}
</select>
</td>
</tr>
<tr>
<td>{{localize "midgard5.mod-operation"}}</td>
<td>
<select class="select-mod-operation" name="data.operation" data-type="String">
{{#select data.operation}}
{{#if (eq data.type "attribute")}}
<option value="add100">{{localize "midgard5.mod-operation-add100"}}</option>
{{/if}}
<option value="add">{{localize "midgard5.mod-operation-add"}}</option>
<option value="set">{{localize "midgard5.mod-operation-set"}}</option>
<option value="fixed">{{localize "midgard5.mod-operation-fixed"}}</option>
{{/select}}
</select>
</td>
</tr>
<tr>
<td>{{localize "midgard5.mod-value"}}</td>
<td><input name="data.value" type="text" value="{{data.value}}" data-dtype="Number" /></td>
</tr>
</tbody>
</table>
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
</div>
</form>