@adatechnology/game-items-goods 0.1.5 → 0.2.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/README.md +33 -2
- package/dist/index.d.ts +100 -1
- package/dist/index.global.js +4187 -414
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +4002 -430
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Catalog of real-world items for [`@adatechnology/game-items`](../game-items): **
|
|
|
5
5
|
melee reach and noise) and the texts in pt-BR (the team's own names) and en. It is data and a thin typed wrapper: no logic, no renderer, no game.
|
|
6
6
|
|
|
7
7
|
The data is **generated** by `tools/items-catalog` from the Vale Cinzento delivery (Itens page, the game, the 3D house viewer) and the household items of the SDK; do not edit
|
|
8
|
-
`src/data/*.json` by hand (except `src/data/locales/en.json`, the English translation, which
|
|
8
|
+
`src/data/*.json` by hand (except `src/data/locales/en.json`, the English translation, `kinds.json`, `item-contracts.json` and `known-gaps.json`, which are kept by hand; what the kinds add to each item lives in `tools/items-catalog/kinds-overlay.json`). Run `pnpm --filter @adatechnology/items-catalog-tool catalog` after changing `decisions.json`.
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -40,7 +40,8 @@ GOODS_STRINGS.en['place.pharmacy'] // 'Pharmacy'
|
|
|
40
40
|
| `GOODS_TABLES` | rarities, storage, depletion, spawn numbers and melee stats as read (the `DEFAULT_RULES` of the engine are proven equal to them by test) |
|
|
41
41
|
| `GOODS_ARSENAL_RECORDS` | ammo boxes, three firearms and two throwables of the game's `EXTRA`, for `itemsFromArsenal(arsenal, { records })` |
|
|
42
42
|
| `GOODS_PROVENANCE` | per item: the team id, the household id, the viewer pool types, the game ids, and where the id and the measure come from |
|
|
43
|
-
| `
|
|
43
|
+
| `GOODS_KINDS`, `createGoodsKinds(options?)`, `checkGoodsItems(options?)`, `ITEM_CONTRACTS`, `createItemContracts(options?)`, `GOODS_KNOWN_GAPS` | the tree of kinds, its registry, the validator over the catalog, the contract checkers and the allowed gaps |
|
|
44
|
+
| `GOODS_STRINGS`, `goodsText(key, locale?)`, `pickGoodsLocale` | texts by key: `item.<id>`, `kind.<id>`, `kind.<id>.description`, `category.<id>`, `place.<id>`, `rarity.<id>`, `container.<id>`, `recipe.<id>` |
|
|
44
45
|
|
|
45
46
|
## Where the items come from
|
|
46
47
|
|
|
@@ -48,6 +49,36 @@ GOODS_STRINGS.en['place.pharmacy'] // 'Pharmacy'
|
|
|
48
49
|
the sources lacked). 38 household items were merged with their team equivalent and keep the household id. Measures are the household's where it had one, the model box times a real scale for the 24
|
|
49
50
|
modelled items, and a reference measure for the rest (`provenance.sizeSource`). Story items (diary, military map, evacuation order...) are not here: they live in the game's slice.
|
|
50
51
|
|
|
52
|
+
## Adding an item
|
|
53
|
+
|
|
54
|
+
Every item has a `kind` (`src/data/kinds.json`, a tree: `item > consumable > food_ready > canned_food`, `item > equipment > electronics`...). The kind carries the defaults (parts and
|
|
55
|
+
materials, impact response, use animation and sounds, leftover, raw effect...) and the **contracts** the item must meet (`physical`, `destructible`, `impact`, `edible`, `use_animation`,
|
|
56
|
+
`leftover`, `preparation`, `recipe_input`, `liquid_container`, `heat_resistant`, `weapon`, `wearable`, `battery`: see `src/contracts.ts`). An item declares only what differs from its kind.
|
|
57
|
+
|
|
58
|
+
1. Pick the closest kind (`createGoodsKinds().ids()`; each has a name and description in the locales as `kind.<id>`). Tuning a kind (say `metal_can`) changes every item of it.
|
|
59
|
+
2. Add the item the way `tools/items-catalog` says (an `extraItems` decision plus its `dimensions`), and give it a row in `tools/items-catalog/kinds-overlay.json`: `{ "kind": "canned_food", ...only what
|
|
60
|
+
differs }`. The generator refuses an item without a row. A real-world value you filled in for lack of a team number goes in the row's `"estimated": ["field", ...]` list: it means "estimated from the real world,
|
|
61
|
+
the teams may adjust it".
|
|
62
|
+
3. Regenerate (`pnpm --filter @adatechnology/items-catalog-tool catalog`) and run **`pnpm check:items`**: it prints every problem (for example `"x" (canned_food): missing nutrition, required by food_ready`) and exits
|
|
63
|
+
non-zero. `known-gaps.json` lists the few gaps allowed so far; it only shrinks (a test fails when a gap stops applying, and caps its size), so a new item has to meet its kind.
|
|
64
|
+
4. A new kind, or a parent inserted between two kinds, is data too, never a change of the engine:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { checkGoodsItems, createGoodsKinds } from '@adatechnology/game-items-goods'
|
|
68
|
+
|
|
69
|
+
const kinds = createGoodsKinds({
|
|
70
|
+
extra: [{ id: 'sealed_can', extends: 'food_ready', defaults: { impact: { response: 'dent', pushImpulse: true, shed: false } } }], // a new kind...
|
|
71
|
+
patches: { canned_food: { extends: 'sealed_can' } }, // ...inserted above canned_food
|
|
72
|
+
})
|
|
73
|
+
const report = checkGoodsItems({ kinds, entries: myItems }) // { ok, problems, allowed }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Português
|
|
77
|
+
|
|
78
|
+
**Adicionando um item.** Todo item tem um `kind` (`src/data/kinds.json`, uma árvore). O kind traz os padrões (partes, impacto, animação de uso, sobra, efeito cru) e os contratos que o item tem de cumprir;
|
|
79
|
+
o item só declara o que muda. Escolha o kind mais próximo, dê ao item uma linha em `tools/items-catalog/kinds-overlay.json` (`"estimated": [...]` marca o que foi estimado do mundo real e os times podem ajustar),
|
|
80
|
+
regenere o catálogo e rode `pnpm check:items`: ele lista cada problema e sai com erro. Kind novo, ou um pai inserido no meio, é dado (`extra` e `patches` de `createGoodsKinds`), não mudança de motor.
|
|
81
|
+
|
|
51
82
|
## Tests
|
|
52
83
|
|
|
53
84
|
`pnpm --filter @adatechnology/game-items-goods test`: the pack validates in `createItems`, ids are unique and English, every reference (category, place, rarity, pool, recipe, effect) exists, provenance covers
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ItemsOptions, ItemsCatalog, ItemPack, ArsenalItemRecord, CategoryDef, ContainerDef, PoolEntry, ItemDef, PlaceDef, RecipeDef, UseEffectDef, FindsProviderOptions, FindsProvider } from '@adatechnology/game-items';
|
|
2
|
+
import { CategoryDef as CategoryDef$1, BodySlot, ContractChecker, CategoryRegistry, CategorizedReport, CategoryOptions } from '@adatechnology/game-contracts';
|
|
2
3
|
|
|
3
4
|
/** The pack for `createItems({ packs })`: items, the three categories the game adds, 24 places, 17 containers, house pools, use effects and recipes. */
|
|
4
5
|
declare const goodsPack: ItemPack;
|
|
@@ -88,6 +89,10 @@ declare const GOODS_TABLES: {
|
|
|
88
89
|
/** Ammo boxes, three firearms and two throwables as items (the game's `EXTRA` table), for `itemsFromArsenal(arsenal, { records })`. */
|
|
89
90
|
declare const GOODS_ARSENAL_RECORDS: readonly ArsenalItemRecord[];
|
|
90
91
|
declare const GOODS_PROVENANCE: Readonly<Record<string, ItemProvenance>>;
|
|
92
|
+
/** The tree of kinds (`kind` of each item): defaults and required contracts per kind, see `createGoodsKinds`. */
|
|
93
|
+
declare const GOODS_KINDS: readonly CategoryDef$1[];
|
|
94
|
+
/** Gaps of the catalog that are known and allowed, by item id: the problem prefixes `checkGoodsItems` lets through. It only shrinks: a test fails when a gap no longer applies. */
|
|
95
|
+
declare const GOODS_KNOWN_GAPS: Readonly<Record<string, readonly string[]>>;
|
|
91
96
|
|
|
92
97
|
type GoodsLocale = 'en' | 'pt-BR';
|
|
93
98
|
/** Texts by key: `item.<id>`, `category.<id>`, `place.<id>`, `rarity.<id>`, `container.<id>`, `recipe.<id>`. The pt-BR names are the team's. */
|
|
@@ -117,4 +122,98 @@ declare const FLOORPLAN_POOL_ALIASES: Readonly<Record<string, string>>;
|
|
|
117
122
|
*/
|
|
118
123
|
declare const createGoodsFindsProvider: (catalog: ItemsCatalog, options?: Omit<FindsProviderOptions, "unknownContainers">) => FindsProvider;
|
|
119
124
|
|
|
120
|
-
|
|
125
|
+
/**
|
|
126
|
+
* The fields the kinds add to `ItemDef`, as a catalog row after `resolveEntry` (the kind's defaults underneath the item's own fields).
|
|
127
|
+
* Every one is plain data: a kind sets it once and the items of the kind inherit it.
|
|
128
|
+
*/
|
|
129
|
+
interface KindedItem extends Omit<ItemDef, 'category' | 'rarity'> {
|
|
130
|
+
readonly category: string;
|
|
131
|
+
readonly kind: string;
|
|
132
|
+
/** The `category` values the kind's items may carry (the loot rolls read `category`): a kind default, never set on an item. */
|
|
133
|
+
readonly lootCategory?: readonly string[] | string;
|
|
134
|
+
/** Parts of the item for the destruction engine; a part may be a full `PartSpec` (shape and position) or only `{ id, material, thickness? }`. */
|
|
135
|
+
readonly parts?: readonly ItemPart[];
|
|
136
|
+
readonly impact?: ItemImpact;
|
|
137
|
+
readonly use?: {
|
|
138
|
+
readonly clip?: string;
|
|
139
|
+
readonly sounds?: readonly string[];
|
|
140
|
+
};
|
|
141
|
+
readonly leftover?: ItemLeftover;
|
|
142
|
+
/** What eating or drinking it raw does. `sickChance` is the chance of getting sick, 0..1. */
|
|
143
|
+
readonly rawEffect?: {
|
|
144
|
+
readonly sickChance?: number;
|
|
145
|
+
};
|
|
146
|
+
/** True when the item never spoils: the explicit form of a missing `shelfLife`. */
|
|
147
|
+
readonly nonPerishable?: boolean;
|
|
148
|
+
/** A container's capacity (an empty bucket); `fluid` is what it holds now. */
|
|
149
|
+
readonly container?: {
|
|
150
|
+
readonly capacityLiters?: number;
|
|
151
|
+
};
|
|
152
|
+
/** Names of the fields whose value was estimated from the real world, not given by a team: the teams may adjust them. */
|
|
153
|
+
readonly estimated?: readonly string[];
|
|
154
|
+
/** The arsenal caliber an ammunition item belongs to. */
|
|
155
|
+
readonly caliber?: string;
|
|
156
|
+
}
|
|
157
|
+
interface ItemPart {
|
|
158
|
+
readonly id: string;
|
|
159
|
+
readonly material: string;
|
|
160
|
+
readonly thickness?: number;
|
|
161
|
+
readonly shape?: unknown;
|
|
162
|
+
readonly position?: unknown;
|
|
163
|
+
}
|
|
164
|
+
/** How the item answers an impact: `response` is one of `IMPACT_RESPONSES`; `shed` says it throws off fragments. */
|
|
165
|
+
interface ItemImpact {
|
|
166
|
+
readonly response?: string;
|
|
167
|
+
readonly pushImpulse?: boolean;
|
|
168
|
+
readonly shed?: boolean;
|
|
169
|
+
}
|
|
170
|
+
type ItemLeftover = 'none' | {
|
|
171
|
+
readonly item?: string;
|
|
172
|
+
readonly despawnSeconds?: number;
|
|
173
|
+
};
|
|
174
|
+
interface ItemContractOptions {
|
|
175
|
+
/** Ids of the destruction materials (`MATERIALS` of game-destruction). Without it the material names are not checked against the engine. */
|
|
176
|
+
readonly materials?: Iterable<string>;
|
|
177
|
+
/** Ids of the weapons of the arsenal (`WEAPONS` of game-weapons). Without it a `weapon` id is only checked to be a name. */
|
|
178
|
+
readonly weaponIds?: Iterable<string>;
|
|
179
|
+
/** Ids of the calibers of the arsenal (`CALIBERS` of game-weapons). */
|
|
180
|
+
readonly calibers?: Iterable<string>;
|
|
181
|
+
/** The catalog the leftovers and recipes are checked against (default: the goods catalog). */
|
|
182
|
+
readonly items?: readonly Pick<KindedItem, 'id' | 'kind' | 'category' | 'cookable'>[];
|
|
183
|
+
readonly recipes?: readonly RecipeDef[];
|
|
184
|
+
/** Kilograms per litre of the bounding box an item may have (default `densityKgPerLitre` of `data/item-contracts.json`). */
|
|
185
|
+
readonly density?: {
|
|
186
|
+
readonly min: number;
|
|
187
|
+
readonly max: number;
|
|
188
|
+
};
|
|
189
|
+
/** Materials that take a flame (default `heatResistantMaterials` of `data/item-contracts.json`). */
|
|
190
|
+
readonly heatResistant?: readonly string[];
|
|
191
|
+
}
|
|
192
|
+
declare const IMPACT_RESPONSES: readonly string[];
|
|
193
|
+
declare const HEAT_RESISTANT_MATERIALS: readonly string[];
|
|
194
|
+
declare const DENSITY_KG_PER_LITRE: {
|
|
195
|
+
min: number;
|
|
196
|
+
max: number;
|
|
197
|
+
};
|
|
198
|
+
/** `BodySlot` of game-contracts, as a list. */
|
|
199
|
+
declare const BODY_SLOTS: readonly BodySlot[];
|
|
200
|
+
/** The checkers of the contracts the kinds of `kinds.json` require, built over the catalog and the engines they are given. */
|
|
201
|
+
declare const createItemContracts: (options?: ItemContractOptions) => readonly ContractChecker<KindedItem>[];
|
|
202
|
+
/** `createItemContracts()` over the goods catalog, without the engine lists (materials, arsenal): the CLI and the tests pass those. */
|
|
203
|
+
declare const ITEM_CONTRACTS: readonly ContractChecker<KindedItem>[];
|
|
204
|
+
|
|
205
|
+
/** The registry of the shipped kinds; `options` adds kinds, patches them by id or removes them (a game's own kinds go in `extra`). */
|
|
206
|
+
declare const createGoodsKinds: (options?: CategoryOptions) => CategoryRegistry;
|
|
207
|
+
interface CheckGoodsOptions extends ItemContractOptions {
|
|
208
|
+
readonly kinds?: CategoryRegistry;
|
|
209
|
+
/** The rows to check (default the goods catalog). */
|
|
210
|
+
readonly entries?: readonly KindedItem[];
|
|
211
|
+
/** Known gaps by item id (default `GOODS_KNOWN_GAPS`). */
|
|
212
|
+
readonly allow?: Readonly<Record<string, readonly string[]>>;
|
|
213
|
+
}
|
|
214
|
+
/** The `category` values a kind lets its items carry (`lootCategory` of its defaults); undefined when the kind declares none. */
|
|
215
|
+
declare const lootCategoriesOf: (kinds: CategoryRegistry, kind: string) => readonly string[] | undefined;
|
|
216
|
+
/** Runs the contracts of every item's kind over the catalog, and checks that `category` (read by the loot rolls) is one the kind declares. */
|
|
217
|
+
declare const checkGoodsItems: (options?: CheckGoodsOptions) => CategorizedReport;
|
|
218
|
+
|
|
219
|
+
export { BODY_SLOTS, type CheckGoodsOptions, DENSITY_KG_PER_LITRE, type DepletionRow, FLOORPLAN_PLACES, FLOORPLAN_POOL_ALIASES, FLOORPLAN_POOL_KEYS, GOODS_ARSENAL_RECORDS, GOODS_CATEGORIES, GOODS_CONTAINERS, GOODS_HOUSE_POOLS, GOODS_ITEMS, GOODS_KINDS, GOODS_KNOWN_GAPS, GOODS_PLACES, GOODS_PROVENANCE, GOODS_RECIPES, GOODS_STRINGS, GOODS_TABLES, GOODS_USE_EFFECTS, type GoodsLocale, type GoodsStrings, HEAT_RESISTANT_MATERIALS, type HousePools, IMPACT_RESPONSES, ITEM_CONTRACTS, type ItemContractOptions, type ItemImpact, type ItemLeftover, type ItemPart, type ItemProvenance, type KindedItem, type MeleeRow, POOL_PLACES, type RarityRow, type StorageRow, checkGoodsItems, createGoodsFindsProvider, createGoodsItems, createGoodsKinds, createItemContracts, goodsPack, goodsText, lootCategoriesOf, pickGoodsLocale };
|