@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.
- package/.prettierrc.yml +1 -0
- package/AUTHORS +1 -0
- package/CHANGELOG.md +5 -0
- package/LICENSE +373 -0
- package/README.md +1 -0
- package/lib/entities/combatTechnique.d.ts +15 -0
- package/lib/entities/combatTechnique.js +59 -0
- package/lib/entities/experienceLevel.d.ts +5 -0
- package/lib/entities/experienceLevel.js +44 -0
- package/lib/entities/liturgicalChant.d.ts +35 -0
- package/lib/entities/liturgicalChant.js +244 -0
- package/lib/entities/partial/rated/activatable/castingTime.d.ts +25 -0
- package/lib/entities/partial/rated/activatable/castingTime.js +50 -0
- package/lib/entities/partial/rated/activatable/checkResultBased.d.ts +7 -0
- package/lib/entities/partial/rated/activatable/checkResultBased.js +28 -0
- package/lib/entities/partial/rated/activatable/cost.d.ts +30 -0
- package/lib/entities/partial/rated/activatable/cost.js +166 -0
- package/lib/entities/partial/rated/activatable/duration.d.ts +40 -0
- package/lib/entities/partial/rated/activatable/duration.js +100 -0
- package/lib/entities/partial/rated/activatable/effect.d.ts +7 -0
- package/lib/entities/partial/rated/activatable/effect.js +37 -0
- package/lib/entities/partial/rated/activatable/entity.d.ts +11 -0
- package/lib/entities/partial/rated/activatable/entity.js +12 -0
- package/lib/entities/partial/rated/activatable/index.d.ts +69 -0
- package/lib/entities/partial/rated/activatable/index.js +59 -0
- package/lib/entities/partial/rated/activatable/isMaximum.d.ts +6 -0
- package/lib/entities/partial/rated/activatable/isMaximum.js +10 -0
- package/lib/entities/partial/rated/activatable/modifiableParameter.d.ts +8 -0
- package/lib/entities/partial/rated/activatable/modifiableParameter.js +9 -0
- package/lib/entities/partial/rated/activatable/nonModifiable.d.ts +9 -0
- package/lib/entities/partial/rated/activatable/nonModifiable.js +75 -0
- package/lib/entities/partial/rated/activatable/parensIf.d.ts +10 -0
- package/lib/entities/partial/rated/activatable/parensIf.js +10 -0
- package/lib/entities/partial/rated/activatable/range.d.ts +36 -0
- package/lib/entities/partial/rated/activatable/range.js +122 -0
- package/lib/entities/partial/rated/activatable/speed.d.ts +12 -0
- package/lib/entities/partial/rated/activatable/speed.js +22 -0
- package/lib/entities/partial/rated/activatable/targetCategory.d.ts +12 -0
- package/lib/entities/partial/rated/activatable/targetCategory.js +36 -0
- package/lib/entities/partial/rated/activatable/units.d.ts +13 -0
- package/lib/entities/partial/rated/activatable/units.js +53 -0
- package/lib/entities/partial/rated/improvementCost.d.ts +7 -0
- package/lib/entities/partial/rated/improvementCost.js +7 -0
- package/lib/entities/partial/rated/skillCheck.d.ts +19 -0
- package/lib/entities/partial/rated/skillCheck.js +58 -0
- package/lib/entities/partial/responsiveText.d.ts +31 -0
- package/lib/entities/partial/responsiveText.js +49 -0
- package/lib/entities/partial/unknown.d.ts +4 -0
- package/lib/entities/partial/unknown.js +4 -0
- package/lib/entities/skill.d.ts +13 -0
- package/lib/entities/skill.js +109 -0
- package/lib/entities/spell.d.ts +38 -0
- package/lib/entities/spell.js +274 -0
- package/lib/helpers/getTypes.d.ts +482 -0
- package/lib/helpers/getTypes.js +1 -0
- package/lib/helpers/translate.d.ts +14 -0
- package/lib/helpers/translate.js +8 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/libraryEntry.d.ts +52 -0
- package/lib/libraryEntry.js +17 -0
- 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;
|