Merge branch 'master' into 10-implement-money

This commit is contained in:
Johannes Loher 2021-01-18 19:48:07 +01:00
commit e89c87f0c1
46 changed files with 1651 additions and 505 deletions

View file

@ -1,12 +1,17 @@
{
"DS4.UserInteractionAddItem": "Neu",
"DS4.UserInteractionEditItem": "Bearbeiten",
"DS4.UserInteractionDeleteItem": "Löschen",
"DS4.NotOwned": "Nicht besessen",
"DS4.HeadingDescription": "Beschreibung",
"DS4.HeadingBiography": "Biografie",
"DS4.HeadingDetails": "Details",
"DS4.HeadingEffects": "Effekte",
"DS4.HeadingInventory": "Inventar",
"DS4.HeadingProfile": "Profil",
"DS4.HeadingTalents": "Talente & Fähigkeiten",
"DS4.HeadingTalentsAbilities": "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",
@ -16,11 +21,13 @@
"DS4.AttackTypeMelee": "Schlagen",
"DS4.AttackTypeRanged": "Schießen",
"DS4.AttackTypeMeleeRanged": "Schlagen + Schießen",
"DS4.Description": "Beschreibung",
"DS4.Quantity": "Menge",
"DS4.PriceGold": "Preis (Gold)",
"DS4.StorageLocation": "Wo gelagert",
"DS4.ItemEquipped": "Ausgerüstet",
"DS4.ItemOwner": "Eigentümer",
"DS4.ItemEquippedAbbr": "A",
"DS4.ItemOwner": "Besitzer",
"DS4.ItemAvailability": "Verfügbarkeit",
"DS4.ItemAvailabilityHamlet": "Dorf",
"DS4.ItemAvailabilityVilage": "Kleinstadt",
@ -36,6 +43,8 @@
"DS4.ItemTypeArmorPlural": "Panzerungen",
"DS4.ItemTypeShield": "Schild",
"DS4.ItemTypeShieldPlural": "Schilde",
"DS4.ItemTypeSpell": "Zauberspruch",
"DS4.ItemTypeSpellPlural": "Zaubersprüche",
"DS4.ItemTypeTrinket": "Schmuckstück",
"DS4.ItemTypeTrinketPlural": "Schmuckstücke",
"DS4.ItemTypeEquipment": "Ausrüstung",
@ -48,6 +57,8 @@
"DS4.ItemTypeLanguagePlural": "Sprachen",
"DS4.ItemTypeAlphabet": "Schriftzeichen",
"DS4.ItemTypeAlphabetPlural": "Schriftzeichen",
"DS4.ItemTypeSpecialCreatureAbility": "Besondere Kreaturenfähigkeit",
"DS4.ItemTypeSpecialCreatureAbilityPlural": "Besondere Kreaturenfähigkeiten",
"DS4.ArmorType": "Panzerungstyp",
"DS4.ArmorTypeAbbr": "PAT",
"DS4.ArmorMaterialType": "Material Typ",
@ -72,6 +83,29 @@
"DS4.ArmorMaterialTypeChainAbbr": "Ketten",
"DS4.ArmorMaterialTypePlate": "Platten",
"DS4.ArmorMaterialTypePlateAbbr": "Platten",
"DS4.SpellType": "Zauberspruchtyp",
"DS4.SpellTypeAbbr": "T",
"DS4.SpellTypeSpellcasting": "Zaubern",
"DS4.SpellTypeTargetedSpellcasting": "Zielzaubern",
"DS4.SpellCategory": "Kategorie",
"DS4.SpellCategoryHealing": "Heilung",
"DS4.SpellCategoryFire": "Feuer",
"DS4.SpellCategoryIce": "Eis",
"DS4.SpellCategoryLight": "Licht",
"DS4.SpellCategoryDarkness": "Schatten",
"DS4.SpellCategoryMindAffecting": "Geistensbeeinflussend",
"DS4.SpellCategoryElectricity": "Elektrizität",
"DS4.SpellCategoryNone": "Keine",
"DS4.SpellCategoryUnset": "Nicht gesetzt",
"DS4.SpellBonus": "Zauberbonus",
"DS4.SpellBonusAbbr": "ZB",
"DS4.SpellMaxDistance": "Reichweite",
"DS4.SpellEffectRadius": "Effektradius",
"DS4.SpellDuration": "Wirkdauer",
"DS4.SpellCooldownDuration": "Abklingzeit",
"DS4.SpellScrollPriceGold": "Schriftrollenpreis (Gold)",
"DS4.ActorTypeCharacter": "Charakter",
"DS4.ActorTypeCreature": "Kreatur",
"DS4.AttributeBody": "Körper",
"DS4.AttributeMobility": "Agilität",
"DS4.AttributeMind": "Geist",
@ -89,35 +123,83 @@
"DS4.CombatValuesRangedAttack": "Schießen",
"DS4.CombatValuesSpellcasting": "Zaubern",
"DS4.CombatValuesTargetedSpellcasting": "Zielzaubern",
"DS4.BaseInfoRace": "Volk",
"DS4.BaseInfoClass": "Klasse",
"DS4.BaseInfoHeroClass": "Helden Klasse",
"DS4.BaseInfoCulture": "Kultur",
"DS4.ProgressionLevel": "Stufe",
"DS4.ProgressionExperiencePoints": "Erfahrungspunkte",
"DS4.ProgressionTalentPoints": "Talentpunkte",
"DS4.ProgressionProgressPoints": "Lernpunkte",
"DS4.CharacterBaseInfoRace": "Volk",
"DS4.CharacterBaseInfoClass": "Klasse",
"DS4.CharacterBaseInfoHeroClass": "Helden Klasse",
"DS4.CharacterBaseInfoCulture": "Kultur",
"DS4.CharacterProgressionLevel": "Stufe",
"DS4.CharacterProgressionExperiencePoints": "Erfahrungspunkte",
"DS4.CharacterProgressionTalentPoints": "Talentpunkte",
"DS4.CharacterProgressionProgressPoints": "Lernpunkte",
"DS4.TalentRank": "Rang",
"DS4.TalentRankBase": "Erworbener Rang",
"DS4.TalentRankMax": "Maximaler Rang",
"DS4.TalentRankMod": "Zusätzlicher Rang",
"DS4.TalentRankTotal": "Gesamter Rang",
"DS4.LanguageLanguages": "Sprachen",
"DS4.LanguageAlphabets": "Schriftzeichen",
"DS4.ProfileGender": "Geschlecht",
"DS4.ProfileBirthday": "Geburtstag",
"DS4.ProfileBirthplace": "Geburtsort",
"DS4.ProfileAge": "Alter",
"DS4.ProfileHeight": "Größe",
"DS4.ProfilHairColor": "Haarfarbe",
"DS4.ProfileWeight": "Gewicht",
"DS4.ProfileEyeColor": "Augenfarbe",
"DS4.ProfileSpecialCharacteristics": "Besondere Eigenschaften",
"DS4.CurrencyGold": "Gold",
"DS4.CurrencySilver": "Silber",
"DS4.CurrencyCopper": "Kupfer",
"DS4.Currency": "Währung",
"DS4.CharacterLanguageLanguages": "Sprachen",
"DS4.CharacterLanguageAlphabets": "Schriftzeichen",
"DS4.SpecialCreatureAbilityExperiencePoints": "Erfahrungspunkte",
"DS4.CharacterProfileBiography": "Biographie",
"DS4.CharacterProfileGender": "Geschlecht",
"DS4.CharacterProfileBirthday": "Geburtstag",
"DS4.CharacterProfileBirthplace": "Geburtsort",
"DS4.CharacterProfileAge": "Alter",
"DS4.CharacterProfileHeight": "Größe",
"DS4.CharacterProfileHairColor": "Haarfarbe",
"DS4.CharacterProfileWeight": "Gewicht",
"DS4.CharacterProfileEyeColor": "Augenfarbe",
"DS4.CharacterProfileSpecialCharacteristics": "Besondere Eigenschaften",
"DS4.CharacterCurrencyGold": "Gold",
"DS4.CharacterCurrencySilver": "Silber",
"DS4.CharacterCurrencyCopper": "Kupfer",
"DS4.CharacterCurrency": "Währung",
"DS4.CreatureTypeAnimal": "Tier",
"DS4.CreatureTypeConstruct": "Konstrukt",
"DS4.CreatureTypeHumanoid": "Humanoid",
"DS4.CreatureTypeMagicalEntity": "Magisches Wesen",
"DS4.CreatureTypePlantBeing": "Pflanzenwesen",
"DS4.CreatureTypeUndead": "Untot",
"DS4.CreatureSizeCategoryTiny": "Winzig",
"DS4.CreatureSizeCategorySmall": "Klein",
"DS4.CreatureSizeCategoryNormal": "Normal",
"DS4.CreatureSizeCategoryLarge": "Groß",
"DS4.CreatureSizeCategoryHuge": "Riesig",
"DS4.CreatureSizeCategoryColossal": "Gewaltig",
"DS4.CreatureBaseInfoLoot": "Beute",
"DS4.CreatureBaseInfoFoeFactor": "Gegnerhärte",
"DS4.CreatureBaseInfoCreatureType": "Kreaturengruppe",
"DS4.CreatureBaseInfoSizeCategory": "Größenkategorie",
"DS4.CreatureBaseInfoExperiencePoints": "Erfahrungspunkte",
"DS4.CreatureBaseInfoDescription": "Beschreibung",
"DS4.WarningManageActiveEffectOnOwnedItem": "Das Verwalten von aktiven Effekten innerhalb eines besessen Items wird derzeit nicht unterstützt und wird in einem nachfolgenden Update hinzugefügt.",
"DS4.WarningActorCannotOwnItem": "Der Aktor '{actorName}' vom Typ '{actorType}' kann das Item '{itemName}' vom Typ '{itemType}' nicht besitzen.",
"DS4.ErrorDiceCritOverlap": "Es gibt eine Überlappung zwischen Patzern und Immersiegen.",
"DS4.ErrorExplodingRecursionLimitExceeded": "Die maximale Rekursionstiefe für slayende Würfelwürfe wurde überschritten."
"DS4.ErrorExplodingRecursionLimitExceeded": "Die maximale Rekursionstiefe für slayende Würfelwürfe wurde überschritten.",
"DS4.UnitRounds": "Runden",
"DS4.UnitRoundsAbbr": "Rnd",
"DS4.UnitMinutes": "Minuten",
"DS4.UnitMinutesAbbr": "min",
"DS4.UnitHours": "Stunden",
"DS4.UnitHoursAbbr": "h",
"DS4.UnitDays": "Tage",
"DS4.UnitDaysAbbr": "d",
"DS4.UnitMeters": "Meter",
"DS4.UnitMetersAbbr": "m",
"DS4.UnitKilometers": "Kilometer",
"DS4.UnitKilometersAbbr": "km",
"DS4.UnitCustom": "individuell",
"DS4.UnitCustomAbbr": " ",
"DS4.RollDialogDefaultTitle": "Proben-Optionen",
"DS4.RollDialogOkButton": "Ok",
"DS4.RollDialogCancelButton": "Abbrechen",
"DS4.ErrorUnexpectedHtmlType": "Typfehler: Erwartet wurde {exType}, tatsächlich erhalten wurde {realType}",
"DS4.RollDialogTargetLabel": "Probenwert",
"DS4.RollDialogModifierLabel": "SL-Modifikator",
"DS4.RollDialogCoupLabel": "Immersieg bis",
"DS4.RollDialogFumbleLabel": "Patzer ab",
"DS4.RollDialogVisibilityLabel": "Sichtbarkeit",
"DS4.ChatVisibilityRoll": "Alle",
"DS4.ChatVisibilityGmRoll": "Selbst & SL",
"DS4.ChatVisibilityBlindRoll": "Nur SL",
"DS4.ChatVisibilitySelfRoll": "Nur selbst"
}

View file

@ -1,12 +1,17 @@
{
"DS4.UserInteractionAddItem": "Add item",
"DS4.UserInteractionEditItem": "Edit item",
"DS4.UserInteractionDeleteItem": "Delete item",
"DS4.NotOwned": "No owner",
"DS4.HeadingDescription": "Description",
"DS4.HeadingBiography": "Biography",
"DS4.HeadingDetails": "Details",
"DS4.HeadingEffects": "Effects",
"DS4.HeadingInventory": "Inventory",
"DS4.HeadingProfile": "Profile",
"DS4.HeadingTalents": "Talents & Abilities",
"DS4.HeadingTalentsAbilities": "Talents & Abilities",
"DS4.HeadingSpells": "Spells",
"DS4.HeadingDescription": "Description",
"DS4.HeadingSpecialCreatureAbilites": "Special Abilites",
"DS4.AttackType": "Attack Type",
"DS4.AttackTypeAbbr": "AT",
"DS4.WeaponBonus": "Weapon Bonus",
@ -16,10 +21,12 @@
"DS4.AttackTypeMelee": "Melee",
"DS4.AttackTypeRanged": "Ranged",
"DS4.AttackTypeMeleeRanged": "Melee / Ranged",
"DS4.Description": "Description",
"DS4.Quantity": "Quantity",
"DS4.PriceGold": "Price (Gold)",
"DS4.StorageLocation": "Stored at",
"DS4.ItemEquipped": "Equipped",
"DS4.ItemEquippedAbbr": "E",
"DS4.ItemOwner": "Owner",
"DS4.ItemAvailability": "Availability",
"DS4.ItemAvailabilityHamlet": "Hamlet",
@ -36,6 +43,8 @@
"DS4.ItemTypeArmorPlural": "Armor",
"DS4.ItemTypeShield": "Shield",
"DS4.ItemTypeShieldPlural": "Shields",
"DS4.ItemTypeSpell": "Spell",
"DS4.ItemTypeSpellPlural": "Spells",
"DS4.ItemTypeTrinket": "Trinket",
"DS4.ItemTypeTrinketPlural": "Trinkets",
"DS4.ItemTypeEquipment": "Equipment",
@ -48,6 +57,8 @@
"DS4.ItemTypeLanguagePlural": "Languages",
"DS4.ItemTypeAlphabet": "Alphabet",
"DS4.ItemTypeAlphabetPlural": "Alphabets",
"DS4.ItemTypeSpecialCreatureAbility": "Special Creature Ability",
"DS4.ItemTypeSpecialCreatureAbilityPlural": "Special Creature Abilities",
"DS4.ArmorType": "Armor Type",
"DS4.ArmorTypeAbbr": "AT",
"DS4.ArmorMaterialType": "Material Type",
@ -72,6 +83,29 @@
"DS4.ArmorMaterialTypeChainAbbr": "Chain",
"DS4.ArmorMaterialTypePlate": "Plate",
"DS4.ArmorMaterialTypePlateAbbr": "Plate",
"DS4.SpellType": "Spell Type",
"DS4.SpellTypeAbbr": "T",
"DS4.SpellTypeSpellcasting": "Spellcasting",
"DS4.SpellTypeTargetedSpellcasting": "Targeted Spellcasting",
"DS4.SpellCategory": "Category",
"DS4.SpellCategoryHealing": "Healing",
"DS4.SpellCategoryFire": "Fire",
"DS4.SpellCategoryIce": "Ice",
"DS4.SpellCategoryLight": "Light",
"DS4.SpellCategoryDarkness": "Darkness",
"DS4.SpellCategoryMindAffecting": "Mind Affecting",
"DS4.SpellCategoryElectricity": "Electricity",
"DS4.SpellCategoryNone": "None",
"DS4.SpellCategoryUnset": "Unset",
"DS4.SpellBonus": "Spell Bonus",
"DS4.SpellBonusAbbr": "SB",
"DS4.SpellMaxDistance": "Range",
"DS4.SpellEffectRadius": "Radius",
"DS4.SpellDuration": "Duration",
"DS4.SpellCooldownDuration": "Cooldown",
"DS4.SpellScrollPriceGold": "Scroll Price (Gold)",
"DS4.ActorTypeCharacter": "Character",
"DS4.ActorTypeCreature": "Creature",
"DS4.AttributeBody": "Body",
"DS4.AttributeMobility": "Mobility",
"DS4.AttributeMind": "Mind",
@ -89,35 +123,83 @@
"DS4.CombatValuesRangedAttack": "Ranged Attack",
"DS4.CombatValuesSpellcasting": "Spellcasting",
"DS4.CombatValuesTargetedSpellcasting": "Targeted Spellcasting",
"DS4.BaseInfoRace": "Race",
"DS4.BaseInfoClass": "Class",
"DS4.BaseInfoHeroClass": "Hero Class",
"DS4.BaseInfoCulture": "Culture",
"DS4.ProgressionLevel": "Level",
"DS4.ProgressionExperiencePoints": "Experience Points",
"DS4.ProgressionTalentPoints": "Talent Points",
"DS4.ProgressionProgressPoints": "Progress Points",
"DS4.CharacterBaseInfoRace": "Race",
"DS4.CharacterBaseInfoClass": "Class",
"DS4.CharacterBaseInfoHeroClass": "Hero Class",
"DS4.CharacterBaseInfoCulture": "Culture",
"DS4.CharacterProgressionLevel": "Level",
"DS4.CharacterProgressionExperiencePoints": "Experience Points",
"DS4.CharacterProgressionTalentPoints": "Talent Points",
"DS4.CharacterProgressionProgressPoints": "Progress Points",
"DS4.TalentRank": "Rank",
"DS4.TalentRankBase": "Acquired Ranks",
"DS4.TalentRankMax": "Maximum Ranks",
"DS4.TalentRankMod": "Additional Ranks",
"DS4.TalentRankTotal": "Total Ranks",
"DS4.LanguageLanguages": "Languages",
"DS4.LanguageAlphabets": "Alphabets",
"DS4.ProfileGender": "Gender",
"DS4.ProfileBirthday": "Birthday",
"DS4.ProfileBirthplace": "Birthplace",
"DS4.ProfileAge": "Age",
"DS4.ProfileHeight": "Height",
"DS4.ProfilHairColor": "Hair Color",
"DS4.ProfileWeight": "Weight",
"DS4.ProfileEyeColor": "Eye Color",
"DS4.ProfileSpecialCharacteristics": "Special Characteristics",
"DS4.CurrencyGold": "Gold",
"DS4.CurrencySilver": "Silver",
"DS4.CurrencyCopper": "Copper",
"DS4.Currency": "Currency",
"DS4.CharacterLanguageLanguages": "Languages",
"DS4.CharacterLanguageAlphabets": "Alphabets",
"DS4.SpecialCreatureAbilityExperiencePoints": "Experience Points",
"DS4.CharacterProfileBiography": "Biography",
"DS4.CharacterProfileGender": "Gender",
"DS4.CharacterProfileBirthday": "Birthday",
"DS4.CharacterProfileBirthplace": "Birthplace",
"DS4.CharacterProfileAge": "Age",
"DS4.CharacterProfileHeight": "Height",
"DS4.CharacterProfileHairColor": "Hair Color",
"DS4.CharacterProfileWeight": "Weight",
"DS4.CharacterProfileEyeColor": "Eye Color",
"DS4.CharacterProfileSpecialCharacteristics": "Special Characteristics",
"DS4.CharacterCurrencyGold": "Gold",
"DS4.CharacterCurrencySilver": "Silver",
"DS4.CharacterCurrencyCopper": "Copper",
"DS4.CharacterCurrency": "Currency",
"DS4.CreatureTypeAnimal": "Animal",
"DS4.CreatureTypeConstruct": "Construct",
"DS4.CreatureTypeHumanoid": "Humanoid",
"DS4.CreatureTypeMagicalEntity": "Magical Entity",
"DS4.CreatureTypePlantBeing": "Plant Being",
"DS4.CreatureTypeUndead": "Undead",
"DS4.CreatureSizeCategoryTiny": "Tiny",
"DS4.CreatureSizeCategorySmall": "Small",
"DS4.CreatureSizeCategoryNormal": "Normal",
"DS4.CreatureSizeCategoryLarge": "Large",
"DS4.CreatureSizeCategoryHuge": "Huge",
"DS4.CreatureSizeCategoryColossal": "Colossal",
"DS4.CreatureBaseInfoLoot": "Loot",
"DS4.CreatureBaseInfoFoeFactor": "Foe Factor",
"DS4.CreatureBaseInfoCreatureType": "Creature Type",
"DS4.CreatureBaseInfoSizeCategory": "Size Category",
"DS4.CreatureBaseInfoExperiencePoints": "Experience Points",
"DS4.CreatureBaseInfoDescription": "Description",
"DS4.WarningManageActiveEffectOnOwnedItem": "Managing Active Effects within an Owned Item is not currently supported and will be added in a subsequent update.",
"DS4.WarningActorCannotOwnItem": "The actor '{actorName}' of type '{actorType}' cannot own the item '{itemName}' of type '{itemType}'.",
"DS4.ErrorDiceCritOverlap": "There's an overlap between Fumbles and Coups",
"DS4.ErrorExplodingRecursionLimitExceeded": "Maximum recursion depth for exploding dice roll exceeded"
"DS4.ErrorExplodingRecursionLimitExceeded": "Maximum recursion depth for exploding dice roll exceeded",
"DS4.UnitRounds": "Rounds",
"DS4.UnitRoundsAbbr": "rnd",
"DS4.UnitMinutes": "Minutes",
"DS4.UnitMinutesAbbr": "min",
"DS4.UnitHours": "Hours",
"DS4.UnitHoursAbbr": "h",
"DS4.UnitDays": "Days",
"DS4.UnitDaysAbbr": "d",
"DS4.UnitMeters": "Meters",
"DS4.UnitMetersAbbr": "m",
"DS4.UnitKilometers": "Kilometers",
"DS4.UnitKilometersAbbr": "km",
"DS4.UnitCustom": "Custom Unit",
"DS4.UnitCustomAbbr": " ",
"DS4.RollDialogDefaultTitle": "Roll Options",
"DS4.RollDialogOkButton": "Ok",
"DS4.RollDialogCancelButton": "Cancel",
"DS4.ErrorUnexpectedHtmlType": "Type Error: Expected {exType}, got {realType}",
"DS4.RollDialogTargetLabel": "Check Target Number",
"DS4.RollDialogModifierLabel": "Game Master Modifier",
"DS4.RollDialogCoupLabel": "Coup to",
"DS4.RollDialogFumbleLabel": "Fumble from",
"DS4.RollDialogVisibilityLabel": "Visibility",
"DS4.ChatVisibilityRoll": "All",
"DS4.ChatVisibilityGmRoll": "Self & GM",
"DS4.ChatVisibilityBlindRoll": "GM only",
"DS4.ChatVisibilitySelfRoll": "Self only"
}

View file

@ -1,39 +1,19 @@
export interface DS4ActorDataType {
import { ModifiableData, ResourceData, UsableResource } from "../common/common-data";
export type DS4ActorDataType = DS4ActorDataCharacter | DS4ActorDataCreature;
interface DS4ActorDataBase {
attributes: DS4ActorDataAttributes;
traits: DS4ActorDataTraits;
combatValues: DS4ActorDataCombatValues;
baseInfo: DS4ActorDataBaseInfo;
progression: DS4ActorDataProgression;
language: DS4ActorDataLanguage;
profile: DS4ActorDataProfile;
currency: DS4ActorDataCurrency;
}
interface DS4ActorDataAttributes {
body: BodyAttribute;
body: ModifiableData<number>;
mobility: ModifiableData<number>;
mind: ModifiableData<number>;
}
export interface ModifiableData<T> {
base: T;
mod: T;
total?: T;
}
interface UsableResource<T> {
total: T;
used: T;
}
interface ResourceData<T> extends ModifiableData<T> {
value: T;
max?: T;
}
// Blueprint in case we need more detailed differentiation
type BodyAttribute = ModifiableData<number>;
interface DS4ActorDataTraits {
strength: ModifiableData<number>;
constitution: ModifiableData<number>;
@ -54,26 +34,35 @@ interface DS4ActorDataCombatValues {
targetedSpellcasting: ModifiableData<number>;
}
interface DS4ActorDataBaseInfo {
interface DS4ActorDataCharacter extends DS4ActorDataBase {
baseInfo: DS4ActorDataCharacterBaseInfo;
progression: DS4ActorDataCharacterProgression;
language: DS4ActorDataCharacterLanguage;
profile: DS4ActorDataCharacterProfile;
currency: DS4ActorDataCharacterCurrency;
}
interface DS4ActorDataCharacterBaseInfo {
race: string;
class: string;
heroClass: string;
culture: string;
}
interface DS4ActorDataProgression {
interface DS4ActorDataCharacterProgression {
level: number;
experiencePoints: number;
talentPoints: UsableResource<number>;
progressPoints: UsableResource<number>;
}
interface DS4ActorDataLanguage {
interface DS4ActorDataCharacterLanguage {
languages: string;
alphabets: string;
}
interface DS4ActorDataProfile {
interface DS4ActorDataCharacterProfile {
biography: string;
gender: string;
birthday: string;
birthplace: string;
@ -85,8 +74,25 @@ interface DS4ActorDataProfile {
specialCharacteristics: string;
}
interface DS4ActorDataCurrency {
interface DS4ActorDataCharacterCurrency {
gold: number;
silver: number;
copper: number;
}
interface DS4ActorDataCreature extends DS4ActorDataBase {
baseInfo: DS4ActorDataCreatureBaseInfo;
}
type CreatureType = "animal" | "construct" | "humanoid" | "magicalEntity" | "plantBeing" | "undead";
type SizeCategory = "tiny" | "small" | "normal" | "large" | "huge" | "colossal";
interface DS4ActorDataCreatureBaseInfo {
loot: string;
foeFactor: number;
creatureType: CreatureType;
sizeCategory: SizeCategory;
experiencePoints: number;
description: string;
}

View file

@ -1,6 +1,7 @@
import { ModifiableData } from "../common/common-data";
import { DS4Item } from "../item/item";
import { DS4ItemDataType } from "../item/item-data";
import { DS4ActorDataType, ModifiableData } from "./actor-data";
import { DS4ItemDataType, ItemType } from "../item/item-data";
import { DS4ActorDataType } from "./actor-data";
export class DS4Actor extends Actor<DS4ActorDataType, DS4ItemDataType, DS4Item> {
/** @override */
@ -21,4 +22,37 @@ export class DS4Actor extends Actor<DS4ActorDataType, DS4ItemDataType, DS4Item>
combatValues.hitPoints.max = combatValues.hitPoints.total;
}
/**
* The list of item types that can be owned by this actor.
*/
get ownableItemTypes(): Array<ItemType> {
switch (this.data.type) {
case "character":
return [
"weapon",
"armor",
"shield",
"trinket",
"equipment",
"spell",
"talent",
"racialAbility",
"language",
"alphabet",
];
case "creature":
return ["weapon", "armor", "shield", "trinket", "equipment", "spell", "specialCreatureAbility"];
default:
return [];
}
}
/**
* Checks whether or not the given item type can be owned by the actor.
* @param itemType the item type to check
*/
canOwnItemType(itemType: ItemType): boolean {
return this.ownableItemTypes.includes(itemType);
}
}

View file

@ -1,12 +1,30 @@
import { DS4ItemDataType } 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
* @extends {ActorSheet}
*/
export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4ItemDataType> {
/** @override */
static get defaultOptions(): FormApplicationOptions {
return mergeObject(super.defaultOptions, {
classes: ["ds4", "sheet", "actor"],
width: 745,
height: 600,
});
}
/** @override */
get template(): string {
const path = "systems/ds4/templates/actor";
return `${path}/${this.actor.data.type}-sheet.hbs`;
}
/* -------------------------------------------- */
/**
* This method returns the data for the template of the actor sheet.
* It explicitly adds the items of the object sorted by type in the
@ -21,21 +39,9 @@ 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;
}
/** @override */
static get defaultOptions(): FormApplicationOptions {
return mergeObject(super.defaultOptions, {
classes: ["ds4", "sheet", "actor"],
template: "systems/ds4/templates/actor/actor-sheet.hbs",
width: 745,
height: 600,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
});
}
/* -------------------------------------------- */
/** @override */
@ -200,4 +206,26 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
});
}
}
/**
* @override
*/
async _onDrop(event: DragEvent): Promise<boolean | unknown> {
const data = JSON.parse(event.dataTransfer?.getData("text/plain")) as { type?: string };
if (data.type === "Item") {
const item = await Item.fromDropData(data as Parameters<typeof DS4Item.fromDropData>[0]);
if (item && !this.actor.canOwnItemType(item.data.type as ItemType)) {
ui.notifications.warn(
game.i18n.format("DS4.WarningActorCannotOwnItem", {
actorName: this.actor.name,
actorType: this.actor.data.type,
itemName: item.name,
itemType: item.data.type,
}),
);
return false;
}
}
return super._onDrop(event);
}
}

View file

@ -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" }],
});
}
}

View file

@ -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: "inventory" }],
});
}
}

View file

@ -0,0 +1,15 @@
export interface ModifiableData<T> {
base: T;
mod: T;
total?: T;
}
export interface ResourceData<T> extends ModifiableData<T> {
value: T;
max?: T;
}
export interface UsableResource<T> {
total: T;
used: T;
}

View file

@ -26,6 +26,14 @@ export const DS4 = {
ranged: "systems/ds4/assets/official/DS4-RAT.png",
},
/**
* Define the file paths to icon images
*/
spellTypesIcons: {
spellcasting: "systems/ds4/assets/official/DS4-SPC.png",
targetedSpellcasting: "systems/ds4/assets/official/DS4-TSC.png",
},
/**
* Define the set of item availabilties
*/
@ -46,12 +54,14 @@ export const DS4 = {
weapon: "DS4.ItemTypeWeapon",
armor: "DS4.ItemTypeArmor",
shield: "DS4.ItemTypeShield",
spell: "DS4.ItemTypeSpell",
trinket: "DS4.ItemTypeTrinket",
equipment: "DS4.ItemTypeEquipment",
talent: "DS4.ItemTypeTalent",
racialAbility: "DS4.ItemTypeRacialAbility",
language: "DS4.ItemTypeLanguage",
alphabet: "DS4.ItemTypeAlphabet",
specialCreatureAbility: "DS4.ItemTypeSpecialCreatureAbility",
},
/**
@ -96,8 +106,33 @@ export const DS4 = {
plate: "DS4.ArmorMaterialTypePlateAbbr",
},
spellTypes: {
spellcasting: "DS4.SpellTypeSpellcasting",
targetedSpellcasting: "DS4.SpellTypeTargetedSpellcasting",
},
spellCategories: {
healing: "DS4.SpellCategoryHealing",
fire: "DS4.SpellCategoryFire",
ice: "DS4.SpellCategoryIce",
light: "DS4.SpellCategoryLight",
darkness: "DS4.SpellCategoryDarkness",
mindAffecting: "DS4.SpellCategoryMindAffecting",
electricity: "DS4.SpellCategoryElectricity",
none: "DS4.SpellCategoryNone",
unset: "DS4.SpellCategoryUnset",
},
/**
* Define the set of attributes a character has
* Define the set of actor types
*/
actorTypes: {
character: "DS4.ActorTypeCharacter",
creature: "DS4.ActorTypeCreature",
},
/**
* Define the set of attributes an actor has
*/
attributes: {
body: "DS4.AttributeBody",
@ -106,7 +141,7 @@ export const DS4 = {
},
/**
* Define the set of traits a character has
* Define the set of traits an actor has
*/
traits: {
strength: "DS4.TraitStrength",
@ -118,7 +153,7 @@ export const DS4 = {
},
/**
* Define the set of combat values a character has
* Define the set of combat values an actor has
*/
combatValues: {
hitPoints: "DS4.CombatValuesHitPoints",
@ -134,50 +169,52 @@ export const DS4 = {
/**
* Define the base info of a character
*/
baseInfo: {
race: "DS4.BaseInfoRace",
class: "DS4.BaseInfoClass",
heroClass: "DS4.BaseInfoHeroClass",
culture: "DS4.BaseInfoCulture",
characterBaseInfo: {
race: "DS4.CharacterBaseInfoRace",
class: "DS4.CharacterBaseInfoClass",
heroClass: "DS4.CharacterBaseInfoHeroClass",
culture: "DS4.CharacterBaseInfoCulture",
},
/**
* Define the progression info of a character
*/
progression: {
level: "DS4.ProgressionLevel",
experiencePoints: "DS4.ProgressionExperiencePoints",
talentPoints: "DS4.ProgressionTalentPoints",
progressPoints: "DS4.ProgressionProgressPoints",
characterProgression: {
level: "DS4.CharacterProgressionLevel",
experiencePoints: "DS4.CharacterProgressionExperiencePoints",
talentPoints: "DS4.CharacterProgressionTalentPoints",
progressPoints: "DS4.CharacterProgressionProgressPoints",
},
/**
* Define the language info of a character
*/
language: {
languages: "DS4.LanguageLanguages",
alphabets: "DS4.LanguageAlphabets",
characterLanguage: {
languages: "DS4.CharacterLanguageLanguages",
alphabets: "DS4.CharacterLanguageAlphabets",
},
/**
* Define the profile info of a character
*/
profile: {
gender: "DS4.ProfileGender",
birthday: "DS4.ProfileBirthday",
birthplace: "DS4.ProfileBirthplace",
age: "DS4.ProfileAge",
height: "DS4.ProfileHeight",
hairColor: "DS4.ProfilHairColor",
weight: "DS4.ProfileWeight",
eyeColor: "DS4.ProfileEyeColor",
specialCharacteristics: "DS4.ProfileSpecialCharacteristics",
characterProfile: {
biography: "DS4.CharacterProfileBiography",
gender: "DS4.CharacterProfileGender",
birthday: "DS4.CharacterProfileBirthday",
birthplace: "DS4.CharacterProfileBirthplace",
age: "DS4.CharacterProfileAge",
height: "DS4.CharacterProfileHeight",
hairColor: "DS4.CharacterProfileHairColor",
weight: "DS4.CharacterProfileWeight",
eyeColor: "DS4.CharacterProfileEyeColor",
specialCharacteristics: "DS4.CharacterProfileSpecialCharacteristics",
},
/**
* Define the profile info types for hanndlebars of a character
* Define the profile info types for handlebars of a character
*/
profileDTypes: {
characterProfileDTypes: {
biography: "String",
gender: "String",
birthday: "String",
birthplace: "String",
@ -192,9 +229,94 @@ export const DS4 = {
/**
* Define currency elements of a character
*/
currency: {
gold: "DS4.CurrencyGold",
silver: "DS4.CurrencySilver",
copper: "DS4.CurrencyCopper",
characterCurrency: {
gold: "DS4.CharacterCurrencyGold",
silver: "DS4.CharacterCurrencySilver",
copper: "DS4.CharacterCurrencyCopper",
},
/**
* Define the different creature types a creature can be
*/
creatureTypes: {
animal: "DS4.CreatureTypeAnimal",
construct: "DS4.CreatureTypeConstruct",
humanoid: "DS4.CreatureTypeHumanoid",
magicalEntity: "DS4.CreatureTypeMagicalEntity",
plantBeing: "DS4.CreatureTypePlantBeing",
undead: "DS4.CreatureTypeUndead",
},
/**
* Define the different size categories creatures fall into
*/
creatureSizeCategories: {
tiny: "DS4.CreatureSizeCategoryTiny",
small: "DS4.CreatureSizeCategorySmall",
normal: "DS4.CreatureSizeCategoryNormal",
large: "DS4.CreatureSizeCategoryLarge",
huge: "DS4.CreatureSizeCategoryHuge",
colossal: "DS4.CreatureSizeCategoryColossal",
},
/**
* Define the base info of a creature
*/
creatureBaseInfo: {
loot: "DS4.CreatureBaseInfoLoot",
foeFactor: "DS4.CreatureBaseInfoFoeFactor",
creatureType: "DS4.CreatureBaseInfoCreatureType",
sizeCategory: "DS4.CreatureBaseInfoSizeCategory",
experiencePoints: "DS4.CreatureBaseInfoExperiencePoints",
description: "DS4.CreatureBaseInfoDescription",
},
/**
* Define translations for available distance units
*/
distanceUnits: {
meter: "DS4.UnitMeters",
kilometer: "DS4.UnitKilometers",
custom: "DS4.UnitCustom",
},
/**
* Define abbreviations for available distance units
*/
distanceUnitsAbbr: {
meter: "DS4.UnitMetersAbbr",
kilometer: "DS4.UnitKilometersAbbr",
custom: "DS4.UnitCustomAbbr",
},
/**
* Define translations for available distance units
*/
temporalUnits: {
rounds: "DS4.UnitRounds",
minutes: "DS4.UnitMinutes",
hours: "DS4.UnitHours",
days: "DS4.UnitDays",
custom: "DS4.UnitCustom",
},
/**
* Define abbreviations for available units
*/
temporalUnitsAbbr: {
rounds: "DS4.UnitRoundsAbbr",
minutes: "DS4.UnitMinutesAbbr",
hours: "DS4.UnitHoursAbbr",
days: "DS4.UnitDaysAbbr",
custom: "DS4.UnitCustomAbbr",
},
/**
* Define localization strings for Chat Visibility
*/
chatVisibilities: {
roll: "DS4.ChatVisibilityRoll",
gmroll: "DS4.ChatVisibilityGmRoll",
blindroll: "DS4.ChatVisibilityBlindRoll",
selfroll: "DS4.ChatVisibilitySelfRoll",
},
};

View file

@ -1,10 +1,12 @@
// 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";
import { createCheckRoll } from "./rolls/check-factory";
Hooks.once("init", async function () {
console.log(`DS4 | Initializing the DS4 Game System\n${DS4.ASCII}`);
@ -13,6 +15,7 @@ Hooks.once("init", async function () {
DS4Actor,
DS4Item,
DS4,
createCheckRoll,
};
// Record configuration
@ -22,6 +25,10 @@ Hooks.once("init", async function () {
CONFIG.Actor.entityClass = DS4Actor as typeof Actor;
CONFIG.Item.entityClass = DS4Item as typeof Item;
// Define localized type labels
CONFIG.Actor.typeLabels = DS4.actorTypes;
CONFIG.Item.typeLabels = DS4.itemTypes;
// Configure Dice
CONFIG.Dice.types = [Die, DS4Check];
CONFIG.Dice.terms = {
@ -32,7 +39,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 });
@ -47,13 +55,15 @@ async function registerHandlebarsPartials() {
"systems/ds4/templates/item/partials/effects.hbs",
"systems/ds4/templates/item/partials/body.hbs",
"systems/ds4/templates/actor/partials/items-overview.hbs",
"systems/ds4/templates/actor/partials/talents-overview.hbs",
"systems/ds4/templates/actor/partials/talents-abilities-overview.hbs",
"systems/ds4/templates/actor/partials/spells-overview.hbs",
"systems/ds4/templates/actor/partials/overview-add-button.hbs",
"systems/ds4/templates/actor/partials/overview-control-buttons.hbs",
"systems/ds4/templates/actor/partials/attributes-traits.hbs",
"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);
}
@ -76,18 +86,28 @@ Hooks.once("setup", function () {
"armorMaterialTypes",
"armorMaterialTypesAbbr",
"armorMaterialTypes",
"spellTypes",
"spellCategories",
"attributes",
"traits",
"combatValues",
"baseInfo",
"progression",
"language",
"profile",
"currency",
"characterBaseInfo",
"characterProgression",
"characterLanguage",
"characterProfile",
"characterCurrency",
"creatureTypes",
"creatureSizeCategories",
"creatureBaseInfo",
"temporalUnits",
"temporalUnitsAbbr",
"distanceUnits",
"distanceUnitsAbbr",
"chatVisibilities",
];
// 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) {

View file

@ -1,15 +1,20 @@
import { ModifiableData } from "../actor/actor-data";
import { ModifiableData } from "../common/common-data";
import { DS4 } from "../config";
export type ItemType = keyof typeof DS4.itemTypes;
export type DS4ItemDataType =
| DS4Weapon
| DS4Armor
| DS4Shield
| DS4Spell
| DS4Trinket
| DS4Equipment
| DS4Talent
| DS4RacialAbility
| DS4Language
| DS4Alphabet;
| DS4Alphabet
| DS4SpecialCreatureAbility;
// types
@ -32,12 +37,35 @@ interface DS4TalentRank extends ModifiableData<number> {
max: number;
}
interface DS4Spell extends DS4ItemBase, DS4ItemEquipable {
spellType: "spellcasting" | "targetedSpellcasting";
bonus: string;
spellCategory:
| "healing"
| "fire"
| "ice"
| "light"
| "darkness"
| "mindAffecting"
| "electricity"
| "none"
| "unset";
maxDistance: UnitData<DistanceUnit>;
effectRadius: UnitData<DistanceUnit>;
duration: UnitData<TemporalUnit>;
cooldownDuration: UnitData<TemporalUnit>;
scrollPrice: number;
}
interface DS4Shield extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable, DS4ItemProtective {}
interface DS4Trinket extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable {}
interface DS4Equipment extends DS4ItemBase, DS4ItemPhysical {}
type DS4RacialAbility = DS4ItemBase;
type DS4Language = DS4ItemBase;
type DS4Alphabet = DS4ItemBase;
interface DS4SpecialCreatureAbility extends DS4ItemBase {
experiencePoints: number;
}
// templates
@ -62,3 +90,10 @@ interface DS4ItemEquipable {
interface DS4ItemProtective {
armorValue: number;
}
interface UnitData<UnitType> {
value: string;
unit: UnitType;
}
type TemporalUnit = "rounds" | "minutes" | "hours" | "days" | "custom";
type DistanceUnit = "meter" | "kilometer" | "custom";

View file

@ -0,0 +1,237 @@
import { DS4 } from "../config";
/**
* Provides default values for all arguments the `CheckFactory` expects.
*/
class DefaultCheckOptions implements DS4CheckFactoryOptions {
maxCritSuccess = 1;
minCritFailure = 20;
useSlayingDice = false;
rollMode: DS4RollMode = "roll";
mergeWith(other: Partial<DS4CheckFactoryOptions>): DS4CheckFactoryOptions {
return { ...this, ...other } as DS4CheckFactoryOptions;
}
}
/**
* Singleton reference for default value extraction.
*/
const defaultCheckOptions = new DefaultCheckOptions();
/**
* Most basic class responsible for generating the chat formula and passing it to the chat as roll.
*/
class CheckFactory {
constructor(
private checkTargetValue: number,
private gmModifier: number,
passedOptions: Partial<DS4CheckFactoryOptions> = {},
) {
this.checkOptions = new DefaultCheckOptions().mergeWith(passedOptions);
}
private checkOptions: DS4CheckFactoryOptions;
async execute(): Promise<ChatMessage | any> {
const rollCls: typeof Roll = CONFIG.Dice.rolls[0];
const formula = [
"ds",
this.createTargetValueTerm(),
this.createCritTerm(),
this.createSlayingDiceTerm(),
].filterJoin("");
const roll = new rollCls(formula);
const rollModeTemplate = this.checkOptions.rollMode;
console.log(rollModeTemplate);
return roll.toMessage({}, { rollMode: rollModeTemplate, create: true });
}
// Term generators
createTargetValueTerm(): string | null {
if (this.checkTargetValue !== null) {
return "v" + (this.checkTargetValue + this.gmModifier);
} else {
return null;
}
}
createCritTerm(): string | null {
const minCritRequired = this.checkOptions.minCritFailure !== defaultCheckOptions.minCritFailure;
const maxCritRequired = this.checkOptions.maxCritSuccess !== defaultCheckOptions.maxCritSuccess;
if (minCritRequired || maxCritRequired) {
return "c" + (this.checkOptions.maxCritSuccess ?? "") + "," + (this.checkOptions.minCritFailure ?? "");
} else {
return null;
}
}
createSlayingDiceTerm(): string | null {
return this.checkOptions.useSlayingDice ? "x" : null;
}
}
/**
* Asks the user for all unknown/necessary information and passes them on to perform a roll.
* @param targetValue {number} The Check Target Number ("CTN")
* @param options {Partial<DS4CheckFactoryOptions>} Options changing the behaviour of the roll and message.
*/
export async function createCheckRoll(
targetValue: number,
options: Partial<DS4CheckFactoryOptions> = {},
): Promise<ChatMessage | any> {
// Ask for additional required data;
const gmModifierData = await askGmModifier(targetValue, options);
const newOptions: Partial<DS4CheckFactoryOptions> = {
maxCritSuccess: gmModifierData.maxCritSuccess ?? options.maxCritSuccess ?? undefined,
minCritFailure: gmModifierData.minCritFailure ?? options.minCritFailure ?? undefined,
useSlayingDice: gmModifierData.useSlayingDice ?? options.useSlayingDice ?? undefined,
rollMode: gmModifierData.rollMode ?? options.rollMode ?? undefined,
};
// Create Factory
const cf = new CheckFactory(gmModifierData.checkTargetValue, gmModifierData.gmModifier, newOptions);
// Possibly additional processing
// Execute roll
await cf.execute();
}
/**
* Responsible for rendering the modal interface asking for the modifier specified by GM and (currently) additional data.
*
* @notes
* At the moment, this asks for more data than it will do after some iterations.
*
* @returns {Promise<IntermediateGmModifierData>} The data given by the user.
*/
async function askGmModifier(
targetValue: number,
options: Partial<DS4CheckFactoryOptions> = {},
{ template, title }: { template?: string; title?: string } = {},
): Promise<IntermediateGmModifierData> {
// Render model interface and return value
const usedTemplate = template ?? "systems/ds4/templates/roll/roll-options.hbs";
const usedTitle = title ?? game.i18n.localize("DS4.RollDialogDefaultTitle");
const templateData = {
cssClass: "roll-option",
title: usedTitle,
checkTargetValue: targetValue,
maxCritSuccess: options.maxCritSuccess ?? defaultCheckOptions.maxCritSuccess,
minCritFailure: options.minCritFailure ?? defaultCheckOptions.minCritFailure,
rollModes: rollModes,
config: DS4,
};
const renderedHtml = await renderTemplate(usedTemplate, templateData);
const dialogPromise = new Promise<HTMLFormElement>((resolve) => {
new Dialog(
{
title: usedTitle,
close: () => {
// Don't do anything
},
content: renderedHtml,
buttons: {
ok: {
label: game.i18n.localize("DS4.RollDialogOkButton"),
callback: (html: HTMLElement | JQuery) => {
if (!("jquery" in html)) {
throw new Error(
game.i18n.format("DS4.ErrorUnexpectedHtmlType", {
exType: "JQuery",
realType: "HTMLElement",
}),
);
} else {
const innerForm = html[0].querySelector("form");
resolve(innerForm);
}
},
},
cancel: {
label: game.i18n.localize("DS4.RollDialogCancelButton"),
callback: () => {
// Don't do anything
},
},
},
default: "ok",
},
{},
).render(true);
});
const dialogForm = await dialogPromise;
return parseDialogFormData(dialogForm, targetValue);
}
/**
* Extracts Dialog data from the returned DOM element.
* @param formData {HTMLFormElement} The filed dialog
* @param targetValue {number} The previously known target value (slated for removal once data automation is available)
*/
function parseDialogFormData(formData: HTMLFormElement, targetValue: number): IntermediateGmModifierData {
return {
checkTargetValue: parseInt(formData["ctv"]?.value) ?? targetValue,
gmModifier: parseInt(formData["gmmod"]?.value) ?? 0,
maxCritSuccess: parseInt(formData["maxcoup"]?.value) ?? defaultCheckOptions.maxCritSuccess,
minCritFailure: parseInt(formData["minfumble"]?.value) ?? defaultCheckOptions.minCritFailure,
useSlayingDice: false,
rollMode: formData["visibility"]?.value ?? defaultCheckOptions.rollMode,
};
}
/**
* Contains data that needs retrieval from an interactive Dialog.
*/
interface GmModifierData {
gmModifier: number;
rollMode: DS4RollMode;
}
/**
* Contains *CURRENTLY* necessary Data for drafting a roll.
*
* @deprecated
* Quite a lot of this information is requested due to a lack of automation:
* - maxCritSuccess
* - minCritFailure
* - useSlayingDice
* - checkTargetValue
*
* They will and should be removed once effects and data retrieval is in place.
* If a "raw" roll dialog is necessary, create another pre-porcessing Dialog
* class asking for the required information.
* This interface should then be replaced with the `GmModifierData`.
*/
interface IntermediateGmModifierData extends GmModifierData {
checkTargetValue: number;
gmModifier: number;
maxCritSuccess: number;
minCritFailure: number;
// TODO: In final version from system settings
useSlayingDice: boolean;
rollMode: DS4RollMode;
}
/**
* The minimum behavioural options that need to be passed to the factory.
*/
export interface DS4CheckFactoryOptions {
maxCritSuccess: number;
minCritFailure: number;
useSlayingDice: boolean;
rollMode: DS4RollMode;
}
/**
* Defines all possible roll modes, both for iterating and typing.
*/
const rollModes = ["roll", "gmroll", "blindroll", "selfroll"] as const;
type DS4RollModeTuple = typeof rollModes;
export type DS4RollMode = DS4RollModeTuple[number];

View file

@ -86,7 +86,7 @@ export class DS4Check extends DiceTerm {
} else {
return ds4roll(targetValueToUse, {
maxCritSuccess: this.maxCritSuccess,
minCritFail: this.minCritFailure,
minCritFailure: this.minCritFailure,
slayingDiceRepetition: slayingDiceRepetition,
useSlayingDice: slayingDiceRepetition,
});
@ -132,7 +132,6 @@ export class DS4Check extends DiceTerm {
static readonly DEFAULT_TARGET_VALUE = 10;
static readonly DEFAULT_MAX_CRIT_SUCCESS = 1;
static readonly DEFAULT_MIN_CRIT_FAILURE = 20;
// TODO: add to Type declarations
static DENOMINATION = "s";
static MODIFIERS = {
x: "explode",

View file

@ -1,13 +1,13 @@
export interface RollOptions {
maxCritSuccess: number;
minCritFail: number;
minCritFailure: number;
useSlayingDice: boolean;
slayingDiceRepetition: boolean;
}
export class DefaultRollOptions implements RollOptions {
public maxCritSuccess = 1;
public minCritFail = 20;
public minCritFailure = 20;
public useSlayingDice = false;
public slayingDiceRepetition = false;

View file

@ -48,7 +48,7 @@ export function rollCheckSingleDie(
if (rolledDie <= usedOptions.maxCritSuccess) {
return new RollResult(checkTargetValue, RollResultStatus.CRITICAL_SUCCESS, usedDice, true);
} else if (rolledDie >= usedOptions.minCritFail && !isSlayingDiceRepetition(usedOptions)) {
} else if (rolledDie >= usedOptions.minCritFailure && !isSlayingDiceRepetition(usedOptions)) {
return new RollResult(0, RollResultStatus.CRITICAL_FAILURE, usedDice, true);
} else {
if (rolledDie <= checkTargetValue) {
@ -90,7 +90,7 @@ export function rollCheckMultipleDice(
const slayingDiceRepetition = isSlayingDiceRepetition(usedOptions);
// Slaying Dice require a different handling.
if (firstResult >= usedOptions.minCritFail && !slayingDiceRepetition) {
if (firstResult >= usedOptions.minCritFailure && !slayingDiceRepetition) {
return new RollResult(0, RollResultStatus.CRITICAL_FAILURE, usedDice, true);
}

View file

@ -9,12 +9,13 @@
.side-property {
margin: 2px 0;
display: grid;
grid-template-columns: minmax(30%, auto) auto;
grid-template-columns: 40% auto;
justify-content: left;
label {
line-height: $default-input-height;
font-weight: bold;
padding-right: 3pt;
}
input,
@ -30,6 +31,17 @@
height: 100%;
margin: 0px;
}
.unit-data-pair {
display: flex;
flex-direction: row;
select {
width: 4em;
}
input {
max-width: 7em;
}
}
}
}

View file

@ -6,7 +6,7 @@
"minimumCoreVersion": "0.7.9",
"compatibleCoreVersion": "0.7.9",
"templateVersion": 2,
"author": "Johannes Loher, Gesina Schwalbe, Oliver Rümpelein",
"author": "Johannes Loher, Gesina Schwalbe, Oliver Rümpelein, Siegfried Krug",
"esmodules": ["module/ds4.js"],
"styles": ["ds4.css"],
"scripts": [],
@ -29,5 +29,6 @@
"url": "https://git.f3l.de/dungeonslayers/ds4",
"manifest": "https://git.f3l.de/dungeonslayers/ds4/-/raw/latest/src/system.json?inline=false",
"download": "https://git.f3l.de/dungeonslayers/ds4/-/jobs/artifacts/0.1.0/download?job=build",
"license": "MIT"
"license": "MIT",
"initiative": "@combatValues.initiative.total"
}

View file

@ -1,84 +1,98 @@
{
"Actor": {
"types": ["character"],
"templates": {},
"types": ["character", "creature"],
"templates": {
"base": {
"attributes": {
"body": {
"base": 0,
"mod": 0
},
"mobility": {
"base": 0,
"mod": 0
},
"mind": {
"base": 0,
"mod": 0
}
},
"traits": {
"strength": {
"base": 0,
"mod": 0
},
"constitution": {
"base": 0,
"mod": 0
},
"agility": {
"base": 0,
"mod": 0
},
"dexterity": {
"base": 0,
"mod": 0
},
"intellect": {
"base": 0,
"mod": 0
},
"aura": {
"base": 0,
"mod": 0
}
},
"combatValues": {
"hitPoints": {
"base": 0,
"mod": 0,
"value": 0
},
"defense": {
"base": 0,
"mod": 0
},
"initiative": {
"base": 0,
"mod": 0
},
"movement": {
"base": 0,
"mod": 0
},
"meleeAttack": {
"base": 0,
"mod": 0
},
"rangedAttack": {
"base": 0,
"mod": 0
},
"spellcasting": {
"base": 0,
"mod": 0
},
"targetedSpellcasting": {
"base": 0,
"mod": 0
}
}
}
},
"creature": {
"templates": ["base"],
"baseInfo": {
"loot": "",
"foeFactor": 1,
"creatureType": "humanoid",
"sizeCategory": "normal",
"experiencePoints": 0,
"description": ""
}
},
"character": {
"templates": [],
"attributes": {
"body": {
"base": 0,
"mod": 0
},
"mobility": {
"base": 0,
"mod": 0
},
"mind": {
"base": 0,
"mod": 0
}
},
"traits": {
"strength": {
"base": 0,
"mod": 0
},
"constitution": {
"base": 0,
"mod": 0
},
"agility": {
"base": 0,
"mod": 0
},
"dexterity": {
"base": 0,
"mod": 0
},
"intellect": {
"base": 0,
"mod": 0
},
"aura": {
"base": 0,
"mod": 0
}
},
"combatValues": {
"hitPoints": {
"base": 0,
"mod": 0,
"value": 0
},
"defense": {
"base": 0,
"mod": 0
},
"initiative": {
"base": 0,
"mod": 0
},
"movement": {
"base": 0,
"mod": 0
},
"meleeAttack": {
"base": 0,
"mod": 0
},
"rangedAttack": {
"base": 0,
"mod": 0
},
"spellcasting": {
"base": 0,
"mod": 0
},
"targetedSpellcasting": {
"base": 0,
"mod": 0
}
},
"templates": ["base"],
"baseInfo": {
"race": "",
"class": "",
@ -98,6 +112,7 @@
}
},
"profile": {
"biography": "",
"gender": "",
"birthday": "",
"birthplace": "",
@ -120,12 +135,14 @@
"weapon",
"armor",
"shield",
"spell",
"trinket",
"equipment",
"talent",
"racialAbility",
"language",
"alphabet"
"alphabet",
"specialCreatureAbility"
],
"templates": {
"base": {
@ -180,6 +197,33 @@
},
"alphabet": {
"templates": ["base"]
},
"spell": {
"templates": ["base", "equipable"],
"spellType": "spellcasting",
"bonus": "",
"spellCategory": "unset",
"maxDistance": {
"value": "",
"unit": "meter"
},
"effectRadius": {
"value": "",
"unit": "meter"
},
"duration": {
"value": "",
"unit": "custom"
},
"cooldownDuration": {
"value": "",
"unit": "custom"
},
"scrollPrice": 0
},
"specialCreatureAbility": {
"templates": ["base"],
"experiencePoints": 0
}
}
}

View file

@ -8,17 +8,19 @@
<div class="flexrow basic-properties">
<div class="basic-property">
<label class="basic-property-label" for="data.baseInfo.race">{{config.baseInfo.race}}</label>
<label class="basic-property-label"
for="data.baseInfo.race">{{config.characterBaseInfo.race}}</label>
<input type="text" name="data.baseInfo.race" value="{{data.baseInfo.race}}" data-dtype="String" />
</div>
<div class="basic-property">
<label class="basic-property-label" for="data.baseInfo.culture">{{config.baseInfo.culture}}</label>
<label class="basic-property-label"
for="data.baseInfo.culture">{{config.characterBaseInfo.culture}}</label>
<input type="text" name="data.baseInfo.culture" value="{{data.baseInfo.culture}}"
data-dtype="String" />
</div>
<div class="basic-property flex125">
<label class="basic-property-label"
for="data.progression.progressPoints.used">{{config.progression.progressPoints}}</label>
for="data.progression.progressPoints.used">{{config.characterProgression.progressPoints}}</label>
<div class="flexrow">
<input type="number" name="data.progression.progressPoints.used"
value="{{data.progression.progressPoints.used}}" data-dtype="Number" /><span
@ -29,7 +31,7 @@
</div>
<div class="basic-property flex125">
<label class="basic-property-label"
for="data.progression.talentPoints.used">{{config.progression.talentPoints}}</label>
for="data.progression.talentPoints.used">{{config.characterProgression.talentPoints}}</label>
<div class="flexrow">
<input type="number" name="data.progression.talentPoints.used"
value="{{data.progression.talentPoints.used}}" data-dtype="Number" /><span
@ -39,12 +41,13 @@
</div>
</div>
<div class="basic-property">
<label class="basic-property-label" for="data.baseInfo.class">{{config.baseInfo.class}}</label>
<label class="basic-property-label"
for="data.baseInfo.class">{{config.characterBaseInfo.class}}</label>
<input type="text" name="data.baseInfo.class" value="{{data.baseInfo.class}}" data-dtype="String" />
</div>
<div class="basic-property">
<label class="basic-property-label"
for="data.baseInfo.heroClass">{{config.baseInfo.heroClass}}</label>
for="data.baseInfo.heroClass">{{config.characterBaseInfo.heroClass}}</label>
<input type="text" name="data.baseInfo.heroClass" value="{{data.baseInfo.heroClass}}"
data-dtype="String" />
</div>
@ -58,26 +61,31 @@
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="description">{{localize 'DS4.HeadingDescription'}}</a>
<a class="item" data-tab="talents">{{localize 'DS4.HeadingTalents'}}</a>
<a class="item" data-tab="profile">{{localize "DS4.HeadingProfile"}}</a>
<a class="item" data-tab="inventory">{{localize 'DS4.HeadingInventory'}}</a>
<a class="item" data-tab="spells">{{localize 'DS4.HeadingSpells'}}</a>
<a class="item" data-tab="talents-abilities">{{localize 'DS4.HeadingTalentsAbilities'}}</a>
<a class="item" data-tab="profile">{{localize "DS4.HeadingProfile"}}</a>
<a class="item" data-tab="biography">{{localize 'DS4.HeadingBiography'}}</a>
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Biography Tab --}}
<div class="tab biography" data-group="primary" data-tab="description">
{{editor content=data.biography target="data.biography" button=true owner=owner editable=editable}}
</div>
{{!-- Items Tab --}}
{{> systems/ds4/templates/actor/partials/items-overview.hbs}}
{{!-- Spells Tab --}}
{{> systems/ds4/templates/actor/partials/spells-overview.hbs}}
{{!-- Talents Tab --}}
{{> systems/ds4/templates/actor/partials/talents-abilities-overview.hbs}}
{{! Profile Tab --}}
{{> systems/ds4/templates/actor/partials/profile.hbs}}
{{!-- Talents Tab --}}
{{> systems/ds4/templates/actor/partials/talents-overview.hbs}}
{{!-- Items Tab --}}
{{> systems/ds4/templates/actor/partials/items-overview.hbs}}
{{!-- Biography Tab --}}
<div class="tab biography" data-group="primary" data-tab="biography">
{{editor content=data.profile.biography target="data.profile.biography" button=true owner=owner
editable=editable}}
</div>
</section>
</form>
</form>

View file

@ -0,0 +1,78 @@
<form class="{{cssClass}} flexcol" autocomplete="off">
{{!-- Sheet Header --}}
<header class="sheet-header">
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100" />
<div class="header-fields flexrow">
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name" /></h1>
<div class="flexrow basic-properties">
<div class="basic-property">
<label>{{config.creatureBaseInfo.creatureType}}</label>
<select name="data.baseInfo.creatureType" data-type="String">
{{#select data.baseInfo.creatureType}}
{{#each config.creatureTypes as |value key|}}
<option value="{{key}}">{{value}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="basic-property">
<label class="basic-property-label"
for="data.baseInfo.loot">{{config.creatureBaseInfo.loot}}</label>
<input type="text" name="data.baseInfo.loot" value="{{data.baseInfo.loot}}" data-dtype="String" />
</div>
<div class="basic-property">
<label class="basic-property-label"
for="data.baseInfo.foeFactor">{{config.creatureBaseInfo.foeFactor}}</label>
<input type="text" name="data.baseInfo.foeFactor" value="{{data.baseInfo.foeFactor}}"
data-dtype="Number" />
</div>
<div class="basic-property">
<label>{{config.creatureBaseInfo.sizeCategory}}</label>
<select name="data.baseInfo.sizeCategory" data-type="String">
{{#select data.baseInfo.sizeCategory}}
{{#each config.creatureSizeCategories as |value key|}}
<option value="{{key}}">{{value}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="basic-property">
<label class="basic-property-label"
for="data.baseInfo.experiencePoints">{{config.creatureBaseInfo.experiencePoints}}</label>
<input type="text" name="data.baseInfo.experiencePoints" value="{{data.baseInfo.experiencePoints}}"
data-dtype="Number" />
</div>
</div>
</div>
<div class="character-values">
{{> systems/ds4/templates/actor/partials/attributes-traits.hbs}}
{{> systems/ds4/templates/actor/partials/combat-values.hbs}}
</div>
</header>
{{!-- 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="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 --}}
<section class="sheet-body">
{{!-- 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}}
{{!-- Description Tab --}}
<div class="tab description" data-group="primary" data-tab="description">
{{editor content=data.baseInfo.description target="data.baseInfo.description" button=true owner=owner
editable=editable}}
</div>
</section>
</form>

View file

@ -1,13 +1,13 @@
<div class="progression flexrow">
<div class="progression-entry">
<h2 class="progression-label"><label for="data.progression.level">{{config.progression.level}}</label>
<h2 class="progression-label"><label for="data.progression.level">{{config.characterProgression.level}}</label>
</h2>
<input class="progression-value" type="number" name="data.progression.level" value="{{data.progression.level}}"
data-dtype="Number" />
</div>
<div class="progression-entry">
<h2 class="progression-label"><label
for="data.progression.experiencePoints">{{config.progression.experiencePoints}}</label>
for="data.progression.experiencePoints">{{config.characterProgression.experiencePoints}}</label>
</h2>
<input class="progression-value" type="number" name="data.progression.experiencePoints"
value="{{data.progression.experiencePoints}}" data-dtype="Number" />

View file

@ -1,5 +1,4 @@
{{!-- 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 --}}
@ -15,9 +14,9 @@
--}}
{{#*inline "ifHasItemOfType"}}
{{#if (and (ne itemsArray undefined) (gt itemsArray.length 0))}}
{{> @partial-block}}
{{> @partial-block}}
{{else}}
{{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType=dataType }}
{{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType=dataType }}
{{/if}}
{{/inline}}
@ -34,24 +33,24 @@
!-- @param partial-block: hand over custom children of the flexbox in the partial block.
--}}
{{#*inline "itemListHeader" }}
<li class="item flexrow item-header">
{{!-- equipped --}}
{{#if (ne dataType 'equipment')}}
<div class="flex05" title="{{localize 'DS4.ItemEquipped'}}">E</div>
{{/if}}
{{!-- image --}}
<div class="flex05 item-image"></div>
{{!-- amount --}}
<div class="flex05 item-num-val" title="{{localize 'DS4.Quantity'}}">#</div>
{{!-- name --}}
<div class="flex3 item-name">{{localize 'DS4.ItemName'}}</div>
{{!-- item type specifics --}}
{{> @partial-block }}
{{!-- description --}}
<div class="flex4">{{localize 'DS4.HeadingDescription'}}</div>
{{!-- add button --}}
{{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType=dataType }}
</li>
<li class="item flexrow item-header">
{{!-- equipped --}}
{{#if (ne dataType 'equipment')}}
<div class="flex05" title="{{localize 'DS4.ItemEquipped'}}">{{localize 'DS4.ItemEquippedAbbr'}}</div>
{{/if}}
{{!-- image --}}
<div class="flex05 item-image"></div>
{{!-- amount --}}
<div class="flex05 item-num-val" title="{{localize 'DS4.Quantity'}}">#</div>
{{!-- name --}}
<div class="flex3 item-name">{{localize 'DS4.ItemName'}}</div>
{{!-- item type specifics --}}
{{> @partial-block }}
{{!-- description --}}
<div class="flex4">{{localize 'DS4.Description'}}</div>
{{!-- add button --}}
{{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType=dataType }}
</li>
{{/inline}}
{{!--
@ -59,36 +58,36 @@
!-- It is a flexbox with a child for each item value of interest.
!-- An equipped checkbox is rendered if item.data.data.equipped is defined.
!-- The partial assumes a variable item to be given in the context.
!-- If the partial is called with a partial block, the partial block
!-- If the partial is called with a partial block, the partial block
!-- content is inserted before the description.
!-- @param item: hand over the item to the partial as hash parameter
!-- @param partial-block: hand over custom children of the flexbox in the partial block.
--}}
{{#*inline "itemListEntry"}}
<li class="item flexrow" data-item-id="{{item._id}}">
{{!-- equipped --}}
{{#if (ne item.data.data.equipped undefined)}}
<input class="flex05 item-change" type="checkbox" {{checked item.data.data.equipped}} data-dtype="Boolean"
data-property="data.equipped" title="{{localize 'DS4.ItemEquipped'}}">
{{/if}}
{{!-- image --}}
<div class="flex05 item-image">
<img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
</div>
{{!-- amount --}}
<input class="flex05 item-num-val item-change" type="number" min="0" step="1" value="{{item.data.data.quantity}}" data-dtype="Number"
data-property="data.quantity" title="{{localize 'DS4.Quantity'}}">
{{!-- name --}}
<input class="flex3 item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
data-property="name" title="{{localize 'DS4.ItemName'}}">
{{!-- item type specifics --}}
{{> @partial-block}}
{{!-- description --}}
<div class="flex4 item-description">{{{item.data.data.description}}}</div>
{{!-- control buttons --}}
{{> systems/ds4/templates/actor/partials/overview-control-buttons.hbs }}
</li>
<li class="item flexrow" data-item-id="{{item._id}}">
{{!-- equipped --}}
{{#if (ne item.data.data.equipped undefined)}}
<input class="flex05 item-change" type="checkbox" {{checked item.data.data.equipped}} data-dtype="Boolean"
data-property="data.equipped" title="{{localize 'DS4.ItemEquipped'}}">
{{/if}}
{{!-- image --}}
<div class="flex05 item-image">
<img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
</div>
{{!-- amount --}}
<input class="flex05 item-num-val item-change" type="number" min="0" step="1" value="{{item.data.data.quantity}}"
data-dtype="Number" data-property="data.quantity" title="{{localize 'DS4.Quantity'}}" />
{{!-- name --}}
<input class="flex3 item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
data-property="name" title="{{localize 'DS4.ItemName'}}" />
{{!-- item type specifics --}}
{{> @partial-block}}
{{!-- description --}}
<div class="flex4 item-description">{{{item.data.data.description}}}</div>
{{!-- control buttons --}}
{{> systems/ds4/templates/actor/partials/overview-control-buttons.hbs }}
</li>
{{/inline}}
@ -98,15 +97,18 @@
<div class="tab inventory" data-group="primary" data-tab="inventory">
{{!-- Money--}}
<h4 class="items-list-title">{{localize 'DS4.Currency'}}</h4>
<h4 class="items-list-title">{{localize 'DS4.CharacterCurrency'}}</h4>
<ol class="items-list">
<li class="item flexrow item-header">
<label for="data.currency.gold" class="flex05">{{config.currency.gold}}</label>
<input class="flex3 item-num-val item-change" type="number" min="0" step="1" name="data.currency.gold" id="data.currency.gold" value="{{data.currency.gold}}" data-dtype="Number" />
<label for="data.currency.silver" class="flex05">{{config.currency.silver}}</label>
<input class="flex3 item-num-val item-change" type="number" min="0" step="1" name="data.currency.silver" id="data.currency.silver" value="{{data.currency.silver}}" data-dtype="Number" />
<label for="data.currency.copper" class="flex05">{{config.currency.copper}}</label>
<input class="flex3 item-num-val item-change" type="number" min="0" step="1" name="data.currency.copper" id="data.currency.copper" value="{{data.currency.copper}}" data-dtype="Number" />
<li class="item flexrow item-header">
<label for="data.currency.gold" class="flex05">{{config.characterCurrency.gold}}</label>
<input class="flex3 item-num-val item-change" type="number" min="0" step="1" name="data.currency.gold"
id="data.currency.gold" value="{{data.currency.gold}}" data-dtype="Number" />
<label for="data.currency.silver" class="flex05">{{config.characterCurrency.silver}}</label>
<input class="flex3 item-num-val item-change" type="number" min="0" step="1" name="data.currency.silver"
id="data.currency.silver" value="{{data.currency.silver}}" data-dtype="Number" />
<label for="data.currency.copper" class="flex05">{{config.characterCurrency.copper}}</label>
<input class="flex3 item-num-val item-change" type="number" min="0" step="1" name="data.currency.copper"
id="data.currency.copper" value="{{data.currency.copper}}" data-dtype="Number" />
</li>
</ol>
@ -116,23 +118,23 @@
{{#> ifHasItemOfType itemsArray=itemsByType.weapon dataType='weapon' }}
<ol class="items-list">
{{#> itemListHeader dataType='weapon'}}
<div class="flex05 item-image" title="{{localize 'DS4.AttackType'}}">{{localize 'DS4.AttackTypeAbbr'}}</div>
<div class="flex05 item-num-val" title="{{localize 'DS4.WeaponBonus'}}">
{{localize 'DS4.WeaponBonusAbbr'}}
</div>
<div class="flex05 item-num-val" title="{{localize 'DS4.OpponentDefense'}}">
{{localize 'DS4.OpponentDefenseAbbr'}}
</div>
<div class="flex05 item-image" title="{{localize 'DS4.AttackType'}}">{{localize 'DS4.AttackTypeAbbr'}}</div>
<div class="flex05 item-num-val" title="{{localize 'DS4.WeaponBonus'}}">
{{localize 'DS4.WeaponBonusAbbr'}}
</div>
<div class="flex05 item-num-val" title="{{localize 'DS4.OpponentDefense'}}">
{{localize 'DS4.OpponentDefenseAbbr'}}
</div>
{{/itemListHeader}}
{{#each itemsByType.weapon as |item id|}}
{{#> itemListEntry item=item}}
<div class="flex05 item-image">
<img src="{{lookup ../../config.attackTypesIcons item.data.data.attackType}}"
title="{{lookup ../../config.attackTypes item.data.data.attackType}}" width="24" height="24" />
</div>
<div class="flex05 item-num-val">{{ item.data.data.weaponBonus}}</div>
<div class="flex05 item-num-val">{{ item.data.data.opponentDefense}}</div>
{{/itemListEntry}}
{{#> itemListEntry item=item}}
<div class="flex05 item-image">
<img src="{{lookup ../../config.attackTypesIcons item.data.data.attackType}}"
title="{{lookup ../../config.attackTypes item.data.data.attackType}}" width="24" height="24" />
</div>
<div class="flex05 item-num-val">{{ item.data.data.weaponBonus}}</div>
<div class="flex05 item-num-val">{{ item.data.data.opponentDefense}}</div>
{{/itemListEntry}}
{{/each}}
</ol>
{{!-- {{else}}
@ -144,22 +146,22 @@
{{#> ifHasItemOfType itemsArray=itemsByType.armor dataType='armor' }}
<ol class="items-list">
{{#> itemListHeader dataType='armor'}}
<div title="{{localize 'DS4.ArmorMaterialType'}}">{{localize 'DS4.ArmorMaterialTypeAbbr'}}</div>
<div title="{{localize 'DS4.ArmorType'}}">{{localize 'DS4.ArmorTypeAbbr'}}</div>
<div class="flex05 item-num-val" title="{{localize 'DS4.ArmorValue'}}">
{{localize 'DS4.ArmorValueAbbr'}}
</div>
<div title="{{localize 'DS4.ArmorMaterialType'}}">{{localize 'DS4.ArmorMaterialTypeAbbr'}}</div>
<div title="{{localize 'DS4.ArmorType'}}">{{localize 'DS4.ArmorTypeAbbr'}}</div>
<div class="flex05 item-num-val" title="{{localize 'DS4.ArmorValue'}}">
{{localize 'DS4.ArmorValueAbbr'}}
</div>
{{/itemListHeader}}
{{#each itemsByType.armor as |item id|}}
{{#> itemListEntry item=item }}
<div title="{{lookup ../../config.armorMaterialTypes item.data.data.armorMaterialType}}">
{{lookup ../../config.armorMaterialTypesAbbr item.data.data.armorMaterialType}}
</div>
<div title="{{lookup ../../config.armorTypes item.data.data.armorType}}">
{{lookup ../../config.armorTypesAbbr item.data.data.armorType}}
</div>
<div class="flex05 item-num-val">{{ item.data.data.armorValue}}</div>
{{/itemListEntry}}
{{#> itemListEntry item=item }}
<div title="{{lookup ../../config.armorMaterialTypes item.data.data.armorMaterialType}}">
{{lookup ../../config.armorMaterialTypesAbbr item.data.data.armorMaterialType}}
</div>
<div title="{{lookup ../../config.armorTypes item.data.data.armorType}}">
{{lookup ../../config.armorTypesAbbr item.data.data.armorType}}
</div>
<div class="flex05 item-num-val">{{ item.data.data.armorValue}}</div>
{{/itemListEntry}}
{{/each}}
</ol>
{{/ifHasItemOfType}}
@ -170,14 +172,14 @@
{{#> ifHasItemOfType itemsArray=itemsByType.shield dataType='shield' }}
<ol class="items-list">
{{#> itemListHeader dataType='shield' }}
<div class="flex05 item-num-val" title="{{localize 'DS4.ArmorValue'}}">
{{localize 'DS4.ArmorValueAbbr'}}
</div>
<div class="flex05 item-num-val" title="{{localize 'DS4.ArmorValue'}}">
{{localize 'DS4.ArmorValueAbbr'}}
</div>
{{/itemListHeader}}
{{#each itemsByType.shield as |item id|}}
{{#> itemListEntry item=item }}
<div class="flex05 item-num-val">{{item.data.data.armorValue}}</div> {{!-- SPECIFIC --}}
{{/itemListEntry}}
{{#> itemListEntry item=item }}
<div class="flex05 item-num-val">{{item.data.data.armorValue}}</div> {{!-- SPECIFIC --}}
{{/itemListEntry}}
{{/each}}
</ol>
{{/ifHasItemOfType}}
@ -187,13 +189,13 @@
{{#> ifHasItemOfType itemsArray=itemsByType.trinket dataType='trinket' }}
<ol class="items-list">
{{#> itemListHeader dataType='trinket'}}
<div class="flex2">{{localize 'DS4.StorageLocation'}}</div>
<div class="flex2">{{localize 'DS4.StorageLocation'}}</div>
{{/itemListHeader}}
{{#each itemsByType.trinket as |item id|}}
{{#> itemListEntry item=item }}
<input class="flex2 item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
{{/itemListEntry}}
{{#> itemListEntry item=item }}
<input class="flex2 item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
{{/itemListEntry}}
{{/each}}
</ol>
{{/ifHasItemOfType}}
@ -203,13 +205,13 @@
{{#> ifHasItemOfType itemsArray=itemsByType.equipment dataType='equipment' }}
<ol class="items-list">
{{#> itemListHeader dataType='equipment'}}
<div class="flex2">{{localize 'DS4.StorageLocation'}}</div>
<div class="flex2">{{localize 'DS4.StorageLocation'}}</div>
{{/itemListHeader}}
{{#each itemsByType.equipment as |item id|}}
{{#> itemListEntry item=item }}
<input class="flex2 item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
{{/itemListEntry}}
{{#> itemListEntry item=item }}
<input class="flex2 item-change" type="text" value="{{item.data.data.storageLocation}}" data-dtype="String"
data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
{{/itemListEntry}}
{{/each}}
</ol>
{{/ifHasItemOfType}}

View file

@ -1,13 +1,15 @@
<div class="tab profile" data-group="primary" data-tab="profile">
<div class="grid grid-2col">
{{#each data.profile as |profile-data-value profile-data-key|}}
{{#if (ne profile-data-key 'biography')}}
<div class="profile-entry">
<label for="data.profile.{{profile-data-key}}">
{{lookup ../config.profile profile-data-key}}
{{lookup ../config.characterProfile profile-data-key}}
</label>
<input type="text" name="data.profile.{{profile-data-key}}" value="{{profile-data-value}}"
data-dtype="{{lookup ../config/profileDTypes profile-data-key}}" />
data-dtype="{{lookup ../config/characterProfileDTypes profile-data-key}}" />
</div>
{{/if}}
{{/each}}
</div>
</div>
</div>

View file

@ -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>

View file

@ -0,0 +1,93 @@
{{!-- ======================================================================== --}}
{{!-- INLINE PARTIAL DEFINITIONS --}}
{{!-- ======================================================================== --}}
{{!--
!-- Base template to display a value with unit.
!-- @param unitDatum: the object to display; must have a value and a unit attribute
!-- @param localizationString
!-- @param unitNames: mapping of allowed unitDatum.unit values to localized unit name
!-- @param unitAbbrs: mapping of allowed unitDatum.unit values to unit abbreviation
--}}
{{#*inline "unit"}}
<div class="unit-data-pair item-num-val"
title="{{localize localizationString}} [{{lookup unitNames unitDatum.unit}}]" >
{{#if unitDatum.value }}
{{unitDatum.value}}{{lookup unitAbbrs unitDatum.unit}}
{{else}}-{{/if}}
</div>
{{/inline}}
{{!--
!-- Two templates based on the "unit" template for displaying values with unit.
!-- Both accept a `config` object holding the unitNames and unitAbbr instead of
!-- directly handing over the latter two.
--}}
{{#*inline "temporalUnit"}}
{{> unit unitNames=config.temporalUnits unitAbbrs=config.temporalUnitsAbbr unitDatum=unitDatum localizationString=localizationString}}
{{/inline}}
{{#*inline "distanceUnit"}}
{{> unit unitNames=config.distanceUnits unitAbbrs=config.distanceUnitsAbbr unitDatum=unitDatum localizationString=localizationString}}
{{/inline}}
{{!-- ======================================================================== --}}
<div class="tab spells" data-group="primary" data-tab="spells">
<ol class="items-list">
<li class="item flexrow item-header">
{{!-- equipped --}}
<div class="flex05 item-image" title="{{localize 'DS4.ItemEquipped'}}">{{localize 'DS4.ItemEquippedAbbr'}}</div>
{{!-- image --}}
<div class="flex05 item-image"></div>
{{!-- name --}}
<div class="flex2 item-name">{{localize 'DS4.ItemName'}}</div>
{{!-- spell type --}}
<div class="item-image" title="{{localize 'DS4.SpellType'}}">{{localize 'DS4.SpellTypeAbbr'}}</div>
{{!-- spell bonus --}}
<div class="item-num-val" title="{{localize 'DS4.SpellBonus'}}">{{localize 'DS4.SpellBonusAbbr'}}</div>
{{!-- max. distance --}}
<div class="item-num-val" title="{{localize 'DS4.SpellMaxDistance'}}"><i class="fas fa-ruler"></i></div>
{{!-- duration --}}
<div class="item-num-val" title="{{localize 'DS4.SpellDuration'}}"><i class="far fa-clock"></i></div>
{{!-- cooldown duration --}}
<div class="item-num-val" title="{{localize 'DS4.SpellCooldownDuration'}}"><i class="fas fa-hourglass-half"></i></div>
{{!-- description --}}
{{!-- <div class="flex3">{{localize 'DS4.Description'}}</div> --}}
{{!-- add button --}}
{{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType='spell' }}
</li>
{{#each itemsByType.spell as |item id|}}
<li class="item flexrow" data-item-id="{{item._id}}">
<input class="flex05 item-image item-change" type="checkbox" {{checked item.data.data.equipped}} data-dtype="Boolean"
data-property="data.equipped" title="{{localize 'DS4.ItemEquipped'}}">
{{!-- image --}}
<div class="flex05 item-image">
<img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
</div>
{{!-- name --}}
<input class="flex2 item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
data-property="name" title="{{localize 'DS4.ItemName'}}" />
{{!-- spell type --}}
<div class="flex05 item-image">
<img src="{{lookup ../config.spellTypesIcons item.data.data.spellType}}"
title="{{lookup ../config.spellTypes item.data.data.spellType}}" width="24" height="24" />
</div>
{{!-- spell bonus --}}
<input class="item-num-val item-change" type="text" data-dtype="String"
data-property="data.bonus" value="{{item.data.data.bonus}}" title="{{localize 'DS4.SpellBonus'}}" />
{{!-- max. distance --}}
{{> distanceUnit localizationString='DS4.SpellMaxDistance' unitDatum=item.data.data.maxDistance config=../config}}
{{!-- duration --}}
{{> temporalUnit localizationString='DS4.SpellDuration' unitDatum=item.data.data.duration config=../config}}
{{!-- cooldown duration --}}
{{> temporalUnit localizationString='DS4.SpellCooldownDuration' unitDatum=item.data.data.cooldownDuration config=../config}}
{{!-- description --}}
{{!-- <div class="flex3 item-description">{{{item.data.data.description}}}</div> --}}
{{!-- control buttons --}}
{{> systems/ds4/templates/actor/partials/overview-control-buttons.hbs }}
</li>
{{/each}}
</ol>
</div>

View file

@ -1,8 +1,8 @@
{{!-- TODO: Refactor to avoid code duplication with creature-special-abilities-overview and talents-overview --}}
{{!-- ======================================================================== --}}
{{!-- INLINE PARTIAL DEFINITIONS --}}
{{!-- ======================================================================== --}}
{{!-- TODO: remove duplicate add and delete button definition --}}
{{!--
@ -110,7 +110,7 @@
{{!-- name --}}
<div class="flex1 item-name">{{localize 'DS4.ItemName'}}</div>
{{!-- description --}}
<div class="flex3">{{localize 'DS4.HeadingDescription'}}</div>
<div class="flex3">{{localize 'DS4.Description'}}</div>
{{!-- add button --}}
{{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType=dataType }}
</li>
@ -120,7 +120,7 @@
{{!-- ======================================================================== --}}
<div class="tab items" data-group="primary" data-tab="talents">
<div class="tab talents-abilities" data-group="primary" data-tab="talents-abilities">
<h4 class="items-list-title">{{localize 'DS4.ItemTypeTalentPlural'}}</h4>
{{#> ifHasItemOfType itemsArray=itemsByType.talent dataType='talent' }}
<ol class="items-list">
@ -132,7 +132,7 @@
{{!-- rank info --}}
<div class="flex3">{{localize 'DS4.TalentRank'}}</div>
{{!-- description --}}
<div class="flex4">{{localize 'DS4.HeadingDescription'}}</div>
<div class="flex4">{{localize 'DS4.Description'}}</div>
{{!-- add button --}}
{{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType='talent' }}
</li>

View file

@ -3,6 +3,6 @@
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{> systems/ds4/templates/item/partials/body.hbs}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -12,7 +12,7 @@
</select>
</div>
<div class="basic-property">
<label>{{localize "DS4.ArmorMaterialType"}}</label>
<label for="data.armorMaterialType">{{localize "DS4.ArmorMaterialType"}}</label>
<select name="data.armorMaterialType" data-type="String">
{{#select data.armorMaterialType}}
{{#each config.armorMaterialTypes as |value key|}}
@ -30,5 +30,5 @@
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{> systems/ds4/templates/item/partials/body.hbs}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -3,5 +3,5 @@
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{> systems/ds4/templates/item/partials/body.hbs}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -3,6 +3,6 @@
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{> systems/ds4/templates/item/partials/body.hbs}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -13,7 +13,9 @@
<section class="sheet-body">
{{!-- Description Tab --}}
{{> systems/ds4/templates/item/partials/description.hbs}}
{{#> systems/ds4/templates/item/partials/description.hbs}}
{{> @partial-block}}
{{/systems/ds4/templates/item/partials/description.hbs}}
{{!-- Effects Tab --}}
{{> systems/ds4/templates/item/partials/effects.hbs}}

View file

@ -1,3 +1,8 @@
{{!--
Render a description tab.
Additional elements of the side-properties div can be handed over via the @partial-block.
--}}
<div class="tab flexrow" data-group="primary" data-tab="description">
<div class="side-properties">
{{#if isOwned}}
@ -24,6 +29,7 @@
{{else}}
<span>{{localize "DS4.NotOwned"}}</span>
{{/if}}
{{> @partial-block}}
</div>
<div class="description" title="{{localize 'DS4.HeadingDescription'}}">
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}

View file

@ -3,18 +3,19 @@
{{!-- As you add new fields, add them in here! --}}
<div class="side-properties">
<div class="side-property">
<label for="data.price">{{localize "DS4.PriceGold"}}</label>
<input type="number" min="0" data-dtype="Number" name="data.price" value="{{data.price}}" />
</div>
<div class="side-property">
<label for="data.availability">{{localize "DS4.ItemAvailability"}}</label>
<select name="data.availability" data-type="String">
{{#select data.availability}}
{{#each config.itemAvailabilities as |value key|}}
<option value="{{key}}">{{value}}</option>
{{/each}}
{{/select}}
</select>
</div>
<label for="data.price">{{localize "DS4.PriceGold"}}</label>
<input type="number" min="0" max="99999" step="0.01" data-dtype="Number"
name="data.price" value="{{data.price}}" />
</div>
<div class="side-property">
<label for="data.availability">{{localize "DS4.ItemAvailability"}}</label>
<select name="data.availability" data-type="String">
{{#select data.availability}}
{{#each config.itemAvailabilities as |value key|}}
<option value="{{key}}">{{value}}</option>
{{/each}}
{{/select}}
</select>
</div>
</div>
</div>

View file

@ -3,6 +3,6 @@
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{> systems/ds4/templates/item/partials/body.hbs}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -10,5 +10,5 @@
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{> systems/ds4/templates/item/partials/body.hbs}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -0,0 +1,15 @@
<form class="{{cssClass}}" autocomplete="off">
{{#> systems/ds4/templates/item/partials/sheet-header.hbs}}
<div class="grid grid-3col basic-properties">
<div class="basic-property">
<label>{{localize "DS4.SpecialCreatureAbilityExperiencePoints"}}</label>
<input type="number" min="0" step="1" name="data.experiencePoints" value="{{data.experiencePoints}}"
placeholder="0" data-dtype="Number" />
</div>
</div>
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -0,0 +1,72 @@
{{!-- ======================================================================== --}}
{{!-- INLINE PARTIAL DEFINITIONS --}}
{{!-- ======================================================================== --}}
{{#*inline "unitDatum" }}
<div class="side-property">
<label>{{localize localizeString}}</label>
<div class="unit-data-pair">
<input class="item-num-val" type="text" data-dtype="String"
name="data.{{property}}.value" value="{{lookup (lookup data property) 'value'}}" />
<select name="data.{{property}}.unit" data-type="String">
{{#select (lookup (lookup data property) 'unit')}}
{{#if (eq unitType 'temporal')}}
{{#each (lookup config 'temporalUnitsAbbr') as |value key|}}<option value="{{key}}">{{value}}</option>{{/each}}
{{else}}
{{#each (lookup config 'distanceUnitsAbbr') as |value key|}}<option value="{{key}}">{{value}}</option>{{/each}}
{{/if}}
{{/select}}
</select>
</div>
</div>
{{/inline}}
{{!-- ======================================================================== --}}
<form class="{{cssClass}}" autocomplete="off">
{{#> systems/ds4/templates/item/partials/sheet-header.hbs}}
<div class="grid grid-4col basic-properties">
<div class="basic-property">
<label for="data.spellType">{{localize "DS4.SpellType"}}</label>
<select name="data.spellType" data-type="String">
{{#select data.spellType}}
{{#each config.spellTypes as |value key|}}
<option value="{{key}}">{{value}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="basic-property">
<label for="data.bonus">{{localize "DS4.SpellBonus"}}</label>
<input type="text" name="data.bonus" value="{{data.bonus}}" data-dtype="String" />
</div>
</div>
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{#> systems/ds4/templates/item/partials/body.hbs}}
<div class="side-property">
<label for="data.spellCategory">{{localize "DS4.SpellCategory"}}</label>
<select name="data.spellCategory" data-type="String">
{{#select data.spellCategory}}
{{#each config.spellCategories as |value key|}}
<option value="{{key}}">{{value}}</option>
{{/each}}
{{/select}}
</select>
</div>
{{> unitDatum data=data property='maxDistance' localizeString='DS4.SpellMaxDistance' unitType='distance' }}
{{> unitDatum data=data property='effectRadius' localizeString='DS4.SpellEffectRadius' unitType='distance' }}
{{> unitDatum data=data property='duration' localizeString='DS4.SpellDuration' unitType='temporal' }}
{{> unitDatum data=data property='cooldownDuration' localizeString='DS4.SpellCooldownDuration' unitType='temporal' }}
<div class="side-property">
<label for="data.scrollPrice">{{localize "DS4.SpellScrollPriceGold"}}</label>
<input type="number" min="0" max="9999" step="0.01" data-dtype="Number"
name="data.scrollPrice" value="{{data.scrollPrice}}" />
</div>
{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -27,6 +27,6 @@
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{> systems/ds4/templates/item/partials/body.hbs}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -3,5 +3,5 @@
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{> systems/ds4/templates/item/partials/body.hbs}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -25,5 +25,5 @@
{{/systems/ds4/templates/item/partials/sheet-header.hbs}}
{{!-- Common Item body --}}
{{> systems/ds4/templates/item/partials/body.hbs}}
{{#> systems/ds4/templates/item/partials/body.hbs}}{{/systems/ds4/templates/item/partials/body.hbs}}
</form>

View file

@ -0,0 +1,16 @@
<form class="{{cssClass}} grid">
<label for="ctv">{{localize "DS4.RollDialogTargetLabel"}}</label>
<input id="ctv" data-type="Number" type="number" name="ctv" value="{{checkTargetValue}}" />
<label for="gmmod">{{localize "DS4.RollDialogModifierLabel"}}</label>
<input id="gmmod" data-type="Number" type="number" name="gmmod" value="0" />
<label for="maxcoup">{{localize "DS4.RollDialogCoupLabel"}}</label>
<input id="maxcoup" data-type="Number" type="number" name="maxcoup" value="{{maxCritSuccess}}" />
<label for="minfumble">{{localize "DS4.RollDialogFumbleLabel"}}</label>
<input id="minfumble" data-type="Number" type="number" name="minfumble" value="{{minCritFailure}}" />
<label for="visibility">{{localize "DS4.RollDialogVisibilityLabel"}}</label>
<select id="visibility" data-type="String">
{{#each rollModes as |rollMode|}}
<option value="{{rollMode}}">{{lookup ../config.chatVisibilities rollMode}}</option>
{{/each}}
</select>
</form>