@optolith/entity-descriptions 0.0.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.
Files changed (62) hide show
  1. package/.prettierrc.yml +1 -0
  2. package/AUTHORS +1 -0
  3. package/CHANGELOG.md +5 -0
  4. package/LICENSE +373 -0
  5. package/README.md +1 -0
  6. package/lib/entities/combatTechnique.d.ts +15 -0
  7. package/lib/entities/combatTechnique.js +59 -0
  8. package/lib/entities/experienceLevel.d.ts +5 -0
  9. package/lib/entities/experienceLevel.js +44 -0
  10. package/lib/entities/liturgicalChant.d.ts +35 -0
  11. package/lib/entities/liturgicalChant.js +244 -0
  12. package/lib/entities/partial/rated/activatable/castingTime.d.ts +25 -0
  13. package/lib/entities/partial/rated/activatable/castingTime.js +50 -0
  14. package/lib/entities/partial/rated/activatable/checkResultBased.d.ts +7 -0
  15. package/lib/entities/partial/rated/activatable/checkResultBased.js +28 -0
  16. package/lib/entities/partial/rated/activatable/cost.d.ts +30 -0
  17. package/lib/entities/partial/rated/activatable/cost.js +166 -0
  18. package/lib/entities/partial/rated/activatable/duration.d.ts +40 -0
  19. package/lib/entities/partial/rated/activatable/duration.js +100 -0
  20. package/lib/entities/partial/rated/activatable/effect.d.ts +7 -0
  21. package/lib/entities/partial/rated/activatable/effect.js +37 -0
  22. package/lib/entities/partial/rated/activatable/entity.d.ts +11 -0
  23. package/lib/entities/partial/rated/activatable/entity.js +12 -0
  24. package/lib/entities/partial/rated/activatable/index.d.ts +69 -0
  25. package/lib/entities/partial/rated/activatable/index.js +59 -0
  26. package/lib/entities/partial/rated/activatable/isMaximum.d.ts +6 -0
  27. package/lib/entities/partial/rated/activatable/isMaximum.js +10 -0
  28. package/lib/entities/partial/rated/activatable/modifiableParameter.d.ts +8 -0
  29. package/lib/entities/partial/rated/activatable/modifiableParameter.js +9 -0
  30. package/lib/entities/partial/rated/activatable/nonModifiable.d.ts +9 -0
  31. package/lib/entities/partial/rated/activatable/nonModifiable.js +75 -0
  32. package/lib/entities/partial/rated/activatable/parensIf.d.ts +10 -0
  33. package/lib/entities/partial/rated/activatable/parensIf.js +10 -0
  34. package/lib/entities/partial/rated/activatable/range.d.ts +36 -0
  35. package/lib/entities/partial/rated/activatable/range.js +122 -0
  36. package/lib/entities/partial/rated/activatable/speed.d.ts +12 -0
  37. package/lib/entities/partial/rated/activatable/speed.js +22 -0
  38. package/lib/entities/partial/rated/activatable/targetCategory.d.ts +12 -0
  39. package/lib/entities/partial/rated/activatable/targetCategory.js +36 -0
  40. package/lib/entities/partial/rated/activatable/units.d.ts +13 -0
  41. package/lib/entities/partial/rated/activatable/units.js +53 -0
  42. package/lib/entities/partial/rated/improvementCost.d.ts +7 -0
  43. package/lib/entities/partial/rated/improvementCost.js +7 -0
  44. package/lib/entities/partial/rated/skillCheck.d.ts +19 -0
  45. package/lib/entities/partial/rated/skillCheck.js +58 -0
  46. package/lib/entities/partial/responsiveText.d.ts +31 -0
  47. package/lib/entities/partial/responsiveText.js +49 -0
  48. package/lib/entities/partial/unknown.d.ts +4 -0
  49. package/lib/entities/partial/unknown.js +4 -0
  50. package/lib/entities/skill.d.ts +13 -0
  51. package/lib/entities/skill.js +109 -0
  52. package/lib/entities/spell.d.ts +38 -0
  53. package/lib/entities/spell.js +274 -0
  54. package/lib/helpers/getTypes.d.ts +482 -0
  55. package/lib/helpers/getTypes.js +1 -0
  56. package/lib/helpers/translate.d.ts +14 -0
  57. package/lib/helpers/translate.js +8 -0
  58. package/lib/index.d.ts +1 -0
  59. package/lib/index.js +1 -0
  60. package/lib/libraryEntry.d.ts +52 -0
  61. package/lib/libraryEntry.js +17 -0
  62. package/package.json +34 -0
@@ -0,0 +1,244 @@
1
+ import { isNotNullish } from "@optolith/helpers/nullable";
2
+ import { assertExhaustive } from "@optolith/helpers/typeSafety";
3
+ import { createLibraryEntryCreator, } from "../libraryEntry.js";
4
+ import { getTextForBlessingDuration } from "./partial/rated/activatable/duration.js";
5
+ import { getTextForEffect } from "./partial/rated/activatable/effect.js";
6
+ import { Entity } from "./partial/rated/activatable/entity.js";
7
+ import { getTextForFastOneTimePerformanceParameters, getTextForFastSustainedPerformanceParameters, getTextForSlowOneTimePerformanceParameters, getTextForSlowSustainedPerformanceParameters, } from "./partial/rated/activatable/index.js";
8
+ import { getTextForBlessingRange } from "./partial/rated/activatable/range.js";
9
+ import { getTextForTargetCategory } from "./partial/rated/activatable/targetCategory.js";
10
+ import { createImprovementCost } from "./partial/rated/improvementCost.js";
11
+ import { getTextForCheck } from "./partial/rated/skillCheck.js";
12
+ import { ResponsiveTextSize } from "./partial/responsiveText.js";
13
+ const getTextForTraditions = (deps, values) => {
14
+ const getAspectName = (ref) => deps.translateMap(deps.getAspectById(ref.id.aspect)?.translations)?.name;
15
+ const text = values
16
+ .map((trad) => {
17
+ switch (trad.tag) {
18
+ case "GeneralAspect":
19
+ return getAspectName(trad.general_aspect);
20
+ case "Tradition": {
21
+ const traditionTranslation = deps.translateMap(deps.getBlessedTraditionById(trad.tradition.tradition.id.blessed_tradition)?.translations);
22
+ const name = traditionTranslation?.name_compressed ?? traditionTranslation?.name;
23
+ if (name === undefined) {
24
+ return undefined;
25
+ }
26
+ const aspects = trad.tradition.aspects
27
+ ?.map(getAspectName)
28
+ .filter(isNotNullish)
29
+ .sort(deps.localeCompare) ?? [];
30
+ if (aspects.length === 0) {
31
+ return name;
32
+ }
33
+ return `${name} (${aspects.join(" and ")})`;
34
+ }
35
+ default:
36
+ return assertExhaustive(trad);
37
+ }
38
+ })
39
+ .filter(isNotNullish)
40
+ .join(", ");
41
+ return {
42
+ label: deps.translate("Traditions"),
43
+ value: text,
44
+ };
45
+ };
46
+ /**
47
+ * Get a JSON representation of the rules text for a blessing.
48
+ */
49
+ export const getBlessingLibraryEntry = createLibraryEntryCreator((entry, { getTargetCategoryById }) => ({ translate, translateMap }) => {
50
+ const translation = translateMap(entry.translations);
51
+ if (translation === undefined) {
52
+ return undefined;
53
+ }
54
+ const range = getTextForBlessingRange({ translate }, entry.parameters.range, {
55
+ responsiveText: ResponsiveTextSize.Full,
56
+ });
57
+ const duration = getTextForBlessingDuration({ translate, translateMap }, entry.parameters.duration, {
58
+ responsiveText: ResponsiveTextSize.Full,
59
+ });
60
+ return {
61
+ title: translation.name,
62
+ className: "blessing",
63
+ content: [
64
+ {
65
+ label: translate("Effect"),
66
+ value: translation.effect,
67
+ },
68
+ {
69
+ label: translate("Range"),
70
+ value: range !== translation.range
71
+ ? `***${range}*** (${translation.range})`
72
+ : range,
73
+ },
74
+ {
75
+ label: translate("Duration"),
76
+ value: duration !== translation.duration
77
+ ? `***${duration}*** (${translation.duration})`
78
+ : duration,
79
+ },
80
+ getTextForTargetCategory({ translate, translateMap, getTargetCategoryById }, entry.target),
81
+ ],
82
+ src: entry.src,
83
+ };
84
+ });
85
+ /**
86
+ * Get a JSON representation of the rules text for a liturgical chant.
87
+ */
88
+ export const getLiturgicalChantLibraryEntry = createLibraryEntryCreator((entry, { getAttributeById, getSpirit, getToughness, getSkillModificationLevelById, getTargetCategoryById, getBlessedTraditionById, getAspectById, }) => ({ translate, translateMap, localeCompare }) => {
89
+ const translation = translateMap(entry.translations);
90
+ if (translation === undefined) {
91
+ return undefined;
92
+ }
93
+ const { castingTime, cost, range, duration } = (() => {
94
+ switch (entry.parameters.tag) {
95
+ case "OneTime":
96
+ return getTextForFastOneTimePerformanceParameters({
97
+ getSkillModificationLevelById,
98
+ translate,
99
+ translateMap,
100
+ }, entry.parameters.one_time, {
101
+ entity: Entity.LiturgicalChant,
102
+ responsiveText: ResponsiveTextSize.Full,
103
+ });
104
+ case "Sustained":
105
+ return getTextForFastSustainedPerformanceParameters({
106
+ getSkillModificationLevelById,
107
+ translate,
108
+ translateMap,
109
+ }, entry.parameters.sustained, {
110
+ entity: Entity.LiturgicalChant,
111
+ responsiveText: ResponsiveTextSize.Full,
112
+ });
113
+ default:
114
+ return assertExhaustive(entry.parameters);
115
+ }
116
+ })();
117
+ return {
118
+ title: translation.name,
119
+ className: "liturgical-chant",
120
+ content: [
121
+ getTextForCheck({ translate, translateMap, getAttributeById }, entry.check, {
122
+ value: entry.check_penalty,
123
+ responsiveText: ResponsiveTextSize.Full,
124
+ getSpirit,
125
+ getToughness,
126
+ }),
127
+ ...getTextForEffect(translation.effect, translate),
128
+ {
129
+ label: translate("Liturgical Time"),
130
+ value: castingTime !== translation.casting_time.full
131
+ ? `***${castingTime}*** (${translation.casting_time.full})`
132
+ : castingTime,
133
+ },
134
+ {
135
+ label: translate("KP Cost"),
136
+ value: cost !== translation.cost.full
137
+ ? `***${cost}*** (${translation.cost.full})`
138
+ : cost,
139
+ },
140
+ {
141
+ label: translate("Range"),
142
+ value: range !== translation.range.full
143
+ ? `***${range}*** (${translation.range.full})`
144
+ : range,
145
+ },
146
+ {
147
+ label: translate("Duration"),
148
+ value: duration !== translation.duration.full
149
+ ? `***${duration}*** (${translation.duration.full})`
150
+ : duration,
151
+ },
152
+ getTextForTargetCategory({ translate, translateMap, getTargetCategoryById }, entry.target),
153
+ getTextForTraditions({
154
+ translate,
155
+ translateMap,
156
+ localeCompare,
157
+ getBlessedTraditionById,
158
+ getAspectById,
159
+ }, entry.traditions),
160
+ createImprovementCost(translate, entry.improvement_cost),
161
+ ],
162
+ src: entry.src,
163
+ };
164
+ });
165
+ /**
166
+ * Get a JSON representation of the rules text for a ceremony.
167
+ */
168
+ export const getCeremonyLibraryEntry = createLibraryEntryCreator((entry, { getAttributeById, getSpirit, getToughness, getSkillModificationLevelById, getTargetCategoryById, getBlessedTraditionById, getAspectById, }) => ({ translate, translateMap, localeCompare }) => {
169
+ const translation = translateMap(entry.translations);
170
+ if (translation === undefined) {
171
+ return undefined;
172
+ }
173
+ const { castingTime, cost, range, duration } = (() => {
174
+ switch (entry.parameters.tag) {
175
+ case "OneTime":
176
+ return getTextForSlowOneTimePerformanceParameters({
177
+ getSkillModificationLevelById,
178
+ translate,
179
+ translateMap,
180
+ }, entry.parameters.one_time, {
181
+ entity: Entity.Ceremony,
182
+ responsiveText: ResponsiveTextSize.Full,
183
+ });
184
+ case "Sustained":
185
+ return getTextForSlowSustainedPerformanceParameters({
186
+ getSkillModificationLevelById,
187
+ translate,
188
+ translateMap,
189
+ }, entry.parameters.sustained, {
190
+ entity: Entity.Ceremony,
191
+ responsiveText: ResponsiveTextSize.Full,
192
+ });
193
+ default:
194
+ return assertExhaustive(entry.parameters);
195
+ }
196
+ })();
197
+ return {
198
+ title: translation.name,
199
+ className: "ceremony",
200
+ content: [
201
+ getTextForCheck({ translate, translateMap, getAttributeById }, entry.check, {
202
+ value: entry.check_penalty,
203
+ responsiveText: ResponsiveTextSize.Full,
204
+ getSpirit,
205
+ getToughness,
206
+ }),
207
+ ...getTextForEffect(translation.effect, translate),
208
+ {
209
+ label: translate("Ceremonial Time"),
210
+ value: castingTime !== translation.casting_time.full
211
+ ? `***${castingTime}*** (${translation.casting_time.full})`
212
+ : castingTime,
213
+ },
214
+ {
215
+ label: translate("KP Cost"),
216
+ value: cost !== translation.cost.full
217
+ ? `***${cost}*** (${translation.cost.full})`
218
+ : cost,
219
+ },
220
+ {
221
+ label: translate("Range"),
222
+ value: range !== translation.range.full
223
+ ? `***${range}*** (${translation.range.full})`
224
+ : range,
225
+ },
226
+ {
227
+ label: translate("Duration"),
228
+ value: duration !== translation.duration.full
229
+ ? `***${duration}*** (${translation.duration.full})`
230
+ : duration,
231
+ },
232
+ getTextForTargetCategory({ translate, translateMap, getTargetCategoryById }, entry.target),
233
+ getTextForTraditions({
234
+ translate,
235
+ translateMap,
236
+ localeCompare,
237
+ getBlessedTraditionById,
238
+ getAspectById,
239
+ }, entry.traditions),
240
+ createImprovementCost(translate, entry.improvement_cost),
241
+ ],
242
+ src: entry.src,
243
+ };
244
+ });
@@ -0,0 +1,25 @@
1
+ import { FastCastingTime, SlowCastingTime } from "optolith-database-schema/types/_ActivatableSkillCastingTime";
2
+ import { GetById } from "../../../../helpers/getTypes.js";
3
+ import { Translate } from "../../../../helpers/translate.js";
4
+ import { ResponsiveTextSize } from "../../responsiveText.js";
5
+ import { Entity } from "./entity.js";
6
+ /**
7
+ * Get the text for the casting time of a fast activatable skill.
8
+ */
9
+ export declare const getTextForFastCastingTime: (deps: {
10
+ getSkillModificationLevelById: GetById.Static.SkillModificationLevel;
11
+ translate: Translate;
12
+ }, value: FastCastingTime, env: {
13
+ entity: Entity;
14
+ responsiveText: ResponsiveTextSize;
15
+ }) => string;
16
+ /**
17
+ * Get the text for the casting time of a slow activatable skill.
18
+ */
19
+ export declare const getTextForSlowCastingTime: (deps: {
20
+ getSkillModificationLevelById: GetById.Static.SkillModificationLevel;
21
+ translate: Translate;
22
+ }, value: SlowCastingTime, env: {
23
+ entity: Entity;
24
+ responsiveText: ResponsiveTextSize;
25
+ }) => string;
@@ -0,0 +1,50 @@
1
+ import { isNotNullish, mapNullable } from "@optolith/helpers/nullable";
2
+ import { assertExhaustive } from "@optolith/helpers/typeSafety";
3
+ import { MISSING_VALUE } from "../../unknown.js";
4
+ import { ModifiableParameter } from "./modifiableParameter.js";
5
+ import { getTextForNonModifiableSuffix } from "./nonModifiable.js";
6
+ import { Speed } from "./speed.js";
7
+ import { formatTimeSpan } from "./units.js";
8
+ const getTextForModifiableCastingTime = (deps, value, env) => mapNullable(deps.getSkillModificationLevelById(value.initial_modification_level), ({ fast: { casting_time: fastTime }, slow: { casting_time: slowTime }, }) => {
9
+ switch (env.speed) {
10
+ case Speed.Fast:
11
+ return formatTimeSpan(deps.translate, env.responsiveText, "Actions", fastTime);
12
+ case Speed.Slow:
13
+ return formatTimeSpan(deps.translate, env.responsiveText, slowTime.unit, slowTime.value);
14
+ default:
15
+ return assertExhaustive(env.speed);
16
+ }
17
+ }) ?? MISSING_VALUE;
18
+ const getTextForFastSkillNonModifiableCastingTime = (deps, value, env) => formatTimeSpan(deps.translate, env.responsiveText, "Actions", value.actions) +
19
+ getTextForNonModifiableSuffix(deps.translate, env.entity, ModifiableParameter.CastingTime, env.responsiveText);
20
+ const getTextForSlowSkillNonModifiableCastingTime = (deps, value, env) => formatTimeSpan(deps.translate, env.responsiveText, value.unit, value.value) +
21
+ getTextForNonModifiableSuffix(deps.translate, env.entity, ModifiableParameter.CastingTime, env.responsiveText);
22
+ const getTextForCastingTime = (deps, value, env, getTextForNonModifiableCastingTime) => {
23
+ switch (value.tag) {
24
+ case "Modifiable":
25
+ return getTextForModifiableCastingTime(deps, value.modifiable, env);
26
+ case "NonModifiable":
27
+ return getTextForNonModifiableCastingTime(value.non_modifiable);
28
+ default:
29
+ return assertExhaustive(value);
30
+ }
31
+ };
32
+ const getTextForCastingTimeDuringLovemaking = (deps, value, env) => formatTimeSpan(deps.translate, env.responsiveText, value.unit, value.value);
33
+ /**
34
+ * Get the text for the casting time of a fast activatable skill.
35
+ */
36
+ export const getTextForFastCastingTime = (deps, value, env) => [
37
+ mapNullable(value.default, (def) => getTextForCastingTime(deps, def, { ...env, speed: Speed.Fast }, (nonModifiableValue) => getTextForFastSkillNonModifiableCastingTime(deps, nonModifiableValue, env))),
38
+ mapNullable(value.during_lovemaking, (duringLovemaking) => getTextForCastingTimeDuringLovemaking(deps, duringLovemaking, env)),
39
+ ]
40
+ .filter(isNotNullish)
41
+ .join(" / ");
42
+ /**
43
+ * Get the text for the casting time of a slow activatable skill.
44
+ */
45
+ export const getTextForSlowCastingTime = (deps, value, env) => [
46
+ mapNullable(value.default, (def) => getTextForCastingTime(deps, def, { ...env, speed: Speed.Slow }, (nonModifiableValue) => getTextForSlowSkillNonModifiableCastingTime(deps, nonModifiableValue, env))),
47
+ mapNullable(value.during_lovemaking, (duringLovemaking) => getTextForCastingTimeDuringLovemaking(deps, duringLovemaking, env)),
48
+ ]
49
+ .filter(isNotNullish)
50
+ .join(" / ");
@@ -0,0 +1,7 @@
1
+ import { CheckResultBased } from "optolith-database-schema/types/_ActivatableSkillCheckResultBased";
2
+ import { Translate } from "../../../../helpers/translate.js";
3
+ /**
4
+ * Returns the value text for a check-result-based parameter of an activatable
5
+ * skill.
6
+ */
7
+ export declare const getTextForCheckResultBased: (value: CheckResultBased, translate: Translate) => string;
@@ -0,0 +1,28 @@
1
+ import { mapNullableDefault } from "@optolith/helpers/nullable";
2
+ import { assertExhaustive } from "@optolith/helpers/typeSafety";
3
+ const getCheckResultBaseValue = (baseValue, translate) => {
4
+ switch (baseValue) {
5
+ case "QualityLevels":
6
+ return translate("QL");
7
+ case "SkillPoints":
8
+ return translate("SP");
9
+ default:
10
+ return assertExhaustive(baseValue);
11
+ }
12
+ };
13
+ const getArithmeticSymbol = (arithmetic) => {
14
+ switch (arithmetic) {
15
+ case "Divide":
16
+ return ` / `;
17
+ case "Multiply":
18
+ return ` × `;
19
+ default:
20
+ return assertExhaustive(arithmetic);
21
+ }
22
+ };
23
+ /**
24
+ * Returns the value text for a check-result-based parameter of an activatable
25
+ * skill.
26
+ */
27
+ export const getTextForCheckResultBased = (value, translate) => getCheckResultBaseValue(value.base, translate) +
28
+ mapNullableDefault(value.modifier, (modifier) => getArithmeticSymbol(modifier.arithmetic) + modifier.value, "");
@@ -0,0 +1,30 @@
1
+ import { OneTimeCost, SustainedCost } from "optolith-database-schema/types/_ActivatableSkillCost";
2
+ import { GetById } from "../../../../helpers/getTypes.js";
3
+ import { Translate, TranslateMap } from "../../../../helpers/translate.js";
4
+ import { ResponsiveTextSize } from "../../responsiveText.js";
5
+ import { Entity } from "./entity.js";
6
+ import { Speed } from "./speed.js";
7
+ /**
8
+ * Returns the text for the cost of a one-time activatable skill.
9
+ */
10
+ export declare const getTextForOneTimeCost: (deps: {
11
+ getSkillModificationLevelById: GetById.Static.SkillModificationLevel;
12
+ translate: Translate;
13
+ translateMap: TranslateMap;
14
+ }, value: OneTimeCost, env: {
15
+ speed: Speed;
16
+ responsiveText: ResponsiveTextSize;
17
+ entity: Entity;
18
+ }) => string;
19
+ /**
20
+ * Returns the text for the cost of a sustained activatable skill.
21
+ */
22
+ export declare const getTextForSustainedCost: (deps: {
23
+ getSkillModificationLevelById: GetById.Static.SkillModificationLevel;
24
+ translate: Translate;
25
+ translateMap: TranslateMap;
26
+ }, value: SustainedCost, env: {
27
+ speed: Speed;
28
+ responsiveText: ResponsiveTextSize;
29
+ entity: Entity;
30
+ }) => string;
@@ -0,0 +1,166 @@
1
+ import { mapNullable, mapNullableDefault } from "@optolith/helpers/nullable";
2
+ import { assertExhaustive } from "@optolith/helpers/typeSafety";
3
+ import { getResponsiveText, getResponsiveTextOptional, replaceTextIfRequested, responsive, } from "../../responsiveText.js";
4
+ import { MISSING_VALUE } from "../../unknown.js";
5
+ import { ModifiableParameter } from "./modifiableParameter.js";
6
+ import { getTextForNonModifiableSuffix } from "./nonModifiable.js";
7
+ import { getModifiableBySpeed, Speed } from "./speed.js";
8
+ import { formatCost, formatTimeSpan } from "./units.js";
9
+ const getTextForModifiableOneTimeCost = (deps, value, env) => mapNullable(deps.getSkillModificationLevelById(value.initial_modification_level), (modificationLevel) => {
10
+ const cost = getModifiableBySpeed(modificationLevel, env.speed, (config) => config.cost, (config) => config.cost);
11
+ return replaceTextIfRequested(value.translations, formatCost(deps.translate, env.entity, cost), deps.translateMap, env.responsiveText);
12
+ }) ?? MISSING_VALUE;
13
+ const getMinimumText = (isMinimum, translate, responsiveText) => isMinimum !== true
14
+ ? ""
15
+ : responsive(responsiveText, () => translate("at least "), () => translate("min. "));
16
+ const getTextForNonModifiableOneTimeCostPerCountable = (deps, value, env) => mapNullable(value, (perCountable) => {
17
+ const countableText = responsive(env.responsiveText, (entity) => deps.translate(" per {0}", entity), (entity) => deps.translate("/{0}", entity), getResponsiveText(deps.translateMap(perCountable.translations)?.countable, env.responsiveText));
18
+ const minimumTotalText = mapNullable(perCountable.minimum_total, (minimumTotal) => deps.translate(", minimum of {0}", deps.formatCost(minimumTotal))) ?? "";
19
+ return countableText + minimumTotalText;
20
+ }) ?? "";
21
+ const getTextForPermanentValue = (value, responsiveText, translate) => value === undefined
22
+ ? ""
23
+ : responsive(responsiveText, (perm) => translate(", {0} of which are permanent", perm), (perm) => translate(" ({0} perm.)", perm), value);
24
+ const getTextForNonModifiableOneTimeCost = (deps, value, env) => {
25
+ const isMinimum = getMinimumText(value.is_minimum, deps.translate, env.responsiveText);
26
+ const formatCostP = formatCost.bind(this, deps.translate, env.entity);
27
+ const per = getTextForNonModifiableOneTimeCostPerCountable({ ...deps, formatCost: formatCostP }, value.per, env);
28
+ const permanent = getTextForPermanentValue(value.permanent_value, env.responsiveText, deps.translate);
29
+ const translation = deps.translateMap(value.translations);
30
+ const note = mapNullableDefault(translation === undefined || translation.note === undefined
31
+ ? undefined
32
+ : getResponsiveTextOptional(translation.note, env.responsiveText), (noteIfPresent) => ` (${noteIfPresent})`, "");
33
+ const cannotModify = getTextForNonModifiableSuffix(deps.translate, env.entity, ModifiableParameter.Cost, env.responsiveText);
34
+ return (isMinimum + formatCostP(value.value) + per + permanent + note + cannotModify);
35
+ };
36
+ const getTextForIndefiniteOneTimeCost = (deps, value, env) => (getResponsiveText(deps.translateMap(value.translations)?.description, env.responsiveText) ?? "") +
37
+ getTextForNonModifiableSuffix(deps.translate, env.entity, ModifiableParameter.Cost, env.responsiveText);
38
+ const getTextForSingleOneTimeCost = (deps, value, env) => {
39
+ switch (value.tag) {
40
+ case "Modifiable":
41
+ return getTextForModifiableOneTimeCost(deps, value.modifiable, env);
42
+ case "NonModifiable":
43
+ return getTextForNonModifiableOneTimeCost(deps, value.non_modifiable, env);
44
+ case "Indefinite":
45
+ return getTextForIndefiniteOneTimeCost(deps, value.indefinite, env);
46
+ default:
47
+ return assertExhaustive(value);
48
+ }
49
+ };
50
+ const getTextForMultipleOneTimeCosts = (deps, value, type, env) => {
51
+ const modifiable = !value.every((part) => part.tag === "Modifiable")
52
+ ? getTextForNonModifiableSuffix(deps.translate, env.entity, ModifiableParameter.Cost, env.responsiveText)
53
+ : "";
54
+ return (value
55
+ .map((part) => getTextForSingleOneTimeCost(deps, part, env))
56
+ .join((() => {
57
+ switch (type) {
58
+ case "conjunction":
59
+ return responsive(env.responsiveText, () => deps.translate(" and "), () => deps.translate(" + "));
60
+ case "disjunction":
61
+ return responsive(env.responsiveText, () => deps.translate(" or "), () => deps.translate(" / "));
62
+ default:
63
+ return assertExhaustive(type);
64
+ }
65
+ })()) + modifiable);
66
+ };
67
+ const getTextForCostMap = (deps, value, env) => {
68
+ const translation = deps.translateMap(value.translations);
69
+ if (value.translations !== undefined && translation === undefined) {
70
+ return MISSING_VALUE;
71
+ }
72
+ if (translation?.replacement !== undefined) {
73
+ return translation.replacement;
74
+ }
75
+ const costs = value.options.map((option) => option.value).join("/");
76
+ const labels = value.options
77
+ .map((option) => deps.translateMap(option.translations)?.label ?? MISSING_VALUE)
78
+ .join("/");
79
+ const permanentCosts = value.options.every((option) => option.permanent_value !== undefined)
80
+ ? value.options.map((option) => option.permanent_value).join("/")
81
+ : undefined;
82
+ const formatCostP = formatCost.bind(this, deps.translate, env.entity);
83
+ const notModifiable = getTextForNonModifiableSuffix(deps.translate, env.entity, ModifiableParameter.Cost, env.responsiveText);
84
+ return (formatCostP(costs) +
85
+ deps.translate(" for ") +
86
+ mapNullableDefault(translation?.list_prepend, (listPrepend) => `${listPrepend} `, "") +
87
+ labels +
88
+ (translation?.list_append ?? "") +
89
+ (permanentCosts !== undefined
90
+ ? deps.translate(", {0} of which are permanent", formatCostP(permanentCosts))
91
+ : "") +
92
+ notModifiable);
93
+ };
94
+ /**
95
+ * Returns the text for the cost of a one-time activatable skill.
96
+ */
97
+ export const getTextForOneTimeCost = (deps, value, env) => {
98
+ switch (value.tag) {
99
+ case "Single":
100
+ return getTextForSingleOneTimeCost(deps, value.single, env);
101
+ case "Conjunction":
102
+ return getTextForMultipleOneTimeCosts(deps, value.conjunction, "conjunction", env);
103
+ case "Disjunction":
104
+ return getTextForMultipleOneTimeCosts(deps, value.disjunction, "disjunction", env);
105
+ case "Map":
106
+ return getTextForCostMap(deps, value.map, env);
107
+ default:
108
+ return assertExhaustive(value);
109
+ }
110
+ };
111
+ /**
112
+ * Returns the text for the cost of a sustained activatable skill.
113
+ */
114
+ export const getTextForSustainedCost = (deps, value, env) => {
115
+ switch (value.tag) {
116
+ case "Modifiable": {
117
+ const modificationLevel = deps.getSkillModificationLevelById(value.modifiable.initial_modification_level);
118
+ if (modificationLevel === undefined) {
119
+ return MISSING_VALUE;
120
+ }
121
+ const cost = (() => {
122
+ switch (env.speed) {
123
+ case Speed.Fast:
124
+ return modificationLevel.fast.cost;
125
+ case Speed.Slow:
126
+ return modificationLevel.slow.cost;
127
+ default:
128
+ return assertExhaustive(env.speed);
129
+ }
130
+ })();
131
+ const formatCostP = formatCost.bind(this, deps.translate, env.entity);
132
+ const interval = formatTimeSpan(deps.translate, env.responsiveText, value.modifiable.interval.unit, value.modifiable.interval.value);
133
+ return responsive(env.responsiveText, () => `${formatCostP(cost) + deps.translate(" (casting)")} + ${formatCostP(cost / 2) + deps.translate(" per {0}", interval)}`, () => `${formatCostP(cost)} + ${formatCostP(cost / 2) + deps.translate("/{0}", interval)}`);
134
+ }
135
+ case "NonModifiable": {
136
+ const isMinimum = getMinimumText(value.non_modifiable.is_minimum, deps.translate, env.responsiveText);
137
+ const cost = value.non_modifiable.value;
138
+ const formatCostP = formatCost.bind(this, deps.translate, env.entity);
139
+ const per = (() => {
140
+ if (value.non_modifiable.per === undefined) {
141
+ return { countable: "", minimumTotal: "" };
142
+ }
143
+ const countable = responsive(env.responsiveText, (entity) => deps.translate(" per {0}", entity), (entity) => deps.translate("/{0}", entity), getResponsiveText(deps.translateMap(value.non_modifiable.per.translations)?.countable, env.responsiveText));
144
+ const minimumTotal = value.non_modifiable.per.minimum_total !== undefined
145
+ ? deps.translate(", minimum of {0}", formatCostP(value.non_modifiable.per.minimum_total))
146
+ : "";
147
+ return { countable, minimumTotal };
148
+ })();
149
+ const interval = formatTimeSpan(deps.translate, env.responsiveText, value.non_modifiable.interval.unit, value.non_modifiable.interval.value);
150
+ return (isMinimum +
151
+ responsive(env.responsiveText, () => `${formatCostP(cost) + deps.translate(" (casting)")} + ${(value.non_modifiable.is_minimum === true
152
+ ? deps.translate("half of the activation cost")
153
+ : formatCostP(cost / 2)) +
154
+ per.countable +
155
+ deps.translate(" per {0}", interval)}`, () => `${formatCostP(cost)} + ${(value.non_modifiable.is_minimum === true
156
+ ? "50%"
157
+ : formatCostP(cost / 2)) +
158
+ per.countable +
159
+ deps.translate("/{0}", interval)}`) +
160
+ per.minimumTotal +
161
+ getTextForNonModifiableSuffix(deps.translate, env.entity, ModifiableParameter.Cost, env.responsiveText));
162
+ }
163
+ default:
164
+ return assertExhaustive(value);
165
+ }
166
+ };
@@ -0,0 +1,40 @@
1
+ import { DurationForOneTime, DurationForSustained } from "optolith-database-schema/types/_ActivatableSkillDuration";
2
+ import { BlessingDuration } from "optolith-database-schema/types/Blessing";
3
+ import { CantripDuration } from "optolith-database-schema/types/Cantrip";
4
+ import { Translate, TranslateMap } from "../../../../helpers/translate.js";
5
+ import { ResponsiveTextSize } from "../../responsiveText.js";
6
+ /**
7
+ * Returns the text for the duration of a one-time activatable skill.
8
+ */
9
+ export declare const getTextForDurationForOneTime: (deps: {
10
+ translate: Translate;
11
+ translateMap: TranslateMap;
12
+ }, value: DurationForOneTime, env: {
13
+ responsiveText: ResponsiveTextSize;
14
+ }) => string;
15
+ /**
16
+ * Returns the text for the duration of a sustained activatable skill.
17
+ */
18
+ export declare const getTextForDurationForSustained: (deps: {
19
+ translate: Translate;
20
+ }, value: DurationForSustained | undefined, env: {
21
+ responsiveText: ResponsiveTextSize;
22
+ }) => string;
23
+ /**
24
+ * Returns the text for the duration of a cantrip.
25
+ */
26
+ export declare const getTextForCantripDuration: (deps: {
27
+ translate: Translate;
28
+ translateMap: TranslateMap;
29
+ }, value: CantripDuration, env: {
30
+ responsiveText: ResponsiveTextSize;
31
+ }) => string;
32
+ /**
33
+ * Returns the text for the duration of a blessing.
34
+ */
35
+ export declare const getTextForBlessingDuration: (deps: {
36
+ translate: Translate;
37
+ translateMap: TranslateMap;
38
+ }, value: BlessingDuration, env: {
39
+ responsiveText: ResponsiveTextSize;
40
+ }) => string;