@optolith/entity-descriptions 0.3.2 → 0.4.1
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 +36 -0
- package/lib/creator.d.ts +2 -2
- package/lib/creator.js +1 -1
- package/lib/entities/activatable.js +35 -64
- package/lib/entities/culture.js +18 -26
- package/lib/entities/curriculum.js +30 -33
- package/lib/entities/derivedCharacteristic.js +1 -1
- package/lib/entities/disease.js +3 -6
- package/lib/entities/elixir.js +6 -4
- package/lib/entities/equipment.js +17 -17
- package/lib/entities/equipmentPackage.js +4 -3
- package/lib/entities/experienceLevel.js +7 -7
- package/lib/entities/focusRule.js +2 -2
- package/lib/entities/influence.js +2 -2
- package/lib/entities/liturgicalChant.d.ts +1 -1
- package/lib/entities/partial/adventurePointsValue.js +14 -19
- package/lib/entities/partial/enhancements.d.ts +1 -1
- package/lib/entities/partial/enhancements.js +1 -1
- package/lib/entities/partial/herbary.js +13 -9
- package/lib/entities/partial/map.d.ts +3 -1
- package/lib/entities/partial/map.js +21 -8
- package/lib/entities/partial/mathOperation.js +12 -17
- package/lib/entities/partial/prerequisites/displayOption.d.ts +2 -2
- package/lib/entities/partial/prerequisites/index.d.ts +3 -3
- package/lib/entities/partial/prerequisites/index.js +10 -4
- package/lib/entities/partial/prerequisites/part.d.ts +1 -1
- package/lib/entities/partial/prerequisites/prerequisiteGroups.d.ts +4 -4
- package/lib/entities/partial/prerequisites/prerequisiteGroups.js +1 -1
- package/lib/entities/partial/prerequisites/single/activatable.d.ts +3 -3
- package/lib/entities/partial/prerequisites/single/animistPower.d.ts +2 -2
- package/lib/entities/partial/prerequisites/single/animistPower.js +1 -1
- package/lib/entities/partial/prerequisites/single/blessedTradition.d.ts +2 -2
- package/lib/entities/partial/prerequisites/single/commonSuggestedByRCP.d.ts +2 -2
- package/lib/entities/partial/prerequisites/single/culture.d.ts +4 -4
- package/lib/entities/partial/prerequisites/single/enhancement.d.ts +4 -4
- package/lib/entities/partial/prerequisites/single/influence.d.ts +3 -3
- package/lib/entities/partial/prerequisites/single/magicalTradition.d.ts +2 -2
- package/lib/entities/partial/prerequisites/single/noOtherAncestorBloodAdvantage.d.ts +2 -2
- package/lib/entities/partial/prerequisites/single/pact.d.ts +3 -3
- package/lib/entities/partial/prerequisites/single/personalityTrait.d.ts +4 -4
- package/lib/entities/partial/prerequisites/single/primaryAttribute.d.ts +3 -3
- package/lib/entities/partial/prerequisites/single/primaryAttribute.js +1 -1
- package/lib/entities/partial/prerequisites/single/profession.d.ts +4 -4
- package/lib/entities/partial/prerequisites/single/publication.d.ts +4 -4
- package/lib/entities/partial/prerequisites/single/race.d.ts +4 -4
- package/lib/entities/partial/prerequisites/single/rated.d.ts +2 -2
- package/lib/entities/partial/prerequisites/single/rated.js +2 -2
- package/lib/entities/partial/prerequisites/single/ratedMinimumNumber.d.ts +3 -3
- package/lib/entities/partial/prerequisites/single/ratedMinimumNumber.js +1 -1
- package/lib/entities/partial/prerequisites/single/ratedSum.d.ts +4 -4
- package/lib/entities/partial/prerequisites/single/rule.d.ts +3 -3
- package/lib/entities/partial/prerequisites/single/sex.d.ts +1 -1
- package/lib/entities/partial/prerequisites/single/sexualCharacteristic.d.ts +3 -3
- package/lib/entities/partial/prerequisites/single/socialStatus.d.ts +3 -3
- package/lib/entities/partial/prerequisites/single/state.d.ts +4 -4
- package/lib/entities/partial/prerequisites/single/text.d.ts +3 -3
- package/lib/entities/partial/rated/activatable/castingTime.d.ts +1 -1
- package/lib/entities/partial/rated/activatable/castingTime.js +6 -8
- package/lib/entities/partial/rated/activatable/cost.d.ts +1 -1
- package/lib/entities/partial/rated/activatable/cost.js +17 -14
- package/lib/entities/partial/rated/activatable/duration.js +4 -4
- package/lib/entities/partial/rated/activatable/effect.js +1 -1
- package/lib/entities/partial/rated/activatable/isMinimumMaximum.js +2 -2
- package/lib/entities/partial/rated/activatable/range.js +6 -6
- package/lib/entities/partial/rated/activatable/speed.d.ts +1 -1
- package/lib/entities/partial/rated/activatable/targetCategory.js +2 -2
- package/lib/entities/partial/reader.d.ts +4 -2
- package/lib/entities/partial/responsiveText.d.ts +5 -1
- package/lib/entities/partial/responsiveText.js +3 -5
- package/lib/entities/partial/units/length.d.ts +1 -1
- package/lib/entities/partial/units/length.js +2 -10
- package/lib/entities/partial/units/timeSpan.d.ts +4 -4
- package/lib/entities/partial/units/timeSpan.js +21 -17
- package/lib/entities/personalityTrait.js +3 -4
- package/lib/entities/poison.js +4 -4
- package/lib/entities/profession.d.ts +1 -1
- package/lib/entities/profession.js +19 -14
- package/lib/entities/race.js +11 -13
- package/lib/entities/sexPractice.js +1 -3
- package/lib/entities/skill.js +2 -3
- package/lib/entities/spell.js +14 -4
- package/lib/helpers/getTypes.d.ts +2 -2
- package/lib/helpers/locale.d.ts +8 -2
- package/lib/helpers/translate.d.ts +1 -1
- package/lib/index.d.ts +11 -2
- package/lib/index.js +5 -0
- package/lib/references/index.d.ts +1 -1
- package/lib/references/index.js +1 -1
- package/lib/references/page.d.ts +3 -3
- package/lib/references/page.js +1 -1
- package/lib/references/pageRange.d.ts +2 -2
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,42 @@
|
|
|
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.1](https://github.com/Optolith/entity-descriptions/compare/v0.4.0...v0.4.1) (2026-03-13)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* apply map style ([414685f](https://github.com/Optolith/entity-descriptions/commit/414685f574e9669943f700564d36a27bd3711ddb))
|
|
11
|
+
* focus rule badge ([c76c4cd](https://github.com/Optolith/entity-descriptions/commit/c76c4cd0c33e0187b080f7a8afb04a99cad6785c))
|
|
12
|
+
* interval style time span as unit ([0c772d1](https://github.com/Optolith/entity-descriptions/commit/0c772d1cc2d65bd97804fe5a96137f4f1a601a02))
|
|
13
|
+
* use more compact diff for activatable skill parameters ([70d7082](https://github.com/Optolith/entity-descriptions/commit/70d70823c24f81a47dbb8f7ced23819464926067))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* do not use typographic formatter for multi-word cost ([fecbae5](https://github.com/Optolith/entity-descriptions/commit/fecbae5bbbccebc45660dbbb6121c8169fce1747))
|
|
19
|
+
* do not wrap maximum duration if replaced ([bac8a49](https://github.com/Optolith/entity-descriptions/commit/bac8a493b2a6d5cf08ab9d461e7f84f8c83c1788))
|
|
20
|
+
* min/max wrapping ([9a435e2](https://github.com/Optolith/entity-descriptions/commit/9a435e25979dea9810332c51a763e093ea403dfb))
|
|
21
|
+
* missing profession specification in title ([2a97e7e](https://github.com/Optolith/entity-descriptions/commit/2a97e7e1f5b8d91a8ed27ac3545c1691d0217aa1))
|
|
22
|
+
* use abbreviated attribute name in prerequisites ([1b2d21b](https://github.com/Optolith/entity-descriptions/commit/1b2d21ba68964ad7dfb542d249842cbc9bea5fa7))
|
|
23
|
+
* use duration level translation if present ([a7790d6](https://github.com/Optolith/entity-descriptions/commit/a7790d68f68fc5762a954c1703a7f6b4fb3dfe07))
|
|
24
|
+
|
|
25
|
+
## [0.4.0](https://github.com/Optolith/entity-descriptions/compare/v0.3.2...v0.4.0) (2026-03-12)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### ⚠ BREAKING CHANGES
|
|
29
|
+
|
|
30
|
+
* require external date formatter
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
* export helpful values and types ([5e73ce0](https://github.com/Optolith/entity-descriptions/commit/5e73ce0cb8098df2919694c72c835134bf520aea))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### Bug Fixes
|
|
38
|
+
|
|
39
|
+
* require external date formatter ([9cdf694](https://github.com/Optolith/entity-descriptions/commit/9cdf69443781203c86256dea85918960b1f17c9c))
|
|
40
|
+
|
|
5
41
|
## [0.3.2](https://github.com/Optolith/entity-descriptions/compare/v0.3.1...v0.3.2) (2026-03-12)
|
|
6
42
|
|
|
7
43
|
|
package/lib/creator.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { EntityMap } from "optolith-database-schema/gen";
|
|
2
2
|
import type { GetInstanceById } from "./helpers/getTypes.js";
|
|
3
|
-
import { LocaleEnvironment } from "./helpers/locale.js";
|
|
4
|
-
import { EntityDescription, RawEntityDescription } from "./index.js";
|
|
3
|
+
import type { LocaleEnvironment } from "./helpers/locale.js";
|
|
4
|
+
import type { EntityDescription, RawEntityDescription } from "./index.js";
|
|
5
5
|
/**
|
|
6
6
|
* A union type of entities with their names as a discriminant property.
|
|
7
7
|
*/
|
package/lib/creator.js
CHANGED
|
@@ -62,7 +62,7 @@ export const createEntityDescriptionCreator = (fn) => (databaseAccessors, locale
|
|
|
62
62
|
...rawEntry,
|
|
63
63
|
body: rawEntry.body.filter(isNotNullish).map(mapRawSection),
|
|
64
64
|
errata: rawEntry.errata?.map(({ date, description }) => ({
|
|
65
|
-
date:
|
|
65
|
+
date: locale.formatDate(date),
|
|
66
66
|
description: description.trim(),
|
|
67
67
|
})),
|
|
68
68
|
references: rawEntry.references === undefined
|
|
@@ -20,7 +20,8 @@ const renderPropertyValue = (getInstanceById, translate, translateMap, propertyD
|
|
|
20
20
|
case "DependingOnSelection":
|
|
21
21
|
return translate("As chosen");
|
|
22
22
|
case "Fixed":
|
|
23
|
-
return (translateMap(getInstanceById("Property", propertyDecl.Fixed)?.translations)?.name ??
|
|
23
|
+
return (translateMap(getInstanceById("Property", propertyDecl.Fixed)?.translations)?.name ??
|
|
24
|
+
MISSING_VALUE);
|
|
24
25
|
default:
|
|
25
26
|
return assertExhaustive(propertyDecl);
|
|
26
27
|
}
|
|
@@ -40,20 +41,14 @@ const renderPenaltyValue = (getInstanceById, translate, translateMap, name, pena
|
|
|
40
41
|
switch (penalty.kind) {
|
|
41
42
|
case "Single":
|
|
42
43
|
return (sign(penalty.Single.value) +
|
|
43
|
-
(penalty.Single.applies_to_parry === true
|
|
44
|
-
? ` (${translate("for parry")})`
|
|
45
|
-
: ""));
|
|
44
|
+
(penalty.Single.applies_to_parry === true ? ` (${translate("for parry")})` : ""));
|
|
46
45
|
case "ByHandedness": {
|
|
47
|
-
const appendParry = penalty.ByHandedness.applies_to_parry === true
|
|
48
|
-
? `; ${translate("for parry")}`
|
|
49
|
-
: "";
|
|
46
|
+
const appendParry = penalty.ByHandedness.applies_to_parry === true ? `; ${translate("for parry")}` : "";
|
|
50
47
|
return `${sign(penalty.ByHandedness.one_handed)} (${translate("one-handed weapon") + appendParry}); ${sign(penalty.ByHandedness.two_handed)} (${translate("two-handed weapon") + appendParry})`;
|
|
51
48
|
}
|
|
52
49
|
case "ByActivation": {
|
|
53
50
|
return `${sign(penalty.ByActivation.active)}/${sign(penalty.ByActivation.inactive)} (${[
|
|
54
|
-
penalty.ByActivation.applies_to_parry === true
|
|
55
|
-
? translate("for parry")
|
|
56
|
-
: undefined,
|
|
51
|
+
penalty.ByActivation.applies_to_parry === true ? translate("for parry") : undefined,
|
|
57
52
|
translate("for secondary fighters with/without special ability {$name}", { name }),
|
|
58
53
|
]
|
|
59
54
|
.filter(isNotNullish)
|
|
@@ -62,9 +57,7 @@ const renderPenaltyValue = (getInstanceById, translate, translateMap, name, pena
|
|
|
62
57
|
case "Selection":
|
|
63
58
|
switch (penalty.Selection.options.kind) {
|
|
64
59
|
case "Specific":
|
|
65
|
-
return penalty.Selection.options.Specific.list
|
|
66
|
-
.map(option => sign(option.value))
|
|
67
|
-
.join("/");
|
|
60
|
+
return penalty.Selection.options.Specific.list.map(option => sign(option.value)).join("/");
|
|
68
61
|
case "Range":
|
|
69
62
|
return translate("{$start} to {$end}", {
|
|
70
63
|
start: sign(penalty.Selection.options.Range.minimum),
|
|
@@ -81,8 +74,8 @@ const renderPenaltyValue = (getInstanceById, translate, translateMap, name, pena
|
|
|
81
74
|
if (external === undefined) {
|
|
82
75
|
return main;
|
|
83
76
|
}
|
|
84
|
-
const externalName = translateMap(getInstanceById(external.kind, fromUniformCase(external))
|
|
85
|
-
?.
|
|
77
|
+
const externalName = translateMap(getInstanceById(external.kind, fromUniformCase(external))?.translations)
|
|
78
|
+
?.name ?? MISSING_VALUE;
|
|
86
79
|
return `${main} (${translate("depending on the level of the special ability {$name}", {
|
|
87
80
|
name: externalName,
|
|
88
81
|
})})`;
|
|
@@ -90,7 +83,7 @@ const renderPenaltyValue = (getInstanceById, translate, translateMap, name, pena
|
|
|
90
83
|
case "ByAttack": {
|
|
91
84
|
const offset = penalty.ByAttack.initial_order ?? 1;
|
|
92
85
|
return penalty.ByAttack.list
|
|
93
|
-
.map((penaltyByAttack, index) => `${penaltyByAttack.value} (${renderPenaltyByAttackLabel(translate, penalty.ByAttack.attack_replacement, index + offset)})`)
|
|
86
|
+
.map((penaltyByAttack, index) => `${penaltyByAttack.value.toFixed()} (${renderPenaltyByAttackLabel(translate, penalty.ByAttack.attack_replacement, index + offset)})`)
|
|
94
87
|
.join("; ");
|
|
95
88
|
}
|
|
96
89
|
case "DependsOnHitZone":
|
|
@@ -135,18 +128,13 @@ const wrapInParens = (args, append = "") => {
|
|
|
135
128
|
}
|
|
136
129
|
return ` (${filteredArgs.join(", ") + append})`;
|
|
137
130
|
};
|
|
138
|
-
const addSpaceIfNoCommaAtStart = (str) => str.startsWith(",") ? str : ` ${str}
|
|
131
|
+
const addSpaceIfNoCommaAtStart = (str) => (str.startsWith(",") ? str : ` ${str}`);
|
|
139
132
|
const renderApplicableCombatTechniquesRestriction = (getInstanceById, locale, main, restriction, translation, weapons, getExcludedInstance) => {
|
|
140
133
|
switch (restriction.kind) {
|
|
141
134
|
case "Improvised":
|
|
142
|
-
return
|
|
143
|
-
wrapInParens([locale.translate("only improvised weapons"), weapons]));
|
|
135
|
+
return main + wrapInParens([locale.translate("only improvised weapons"), weapons]);
|
|
144
136
|
case "PointedBlade":
|
|
145
|
-
return
|
|
146
|
-
wrapInParens([
|
|
147
|
-
locale.translate("weapon must have a pointed blade"),
|
|
148
|
-
weapons,
|
|
149
|
-
]));
|
|
137
|
+
return main + wrapInParens([locale.translate("weapon must have a pointed blade"), weapons]);
|
|
150
138
|
case "Mount":
|
|
151
139
|
if (weapons === undefined) {
|
|
152
140
|
return `${main} ${locale.translate("while mounted")}`;
|
|
@@ -183,23 +171,15 @@ const renderApplicableCombatTechniquesRestriction = (getInstanceById, locale, ma
|
|
|
183
171
|
addSpaceIfNoCommaAtStart(locale.translate("that may be performed with one-handed weapons")) +
|
|
184
172
|
wrapInParens([weapons]));
|
|
185
173
|
case "TwoHanded":
|
|
186
|
-
return
|
|
174
|
+
return locale.translate("All Two-Handed Weapons") + wrapInParens([weapons]);
|
|
187
175
|
case "ParryingWeapon":
|
|
188
176
|
return locale.translate("All Parrying Weapons") + wrapInParens([weapons]);
|
|
189
177
|
case "Level": {
|
|
190
|
-
const nameWithLevel = `${translation} ${romanize(restriction.Level.level)}`;
|
|
191
|
-
return (main +
|
|
192
|
-
wrapInParens([
|
|
193
|
-
locale.translate("only {$nameWithLevel}", { nameWithLevel }),
|
|
194
|
-
weapons,
|
|
195
|
-
]));
|
|
178
|
+
const nameWithLevel = `${translation.name_in_library ?? translation.name} ${romanize(restriction.Level.level)}`;
|
|
179
|
+
return (main + wrapInParens([locale.translate("only {$nameWithLevel}", { nameWithLevel }), weapons]));
|
|
196
180
|
}
|
|
197
181
|
case "OneBluntSide":
|
|
198
|
-
return (main +
|
|
199
|
-
wrapInParens([
|
|
200
|
-
locale.translate("only those with at least one blunt side"),
|
|
201
|
-
weapons,
|
|
202
|
-
]));
|
|
182
|
+
return (main + wrapInParens([locale.translate("only those with at least one blunt side"), weapons]));
|
|
203
183
|
default:
|
|
204
184
|
return assertExhaustive(restriction);
|
|
205
185
|
}
|
|
@@ -242,8 +222,8 @@ const renderApplicableCombatTechniquesValue = (getInstanceById, locale, translat
|
|
|
242
222
|
? undefined
|
|
243
223
|
: locale.translate("only {$weapons}", {
|
|
244
224
|
weapons: locale.join(specific.weapons
|
|
245
|
-
.map(weapon => locale.translateMap(getInstanceById("Weapon", weapon)
|
|
246
|
-
?.
|
|
225
|
+
.map(weapon => locale.translateMap(getInstanceById("Weapon", weapon)?.translations)
|
|
226
|
+
?.name ?? MISSING_VALUE)
|
|
247
227
|
.toSorted(locale.compare), "conjunction"),
|
|
248
228
|
}), undefined);
|
|
249
229
|
return mainWithRestriction;
|
|
@@ -272,9 +252,7 @@ const renderVolumeValue = (translate, translateMap, getAllResolvedSelectOptions,
|
|
|
272
252
|
case "ByLevel":
|
|
273
253
|
return translate("{$points} points for levels {$levels}", {
|
|
274
254
|
points: volume.ByLevel.list.map(item => item.points).join("/"),
|
|
275
|
-
levels: volume.ByLevel.list
|
|
276
|
-
.map((_, index) => romanize(index + 1))
|
|
277
|
-
.join("/"),
|
|
255
|
+
levels: volume.ByLevel.list.map((_, index) => romanize(index + 1)).join("/"),
|
|
278
256
|
});
|
|
279
257
|
case "Map":
|
|
280
258
|
return renderResponsiveMap(volume.Map, option => option.points, values => translate("{$points} points", { points: values })).run({
|
|
@@ -292,8 +270,7 @@ const renderVolumeValue = (translate, translateMap, getAllResolvedSelectOptions,
|
|
|
292
270
|
points: groups.map(group => group[0]).join("/"),
|
|
293
271
|
})} ${translate("for")} ${groups
|
|
294
272
|
.map(group => group[1]
|
|
295
|
-
.map(groupItem => translateMap(groupItem.content.translations)?.name ??
|
|
296
|
-
MISSING_VALUE)
|
|
273
|
+
.map(groupItem => translateMap(groupItem.content.translations)?.name ?? MISSING_VALUE)
|
|
297
274
|
.join(", "))
|
|
298
275
|
.join(separator)}`;
|
|
299
276
|
}
|
|
@@ -320,7 +297,7 @@ const renderArcaneEnergyCost = (translate, translateMap, localeJoin, responsiveT
|
|
|
320
297
|
if (cost.Fixed.per_level === undefined) {
|
|
321
298
|
return prev => prev(cost.Fixed.value);
|
|
322
299
|
}
|
|
323
|
-
switch (cost.Fixed.per_level
|
|
300
|
+
switch (cost.Fixed.per_level.kind) {
|
|
324
301
|
case "Compressed":
|
|
325
302
|
return prev => translate("{$cost} per level", { cost: prev(cost.Fixed.value) });
|
|
326
303
|
case "Verbose":
|
|
@@ -333,8 +310,7 @@ const renderArcaneEnergyCost = (translate, translateMap, localeJoin, responsiveT
|
|
|
333
310
|
}
|
|
334
311
|
})();
|
|
335
312
|
const noteInParens = parensIf(mapNullable(translateMap(cost.Fixed.translations)?.note, note => getResponsiveTextOptional(note, responsiveTextSize)));
|
|
336
|
-
return
|
|
337
|
-
noteInParens);
|
|
313
|
+
return wrapInPerLevel(value => wrapInInterval(translationWrapper(value))) + noteInParens;
|
|
338
314
|
}
|
|
339
315
|
case "Constant":
|
|
340
316
|
return (translate("{$value} AE", { value: cost.Constant.value }) +
|
|
@@ -369,11 +345,11 @@ const renderArcaneEnergyCost = (translate, translateMap, localeJoin, responsiveT
|
|
|
369
345
|
interval: formatTimeSpan(translate, responsiveTextSize, cost.ActivationAndHalfInterval.interval.unit, cost.ActivationAndHalfInterval.interval.value),
|
|
370
346
|
}));
|
|
371
347
|
case "Indefinite":
|
|
372
|
-
return (mapNullable(translateMap(cost.Indefinite.translations)?.description, description => getResponsiveText(description, responsiveTextSize)) +
|
|
348
|
+
return ((mapNullable(translateMap(cost.Indefinite.translations)?.description, description => getResponsiveText(description, responsiveTextSize)) ?? MISSING_VALUE) +
|
|
373
349
|
mapNullableDefault(cost.Indefinite.modifier, modifier => ` + ${translate("{$value} AE", { value: modifier.value })}`, ""));
|
|
374
350
|
case "Disjunction":
|
|
375
351
|
return translate("{$value} AE", {
|
|
376
|
-
value: localeJoin(cost.Disjunction.options.map(option => option.value +
|
|
352
|
+
value: localeJoin(cost.Disjunction.options.map(option => option.value.toFixed() +
|
|
377
353
|
mapNullableDefault(translateMap(option.translations)?.note, note => parensIf(getResponsiveTextOptional(note, responsiveTextSize)), "")), "disjunction"),
|
|
378
354
|
});
|
|
379
355
|
case "Map":
|
|
@@ -382,6 +358,7 @@ const renderArcaneEnergyCost = (translate, translateMap, localeJoin, responsiveT
|
|
|
382
358
|
surround: values => translate(", {$value} of which are permanent", {
|
|
383
359
|
value: values,
|
|
384
360
|
}),
|
|
361
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- is checked beforehand
|
|
385
362
|
getAdditionalValue: option => option.permanent_value,
|
|
386
363
|
}
|
|
387
364
|
: undefined).run({
|
|
@@ -442,8 +419,7 @@ const renderBindingCost = (translate, translateMap, localeCompare, getAllResolve
|
|
|
442
419
|
value: groups.map(group => group[0]).join("/"),
|
|
443
420
|
})} ${translate("for")} ${groups
|
|
444
421
|
.map(group => group[1]
|
|
445
|
-
.map(groupItem => translateMap(groupItem.content.translations)?.name ??
|
|
446
|
-
MISSING_VALUE)
|
|
422
|
+
.map(groupItem => translateMap(groupItem.content.translations)?.name ?? MISSING_VALUE)
|
|
447
423
|
.toSorted(localeCompare)
|
|
448
424
|
.join(", "))
|
|
449
425
|
.join(separator)}`;
|
|
@@ -471,8 +447,7 @@ const renderCost = (translate, translateMap, localeJoin, localeCompare, getAllRe
|
|
|
471
447
|
label: translate("AE Cost"),
|
|
472
448
|
value: cost.kind === "ArcaneEnergyCost"
|
|
473
449
|
? "ae_cost" in cost.ArcaneEnergyCost
|
|
474
|
-
? renderArcaneEnergyCost(translate, translateMap, localeJoin, responsiveTextSize, levels, cost.ArcaneEnergyCost.ae_cost) +
|
|
475
|
-
renderLifePointsCost(translate, cost.ArcaneEnergyCost.lp_cost)
|
|
450
|
+
? renderArcaneEnergyCost(translate, translateMap, localeJoin, responsiveTextSize, levels, cost.ArcaneEnergyCost.ae_cost) + renderLifePointsCost(translate, cost.ArcaneEnergyCost.lp_cost)
|
|
476
451
|
: renderArcaneEnergyCost(translate, translateMap, localeJoin, responsiveTextSize, levels, cost.ArcaneEnergyCost)
|
|
477
452
|
: renderArcaneEnergyCost(translate, translateMap, localeJoin, responsiveTextSize, levels, cost),
|
|
478
453
|
};
|
|
@@ -488,7 +463,7 @@ const renderCost = (translate, translateMap, localeJoin, localeCompare, getAllRe
|
|
|
488
463
|
/**
|
|
489
464
|
* Get a JSON representation of the rules text for a special ability.
|
|
490
465
|
*/
|
|
491
|
-
export const getActivatableEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getAllInstances, getResolvedSelectOptionById, getAllResolvedSelectOptions
|
|
466
|
+
export const getActivatableEntityDescription = createEntityDescriptionCreator(({ getInstanceById, getAllInstances, getResolvedSelectOptionById, getAllResolvedSelectOptions }, locale, { entity: entityName, content: entry, id }) => {
|
|
492
467
|
const { translate, translateMap } = locale;
|
|
493
468
|
const translation = translateMap(entry.translations);
|
|
494
469
|
const responsiveTextSize = ResponsiveTextSize.Full;
|
|
@@ -500,9 +475,7 @@ export const getActivatableEntityDescription = createEntityDescriptionCreator(({
|
|
|
500
475
|
return {
|
|
501
476
|
title: translation.name_in_library ??
|
|
502
477
|
translation.name +
|
|
503
|
-
(baseEntry.levels !== undefined
|
|
504
|
-
? ` I–${romanize(baseEntry.levels)}`
|
|
505
|
-
: ""),
|
|
478
|
+
(baseEntry.levels !== undefined ? ` I–${romanize(baseEntry.levels)}` : ""),
|
|
506
479
|
subtitle: mapNullable(baseEntry.usage_type, usageType => {
|
|
507
480
|
switch (usageType.kind) {
|
|
508
481
|
case "Passive":
|
|
@@ -546,8 +519,8 @@ export const getActivatableEntityDescription = createEntityDescriptionCreator(({
|
|
|
546
519
|
})),
|
|
547
520
|
mapNullable(baseEntry.aspect, aspect => ({
|
|
548
521
|
label: translate("Aspect"),
|
|
549
|
-
value: translateMap(getInstanceById("Aspect", aspect)?.translations)
|
|
550
|
-
|
|
522
|
+
value: translateMap(getInstanceById("Aspect", aspect)?.translations)?.name ??
|
|
523
|
+
MISSING_VALUE,
|
|
551
524
|
})),
|
|
552
525
|
mapNullable(translation.range, range => ({
|
|
553
526
|
label: translate("Range"),
|
|
@@ -559,8 +532,7 @@ export const getActivatableEntityDescription = createEntityDescriptionCreator(({
|
|
|
559
532
|
})),
|
|
560
533
|
mapNullable(entry.prerequisites, prerequisites => ({
|
|
561
534
|
label: translate("Prerequisites"),
|
|
562
|
-
value: wrappedId.kind === "Advantage" ||
|
|
563
|
-
wrappedId.kind === "Disadvantage"
|
|
535
|
+
value: wrappedId.kind === "Advantage" || wrappedId.kind === "Disadvantage"
|
|
564
536
|
? printAdvantageDisadvantagePrerequisites(getInstanceById, getResolvedSelectOptionById, locale, prerequisites, translation.name, wrappedId.kind)
|
|
565
537
|
: printGeneralPrerequisites(getInstanceById, getResolvedSelectOptionById, locale, prerequisites, mapNullable(baseEntry.levels, levels => ({
|
|
566
538
|
id: wrappedId,
|
|
@@ -581,12 +553,11 @@ export const getActivatableEntityDescription = createEntityDescriptionCreator(({
|
|
|
581
553
|
value: renderPropertyValue(getInstanceById, translate, translateMap, property),
|
|
582
554
|
})),
|
|
583
555
|
mapNullable(entry.ap_value, apValue => {
|
|
584
|
-
const append = translation.ap_value_append !== undefined
|
|
585
|
-
? ` ${translation.ap_value_append}`
|
|
586
|
-
: "";
|
|
556
|
+
const append = translation.ap_value_append !== undefined ? ` ${translation.ap_value_append}` : "";
|
|
587
557
|
return {
|
|
588
558
|
label: translate("AP Value"),
|
|
589
|
-
value: renderAdventurePointsValue(locale, activatableId => locale.translateMap(getInstanceById(activatableId.kind, fromUniformCase(activatableId))
|
|
559
|
+
value: renderAdventurePointsValue(locale, activatableId => locale.translateMap(getInstanceById(activatableId.kind, fromUniformCase(activatableId))
|
|
560
|
+
?.translations)?.name, selectOptionId => {
|
|
590
561
|
const selectOption = getResolvedSelectOptionById(wrappedId, selectOptionId);
|
|
591
562
|
if (selectOption === undefined) {
|
|
592
563
|
return undefined;
|
package/lib/entities/culture.js
CHANGED
|
@@ -7,19 +7,21 @@ import { isNotNullish, mapNullable } from "@elyukai/utils/nullable";
|
|
|
7
7
|
import { Reader } from "@elyukai/utils/reader";
|
|
8
8
|
import { sign } from "@elyukai/utils/string/number";
|
|
9
9
|
import { assertExhaustive } from "@elyukai/utils/typeSafety";
|
|
10
|
+
import { getAdventurePointsForRatingRange } from "@optolith/adventure-points/improvement-cost";
|
|
10
11
|
import { createEntityDescriptionCreator } from "../creator.js";
|
|
11
12
|
import { renderCommonnessRatedAdvantagesOrDisadvantages, renderValueWithPossibleTranslation, } from "./partial/commonnessRatedAdvantagesAndDisadvantages.js";
|
|
12
13
|
import { getProfessionName } from "./partial/professions.js";
|
|
13
14
|
import { parensIf } from "./partial/rated/activatable/parensIf.js";
|
|
14
|
-
import { translateR
|
|
15
|
+
import { translateR } from "./partial/reader.js";
|
|
15
16
|
import { MISSING_VALUE } from "./partial/unknown.js";
|
|
16
|
-
import { getAdventurePointsForRatingRange } from "@optolith/adventure-points/improvement-cost";
|
|
17
17
|
const renderListOperation = (operation, list) => {
|
|
18
18
|
switch (operation.kind) {
|
|
19
19
|
case "Intersection":
|
|
20
20
|
return Reader.of(list.join(", "));
|
|
21
21
|
case "Difference":
|
|
22
|
-
return translateR("all but {$excludedProfessions :list type=conjunction}", {
|
|
22
|
+
return translateR("all but {$excludedProfessions :list type=conjunction}", {
|
|
23
|
+
excludedProfessions: list,
|
|
24
|
+
});
|
|
23
25
|
default:
|
|
24
26
|
return assertExhaustive(operation);
|
|
25
27
|
}
|
|
@@ -49,10 +51,7 @@ const renderWeighted = (weightedVariants, getName) => {
|
|
|
49
51
|
return Reader.of(undefined);
|
|
50
52
|
}
|
|
51
53
|
return Reader.asks(({ translate, localeCompare }) => {
|
|
52
|
-
const variants = ensureNonEmpty(weightedVariants.elements
|
|
53
|
-
.map(getName)
|
|
54
|
-
.filter(isNotNullish)
|
|
55
|
-
.toSorted(localeCompare));
|
|
54
|
+
const variants = ensureNonEmpty(weightedVariants.elements.map(getName).filter(isNotNullish).toSorted(localeCompare));
|
|
56
55
|
if (variants === undefined) {
|
|
57
56
|
return undefined;
|
|
58
57
|
}
|
|
@@ -74,10 +73,9 @@ const renderProfessionConstraint = (getChildInstancesForInstanceId, constraint)
|
|
|
74
73
|
? Reader.of(undefined)
|
|
75
74
|
: Reader.sequence([
|
|
76
75
|
renderRarity(constraint.rarity),
|
|
77
|
-
Reader.asks(({ translateMap, getInstanceById
|
|
78
|
-
?.
|
|
79
|
-
]).map(notes => baseName +
|
|
80
|
-
parensIf(ensureNonEmpty(notes.filter(isNotNullish))?.join("; "))));
|
|
76
|
+
Reader.asks(({ translateMap, getInstanceById }) => renderWeighted(constraint.weighted_variants, variantId => translateMap(getInstanceById("ProfessionVariant", variantId)?.translations)
|
|
77
|
+
?.name.default)).thenW(identity),
|
|
78
|
+
]).map(notes => baseName + parensIf(ensureNonEmpty(notes.filter(isNotNullish))?.join("; "))));
|
|
81
79
|
const renderTraditionConstraint = (getChildInstancesForInstanceId, entity, constraint) => Reader.asks(({ translateMap, getInstanceById }) => {
|
|
82
80
|
const translation = translateMap(getInstanceById(entity, constraint.id)?.translations);
|
|
83
81
|
return translation?.nameOfBlessedOnes ?? translation?.name;
|
|
@@ -86,8 +84,7 @@ const renderTraditionConstraint = (getChildInstancesForInstanceId, entity, const
|
|
|
86
84
|
: Reader.sequence([
|
|
87
85
|
renderRarity(constraint.rarity),
|
|
88
86
|
Reader.asks(({ translateMap }) => renderWeighted(constraint.weighted_professions, profId => getProfessionName(translateMap, getChildInstancesForInstanceId, profId))).thenW(identity),
|
|
89
|
-
]).map(notes => baseName +
|
|
90
|
-
parensIf(ensureNonEmpty(notes.filter(isNotNullish))?.join("; "))));
|
|
87
|
+
]).map(notes => baseName + parensIf(ensureNonEmpty(notes.filter(isNotNullish))?.join("; "))));
|
|
91
88
|
const renderCommonProfessions = (getChildInstancesForInstanceId, commonProfessions) => {
|
|
92
89
|
switch (commonProfessions.kind) {
|
|
93
90
|
case "Plain":
|
|
@@ -121,8 +118,7 @@ const renderCommonProfessions = (getChildInstancesForInstanceId, commonProfessio
|
|
|
121
118
|
const renderCommonSkills = (items) => Reader.asks(({ translate, translateMap, getInstanceById, localeCompare }) => items === undefined || !isNotEmpty(items)
|
|
122
119
|
? translate("none")
|
|
123
120
|
: items
|
|
124
|
-
.map(itemId => translateMap(getInstanceById("Skill", itemId)?.translations)
|
|
125
|
-
?.name)
|
|
121
|
+
.map(itemId => translateMap(getInstanceById("Skill", itemId)?.translations)?.name)
|
|
126
122
|
.filter(isNotNullish)
|
|
127
123
|
.toSorted(localeCompare)
|
|
128
124
|
.join(", "));
|
|
@@ -161,7 +157,7 @@ const renderCulturalPackage = (items) => Reader.asks(({ translate, translateMap,
|
|
|
161
157
|
return [MISSING_VALUE, 0];
|
|
162
158
|
}
|
|
163
159
|
return [
|
|
164
|
-
`${instanceTranslation.name
|
|
160
|
+
`${instanceTranslation.name} ${sign(item.points)}`,
|
|
165
161
|
getAdventurePointsForRatingRange(instance.improvement_cost.kind, 0, item.points),
|
|
166
162
|
];
|
|
167
163
|
});
|
|
@@ -201,8 +197,7 @@ export const getCultureEntityDescription = createEntityDescriptionCreator(({ get
|
|
|
201
197
|
.map(lang => {
|
|
202
198
|
const language = getInstanceById("Language", lang.id);
|
|
203
199
|
const languageTranslation = translateMap(language?.translations);
|
|
204
|
-
if (language === undefined ||
|
|
205
|
-
languageTranslation === undefined) {
|
|
200
|
+
if (language === undefined || languageTranslation === undefined) {
|
|
206
201
|
return MISSING_VALUE;
|
|
207
202
|
}
|
|
208
203
|
return (languageTranslation.name +
|
|
@@ -224,8 +219,7 @@ export const getCultureEntityDescription = createEntityDescriptionCreator(({ get
|
|
|
224
219
|
const processedScripts = entry.script.map((scriptId) => {
|
|
225
220
|
const script = getInstanceById("Script", scriptId);
|
|
226
221
|
const scriptTranslation = translateMap(script?.translations);
|
|
227
|
-
if (script === undefined ||
|
|
228
|
-
scriptTranslation === undefined) {
|
|
222
|
+
if (script === undefined || scriptTranslation === undefined) {
|
|
229
223
|
return [MISSING_VALUE, 0];
|
|
230
224
|
}
|
|
231
225
|
return [scriptTranslation.name, script.ap_value ?? 0];
|
|
@@ -234,9 +228,7 @@ export const getCultureEntityDescription = createEntityDescriptionCreator(({ get
|
|
|
234
228
|
return translate("none");
|
|
235
229
|
}
|
|
236
230
|
if (allSame(processedScripts, on(([, apValue]) => apValue, equal))) {
|
|
237
|
-
return (localeJoin(processedScripts
|
|
238
|
-
.map(([name]) => name)
|
|
239
|
-
.toSorted(localeCompare), "disjunction") +
|
|
231
|
+
return (localeJoin(processedScripts.map(([name]) => name).toSorted(localeCompare), "disjunction") +
|
|
240
232
|
parensIf(translate("{$value} AP", {
|
|
241
233
|
value: processedScripts[0][1],
|
|
242
234
|
})));
|
|
@@ -265,7 +257,8 @@ export const getCultureEntityDescription = createEntityDescriptionCreator(({ get
|
|
|
265
257
|
{
|
|
266
258
|
label: translate("Social Status"),
|
|
267
259
|
value: entry.social_status
|
|
268
|
-
.map(status => translateMap(getInstanceById("SocialStatus", status)?.translations)?.name ??
|
|
260
|
+
.map(status => translateMap(getInstanceById("SocialStatus", status)?.translations)?.name ??
|
|
261
|
+
MISSING_VALUE)
|
|
269
262
|
.toSorted(localeCompare)
|
|
270
263
|
.join(", "),
|
|
271
264
|
},
|
|
@@ -295,8 +288,7 @@ export const getCultureEntityDescription = createEntityDescriptionCreator(({ get
|
|
|
295
288
|
type: "labeled",
|
|
296
289
|
label: translate("Cultural Package {$cultureName}", {
|
|
297
290
|
cultureName: translation.name,
|
|
298
|
-
}) +
|
|
299
|
-
parensIf(translate("{$value} AP", { value: culturalPackageApValue })),
|
|
291
|
+
}) + parensIf(translate("{$value} AP", { value: culturalPackageApValue })),
|
|
300
292
|
value: {
|
|
301
293
|
type: "plain",
|
|
302
294
|
text: culturePackageText,
|
|
@@ -19,8 +19,8 @@ const renderElectiveSpellworks = (translate, translateMap, localeCompare, getIns
|
|
|
19
19
|
return name;
|
|
20
20
|
}
|
|
21
21
|
return (name +
|
|
22
|
-
parensIf(translateMap(getInstanceById("Element", item.restriction.Element)
|
|
23
|
-
?.
|
|
22
|
+
parensIf(translateMap(getInstanceById("Element", item.restriction.Element)?.translations)
|
|
23
|
+
?.name ?? MISSING_VALUE));
|
|
24
24
|
}))
|
|
25
25
|
.filter(isNotNullish)
|
|
26
26
|
.toSorted(localeCompare)
|
|
@@ -32,11 +32,9 @@ const renderElectiveSpellworks = (translate, translateMap, localeCompare, getIns
|
|
|
32
32
|
const renderRestrictedSpellworks = (translate, translateMap, localeCompare, localeJoin, getInstanceById, restrictedSpellworks) => {
|
|
33
33
|
const restrictedGroups = Dictionary.groupBy(restrictedSpellworks, restriction => restriction.kind === "Spellwork"
|
|
34
34
|
? "spellwork"
|
|
35
|
-
: restriction.kind === "Property" &&
|
|
36
|
-
restriction.Property.maximum !== undefined
|
|
35
|
+
: restriction.kind === "Property" && restriction.Property.maximum !== undefined
|
|
37
36
|
? "restrictedProperty"
|
|
38
|
-
: restriction.kind === "Property" ||
|
|
39
|
-
restriction.kind === "DemonSummoning"
|
|
37
|
+
: restriction.kind === "Property" || restriction.kind === "DemonSummoning"
|
|
40
38
|
? "property"
|
|
41
39
|
: "other");
|
|
42
40
|
const addExclusion = (excludedSpellworks) => {
|
|
@@ -55,16 +53,16 @@ const renderRestrictedSpellworks = (translate, translateMap, localeCompare, loca
|
|
|
55
53
|
};
|
|
56
54
|
const restrictedProperties = restrictedGroups.get("restrictedProperty")?.map(restriction => translate(".input {$count :number} {{only {$count} additional spellworks with the Property {$property}}}", {
|
|
57
55
|
count: restriction.Property.maximum,
|
|
58
|
-
property: translateMap(getInstanceById("Property", restriction.Property.id)
|
|
59
|
-
?.
|
|
56
|
+
property: translateMap(getInstanceById("Property", restriction.Property.id)?.translations)
|
|
57
|
+
?.name ?? MISSING_VALUE,
|
|
60
58
|
}) + addExclusion(restriction.Property.exclude)) ?? [];
|
|
61
59
|
const propertyGroup = restrictedGroups.get("property");
|
|
62
60
|
const translatedProperties = propertyGroup
|
|
63
61
|
?.map(restriction => {
|
|
64
62
|
switch (restriction.kind) {
|
|
65
63
|
case "Property":
|
|
66
|
-
return translateMap(getInstanceById("Property", restriction.Property.id)
|
|
67
|
-
?.
|
|
64
|
+
return translateMap(getInstanceById("Property", restriction.Property.id)?.translations)
|
|
65
|
+
?.name;
|
|
68
66
|
case "DemonSummoning":
|
|
69
67
|
return translate("Demon Summoning");
|
|
70
68
|
default:
|
|
@@ -82,8 +80,7 @@ const renderRestrictedSpellworks = (translate, translateMap, localeCompare, loca
|
|
|
82
80
|
: [];
|
|
83
81
|
const spellworkGroup = restrictedGroups.get("spellwork");
|
|
84
82
|
const translatedSpellworks = spellworkGroup
|
|
85
|
-
?.map(restriction => translateMap(getInstanceById(restriction.Spellwork)?.translations)
|
|
86
|
-
?.name)
|
|
83
|
+
?.map(restriction => translateMap(getInstanceById(restriction.Spellwork)?.translations)?.name)
|
|
87
84
|
.filter(isNotNullish)
|
|
88
85
|
.toSorted(localeCompare) ?? [];
|
|
89
86
|
const spellworks = translatedSpellworks.length > 0
|
|
@@ -104,29 +101,26 @@ const renderRestrictedSpellworks = (translate, translateMap, localeCompare, loca
|
|
|
104
101
|
return assertExhaustive(restriction);
|
|
105
102
|
}
|
|
106
103
|
}) ?? [];
|
|
107
|
-
return [
|
|
108
|
-
...restrictedProperties,
|
|
109
|
-
...properties,
|
|
110
|
-
...others,
|
|
111
|
-
...spellworks,
|
|
112
|
-
].join("; ");
|
|
104
|
+
return [...restrictedProperties, ...properties, ...others, ...spellworks].join("; ");
|
|
113
105
|
};
|
|
114
|
-
const renderSpellworkAdjustment = (translateMap, getInstanceById, adjustment) => `${translateMap(getInstanceById(adjustment.id)?.translations)?.name ??
|
|
115
|
-
MISSING_VALUE} ${adjustment.points}${parensIf(adjustment.tradition === undefined
|
|
106
|
+
const renderSpellworkAdjustment = (translateMap, getInstanceById, adjustment) => `${translateMap(getInstanceById(adjustment.id)?.translations)?.name ?? MISSING_VALUE} ${adjustment.points.toFixed()}${parensIf(adjustment.tradition === undefined
|
|
116
107
|
? undefined
|
|
117
|
-
: translateMap(getInstanceById("MagicalTradition", adjustment.tradition)
|
|
118
|
-
?.translations)?.name)}`;
|
|
108
|
+
: translateMap(getInstanceById("MagicalTradition", adjustment.tradition)?.translations)?.name)}`;
|
|
119
109
|
const renderAbilityAdjustmentName = (translateMap, getInstanceById, abilityAdjustment) => {
|
|
120
110
|
switch (abilityAdjustment.kind) {
|
|
121
111
|
case "Skill":
|
|
122
|
-
return (translateMap(getInstanceById("Skill", abilityAdjustment.Skill.id)?.translations)?.name ??
|
|
112
|
+
return (translateMap(getInstanceById("Skill", abilityAdjustment.Skill.id)?.translations)?.name ??
|
|
113
|
+
MISSING_VALUE);
|
|
123
114
|
case "CombatTechnique":
|
|
124
|
-
return (translateMap(getInstanceById(abilityAdjustment.CombatTechnique.id)?.translations)?.name ??
|
|
115
|
+
return (translateMap(getInstanceById(abilityAdjustment.CombatTechnique.id)?.translations)?.name ??
|
|
116
|
+
MISSING_VALUE);
|
|
125
117
|
case "Spellwork":
|
|
126
|
-
return ((translateMap(getInstanceById(abilityAdjustment.Spellwork.id)?.translations)?.name ??
|
|
118
|
+
return ((translateMap(getInstanceById(abilityAdjustment.Spellwork.id)?.translations)?.name ??
|
|
119
|
+
MISSING_VALUE) +
|
|
127
120
|
parensIf(abilityAdjustment.Spellwork.tradition === undefined
|
|
128
121
|
? undefined
|
|
129
|
-
: translateMap(getInstanceById("MagicalTradition", abilityAdjustment.Spellwork.tradition)
|
|
122
|
+
: translateMap(getInstanceById("MagicalTradition", abilityAdjustment.Spellwork.tradition)
|
|
123
|
+
?.translations)?.name));
|
|
130
124
|
default:
|
|
131
125
|
return assertExhaustive(abilityAdjustment);
|
|
132
126
|
}
|
|
@@ -134,7 +128,8 @@ const renderAbilityAdjustmentName = (translateMap, getInstanceById, abilityAdjus
|
|
|
134
128
|
const renderAbilityAdjustmentBaseValue = (baseProfessionPackage, abilityAdjustment) => {
|
|
135
129
|
switch (abilityAdjustment.kind) {
|
|
136
130
|
case "Skill":
|
|
137
|
-
return baseProfessionPackage.skills?.find(skill => skill.id === abilityAdjustment.Skill.id)
|
|
131
|
+
return baseProfessionPackage.skills?.find(skill => skill.id === abilityAdjustment.Skill.id)
|
|
132
|
+
?.rating_modifier;
|
|
138
133
|
case "CombatTechnique":
|
|
139
134
|
return baseProfessionPackage.combat_techniques?.find(skill => deepEqual(skill.id, abilityAdjustment.CombatTechnique.id))?.rating_modifier;
|
|
140
135
|
case "Spellwork":
|
|
@@ -171,16 +166,17 @@ const renderAbilityAdjustmentDefaultValue = (abilityAdjustment) => {
|
|
|
171
166
|
const renderAbilityAdjustment = (translate, translateMap, getInstanceById, baseProfessionPackage) => baseProfessionPackage === undefined
|
|
172
167
|
? abilityAdjustment => `${renderAbilityAdjustmentName(translateMap, getInstanceById, abilityAdjustment)} ${sign(renderAbilityAdjustmentModifierValue(abilityAdjustment))}`
|
|
173
168
|
: abilityAdjustment => {
|
|
174
|
-
const basePoints = (renderAbilityAdjustmentBaseValue(baseProfessionPackage, abilityAdjustment) ?? 0) +
|
|
169
|
+
const basePoints = (renderAbilityAdjustmentBaseValue(baseProfessionPackage, abilityAdjustment) ?? 0) +
|
|
170
|
+
renderAbilityAdjustmentDefaultValue(abilityAdjustment);
|
|
175
171
|
return translate("{$replacement} instead of {$base}", {
|
|
176
172
|
base: basePoints,
|
|
177
|
-
replacement: `${renderAbilityAdjustmentName(translateMap, getInstanceById, abilityAdjustment)} ${basePoints + renderAbilityAdjustmentModifierValue(abilityAdjustment)}`,
|
|
173
|
+
replacement: `${renderAbilityAdjustmentName(translateMap, getInstanceById, abilityAdjustment)} ${(basePoints + renderAbilityAdjustmentModifierValue(abilityAdjustment)).toFixed()}`,
|
|
178
174
|
});
|
|
179
175
|
};
|
|
180
176
|
const renderAbilityAdjustments = (translate, translateMap, localeCompare, getInstanceById, baseProfessionPackage, list) => list
|
|
181
|
-
|
|
177
|
+
.map(renderAbilityAdjustment(translate, translateMap, getInstanceById, baseProfessionPackage))
|
|
182
178
|
.toSorted(localeCompare)
|
|
183
|
-
.join(", ")
|
|
179
|
+
.join(", ");
|
|
184
180
|
/**
|
|
185
181
|
* Get a JSON representation of the rules text for a curriculum.
|
|
186
182
|
*/
|
|
@@ -199,7 +195,8 @@ export const getCurriculumEntityDescription = createEntityDescriptionCreator(({
|
|
|
199
195
|
items: [
|
|
200
196
|
{
|
|
201
197
|
label: translate("Guideline"),
|
|
202
|
-
value: translateMap(getInstanceById("Guideline", entry.guideline)?.translations)?.name ??
|
|
198
|
+
value: translateMap(getInstanceById("Guideline", entry.guideline)?.translations)?.name ??
|
|
199
|
+
MISSING_VALUE,
|
|
203
200
|
},
|
|
204
201
|
{
|
|
205
202
|
label: translate("Elective Spellworks Package"),
|
|
@@ -237,7 +234,7 @@ export const getCurriculumEntityDescription = createEntityDescriptionCreator(({
|
|
|
237
234
|
items: [
|
|
238
235
|
{
|
|
239
236
|
label: translate("Spellwork Changes"),
|
|
240
|
-
value: lessonPackageTranslation
|
|
237
|
+
value: lessonPackageTranslation.spellwork_changes ??
|
|
241
238
|
lessonPackage.content.spellwork_changes
|
|
242
239
|
?.map(change => translate("{$replacement} instead of {$base}", {
|
|
243
240
|
base: renderSpellworkAdjustment(translateMap, getInstanceById, change.base),
|
|
@@ -34,7 +34,7 @@ const getRaceBaseValue = (translate, translateMap, getInstanceById, idMap, raceB
|
|
|
34
34
|
const renderBaseCalculation = (getInstanceById, translate, translateMap, idMap, calculation, style = "full") => renderMathOperation(calculation, value => {
|
|
35
35
|
switch (value.kind) {
|
|
36
36
|
case "Constant":
|
|
37
|
-
return value.Constant.
|
|
37
|
+
return value.Constant.toFixed();
|
|
38
38
|
case "Attribute":
|
|
39
39
|
return getAttribute(getInstanceById, translateMap, value.Attribute, style);
|
|
40
40
|
case "RaceBaseValue":
|
package/lib/entities/disease.js
CHANGED
|
@@ -2,7 +2,7 @@ import { ensureNonEmpty } from "@elyukai/utils/array/nonEmpty";
|
|
|
2
2
|
import { isNotNullish } from "@elyukai/utils/nullable";
|
|
3
3
|
import { createEntityDescriptionCreator } from "../creator.js";
|
|
4
4
|
import { renderAnimalTypesSection } from "./partial/animalTypes.js";
|
|
5
|
-
import { renderAlternativeNames, renderChance, renderResistance
|
|
5
|
+
import { renderAlternativeNames, renderChance, renderResistance } from "./partial/herbary.js";
|
|
6
6
|
import { parensIf } from "./partial/rated/activatable/parensIf.js";
|
|
7
7
|
import { MISSING_VALUE } from "./partial/unknown.js";
|
|
8
8
|
const renderCauses = (translate, translateMap, causes) => causes
|
|
@@ -12,10 +12,7 @@ const renderCauses = (translate, translateMap, causes) => causes
|
|
|
12
12
|
return MISSING_VALUE;
|
|
13
13
|
}
|
|
14
14
|
return (causeTranslation.name +
|
|
15
|
-
parensIf(ensureNonEmpty([
|
|
16
|
-
renderChance(translate, translateMap, cause, true),
|
|
17
|
-
causeTranslation.note,
|
|
18
|
-
].filter(isNotNullish))?.join("; ")));
|
|
15
|
+
parensIf(ensureNonEmpty([renderChance(translate, translateMap, cause, true), causeTranslation.note].filter(isNotNullish))?.join("; ")));
|
|
19
16
|
})
|
|
20
17
|
.join(", ");
|
|
21
18
|
/**
|
|
@@ -35,7 +32,7 @@ export const getDiseaseEntityDescription = createEntityDescriptionCreator(({ get
|
|
|
35
32
|
type: "definitionList",
|
|
36
33
|
items: [
|
|
37
34
|
renderAlternativeNames(translate, translation.alternative_names),
|
|
38
|
-
{ label: translate("Level"), value: baseEntry.level.
|
|
35
|
+
{ label: translate("Level"), value: baseEntry.level.toFixed() },
|
|
39
36
|
{ label: translate("Progress"), value: translation.progress },
|
|
40
37
|
{
|
|
41
38
|
label: translate("Resistance"),
|