@optolith/entity-descriptions 0.4.13 → 0.4.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/lib/entities/activatable.d.ts +1 -1
- package/lib/entities/activatable.js +5 -2
- package/lib/entities/culture.js +10 -1
- package/lib/entities/elixir.d.ts +1 -1
- package/lib/entities/partial/adventurePointsValue.d.ts +1 -1
- package/lib/entities/partial/adventurePointsValue.js +66 -29
- package/lib/entities/partial/commonnessRatedAdvantagesAndDisadvantages.js +6 -10
- package/lib/entities/partial/prerequisites/index.d.ts +3 -3
- package/lib/entities/partial/prerequisites/prerequisiteGroups.d.ts +2 -2
- package/lib/entities/partial/prerequisites/prerequisiteGroups.js +3 -0
- package/lib/entities/partial/prerequisites/single/rated.js +2 -1
- package/lib/entities/partial/rated/activatable/cost.d.ts +5 -4
- package/lib/entities/partial/rated/activatable/cost.js +13 -6
- package/lib/entities/partial/units/timeSpan.d.ts +9 -0
- package/lib/entities/partial/units/timeSpan.js +4 -0
- package/lib/entities/poison.d.ts +1 -1
- package/lib/entities/profession.js +13 -7
- package/lib/index.d.ts +55 -55
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [0.4.15](https://github.com/Optolith/entity-descriptions/compare/v0.4.14...v0.4.15) (2026-06-07)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* add sustained cost map interval ([f7c1b31](https://github.com/Optolith/entity-descriptions/commit/f7c1b31452befa0c898a6f21e4624c8084ea5df5))
|
|
11
|
+
* display full tradition name ([2d07eff](https://github.com/Optolith/entity-descriptions/commit/2d07eff1d4b6a5b72ce705e24969e4a384a1d486))
|
|
12
|
+
* ignore rating in prerequisite when zero ([b375702](https://github.com/Optolith/entity-descriptions/commit/b375702ea644fc21b92bb64b811e204aeda7370c))
|
|
13
|
+
* render ap value from explicit select options ([df2178f](https://github.com/Optolith/entity-descriptions/commit/df2178fe131ed9e9d3427ee092a46b2448b09650))
|
|
14
|
+
|
|
15
|
+
## [0.4.14](https://github.com/Optolith/entity-descriptions/compare/v0.4.13...v0.4.14) (2026-06-07)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* display negative disadvantage AP values ([8dd72a0](https://github.com/Optolith/entity-descriptions/commit/8dd72a04ef10aeb300b54ed8fa25ddfb60318a3e))
|
|
21
|
+
* render shorter variant of commonness-rated options ([9f9eae0](https://github.com/Optolith/entity-descriptions/commit/9f9eae0af0800b17247aa2db8c300e0f693eb336))
|
|
22
|
+
* separate variant values and concluding text with a period ([d58ebeb](https://github.com/Optolith/entity-descriptions/commit/d58ebeb35839ced633ba7a47bf6c69283522803d))
|
|
23
|
+
* sort commonness-rated options alphabetically ([25c50dd](https://github.com/Optolith/entity-descriptions/commit/25c50dde77a34a207eb129fbe9ef63bb41e589cc))
|
|
24
|
+
* sort skill spec skill options ([5b63ea8](https://github.com/Optolith/entity-descriptions/commit/5b63ea8244bc499027069e2edd1f48064bf98df4))
|
|
25
|
+
* wrap skill spec options in parens if needed ([dd0562b](https://github.com/Optolith/entity-descriptions/commit/dd0562bfd09b7cf11d8e9c277b3fdcfba11204bc))
|
|
26
|
+
|
|
5
27
|
## [0.4.13](https://github.com/Optolith/entity-descriptions/compare/v0.4.12...v0.4.13) (2026-06-01)
|
|
6
28
|
|
|
7
29
|
|
|
@@ -47,7 +47,7 @@ export type BaseActivatableTranslation = {
|
|
|
47
47
|
* Get a JSON representation of the rules text for a special ability.
|
|
48
48
|
*/
|
|
49
49
|
export declare const getActivatableEntityDescription: import("../creator.js").EntityDescriptionCreator<"Advantage" | "Disadvantage" | "AdvancedCombatSpecialAbility" | "AdvancedKarmaSpecialAbility" | "AdvancedMagicalSpecialAbility" | "AdvancedSkillSpecialAbility" | "AncestorGlyph" | "ArcaneOrbEnchantment" | "AttireEnchantment" | "Beutelzauber" | "BlessedTradition" | "BowlEnchantment" | "BrawlingSpecialAbility" | "CauldronEnchantment" | "CeremonialItemSpecialAbility" | "ChronicleEnchantment" | "CombatSpecialAbility" | "CombatStyleSpecialAbility" | "CommandSpecialAbility" | "DaggerRitual" | "FamiliarSpecialAbility" | "FatePointSexSpecialAbility" | "FatePointSpecialAbility" | "FoolsHatEnchantment" | "GeneralSpecialAbility" | "Haubenzauber" | "InstrumentEnchantment" | "KarmaSpecialAbility" | "Krallenkettenzauber" | "Kristallkugelzauber" | "LiturgicalStyleSpecialAbility" | "LycantropicGift" | "MagicalSign" | "MagicalSpecialAbility" | "MagicalTradition" | "MagicStyleSpecialAbility" | "OrbEnchantment" | "PactGift" | "ProtectiveWardingCircleSpecialAbility" | "RingEnchantment" | "Sermon" | "SexSpecialAbility" | "SickleRitual" | "SikaryanDrainSpecialAbility" | "SkillStyleSpecialAbility" | "SpellSwordEnchantment" | "StaffEnchantment" | "ToyEnchantment" | "Trinkhornzauber" | "VampiricGift" | "Vision" | "WandEnchantment" | "WeaponEnchantment", {
|
|
50
|
-
getInstanceById: GetInstanceById<"Publication" | "Subject" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "TradeSecret" | "Aspect" | "Property" | "Race" | "Culture" | "State" | "Enhancement" | "PactCategory" | "PactDomain" | "SocialStatus" | "Weapon" | "Patron">;
|
|
50
|
+
getInstanceById: GetInstanceById<"Publication" | "Subject" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "TradeSecret" | "Aspect" | "Property" | "Race" | "Culture" | "State" | "Enhancement" | "PactCategory" | "PactDomain" | "SocialStatus" | "Weapon" | "Patron" | "PersonalityTrait">;
|
|
51
51
|
getAllInstances: GetAllInstances<"Script">;
|
|
52
52
|
getResolvedSelectOptionById: GetResolvedSelectOptionById;
|
|
53
53
|
getAllResolvedSelectOptions: GetAllResolvedSelectOptions;
|
|
@@ -705,8 +705,11 @@ export const getActivatableEntityDescription = createEntityDescriptionCreator(({
|
|
|
705
705
|
: entityName === "MagicalTradition"
|
|
706
706
|
? renderAdditionalSpecialRules(translation.name, translation.nameOfSpellcasters, undefined, undefined, undefined, entry.primary).run(env)
|
|
707
707
|
: [];
|
|
708
|
+
const makeTraditionName = entityName === "BlessedTradition" || entityName === "MagicalTradition"
|
|
709
|
+
? name => translate("Tradition ({$tradition})", { tradition: name })
|
|
710
|
+
: name => name;
|
|
708
711
|
return {
|
|
709
|
-
title: (translation.name_in_library ?? translation.name) +
|
|
712
|
+
title: makeTraditionName(translation.name_in_library ?? translation.name) +
|
|
710
713
|
(baseEntry.levels !== undefined ? ` I–${romanize(baseEntry.levels)}` : ""),
|
|
711
714
|
subtitle: mapNullable(baseEntry.usage_type, usageType => {
|
|
712
715
|
switch (usageType.kind) {
|
|
@@ -807,7 +810,7 @@ export const getActivatableEntityDescription = createEntityDescriptionCreator(({
|
|
|
807
810
|
}
|
|
808
811
|
const { parent: parentId } = selectOption.content;
|
|
809
812
|
return locale.translateMap(getInstanceById(parentId.kind, fromUniformCase(parentId))?.translations)?.name;
|
|
810
|
-
}, () => getAllResolvedSelectOptions(wrappedId), getAllInstances, apValue, entry, translation) + append,
|
|
813
|
+
}, () => getAllResolvedSelectOptions(wrappedId), getAllInstances, apValue, entry, translation, entityName === "Disadvantage") + append,
|
|
811
814
|
};
|
|
812
815
|
}),
|
|
813
816
|
],
|
package/lib/entities/culture.js
CHANGED
|
@@ -109,7 +109,16 @@ const renderCommonProfessions = (getChildInstancesForInstanceId, commonProfessio
|
|
|
109
109
|
default:
|
|
110
110
|
return assertExhaustive(constraint);
|
|
111
111
|
}
|
|
112
|
-
}).then(magic => renderCommonProfessionGroup("Blessed Professions", commonProfessions.Grouped.blessed, constraint =>
|
|
112
|
+
}).then(magic => renderCommonProfessionGroup("Blessed Professions", commonProfessions.Grouped.blessed, constraint => {
|
|
113
|
+
switch (constraint.kind) {
|
|
114
|
+
case "Profession":
|
|
115
|
+
return renderProfessionConstraint(getChildInstancesForInstanceId, constraint.Profession);
|
|
116
|
+
case "Tradition":
|
|
117
|
+
return renderTraditionConstraint(getChildInstancesForInstanceId, "BlessedTradition", constraint.Tradition);
|
|
118
|
+
default:
|
|
119
|
+
return assertExhaustive(constraint);
|
|
120
|
+
}
|
|
121
|
+
}).map(blessed => [
|
|
113
122
|
{
|
|
114
123
|
type: "definitionList",
|
|
115
124
|
style: "nested",
|
package/lib/entities/elixir.d.ts
CHANGED
|
@@ -5,6 +5,6 @@ import type { GetResolvedSelectOptionById } from "./partial/prerequisites/single
|
|
|
5
5
|
* Get a JSON representation of the rules text for an elixir.
|
|
6
6
|
*/
|
|
7
7
|
export declare const getElixirEntityDescription: import("../creator.js").EntityDescriptionCreator<"Elixir", {
|
|
8
|
-
getInstanceById: GetInstanceById<"Publication" | "DerivedCharacteristic" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Race" | "Culture" | "State" | "Enhancement" | "PactCategory" | "PactDomain" | "SocialStatus" | "Aspect" | "Property">;
|
|
8
|
+
getInstanceById: GetInstanceById<"Publication" | "DerivedCharacteristic" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Race" | "Culture" | "State" | "Enhancement" | "PactCategory" | "PactDomain" | "SocialStatus" | "Aspect" | "Property" | "PersonalityTrait">;
|
|
9
9
|
getResolvedSelectOptionById: GetResolvedSelectOptionById;
|
|
10
10
|
}, import("../index.js").EntityDescription>;
|
|
@@ -6,4 +6,4 @@ import type { BaseActivatable, BaseActivatableTranslation } from "../activatable
|
|
|
6
6
|
/**
|
|
7
7
|
* Renders an adventure points value to a human-readable string, using the provided locale for translations and formatting. For values that depend on select options or other instances, the necessary lookup functions are provided as arguments.
|
|
8
8
|
*/
|
|
9
|
-
export declare const renderAdventurePointsValue: (locale: LocaleEnvironment, getNameForId: (id: ActivatableIdentifier) => string | undefined, getNameForSelectOptionId: (id: ResolvedSelectOptionIdentifier) => string | undefined, getAllSelectOptions: () => ResolvedSelectOption[], getAllInstances: GetAllInstances<"Script" | "AnimalShapeSize">, value: AdventurePointsValue | number, entry: BaseActivatable, translation: BaseActivatableTranslation) => string;
|
|
9
|
+
export declare const renderAdventurePointsValue: (locale: LocaleEnvironment, getNameForId: (id: ActivatableIdentifier) => string | undefined, getNameForSelectOptionId: (id: ResolvedSelectOptionIdentifier) => string | undefined, getAllSelectOptions: () => ResolvedSelectOption[], getAllInstances: GetAllInstances<"Script" | "AnimalShapeSize">, value: AdventurePointsValue | number, entry: BaseActivatable, translation: BaseActivatableTranslation, negative: boolean) => string;
|
|
@@ -1,11 +1,41 @@
|
|
|
1
1
|
import { on } from "@elyukai/utils/function";
|
|
2
|
+
import { isNotNullish } from "@elyukai/utils/nullable";
|
|
2
3
|
import { unique } from "@optolith/helpers/array";
|
|
3
4
|
import { deepEqual, numAsc } from "@optolith/helpers/compare";
|
|
4
5
|
import { romanize } from "@optolith/helpers/roman";
|
|
5
6
|
import { assertExhaustive } from "@optolith/helpers/typeSafety";
|
|
6
7
|
import { evaluateMathOperation } from "./mathOperation.js";
|
|
7
8
|
import { MISSING_VALUE } from "./unknown.js";
|
|
8
|
-
const
|
|
9
|
+
const typographicSign = (num) => (num > 0 ? "" : "−") + Math.abs(num).toFixed();
|
|
10
|
+
const renderFixedSelectOptionsAdventurePointsValue = (locale, getAllSelectOptions, getNameForSelectOptionId, getApValueForSelectOption, applyNegative) => {
|
|
11
|
+
const entriesMap = Map.groupBy(getAllSelectOptions().map((item) => [
|
|
12
|
+
getApValueForSelectOption(item, item.id),
|
|
13
|
+
item,
|
|
14
|
+
]), item => item[0])
|
|
15
|
+
.entries()
|
|
16
|
+
.toArray();
|
|
17
|
+
if (entriesMap.every((entry) => typeof entry[0] === "number" && entry[1].length === 1)) {
|
|
18
|
+
const entriesSortedByApValue = entriesMap.toSorted(on(item => item[0], numAsc));
|
|
19
|
+
return entriesSortedByApValue
|
|
20
|
+
.map(entry => locale.translateMap(entry[1][0][1].content.translations)?.name ?? MISSING_VALUE)
|
|
21
|
+
.join("/")
|
|
22
|
+
.concat(`: ${locale.translate("{$value} Adventure Points", { value: entriesSortedByApValue.map(entry => typographicSign(applyNegative(entry[0]))).join("/") })}`);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return entriesMap
|
|
26
|
+
.map(([apValue, items]) => [
|
|
27
|
+
apValue,
|
|
28
|
+
locale.join(items
|
|
29
|
+
.map(item => getNameForSelectOptionId(item[1].id))
|
|
30
|
+
.filter(name => name !== undefined)
|
|
31
|
+
.toSorted(locale.compare), "conjunction"),
|
|
32
|
+
])
|
|
33
|
+
.toSorted(on(item => item[1], locale.compare))
|
|
34
|
+
.map(([apValue, itemNames]) => `${itemNames}: ${locale.translate("{$value} Adventure Points", { value: typeof apValue === "number" ? applyNegative(apValue) : apValue })}`)
|
|
35
|
+
.join("; ");
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const renderSelectOptionsAdventurePointsValue = (locale, derivedLabel, getAllSelectOptions, getNameForSelectOptionId, config, applyNegative) => {
|
|
9
39
|
if (config === undefined) {
|
|
10
40
|
return MISSING_VALUE;
|
|
11
41
|
}
|
|
@@ -18,23 +48,8 @@ const renderSelectOptionsAdventurePointsValue = (locale, derivedLabel, getAllSel
|
|
|
18
48
|
})}`;
|
|
19
49
|
}
|
|
20
50
|
case "Fixed":
|
|
21
|
-
return
|
|
22
|
-
config.Fixed.
|
|
23
|
-
config.Fixed.default,
|
|
24
|
-
item,
|
|
25
|
-
]), item => item[0])
|
|
26
|
-
.entries()
|
|
27
|
-
.map(([apValue, items]) => [
|
|
28
|
-
apValue,
|
|
29
|
-
locale.join(items
|
|
30
|
-
.map(item => getNameForSelectOptionId(item[1].id))
|
|
31
|
-
.filter(name => name !== undefined)
|
|
32
|
-
.toSorted(locale.compare), "conjunction"),
|
|
33
|
-
])
|
|
34
|
-
.toArray()
|
|
35
|
-
.toSorted(on(item => item[1], locale.compare))
|
|
36
|
-
.map(([apValue, itemNames]) => `${itemNames}: ${locale.translate("{$value} Adventure Points", { value: apValue })}`)
|
|
37
|
-
.join("; ");
|
|
51
|
+
return renderFixedSelectOptionsAdventurePointsValue(locale, getAllSelectOptions, getNameForSelectOptionId, item => config.Fixed.map.find(mapItem => deepEqual(mapItem.id, item.id))?.ap_value ??
|
|
52
|
+
config.Fixed.default, applyNegative);
|
|
38
53
|
default:
|
|
39
54
|
return assertExhaustive(config);
|
|
40
55
|
}
|
|
@@ -42,23 +57,26 @@ const renderSelectOptionsAdventurePointsValue = (locale, derivedLabel, getAllSel
|
|
|
42
57
|
/**
|
|
43
58
|
* Renders an adventure points value to a human-readable string, using the provided locale for translations and formatting. For values that depend on select options or other instances, the necessary lookup functions are provided as arguments.
|
|
44
59
|
*/
|
|
45
|
-
export const renderAdventurePointsValue = (locale, getNameForId, getNameForSelectOptionId, getAllSelectOptions, getAllInstances, value, entry, translation) => {
|
|
60
|
+
export const renderAdventurePointsValue = (locale, getNameForId, getNameForSelectOptionId, getAllSelectOptions, getAllInstances, value, entry, translation, negative) => {
|
|
46
61
|
const { translate, translateMap } = locale;
|
|
62
|
+
const applyNegative = negative
|
|
63
|
+
? numValue => -numValue
|
|
64
|
+
: numValue => numValue;
|
|
47
65
|
if (typeof value === "number") {
|
|
48
66
|
return translate(".input {$value :number} {{{$value} Adventure Points}}", {
|
|
49
|
-
value,
|
|
67
|
+
value: applyNegative(value),
|
|
50
68
|
});
|
|
51
69
|
}
|
|
52
70
|
switch (value.kind) {
|
|
53
71
|
case "Fixed": {
|
|
54
72
|
if (entry.levels === undefined) {
|
|
55
73
|
return translate(".input {$value :number} {{{$value} Adventure Points}}", {
|
|
56
|
-
value: value.Fixed,
|
|
74
|
+
value: applyNegative(value.Fixed),
|
|
57
75
|
});
|
|
58
76
|
}
|
|
59
77
|
else {
|
|
60
78
|
return translate(".input {$value :number} {{{$value} Adventure Points per level}}", {
|
|
61
|
-
value: value.Fixed,
|
|
79
|
+
value: applyNegative(value.Fixed),
|
|
62
80
|
});
|
|
63
81
|
}
|
|
64
82
|
}
|
|
@@ -68,7 +86,7 @@ export const renderAdventurePointsValue = (locale, getNameForId, getNameForSelec
|
|
|
68
86
|
}
|
|
69
87
|
const mainValue = `${translate("Level {$level}", {
|
|
70
88
|
level: Array.from({ length: entry.levels }, (_, index) => romanize(index + 1)).join("/"),
|
|
71
|
-
})}: ${value.ByLevel.list.join("/")}`;
|
|
89
|
+
})}: ${value.ByLevel.list.map(applyNegative).join("/")}`;
|
|
72
90
|
const { additionalBySizeCategory } = value.ByLevel;
|
|
73
91
|
if (additionalBySizeCategory === undefined) {
|
|
74
92
|
return mainValue;
|
|
@@ -76,7 +94,7 @@ export const renderAdventurePointsValue = (locale, getNameForId, getNameForSelec
|
|
|
76
94
|
else {
|
|
77
95
|
const sizeCategories = ["tiny", "small", "medium", "large", "huge"];
|
|
78
96
|
const values = sizeCategories
|
|
79
|
-
.map(sizeCategory => additionalBySizeCategory[sizeCategory])
|
|
97
|
+
.map(sizeCategory => applyNegative(additionalBySizeCategory[sizeCategory]))
|
|
80
98
|
.join("/");
|
|
81
99
|
const labels = sizeCategories.map(sizeCategory => translate(sizeCategory)).join("/");
|
|
82
100
|
return `${mainValue} + ${translate("{$values} AP for size category {$labels} (per level)", { values, labels })}`;
|
|
@@ -85,7 +103,25 @@ export const renderAdventurePointsValue = (locale, getNameForId, getNameForSelec
|
|
|
85
103
|
case "DerivedFromSelection": {
|
|
86
104
|
const derivedSelectOptions = entry.select_options?.derived;
|
|
87
105
|
if (derivedSelectOptions === undefined) {
|
|
88
|
-
return
|
|
106
|
+
return renderFixedSelectOptionsAdventurePointsValue(locale, getAllSelectOptions, getNameForSelectOptionId, item => {
|
|
107
|
+
switch (item.content.ap_value?.kind) {
|
|
108
|
+
case "Fixed":
|
|
109
|
+
return item.content.ap_value.Fixed;
|
|
110
|
+
case "DependingOnActiveInstances":
|
|
111
|
+
switch (item.content.ap_value.DependingOnActiveInstances.kind) {
|
|
112
|
+
case "Threshold":
|
|
113
|
+
return item.content.ap_value.DependingOnActiveInstances.Threshold.normal;
|
|
114
|
+
case "Expression":
|
|
115
|
+
return MISSING_VALUE;
|
|
116
|
+
default:
|
|
117
|
+
return assertExhaustive(item.content.ap_value.DependingOnActiveInstances);
|
|
118
|
+
}
|
|
119
|
+
case undefined:
|
|
120
|
+
return MISSING_VALUE;
|
|
121
|
+
default:
|
|
122
|
+
return assertExhaustive(item.content.ap_value);
|
|
123
|
+
}
|
|
124
|
+
}, applyNegative);
|
|
89
125
|
}
|
|
90
126
|
switch (derivedSelectOptions.kind) {
|
|
91
127
|
case "Blessings":
|
|
@@ -98,14 +134,15 @@ export const renderAdventurePointsValue = (locale, getNameForId, getNameForSelec
|
|
|
98
134
|
return translate("{$value} Adventure Points", {
|
|
99
135
|
value: unique(getAllInstances("Script")
|
|
100
136
|
.map(script => script.content.ap_value)
|
|
101
|
-
.filter(
|
|
137
|
+
.filter(isNotNullish))
|
|
102
138
|
.toSorted(numAsc)
|
|
139
|
+
.map(applyNegative)
|
|
103
140
|
.join("/"),
|
|
104
141
|
});
|
|
105
142
|
case "AnimalShapes": {
|
|
106
143
|
const sizes = getAllInstances("AnimalShapeSize").toSorted(on(x => x.content.ap_value, numAsc));
|
|
107
144
|
return translate("{$values} adventure points for a {$sized} animal shape", {
|
|
108
|
-
values: sizes.map(size => size.content.ap_value).join("/"),
|
|
145
|
+
values: sizes.map(size => applyNegative(size.content.ap_value)).join("/"),
|
|
109
146
|
sized: sizes
|
|
110
147
|
.map(size => translateMap(size.content.translations)?.name ?? MISSING_VALUE)
|
|
111
148
|
.join("/"),
|
|
@@ -179,9 +216,9 @@ export const renderAdventurePointsValue = (locale, getNameForId, getNameForSelec
|
|
|
179
216
|
default:
|
|
180
217
|
return translate("A/B/C/D ability");
|
|
181
218
|
}
|
|
182
|
-
}, getAllSelectOptions, getNameForSelectOptionId, derivedSelectOptions.Skills.ap_value);
|
|
219
|
+
}, getAllSelectOptions, getNameForSelectOptionId, derivedSelectOptions.Skills.ap_value, applyNegative);
|
|
183
220
|
case "CombatTechniques":
|
|
184
|
-
return renderSelectOptionsAdventurePointsValue(locale, () => translate("B/C/D combat technique"), getAllSelectOptions, getNameForSelectOptionId, derivedSelectOptions.CombatTechniques.ap_value);
|
|
221
|
+
return renderSelectOptionsAdventurePointsValue(locale, () => translate("B/C/D combat technique"), getAllSelectOptions, getNameForSelectOptionId, derivedSelectOptions.CombatTechniques.ap_value, applyNegative);
|
|
185
222
|
case "TargetCategories":
|
|
186
223
|
return MISSING_VALUE;
|
|
187
224
|
default:
|
|
@@ -27,7 +27,7 @@ const makeActivatableIdentifierForCommonnessRatedAdvantageOrDisadvantage = (enti
|
|
|
27
27
|
return assertExhaustive(entity);
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
|
-
const renderCommonnessRatedAdvantageOrDisadvantageName = (translateMap, getInstanceById, getResolvedSelectOptionById, entity, item) => {
|
|
30
|
+
const renderCommonnessRatedAdvantageOrDisadvantageName = (translateMap, getInstanceById, getResolvedSelectOptionById, localeCompare, entity, item) => {
|
|
31
31
|
const customTranslation = translateMap(item.translations);
|
|
32
32
|
return (attributedCustomName(translateMap, getInstanceById, entity, (translation, instance) => {
|
|
33
33
|
if (customTranslation?.full !== undefined) {
|
|
@@ -38,7 +38,7 @@ const renderCommonnessRatedAdvantageOrDisadvantageName = (translateMap, getInsta
|
|
|
38
38
|
? undefined
|
|
39
39
|
: convertCommonnessRatedAdvantageOrDisadvantageLevel(item.level);
|
|
40
40
|
const options = customTranslation?.options === undefined
|
|
41
|
-
? (item.options?.map(option => renderNameComponentsOptions(
|
|
41
|
+
? (item.options?.map(option => renderNameComponentsOptions(true, getResolvedSelectOptionById, id, [option]) ??
|
|
42
42
|
MISSING_VALUE) ?? [])
|
|
43
43
|
: [customTranslation.options];
|
|
44
44
|
const name = translation.name_in_library !== undefined && options.length === 0
|
|
@@ -49,12 +49,8 @@ const renderCommonnessRatedAdvantageOrDisadvantageName = (translateMap, getInsta
|
|
|
49
49
|
base: name,
|
|
50
50
|
level,
|
|
51
51
|
nameBuilderRules: makeNameBuilderRulesWithDefaults(instance.nameBuilderRules),
|
|
52
|
-
options
|
|
53
|
-
|
|
54
|
-
option,
|
|
55
|
-
]) ?? MISSING_VALUE) ?? [])
|
|
56
|
-
: [customTranslation.options],
|
|
57
|
-
}, false);
|
|
52
|
+
options,
|
|
53
|
+
}, false, list => list.toSorted(localeCompare).join(", "));
|
|
58
54
|
}, entity, item.id) ?? MISSING_VALUE);
|
|
59
55
|
};
|
|
60
56
|
/**
|
|
@@ -63,13 +59,13 @@ const renderCommonnessRatedAdvantageOrDisadvantageName = (translateMap, getInsta
|
|
|
63
59
|
export const renderCommonnessRatedAdvantagesOrDisadvantages = (entity, items, emptyString) => Reader.asks(({ translateMap, getInstanceById, getResolvedSelectOptionById, localeCompare }) => items === undefined || !isNotEmpty(items)
|
|
64
60
|
? emptyString
|
|
65
61
|
: items
|
|
66
|
-
.map(item => renderCommonnessRatedAdvantageOrDisadvantageName(translateMap, getInstanceById, getResolvedSelectOptionById, entity, item))
|
|
62
|
+
.map(item => renderCommonnessRatedAdvantageOrDisadvantageName(translateMap, getInstanceById, getResolvedSelectOptionById, localeCompare, entity, item))
|
|
67
63
|
.toSorted(localeCompare)
|
|
68
64
|
.join(", "));
|
|
69
65
|
/**
|
|
70
66
|
* Render the names of commonness-rated advantages and disadvantages together.
|
|
71
67
|
*/
|
|
72
|
-
export const renderCommonnessRatedAdvantagesAndDisadvantages = (advantages, disadvantages, emptyString) => Reader.asks(({ translateMap, getInstanceById, getResolvedSelectOptionById, localeCompare }) => mapNullable(ensureNonEmpty([["Advantage", advantages], ["Disadvantage", disadvantages]].flatMap(([entity, items]) => items?.map(item => renderCommonnessRatedAdvantageOrDisadvantageName(translateMap, getInstanceById, getResolvedSelectOptionById, entity, item)) ?? [])), renderedItems => renderedItems.toSorted(localeCompare).join(", ")) ?? emptyString);
|
|
68
|
+
export const renderCommonnessRatedAdvantagesAndDisadvantages = (advantages, disadvantages, emptyString) => Reader.asks(({ translateMap, getInstanceById, getResolvedSelectOptionById, localeCompare }) => mapNullable(ensureNonEmpty([["Advantage", advantages], ["Disadvantage", disadvantages]].flatMap(([entity, items]) => items?.map(item => renderCommonnessRatedAdvantageOrDisadvantageName(translateMap, getInstanceById, getResolvedSelectOptionById, localeCompare, entity, item)) ?? [])), renderedItems => renderedItems.toSorted(localeCompare).join(", ")) ?? emptyString);
|
|
73
69
|
/**
|
|
74
70
|
* Render a value with a possible translation, falling back to explicity rendering the value if no translation is available.
|
|
75
71
|
*/
|
|
@@ -13,11 +13,11 @@ export declare const printPublicationPrerequisites: (getInstanceById: GetInstanc
|
|
|
13
13
|
/**
|
|
14
14
|
* Print plain general prerequisites as a string.
|
|
15
15
|
*/
|
|
16
|
-
export declare const printPlainGeneralPrerequisites: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, value: PlainGeneralPrerequisites) => string;
|
|
16
|
+
export declare const printPlainGeneralPrerequisites: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement" | "PersonalityTrait">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, value: PlainGeneralPrerequisites) => string;
|
|
17
17
|
/**
|
|
18
18
|
* Print general prerequisites as a string.
|
|
19
19
|
*/
|
|
20
|
-
export declare const printGeneralPrerequisites: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, value: GeneralPrerequisites, printPreviousLevelPrerequisites?: {
|
|
20
|
+
export declare const printGeneralPrerequisites: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement" | "PersonalityTrait">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, value: GeneralPrerequisites, printPreviousLevelPrerequisites?: {
|
|
21
21
|
id: ActivatableIdentifier;
|
|
22
22
|
levels: number;
|
|
23
23
|
}, trailingText?: string) => string;
|
|
@@ -28,7 +28,7 @@ export declare const printProfessionPrerequisites: (getInstanceById: GetInstance
|
|
|
28
28
|
/**
|
|
29
29
|
* Print advantage disadvantage prerequisites as a string.
|
|
30
30
|
*/
|
|
31
|
-
export declare const printAdvantageDisadvantagePrerequisites: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, value: AdvantageDisadvantagePrerequisites, name: string, type: "Advantage" | "Disadvantage") => string;
|
|
31
|
+
export declare const printAdvantageDisadvantagePrerequisites: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement" | "PersonalityTrait">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, value: AdvantageDisadvantagePrerequisites, name: string, type: "Advantage" | "Disadvantage") => string;
|
|
32
32
|
/**
|
|
33
33
|
* Print arcane tradition prerequisites as a string.
|
|
34
34
|
*/
|
|
@@ -14,7 +14,7 @@ export declare const printPublicationPrerequisiteGroup: (getInstanceById: GetIns
|
|
|
14
14
|
/**
|
|
15
15
|
* Print the translation of a general prerequisite group.
|
|
16
16
|
*/
|
|
17
|
-
export declare const printGeneralPrerequisiteGroup: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, prerequisite: GeneralPrerequisiteGroup) => PrerequisitePart | undefined;
|
|
17
|
+
export declare const printGeneralPrerequisiteGroup: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement" | "PersonalityTrait">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, prerequisite: GeneralPrerequisiteGroup) => PrerequisitePart | undefined;
|
|
18
18
|
/**
|
|
19
19
|
* Print the translation of a profession prerequisite group.
|
|
20
20
|
*/
|
|
@@ -22,7 +22,7 @@ export declare const printProfessionPrerequisiteGroup: (getInstanceById: GetInst
|
|
|
22
22
|
/**
|
|
23
23
|
* Print the translation of an advantage/disadvantage prerequisite group.
|
|
24
24
|
*/
|
|
25
|
-
export declare const printAdvantageDisadvantagePrerequisiteGroup: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, prerequisite: AdvantageDisadvantagePrerequisiteGroup, name: string, type: "Advantage" | "Disadvantage") => PrerequisitePart | undefined;
|
|
25
|
+
export declare const printAdvantageDisadvantagePrerequisiteGroup: (getInstanceById: GetInstanceById<"Race" | "Culture" | "PactCategory" | "PactDomain" | "SocialStatus" | "State" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Property" | "Aspect" | "Enhancement" | "PersonalityTrait">, getResolvedSelectOptionById: GetResolvedSelectOptionById, locale: LocaleEnvironment, prerequisite: AdvantageDisadvantagePrerequisiteGroup, name: string, type: "Advantage" | "Disadvantage") => PrerequisitePart | undefined;
|
|
26
26
|
/**
|
|
27
27
|
* Print the translation of an arcane tradition prerequisite group.
|
|
28
28
|
*/
|
|
@@ -87,6 +87,8 @@ export const printGeneralPrerequisiteGroup = (getInstanceById, getResolvedSelect
|
|
|
87
87
|
return printTextPrerequisite(locale, prerequisite.Text);
|
|
88
88
|
case "SexualCharacteristic":
|
|
89
89
|
return printSexualCharacteristicPrerequisite(locale, prerequisite.SexualCharacteristic);
|
|
90
|
+
case "PersonalityTrait":
|
|
91
|
+
return printPersonalityTraitPrerequisite(getInstanceById, locale, prerequisite.PersonalityTrait);
|
|
90
92
|
default:
|
|
91
93
|
return assertExhaustive(prerequisite);
|
|
92
94
|
}
|
|
@@ -136,6 +138,7 @@ export const printAdvantageDisadvantagePrerequisiteGroup = (getInstanceById, get
|
|
|
136
138
|
case "Enhancement":
|
|
137
139
|
case "Text":
|
|
138
140
|
case "SexualCharacteristic":
|
|
141
|
+
case "PersonalityTrait":
|
|
139
142
|
return printGeneralPrerequisiteGroup(getInstanceById, getResolvedSelectOptionById, locale, prerequisite);
|
|
140
143
|
default:
|
|
141
144
|
return assertExhaustive(prerequisite);
|
|
@@ -8,8 +8,9 @@ export const printRatedPrerequisite = (getInstanceById, locale, prerequisite) =>
|
|
|
8
8
|
if (prerequisite.display_option !== undefined) {
|
|
9
9
|
return printDisplayOption(locale.translateMap, prerequisite.display_option);
|
|
10
10
|
}
|
|
11
|
+
const name = attributedCustomName(locale.translateMap, getInstanceById, "prerequisite", (t) => t.abbreviation ?? t.name, prerequisite.id) ?? MISSING_VALUE;
|
|
11
12
|
return {
|
|
12
|
-
value:
|
|
13
|
+
value: prerequisite.value > 0 ? `${name} ${prerequisite.value.toFixed()}` : name,
|
|
13
14
|
sentenceType: undefined,
|
|
14
15
|
isMeta: false,
|
|
15
16
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Reader } from "@elyukai/utils/reader";
|
|
2
2
|
import type { CheckResultBasedModifier, DurationUnitValue, ElvenMagicalSongPermanentCost, FirstPersonMagicalMelodyCost, NonModifiableOneTimeCostPerCountable, NonModifiableSustainedCost, OneTimeCost, OneTimeCostMap, ResponsiveText, ResponsiveTextOptional, ResponsiveTextReplace, SkillModificationLevel_ID, SustainedCost } from "@optolith/database-schema/gen";
|
|
3
|
-
import { type LocaleMap } from "../../../../helpers/translate.js";
|
|
3
|
+
import { type LocaleMap, type Translate } from "../../../../helpers/translate.js";
|
|
4
4
|
import { type StdEnv, type StdReader } from "../../reader.js";
|
|
5
|
+
import { type ResponsiveTextSize } from "../../responsiveText.js";
|
|
5
6
|
/**
|
|
6
7
|
* Returns the text for the modifiable one-time cost of an activatable skill.
|
|
7
8
|
*/
|
|
@@ -51,11 +52,11 @@ export declare const renderOneTimeCost: (value: OneTimeCost) => StdReader<string
|
|
|
51
52
|
* Returns the text for the non-modifiable cost of a sustained activatable skill.
|
|
52
53
|
*/
|
|
53
54
|
export declare const renderNonModifiableSustainedCost: (value: NonModifiableSustainedCost) => Reader<{
|
|
54
|
-
translate:
|
|
55
|
+
translate: Translate;
|
|
55
56
|
energyUnit: import("../../units/energy.js").EnergyUnit;
|
|
56
57
|
} & {
|
|
57
|
-
translate:
|
|
58
|
-
responsiveTextSize:
|
|
58
|
+
translate: Translate;
|
|
59
|
+
responsiveTextSize: ResponsiveTextSize;
|
|
59
60
|
} & StdEnv<"t" | "rts" | "tm" | "eu", never, never, never>, string>;
|
|
60
61
|
/**
|
|
61
62
|
* Returns the text for the cost of a sustained activatable skill.
|
|
@@ -2,10 +2,11 @@ import { identity } from "@elyukai/utils/function";
|
|
|
2
2
|
import { Reader } from "@elyukai/utils/reader";
|
|
3
3
|
import { mapNullable } from "@optolith/helpers/nullable";
|
|
4
4
|
import { assertExhaustive } from "@optolith/helpers/typeSafety";
|
|
5
|
+
import { responsiveTranslate, } from "../../../../helpers/translate.js";
|
|
5
6
|
import { renderResponsiveMap } from "../../map.js";
|
|
6
7
|
import { formatEnergyFnR, formatEnergyR, getInstanceByIdFnR, modifiableBySpeedR, responsiveLocaleJoinR, responsiveR, responsiveTextR, responsiveTranslateR, translateMapR, translateR, } from "../../reader.js";
|
|
7
|
-
import { appendNoteIfNeeded, replaceTextIfNeeded } from "../../responsiveText.js";
|
|
8
|
-
import { formatCombinedTimeSpanR } from "../../units/timeSpan.js";
|
|
8
|
+
import { appendNoteIfNeeded, replaceTextIfNeeded, } from "../../responsiveText.js";
|
|
9
|
+
import { formatCombinedTimeSpan, formatCombinedTimeSpanR } from "../../units/timeSpan.js";
|
|
9
10
|
import { MISSING_VALUE } from "../../unknown.js";
|
|
10
11
|
import { appendCheckResultModifier } from "./checkResultBased.js";
|
|
11
12
|
import { wrapIfMinimum } from "./isMinimumMaximum.js";
|
|
@@ -57,12 +58,18 @@ export const renderModifiableOneTimeCost = (value) => deriveModifiableCost(value
|
|
|
57
58
|
}
|
|
58
59
|
return responsiveTextR(translation.additional).map(additional => `${text} + ${additional}`);
|
|
59
60
|
})));
|
|
60
|
-
const
|
|
61
|
+
const appendIntervalToCostR = (interval, baseCost) => interval === undefined
|
|
61
62
|
? Reader.of(baseCost)
|
|
62
63
|
: formatCombinedTimeSpanR(interval, true).then(formattedInterval => responsiveTranslateR("{$cost} per {$interval}", "{$cost}/{$interval}", {
|
|
63
64
|
cost: baseCost,
|
|
64
65
|
interval: formattedInterval,
|
|
65
66
|
}));
|
|
67
|
+
const appendIntervalToCost = (translate, responsiveTextSize, interval, baseCost) => interval === undefined
|
|
68
|
+
? baseCost
|
|
69
|
+
: responsiveTranslate(translate, responsiveTextSize, "{$cost} per {$interval}", "{$cost}/{$interval}", {
|
|
70
|
+
cost: baseCost,
|
|
71
|
+
interval: formatCombinedTimeSpan(translate, responsiveTextSize, interval, true),
|
|
72
|
+
});
|
|
66
73
|
/**
|
|
67
74
|
* Returns the text for a non-modifiable one-time cost of an activatable skill.
|
|
68
75
|
*/
|
|
@@ -70,7 +77,7 @@ export const renderNonModifiableOneTimeCost = (value, shouldAppendNonModifiableS
|
|
|
70
77
|
.thenW(base => appendFamiliarsTrickLPCostIfNeeded(value.lp_value, base))
|
|
71
78
|
.thenW(base => appendPerCountableToCostIfNeeded(value.per, base))
|
|
72
79
|
.then(base => appendPermanentCostIfNeeded(value.permanent_value, base))
|
|
73
|
-
.then(base =>
|
|
80
|
+
.then(base => appendIntervalToCostR(value.interval, base))
|
|
74
81
|
.then(base => appendElvenPermanentCostIfNeeded(value.permanent, base))
|
|
75
82
|
.then(base => wrapIfMinimum(value.is_minimum, base))
|
|
76
83
|
.then(base => appendNoteIfNeeded(value.translations, base))
|
|
@@ -126,7 +133,7 @@ export const renderOneTimeCostMap = (value) => Reader.asks(({ translate }) => tr
|
|
|
126
133
|
: undefined))
|
|
127
134
|
.then(text => appendNonModifiableSuffix(ModifiableParameter.Cost, text)));
|
|
128
135
|
const renderSustainedCostMap = (value) => formatEnergyFnR
|
|
129
|
-
.thenW(formatEnergy => renderResponsiveMap(value, option => option.value, formatEnergy))
|
|
136
|
+
.thenW(formatEnergy => Reader.ask().thenW(({ translate, responsiveTextSize }) => renderResponsiveMap(value, option => option.value, singleValue => appendIntervalToCost(translate, responsiveTextSize, value.interval, formatEnergy(singleValue)))))
|
|
130
137
|
.then(text => appendNonModifiableSuffix(ModifiableParameter.Cost, text));
|
|
131
138
|
/**
|
|
132
139
|
* Returns the text for the cost of a one-time activatable skill.
|
|
@@ -147,7 +154,7 @@ export const renderOneTimeCost = (value) => {
|
|
|
147
154
|
};
|
|
148
155
|
const buildSustainedCost = (activationCost, intervalCost, interval) => {
|
|
149
156
|
const activationCostWithLabel = responsiveR(() => translateR("activation").map(label => `${activationCost} (${label})`), () => Reader.of(activationCost)).thenW(identity);
|
|
150
|
-
const intervalCostWithLabel =
|
|
157
|
+
const intervalCostWithLabel = appendIntervalToCostR(interval, intervalCost);
|
|
151
158
|
return activationCostWithLabel.map2(intervalCostWithLabel, (activationStr, intervalStr) => `${activationStr} + ${intervalStr}`);
|
|
152
159
|
};
|
|
153
160
|
const renderModifiableSustainedCost = (value) => deriveModifiableCost(value.initial_modification_level).thenW(cost => cost === undefined
|
|
@@ -12,6 +12,15 @@ export type TimeSpanUnit = "Seconds" | "Minutes" | "Hours" | "Days" | "Weeks" |
|
|
|
12
12
|
export declare const formatTimeSpan: (translate: Translate, responsiveTextSize: ResponsiveTextSize, unit: {
|
|
13
13
|
kind: TimeSpanUnit;
|
|
14
14
|
} | TimeSpanUnit, value: number | string, interval?: boolean) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the text for a time span unit.
|
|
17
|
+
*/
|
|
18
|
+
export declare const formatCombinedTimeSpan: (translate: Translate, responsiveTextSize: ResponsiveTextSize, object: {
|
|
19
|
+
unit: {
|
|
20
|
+
kind: TimeSpanUnit;
|
|
21
|
+
};
|
|
22
|
+
value: number | string;
|
|
23
|
+
}, interval?: boolean) => string;
|
|
15
24
|
/**
|
|
16
25
|
* Returns the text for a time span unit.
|
|
17
26
|
*/
|
|
@@ -28,6 +28,10 @@ export const formatTimeSpan = (translate, responsiveTextSize, unit, value, inter
|
|
|
28
28
|
style: interval ? "interval" : "default",
|
|
29
29
|
}));
|
|
30
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Returns the text for a time span unit.
|
|
33
|
+
*/
|
|
34
|
+
export const formatCombinedTimeSpan = (translate, responsiveTextSize, object, interval = false) => formatTimeSpan(translate, responsiveTextSize, object.unit, object.value, interval);
|
|
31
35
|
/**
|
|
32
36
|
* Returns the text for a time span unit.
|
|
33
37
|
*/
|
package/lib/entities/poison.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { GetResolvedSelectOptionById } from "./partial/prerequisites/single
|
|
|
6
6
|
* Get a JSON representation of the rules text for a poison.
|
|
7
7
|
*/
|
|
8
8
|
export declare const getPoisonEntityDescription: import("../creator.js").EntityDescriptionCreator<"Poison", {
|
|
9
|
-
getInstanceById: GetInstanceById<"Publication" | "DerivedCharacteristic" | "Disease" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Race" | "Culture" | "State" | "Enhancement" | "PactCategory" | "PactDomain" | "SocialStatus" | "Aspect" | "Property">;
|
|
9
|
+
getInstanceById: GetInstanceById<"Publication" | "DerivedCharacteristic" | "Disease" | ActivatableIdentifier["kind"] | RatedIdentifier["kind"] | "Race" | "Culture" | "State" | "Enhancement" | "PactCategory" | "PactDomain" | "SocialStatus" | "Aspect" | "Property" | "PersonalityTrait">;
|
|
10
10
|
getResolvedSelectOptionById: GetResolvedSelectOptionById;
|
|
11
11
|
idMap: IdMap;
|
|
12
12
|
}, import("../index.js").EntityDescription>;
|
|
@@ -77,12 +77,15 @@ const renderVariantLanguagesScriptsOption = (baseOptions, variantOptions) => ren
|
|
|
77
77
|
})),
|
|
78
78
|
});
|
|
79
79
|
const renderLanguagesScriptsOption = (option) => renderVariantLanguagesScriptsOption(undefined, { kind: "Override", Override: option });
|
|
80
|
-
const
|
|
80
|
+
const wrapInParensIf = (text, condition) => (condition ? parensIf(text) : text);
|
|
81
|
+
const renderSkillSpecializationOption = (option) => Reader.asks(({ format, translate, translateMap, localeJoin, localeCompare, getInstanceById }) => {
|
|
81
82
|
switch (option.kind) {
|
|
82
83
|
case "Specific":
|
|
83
84
|
return translate("Skill Specialization {$possibleSkills}", {
|
|
84
|
-
possibleSkills: localeJoin(option.Specific.options
|
|
85
|
-
|
|
85
|
+
possibleSkills: wrapInParensIf(localeJoin(option.Specific.options
|
|
86
|
+
.map(id => attributedName(translateMap, getInstanceById, "profession", "Skill", id) ??
|
|
87
|
+
MISSING_VALUE)
|
|
88
|
+
.toSorted(localeCompare), "disjunction"), option.Specific.options.length > 2),
|
|
86
89
|
});
|
|
87
90
|
case "Group":
|
|
88
91
|
return translate("Skill Specialization for a {$skillOfGroup}", {
|
|
@@ -563,10 +566,13 @@ const renderProfessionVariantText = (base, variant, translation) => translation.
|
|
|
563
566
|
renderRatedVariantChanges(base.spells, variant.spells, renderSpellworkName),
|
|
564
567
|
renderBlessingsForVariant(variant),
|
|
565
568
|
renderRatedVariantChanges(baseHasNoTradition(base) ? "ignore" : base.liturgical_chants, variant.liturgical_chants, renderLiturgicalChantName),
|
|
566
|
-
]).map(lists =>
|
|
567
|
-
.filter(isNotEmpty)
|
|
568
|
-
.map(list => list.join(", "))
|
|
569
|
-
|
|
569
|
+
]).map(lists => {
|
|
570
|
+
const nonEmptyLists = lists.filter(isNotEmpty);
|
|
571
|
+
return (nonEmptyLists.map(list => list.join(", ")).join("; ") +
|
|
572
|
+
(translation.concluding_text !== undefined
|
|
573
|
+
? `${nonEmptyLists.length > 0 ? ". " : ""}${translation.concluding_text}`
|
|
574
|
+
: ""));
|
|
575
|
+
});
|
|
570
576
|
const renderProfessionVariant = (base, variants) => translateMapFnR.thenW(translateMap => {
|
|
571
577
|
const translations = variants
|
|
572
578
|
.map(variant => mapNullable(translateMap(variant.content.translations), t => ({
|