delta-force-core 0.2.3 → 0.2.5
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.en.md +1020 -0
- package/dist/data/ammo.d.ts.map +1 -1
- package/dist/data/ammo.js +3 -1
- package/dist/data/ammo.js.map +1 -1
- package/dist/data/weapons.d.ts.map +1 -1
- package/dist/data/weapons.js +71 -68
- package/dist/data/weapons.js.map +1 -1
- package/index.json +218 -72
- package/package.json +1 -1
package/README.en.md
ADDED
|
@@ -0,0 +1,1020 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="./assets/logo.svg" alt="delta-force-core logo" width="200" />
|
|
4
|
+
|
|
5
|
+
# delta-force-core
|
|
6
|
+
|
|
7
|
+
**Core data & random-pick toolkit for Delta Force.**
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/delta-force-core)
|
|
10
|
+
[](https://www.npmjs.com/package/delta-force-core)
|
|
11
|
+
[](./LICENSE)
|
|
12
|
+
[](https://www.typescriptlang.org/)
|
|
13
|
+
[](https://nodejs.org/)
|
|
14
|
+
[](https://github.com/Zhoyi011/delta-force-core/stargazers)
|
|
15
|
+
[](./CONTRIBUTING.md)
|
|
16
|
+
|
|
17
|
+
[简体中文](./README.md) · [English](./README.en.md)
|
|
18
|
+
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<a id="status"></a>
|
|
24
|
+
> ## 📢 Project Status
|
|
25
|
+
>
|
|
26
|
+
> **v0.2.x** — Stable. Covers **operators / weapons / equipment / ammo**.
|
|
27
|
+
>
|
|
28
|
+
> **Roadmap**: attachment system, ammo variants (T1–T6), image assets, i18n.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
<a id="toc"></a>
|
|
33
|
+
## 📖 Table of Contents
|
|
34
|
+
|
|
35
|
+
- [✨ Features](#features)
|
|
36
|
+
- [🎯 Use Cases](#use-cases)
|
|
37
|
+
- [🧠 Design Philosophy](#design)
|
|
38
|
+
- [📦 Installation](#install)
|
|
39
|
+
- [🚀 Quick Start](#quick-start)
|
|
40
|
+
- [🧩 Core Concepts](#concepts)
|
|
41
|
+
- [📘 API Reference](#api)
|
|
42
|
+
- [Engine](#api-engine)
|
|
43
|
+
- [Random Picker Functions](#api-random)
|
|
44
|
+
- [Query Functions](#api-query)
|
|
45
|
+
- [List Functions](#api-list)
|
|
46
|
+
- [User Overrides](#api-override)
|
|
47
|
+
- [📚 Data Modules](#data)
|
|
48
|
+
- [Operators](#data-operators)
|
|
49
|
+
- [Weapons](#data-weapons)
|
|
50
|
+
- [Equipment](#data-equipment)
|
|
51
|
+
- [Ammo](#data-ammo)
|
|
52
|
+
- [📄 index.json](#index-json)
|
|
53
|
+
- [🌐 Ecosystem & Integrations](#ecosystem)
|
|
54
|
+
- [🤝 Contributing](#contributing)
|
|
55
|
+
- [🛠 Development](#dev)
|
|
56
|
+
- [📅 Roadmap](#roadmap)
|
|
57
|
+
- [❓ FAQ](#faq)
|
|
58
|
+
- [📜 License](#license)
|
|
59
|
+
- [❤️ Credits](#thanks)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
<a id="features"></a>
|
|
64
|
+
## ✨ Features
|
|
65
|
+
|
|
66
|
+
<table>
|
|
67
|
+
<tr>
|
|
68
|
+
<td align="center" width="25%">
|
|
69
|
+
<h3>📚 Complete Data</h3>
|
|
70
|
+
<p>Operators / Weapons / Equipment / Ammo<br/>All official fields covered</p>
|
|
71
|
+
</td>
|
|
72
|
+
<td align="center" width="25%">
|
|
73
|
+
<h3>🎲 Random Picker</h3>
|
|
74
|
+
<p>Random operator, weapon, gear<br/>One-click full loadout</p>
|
|
75
|
+
</td>
|
|
76
|
+
<td align="center" width="25%">
|
|
77
|
+
<h3>🔍 Query Tools</h3>
|
|
78
|
+
<p>By id / caliber / alias<br/>Type-safe with IDE hints</p>
|
|
79
|
+
</td>
|
|
80
|
+
<td align="center" width="25%">
|
|
81
|
+
<h3>🎨 User Overrides</h3>
|
|
82
|
+
<p>Quality / alias / tags<br/>Runtime-injected, non-invasive</p>
|
|
83
|
+
</td>
|
|
84
|
+
</tr>
|
|
85
|
+
</table>
|
|
86
|
+
|
|
87
|
+
- ✅ **Native TypeScript** — Full type definitions, IDE IntelliSense
|
|
88
|
+
- ✅ **ES Module** — Modern module system, tree-shaking friendly
|
|
89
|
+
- ✅ **Zero Dependencies** — Core library has no third-party deps
|
|
90
|
+
- ✅ **Forward Compatible** — All optional fields use `?:`, no breaking changes
|
|
91
|
+
- ✅ **Node + Browser** — Node.js ≥ 18 and modern browsers
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
<a id="use-cases"></a>
|
|
96
|
+
## 🎯 Use Cases
|
|
97
|
+
|
|
98
|
+
<table>
|
|
99
|
+
<tr>
|
|
100
|
+
<th width="20%">Scenario</th>
|
|
101
|
+
<th>Example</th>
|
|
102
|
+
</tr>
|
|
103
|
+
<tr>
|
|
104
|
+
<td>🎮 <b>Gacha Apps</b></td>
|
|
105
|
+
<td>One-click random loadout, inject your own quality ratings</td>
|
|
106
|
+
</tr>
|
|
107
|
+
<tr>
|
|
108
|
+
<td>📚 <b>Wiki / Data Sites</b></td>
|
|
109
|
+
<td>Consume structured data directly to render lists</td>
|
|
110
|
+
</tr>
|
|
111
|
+
<tr>
|
|
112
|
+
<td>🤖 <b>Discord / QQ Bots</b></td>
|
|
113
|
+
<td><code>getRandomLoadout()</code> works out of the box</td>
|
|
114
|
+
</tr>
|
|
115
|
+
<tr>
|
|
116
|
+
<td>🧪 <b>Game Data Research</b></td>
|
|
117
|
+
<td>Filter by caliber, tier, mode for statistical analysis</td>
|
|
118
|
+
</tr>
|
|
119
|
+
<tr>
|
|
120
|
+
<td>🌐 <b>Static Sites / CDN</b></td>
|
|
121
|
+
<td>Fetch <code>index.json</code> directly, no build needed</td>
|
|
122
|
+
</tr>
|
|
123
|
+
</table>
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
<a id="design"></a>
|
|
128
|
+
## 🧠 Design Philosophy
|
|
129
|
+
|
|
130
|
+
### 1. Data and Logic are Separated
|
|
131
|
+
|
|
132
|
+
**Official data is read-only** and maintained by the library; **user preferences are injected at runtime** without polluting official data.
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
┌──────────────────────────────────────┐
|
|
136
|
+
│ Official Data (hardcoded, readonly) │
|
|
137
|
+
│ OPERATORS / WEAPONS / │
|
|
138
|
+
│ EQUIPMENT / AMMO │
|
|
139
|
+
└──────────────────┬───────────────────┘
|
|
140
|
+
│
|
|
141
|
+
▼
|
|
142
|
+
┌──────────────────────────────────────┐
|
|
143
|
+
│ User Overrides (optional, runtime) │
|
|
144
|
+
│ qualityOverride / aliasOverride / │
|
|
145
|
+
│ tagOverride │
|
|
146
|
+
└──────────────────┬───────────────────┘
|
|
147
|
+
│
|
|
148
|
+
▼
|
|
149
|
+
┌──────────────────────────────────────┐
|
|
150
|
+
│ Engine │
|
|
151
|
+
│ · Random picker · Query │
|
|
152
|
+
└──────────────────────────────────────┘
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 2. Why isn't `quality` part of official data?
|
|
156
|
+
|
|
157
|
+
Weapon quality in Delta Force (green / blue / purple / gold) is **not officially specified** — it's a **subjective rating** by the player community. Therefore:
|
|
158
|
+
|
|
159
|
+
- Official `Weapon` type **does NOT contain `quality`**
|
|
160
|
+
- Users inject their own ratings via `createEngine({ qualityOverride })`
|
|
161
|
+
- The default engine (no overrides) **returns empty when filtering by quality**
|
|
162
|
+
|
|
163
|
+
This is **by design** — we don't force one person's subjective ratings on everyone.
|
|
164
|
+
|
|
165
|
+
### 3. Forward Compatible
|
|
166
|
+
|
|
167
|
+
All optional fields use `?:`. Adding new fields later (e.g., `caliber`, `image`, `slots`) won't break existing users.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
<a id="install"></a>
|
|
172
|
+
## 📦 Installation
|
|
173
|
+
|
|
174
|
+
<details open>
|
|
175
|
+
<summary><b>npm / yarn / pnpm / bun</b></summary>
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# npm
|
|
179
|
+
npm install delta-force-core
|
|
180
|
+
|
|
181
|
+
# yarn
|
|
182
|
+
yarn add delta-force-core
|
|
183
|
+
|
|
184
|
+
# pnpm
|
|
185
|
+
pnpm add delta-force-core
|
|
186
|
+
|
|
187
|
+
# bun
|
|
188
|
+
bun add delta-force-core
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
</details>
|
|
192
|
+
|
|
193
|
+
<details>
|
|
194
|
+
<summary><b>CDN (browser)</b></summary>
|
|
195
|
+
|
|
196
|
+
```html
|
|
197
|
+
<!-- ES Module -->
|
|
198
|
+
<script type="module">
|
|
199
|
+
import { getRandomLoadout } from 'https://esm.sh/delta-force-core';
|
|
200
|
+
console.log(getRandomLoadout());
|
|
201
|
+
</script>
|
|
202
|
+
|
|
203
|
+
<!-- Or fetch raw JSON -->
|
|
204
|
+
<script type="module">
|
|
205
|
+
const res = await fetch('https://unpkg.com/delta-force-core/index.json');
|
|
206
|
+
const data = await res.json();
|
|
207
|
+
console.log(data.weapons);
|
|
208
|
+
</script>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
</details>
|
|
212
|
+
|
|
213
|
+
**Requirements**: Node.js ≥ 18 or any modern browser supporting ES Modules.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
<a id="quick-start"></a>
|
|
218
|
+
## 🚀 Quick Start
|
|
219
|
+
|
|
220
|
+
### Scenario 1 · Just reading data (Wiki users)
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
import { WEAPONS, OPERATORS, EQUIPMENT, AMMO } from 'delta-force-core';
|
|
224
|
+
|
|
225
|
+
console.log(WEAPONS); // all weapons
|
|
226
|
+
console.log(OPERATORS); // all operators
|
|
227
|
+
console.log(EQUIPMENT.armors); // all armors
|
|
228
|
+
console.log(AMMO); // all ammo types
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Scenario 2 · Random picking (gacha apps)
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
import { getRandomWeapon, getRandomLoadout } from 'delta-force-core';
|
|
235
|
+
|
|
236
|
+
console.log(getRandomWeapon()); // random weapon
|
|
237
|
+
console.log(getRandomLoadout()); // full random loadout
|
|
238
|
+
console.log(getRandomLoadout({ allowNormal: true })); // normal mode only
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Scenario 3 · Bring your own quality ratings
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
import { createEngine } from 'delta-force-core';
|
|
245
|
+
|
|
246
|
+
const engine = createEngine({
|
|
247
|
+
qualityOverride: {
|
|
248
|
+
m4a1: '金色', // Gold
|
|
249
|
+
akm: '紫色', // Purple
|
|
250
|
+
k416: '金色', // Gold
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
console.log(engine.getRandomWeapon({ quality: '金色' }));
|
|
255
|
+
console.log(engine.getWeaponQuality('m4a1')); // '金色'
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Scenario 4 · Plain JS / JSON environments
|
|
259
|
+
|
|
260
|
+
```js
|
|
261
|
+
import data from 'delta-force-core/index.json' with { type: 'json' };
|
|
262
|
+
|
|
263
|
+
console.log(data.weapons);
|
|
264
|
+
console.log(data.equipment.helmets);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
<a id="concepts"></a>
|
|
270
|
+
## 🧩 Core Concepts
|
|
271
|
+
|
|
272
|
+
### Engine
|
|
273
|
+
|
|
274
|
+
`Engine` is the unified entry point for **all random picking and querying capabilities**. It consists of:
|
|
275
|
+
|
|
276
|
+
> **Official Data (fixed)** + **User Overrides (optional)** = **Engine**
|
|
277
|
+
|
|
278
|
+
- **Default Engine**: `defaultEngine` — official data + empty overrides, auto-registered on import
|
|
279
|
+
- **Custom Engine**: `createEngine(options)` — inject your own overrides
|
|
280
|
+
|
|
281
|
+
### Overrides
|
|
282
|
+
|
|
283
|
+
| Override | Purpose | Impact |
|
|
284
|
+
|---|---|---|
|
|
285
|
+
| `qualityOverride` | Weapon quality rating | Affects `getRandomWeapon({ quality })` |
|
|
286
|
+
| `aliasOverride` | Aliases (e.g., `M4` → `m4a1`) | Affects `findWeaponByAlias()` |
|
|
287
|
+
| `tagOverride` | Personal tags | Metadata only, no effect on picking |
|
|
288
|
+
|
|
289
|
+
### Normal Mode (`allowNormal`)
|
|
290
|
+
|
|
291
|
+
| Value | Behavior |
|
|
292
|
+
|---|---|
|
|
293
|
+
| `true` | Only items **allowed** in normal mode |
|
|
294
|
+
| `false` | Only items **blocked** in normal mode (e.g., AWM / M82) |
|
|
295
|
+
| `undefined` | No filter, everything in pool |
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
<a id="api"></a>
|
|
300
|
+
## 📘 API Reference
|
|
301
|
+
|
|
302
|
+
> 💡 **Tip**: All functions exported as `defaultEngine`-bound are equivalent to calling `createEngine()` first. Use `createEngine` for custom behavior.
|
|
303
|
+
|
|
304
|
+
<a id="api-engine"></a>
|
|
305
|
+
### Engine
|
|
306
|
+
|
|
307
|
+
#### `createEngine(options?: EngineOptions): Engine`
|
|
308
|
+
|
|
309
|
+
Creates an engine instance.
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
import { createEngine } from 'delta-force-core';
|
|
313
|
+
|
|
314
|
+
const engine = createEngine({
|
|
315
|
+
qualityOverride: { m4a1: '金色' },
|
|
316
|
+
aliasOverride: { m4a1: ['M4', 'M4卡宾枪'] },
|
|
317
|
+
tagOverride: { m4a1: ['经典', '入门'] },
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
<details>
|
|
322
|
+
<summary><b>View EngineOptions type</b></summary>
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
interface EngineOptions {
|
|
326
|
+
/** Weapon quality rating: weaponId → '绿色' | '蓝色' | '紫色' | '金色' */
|
|
327
|
+
qualityOverride?: Record<string, WeaponQuality>;
|
|
328
|
+
/** Aliases: entityId → string[] */
|
|
329
|
+
aliasOverride?: Record<string, string[]>;
|
|
330
|
+
/** Personal tags: entityId → string[] */
|
|
331
|
+
tagOverride?: Record<string, string[]>;
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
</details>
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
#### `defaultEngine`
|
|
340
|
+
|
|
341
|
+
Default engine with official data + empty overrides.
|
|
342
|
+
|
|
343
|
+
```ts
|
|
344
|
+
import { defaultEngine } from 'delta-force-core';
|
|
345
|
+
|
|
346
|
+
defaultEngine.getRandomWeapon();
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
All picker / query functions are also exported as default-engine-bound:
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
import { getRandomWeapon } from 'delta-force-core';
|
|
353
|
+
// Equivalent to
|
|
354
|
+
import { defaultEngine } from 'delta-force-core';
|
|
355
|
+
defaultEngine.getRandomWeapon();
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
<a id="api-random"></a>
|
|
361
|
+
### Random Picker Functions
|
|
362
|
+
|
|
363
|
+
All pickers use `Math.random()` with uniform distribution. **Empty pool throws.**
|
|
364
|
+
|
|
365
|
+
#### `getRandomOperator(category?: string): Operator`
|
|
366
|
+
|
|
367
|
+
Pick a random operator.
|
|
368
|
+
|
|
369
|
+
| Param | Type | Description |
|
|
370
|
+
|---|---|---|
|
|
371
|
+
| `category` | `string?` | Role category (`突击兵` / `支援兵` / `工程兵` / `侦察兵`), omit for all |
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
getRandomOperator(); // any operator
|
|
375
|
+
getRandomOperator('突击兵'); // assault only
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
#### `getRandomWeapon(options?: WeaponOptions): Weapon`
|
|
381
|
+
|
|
382
|
+
Pick a random weapon.
|
|
383
|
+
|
|
384
|
+
| Option | Type | Description |
|
|
385
|
+
|---|---|---|
|
|
386
|
+
| `category` | `string?` | Weapon category |
|
|
387
|
+
| `quality` | `WeaponQuality?` | Quality (requires `qualityOverride`) |
|
|
388
|
+
| `allowNormal` | `boolean?` | Normal-mode filter |
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
getRandomWeapon();
|
|
392
|
+
getRandomWeapon({ category: '突击步枪' });
|
|
393
|
+
getRandomWeapon({ allowNormal: true });
|
|
394
|
+
getRandomWeapon({ category: '狙击步枪', allowNormal: false });
|
|
395
|
+
engine.getRandomWeapon({ quality: '金色' });
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
#### `getRandomAmmo(options?: AmmoOptions): Ammo`
|
|
401
|
+
|
|
402
|
+
Pick a random ammo type.
|
|
403
|
+
|
|
404
|
+
| Option | Type | Description |
|
|
405
|
+
|---|---|---|
|
|
406
|
+
| `caliber` | `string?` | Caliber filter, e.g. `5.56x45mm` |
|
|
407
|
+
|
|
408
|
+
```ts
|
|
409
|
+
getRandomAmmo();
|
|
410
|
+
getRandomAmmo({ caliber: '5.56x45mm' });
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
#### `getRandomArmor` / `getRandomHelmet` / `getRandomBackpack` / `getRandomChestRig`
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
getRandomArmor(options?: TierOptions): EquipmentItem
|
|
419
|
+
getRandomHelmet(options?: TierOptions): EquipmentItem
|
|
420
|
+
getRandomBackpack(options?: TierOptions): EquipmentItem
|
|
421
|
+
getRandomChestRig(options?: TierOptions): EquipmentItem
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
| Option | Type | Description |
|
|
425
|
+
|---|---|---|
|
|
426
|
+
| `tier` | `number?` | Specific tier (1–6), omit for all |
|
|
427
|
+
| `allowNormal` | `boolean?` | Normal-mode filter (armor/helmet) |
|
|
428
|
+
|
|
429
|
+
```ts
|
|
430
|
+
getRandomArmor();
|
|
431
|
+
getRandomArmor({ tier: 5 });
|
|
432
|
+
getRandomHelmet({ allowNormal: true });
|
|
433
|
+
getRandomBackpack({ tier: 6 });
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
#### `getRandomLoadout(options?: LoadoutOptions): Loadout`
|
|
439
|
+
|
|
440
|
+
Generate a full random loadout.
|
|
441
|
+
|
|
442
|
+
```ts
|
|
443
|
+
const loadout = getRandomLoadout({ allowNormal: true });
|
|
444
|
+
|
|
445
|
+
// Returns:
|
|
446
|
+
// {
|
|
447
|
+
// operator: {...},
|
|
448
|
+
// weapon: {...},
|
|
449
|
+
// armor: {...},
|
|
450
|
+
// helmet: {...},
|
|
451
|
+
// backpack: {...},
|
|
452
|
+
// chestRig: {...}
|
|
453
|
+
// }
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
<a id="api-query"></a>
|
|
459
|
+
### Query Functions
|
|
460
|
+
|
|
461
|
+
| Function | Description |
|
|
462
|
+
|---|---|
|
|
463
|
+
| `findOperatorById(id)` | Find operator by id |
|
|
464
|
+
| `findWeaponById(id)` | Find weapon by id |
|
|
465
|
+
| `findAmmoById(id)` | Find ammo by id |
|
|
466
|
+
| `findArmorById(id)` | Find armor by id |
|
|
467
|
+
| `findHelmetById(id)` | Find helmet by id |
|
|
468
|
+
| `findBackpackById(id)` | Find backpack by id |
|
|
469
|
+
| `findChestRigById(id)` | Find chest rig by id |
|
|
470
|
+
| `findWeaponsByCaliber(caliber)` | Find weapons by caliber |
|
|
471
|
+
| `findAmmoByCaliber(caliber)` | Find ammo by caliber |
|
|
472
|
+
| `findWeaponByAlias(alias)` | Find weapon by alias (needs aliasOverride) |
|
|
473
|
+
|
|
474
|
+
```ts
|
|
475
|
+
findWeaponById('m4a1');
|
|
476
|
+
// { id: 'm4a1', name: 'M4A1突击步枪', allowNormal: true }
|
|
477
|
+
|
|
478
|
+
findHelmetById('helmet_l4_gt1');
|
|
479
|
+
findWeaponsByCaliber('5.56x45mm');
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
<a id="api-list"></a>
|
|
485
|
+
### List Functions
|
|
486
|
+
|
|
487
|
+
```ts
|
|
488
|
+
listOperatorCategories();
|
|
489
|
+
// ['突击兵', '支援兵', '工程兵', '侦察兵']
|
|
490
|
+
|
|
491
|
+
listWeaponCategories();
|
|
492
|
+
// ['突击步枪', '冲锋枪', '精确射手步枪', '狙击步枪', '轻机枪', '霰弹枪', '手枪', '特殊武器']
|
|
493
|
+
|
|
494
|
+
listAllOperators(); // all operators flattened
|
|
495
|
+
listAllWeapons(); // all weapons flattened
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
<a id="api-override"></a>
|
|
501
|
+
### User Overrides
|
|
502
|
+
|
|
503
|
+
```ts
|
|
504
|
+
const engine = createEngine({
|
|
505
|
+
qualityOverride: { m4a1: '金色' },
|
|
506
|
+
aliasOverride: { m4a1: ['M4', 'M4卡宾枪'] },
|
|
507
|
+
tagOverride: { m4a1: ['经典', '入门'] },
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
engine.getWeaponQuality('m4a1'); // '金色'
|
|
511
|
+
engine.getAliases('m4a1'); // ['M4', 'M4卡宾枪']
|
|
512
|
+
engine.getTags('m4a1'); // ['经典', '入门']
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
<a id="data"></a>
|
|
518
|
+
## 📚 Data Modules
|
|
519
|
+
|
|
520
|
+
<a id="data-operators"></a>
|
|
521
|
+
### Operators
|
|
522
|
+
|
|
523
|
+
**Structure**
|
|
524
|
+
|
|
525
|
+
```ts
|
|
526
|
+
interface Operator {
|
|
527
|
+
id: string;
|
|
528
|
+
name: string;
|
|
529
|
+
features?: string;
|
|
530
|
+
description?: string;
|
|
531
|
+
image?: string;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
interface OperatorCategory {
|
|
535
|
+
category: string;
|
|
536
|
+
operators: Operator[];
|
|
537
|
+
}
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**Export**
|
|
541
|
+
|
|
542
|
+
```ts
|
|
543
|
+
import { OPERATORS } from 'delta-force-core';
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
**Categories**: 突击兵 / 支援兵 / 工程兵 / 侦察兵 (Assault / Support / Engineer / Recon)
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
<a id="data-weapons"></a>
|
|
551
|
+
### Weapons
|
|
552
|
+
|
|
553
|
+
**Structure**
|
|
554
|
+
|
|
555
|
+
```ts
|
|
556
|
+
interface Weapon {
|
|
557
|
+
id: string;
|
|
558
|
+
name: string;
|
|
559
|
+
caliber?: string;
|
|
560
|
+
baseDamage?: number;
|
|
561
|
+
description?: string;
|
|
562
|
+
image?: string;
|
|
563
|
+
allowNormal?: boolean; // defaults to true
|
|
564
|
+
}
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
> ⚠️ **Note**: Official `Weapon` has **no `quality`**. Quality comes from user overrides.
|
|
568
|
+
|
|
569
|
+
**Export**
|
|
570
|
+
|
|
571
|
+
```ts
|
|
572
|
+
import { WEAPONS } from 'delta-force-core';
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
**Categories & counts**:
|
|
576
|
+
|
|
577
|
+
| Category | Count |
|
|
578
|
+
|---|---|
|
|
579
|
+
| Assault Rifles | 24 |
|
|
580
|
+
| SMGs | 12 |
|
|
581
|
+
| DMRs | 10 |
|
|
582
|
+
| Sniper Rifles | 5 |
|
|
583
|
+
| LMGs | 4 |
|
|
584
|
+
| Shotguns | 5 |
|
|
585
|
+
| Pistols | 7 |
|
|
586
|
+
| Special | 1 |
|
|
587
|
+
| **Total** | **68** |
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
<a id="data-equipment"></a>
|
|
592
|
+
### Equipment
|
|
593
|
+
|
|
594
|
+
**Structure**
|
|
595
|
+
|
|
596
|
+
```ts
|
|
597
|
+
interface EquipmentItem {
|
|
598
|
+
id: string;
|
|
599
|
+
name: string;
|
|
600
|
+
features?: string;
|
|
601
|
+
comment?: string;
|
|
602
|
+
description?: string;
|
|
603
|
+
image?: string;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
interface EquipmentTier {
|
|
607
|
+
tier: number;
|
|
608
|
+
allowNormal?: boolean;
|
|
609
|
+
items: EquipmentItem[];
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
interface Equipment {
|
|
613
|
+
armors: EquipmentTier[];
|
|
614
|
+
helmets: EquipmentTier[];
|
|
615
|
+
backpacks: EquipmentTier[];
|
|
616
|
+
chest_rigs: EquipmentTier[];
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
**Export**
|
|
621
|
+
|
|
622
|
+
```ts
|
|
623
|
+
import { EQUIPMENT } from 'delta-force-core';
|
|
624
|
+
|
|
625
|
+
EQUIPMENT.armors; // Armor, tiers 1–6
|
|
626
|
+
EQUIPMENT.helmets; // Helmet, tiers 1–6
|
|
627
|
+
EQUIPMENT.backpacks; // Backpack, tiers 1–6
|
|
628
|
+
EQUIPMENT.chest_rigs; // Chest rig, tiers 1–5
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
<a id="data-ammo"></a>
|
|
634
|
+
### Ammo
|
|
635
|
+
|
|
636
|
+
**Structure**
|
|
637
|
+
|
|
638
|
+
```ts
|
|
639
|
+
interface Ammo {
|
|
640
|
+
id: string;
|
|
641
|
+
name: string;
|
|
642
|
+
caliber: string;
|
|
643
|
+
description?: string;
|
|
644
|
+
image?: string;
|
|
645
|
+
}
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
> ⚠️ **Current granularity**: only caliber. Variants (e.g., M855 / M995) come later.
|
|
649
|
+
|
|
650
|
+
**Export**
|
|
651
|
+
|
|
652
|
+
```ts
|
|
653
|
+
import { AMMO } from 'delta-force-core';
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
**19 calibers currently**:
|
|
657
|
+
|
|
658
|
+
`.357 Magnum`, `.45 ACP`, `.58 AE`, `12 Gauge`, `12.7x55mm`, `5.45x39mm`, `5.56x45mm`, `5.7x28mm`, `5.8x42mm`, `6.8x51mm`, `7.62x39mm`, `7.62x51mm`, `7.62x54mm`, `9x19mm`, `9x39mm`, `4.6x30mm`, `.300 Blackout`, `箭矢`, `45-70 Govt`
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
<a id="index-json"></a>
|
|
663
|
+
## 📄 index.json
|
|
664
|
+
|
|
665
|
+
A full snapshot of the official data is generated at build time:
|
|
666
|
+
|
|
667
|
+
```json
|
|
668
|
+
{
|
|
669
|
+
"$schema": "https://raw.githubusercontent.com/delta-force-core/schema/main/v1.json",
|
|
670
|
+
"version": "0.2.0",
|
|
671
|
+
"generatedAt": "2026-10-14T00:34:01.102Z",
|
|
672
|
+
"operators": [...],
|
|
673
|
+
"weapons": [...],
|
|
674
|
+
"equipment": {...},
|
|
675
|
+
"ammo": [...]
|
|
676
|
+
}
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
**Use cases**:
|
|
680
|
+
|
|
681
|
+
- 🐍 Non-JS environments (e.g., Python scripts)
|
|
682
|
+
- 🌐 Direct CDN fetch (`https://unpkg.com/delta-force-core/index.json`)
|
|
683
|
+
- 📊 Data diffing
|
|
684
|
+
|
|
685
|
+
```js
|
|
686
|
+
// ESM
|
|
687
|
+
import data from 'delta-force-core/index.json' with { type: 'json' };
|
|
688
|
+
|
|
689
|
+
// CommonJS
|
|
690
|
+
const data = require('delta-force-core/index.json');
|
|
691
|
+
|
|
692
|
+
// HTTP
|
|
693
|
+
const res = await fetch('https://unpkg.com/delta-force-core/index.json');
|
|
694
|
+
const data = await res.json();
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
---
|
|
698
|
+
|
|
699
|
+
<a id="ecosystem"></a>
|
|
700
|
+
## 🌐 Ecosystem & Integrations
|
|
701
|
+
|
|
702
|
+
| Platform | Usage |
|
|
703
|
+
|---|---|
|
|
704
|
+
| **Node.js** | `npm install delta-force-core` |
|
|
705
|
+
| **Browser** | `https://esm.sh/delta-force-core` |
|
|
706
|
+
| **Deno** | `import ... from 'npm:delta-force-core'` |
|
|
707
|
+
| **Bun** | `bun add delta-force-core` |
|
|
708
|
+
| **Python** | Read `index.json` |
|
|
709
|
+
| **Discord.js** | See example below |
|
|
710
|
+
|
|
711
|
+
### Discord.js Example
|
|
712
|
+
|
|
713
|
+
```ts
|
|
714
|
+
import { Client, GatewayIntentBits, Events } from 'discord.js';
|
|
715
|
+
import { getRandomLoadout } from 'delta-force-core';
|
|
716
|
+
|
|
717
|
+
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
|
|
718
|
+
|
|
719
|
+
client.on(Events.InteractionCreate, async (interaction) => {
|
|
720
|
+
if (!interaction.isChatInputCommand()) return;
|
|
721
|
+
if (interaction.commandName !== 'random-loadout') return;
|
|
722
|
+
|
|
723
|
+
const l = getRandomLoadout({ allowNormal: true });
|
|
724
|
+
await interaction.reply({
|
|
725
|
+
content: [
|
|
726
|
+
`🧑 **Operator**: ${l.operator.name}`,
|
|
727
|
+
`🔫 **Weapon**: ${l.weapon.name}`,
|
|
728
|
+
`🛡 **Armor**: ${l.armor.name}`,
|
|
729
|
+
`⛑ **Helmet**: ${l.helmet.name}`,
|
|
730
|
+
`🎒 **Backpack**: ${l.backpack.name}`,
|
|
731
|
+
`🎽 **Chest rig**: ${l.chestRig.name}`,
|
|
732
|
+
].join('\n'),
|
|
733
|
+
});
|
|
734
|
+
});
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
---
|
|
738
|
+
|
|
739
|
+
<a id="contributing"></a>
|
|
740
|
+
## 🤝 Contributing
|
|
741
|
+
|
|
742
|
+
### Updating Data
|
|
743
|
+
|
|
744
|
+
**Just edit the corresponding file**:
|
|
745
|
+
|
|
746
|
+
```
|
|
747
|
+
src/data/
|
|
748
|
+
├─ operators.ts ← operators
|
|
749
|
+
├─ weapons.ts ← weapons
|
|
750
|
+
├─ equipment.ts ← equipment (armor / helmet / backpack / chest rig)
|
|
751
|
+
└─ ammo.ts ← ammo
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
### Example: add a weapon
|
|
755
|
+
|
|
756
|
+
```ts
|
|
757
|
+
// src/data/weapons.ts
|
|
758
|
+
{
|
|
759
|
+
category: '突击步枪',
|
|
760
|
+
weapons: [
|
|
761
|
+
// ...existing
|
|
762
|
+
{ id: 'new_rifle', name: 'New Rifle', allowNormal: true }, // ← add one line
|
|
763
|
+
],
|
|
764
|
+
},
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
### Workflow
|
|
768
|
+
|
|
769
|
+
```bash
|
|
770
|
+
# 1. edit data
|
|
771
|
+
vim src/data/weapons.ts
|
|
772
|
+
|
|
773
|
+
# 2. build + regenerate index.json
|
|
774
|
+
npm run build
|
|
775
|
+
|
|
776
|
+
# 3. commit
|
|
777
|
+
git add .
|
|
778
|
+
git commit -m "data: add XXX weapon"
|
|
779
|
+
git push origin main
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
### Rules
|
|
783
|
+
|
|
784
|
+
| Rule | Detail |
|
|
785
|
+
|---|---|
|
|
786
|
+
| `id` must be globally unique | Used for lookup; duplicates cause silent bugs |
|
|
787
|
+
| Do NOT add `quality` | Official data has no quality; users override it |
|
|
788
|
+
| `allowNormal` defaults to `true` | Only set `false` when needed |
|
|
789
|
+
| All optional fields use `?:` | Forward compatibility |
|
|
790
|
+
| New categories | Just append `{ category, weapons: [...] }` |
|
|
791
|
+
|
|
792
|
+
### Commit Convention
|
|
793
|
+
|
|
794
|
+
Following [Conventional Commits](https://www.conventionalcommits.org/):
|
|
795
|
+
|
|
796
|
+
| Prefix | Purpose |
|
|
797
|
+
|---|---|
|
|
798
|
+
| `feat:` | New feature |
|
|
799
|
+
| `fix:` | Bug fix |
|
|
800
|
+
| `data:` | Data update |
|
|
801
|
+
| `refactor:` | Refactor |
|
|
802
|
+
| `docs:` | Docs |
|
|
803
|
+
| `chore:` | Chore |
|
|
804
|
+
| `test:` | Tests |
|
|
805
|
+
|
|
806
|
+
Examples:
|
|
807
|
+
|
|
808
|
+
```
|
|
809
|
+
feat: add getRandomAmmo() with caliber filter
|
|
810
|
+
data: add 5 assault rifles
|
|
811
|
+
fix: correct AKM allowNormal flag
|
|
812
|
+
docs: update README installation
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
---
|
|
816
|
+
|
|
817
|
+
<a id="dev"></a>
|
|
818
|
+
## 🛠 Development
|
|
819
|
+
|
|
820
|
+
### Requirements
|
|
821
|
+
|
|
822
|
+
- Node.js ≥ 18
|
|
823
|
+
- TypeScript ≥ 5.4
|
|
824
|
+
|
|
825
|
+
### Setup
|
|
826
|
+
|
|
827
|
+
```bash
|
|
828
|
+
git clone https://github.com/Zhoyi011/delta-force-core.git
|
|
829
|
+
cd delta-force-core
|
|
830
|
+
npm install
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
### Project Structure
|
|
834
|
+
|
|
835
|
+
```text
|
|
836
|
+
delta-force-core/
|
|
837
|
+
├─ .gitignore
|
|
838
|
+
├─ package.json
|
|
839
|
+
├─ tsconfig.json
|
|
840
|
+
├─ README.md
|
|
841
|
+
├─ README.en.md
|
|
842
|
+
├─ LICENSE
|
|
843
|
+
├─ CONTRIBUTING.md
|
|
844
|
+
├─ index.json ← build artifact
|
|
845
|
+
├─ scripts/
|
|
846
|
+
│ └─ emit-json.mjs ← generate index.json
|
|
847
|
+
├─ src/
|
|
848
|
+
│ ├─ types.ts ← all type definitions
|
|
849
|
+
│ ├─ engine.ts ← engine (createEngine + all methods)
|
|
850
|
+
│ ├─ index.ts ← main entry
|
|
851
|
+
│ └─ data/
|
|
852
|
+
│ ├─ index.ts ← data barrel export
|
|
853
|
+
│ ├─ operators.ts
|
|
854
|
+
│ ├─ weapons.ts
|
|
855
|
+
│ ├─ equipment.ts
|
|
856
|
+
│ └─ ammo.ts
|
|
857
|
+
└─ .github/
|
|
858
|
+
└─ workflows/ ← CI / auto-publish
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
### Commands
|
|
862
|
+
|
|
863
|
+
```bash
|
|
864
|
+
npm run build # compile + generate index.json
|
|
865
|
+
npm run dev # watch mode
|
|
866
|
+
npm run emit-json # only generate index.json
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
### Publishing to npm
|
|
870
|
+
|
|
871
|
+
```bash
|
|
872
|
+
npm version patch # or minor / major
|
|
873
|
+
npm publish # auto-runs prepublishOnly → npm run build
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
---
|
|
877
|
+
|
|
878
|
+
<a id="roadmap"></a>
|
|
879
|
+
## 📅 Roadmap
|
|
880
|
+
|
|
881
|
+
<table>
|
|
882
|
+
<tr>
|
|
883
|
+
<th>Status</th>
|
|
884
|
+
<th>Feature</th>
|
|
885
|
+
<th>Version</th>
|
|
886
|
+
</tr>
|
|
887
|
+
<tr><td>✅ Done</td><td>Operators / Weapons / Equipment / Ammo</td><td>v0.1</td></tr>
|
|
888
|
+
<tr><td>✅ Done</td><td>Engine + user overrides (quality / alias / tag)</td><td>v0.2</td></tr>
|
|
889
|
+
<tr><td>🔄 In progress</td><td>Full README + docs</td><td>v0.2.x</td></tr>
|
|
890
|
+
<tr><td>📋 Planned</td><td>Attachment system (slots / compatibility)</td><td>v0.3</td></tr>
|
|
891
|
+
<tr><td>📋 Planned</td><td>Ammo variants (T1–T6, damage / pen)</td><td>v0.3</td></tr>
|
|
892
|
+
<tr><td>📋 Planned</td><td>Image assets</td><td>v0.4</td></tr>
|
|
893
|
+
<tr><td>💭 Considering</td><td>i18n (English / 日本語)</td><td>v1.0</td></tr>
|
|
894
|
+
</table>
|
|
895
|
+
|
|
896
|
+
---
|
|
897
|
+
|
|
898
|
+
<a id="faq"></a>
|
|
899
|
+
## ❓ FAQ
|
|
900
|
+
|
|
901
|
+
<details>
|
|
902
|
+
<summary><b>Q1: Why is there no <code>quality</code> on official weapons?</b></summary>
|
|
903
|
+
|
|
904
|
+
Quality is a **subjective rating**, not official data. We put it in the user override layer (`qualityOverride`) so everyone can use their own standards.
|
|
905
|
+
|
|
906
|
+
```ts
|
|
907
|
+
const engine = createEngine({
|
|
908
|
+
qualityOverride: { m4a1: '金色' },
|
|
909
|
+
});
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
</details>
|
|
913
|
+
|
|
914
|
+
<details>
|
|
915
|
+
<summary><b>Q2: Default engine vs custom engine?</b></summary>
|
|
916
|
+
|
|
917
|
+
**Default engine** `defaultEngine` = official data + empty overrides.
|
|
918
|
+
|
|
919
|
+
**Custom engine** = official data + your overrides. All methods behave identically, except custom engine applies your quality/alias/tag.
|
|
920
|
+
|
|
921
|
+
</details>
|
|
922
|
+
|
|
923
|
+
<details>
|
|
924
|
+
<summary><b>Q3: Can I use only the data without random picking?</b></summary>
|
|
925
|
+
|
|
926
|
+
Yes. Import data constants directly:
|
|
927
|
+
|
|
928
|
+
```ts
|
|
929
|
+
import { WEAPONS, OPERATORS, EQUIPMENT, AMMO } from 'delta-force-core';
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
Or use `index.json` (for non-JS environments).
|
|
933
|
+
|
|
934
|
+
</details>
|
|
935
|
+
|
|
936
|
+
<details>
|
|
937
|
+
<summary><b>Q4: How often is data updated?</b></summary>
|
|
938
|
+
|
|
939
|
+
Following game updates. We sync new equipment / weapons / operators as soon as possible.
|
|
940
|
+
|
|
941
|
+
You can also submit a PR to edit data files directly.
|
|
942
|
+
|
|
943
|
+
</details>
|
|
944
|
+
|
|
945
|
+
<details>
|
|
946
|
+
<summary><b>Q5: TypeScript support?</b></summary>
|
|
947
|
+
|
|
948
|
+
Written in native TypeScript, full type definitions. IDEs provide IntelliSense and type checking.
|
|
949
|
+
|
|
950
|
+
</details>
|
|
951
|
+
|
|
952
|
+
<details>
|
|
953
|
+
<summary><b>Q6: CommonJS support?</b></summary>
|
|
954
|
+
|
|
955
|
+
Main entry is **ES Module**. For CommonJS projects:
|
|
956
|
+
|
|
957
|
+
```js
|
|
958
|
+
// Option 1: dynamic import
|
|
959
|
+
const { getRandomLoadout } = await import('delta-force-core');
|
|
960
|
+
|
|
961
|
+
// Option 2: use JSON directly
|
|
962
|
+
const data = require('delta-force-core/index.json');
|
|
963
|
+
```
|
|
964
|
+
|
|
965
|
+
</details>
|
|
966
|
+
|
|
967
|
+
<details>
|
|
968
|
+
<summary><b>Q7: How to deploy my own <code>index.json</code>?</b></summary>
|
|
969
|
+
|
|
970
|
+
```bash
|
|
971
|
+
# fork the repo → edit data → build
|
|
972
|
+
npm run build
|
|
973
|
+
# output in dist/, index.json at root
|
|
974
|
+
```
|
|
975
|
+
|
|
976
|
+
Or use the one from the npm package:
|
|
977
|
+
|
|
978
|
+
```
|
|
979
|
+
https://unpkg.com/delta-force-core/index.json
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
</details>
|
|
983
|
+
|
|
984
|
+
<details>
|
|
985
|
+
<summary><b>Q8: How to contribute data fixes?</b></summary>
|
|
986
|
+
|
|
987
|
+
1. Fork the repo
|
|
988
|
+
2. Edit `src/data/*.ts`
|
|
989
|
+
3. `npm run build` to verify compilation
|
|
990
|
+
4. Submit a PR with source (screenshot / official announcement)
|
|
991
|
+
|
|
992
|
+
See the [Contributing](#contributing) section.
|
|
993
|
+
|
|
994
|
+
</details>
|
|
995
|
+
|
|
996
|
+
---
|
|
997
|
+
|
|
998
|
+
<a id="license"></a>
|
|
999
|
+
## 📜 License
|
|
1000
|
+
|
|
1001
|
+
Released under the [MIT License](./LICENSE).
|
|
1002
|
+
|
|
1003
|
+
---
|
|
1004
|
+
|
|
1005
|
+
<a id="thanks"></a>
|
|
1006
|
+
## ❤️ Credits
|
|
1007
|
+
|
|
1008
|
+
- Thanks to all community members who contributed Delta Force data
|
|
1009
|
+
- Thanks to [Shields.io](https://shields.io/) for badges
|
|
1010
|
+
- Thanks to [unpkg](https://unpkg.com/) / [esm.sh](https://esm.sh/) for CDN
|
|
1011
|
+
|
|
1012
|
+
---
|
|
1013
|
+
|
|
1014
|
+
<div align="center">
|
|
1015
|
+
|
|
1016
|
+
**If this project helps you, please give it a ⭐ Star!**
|
|
1017
|
+
|
|
1018
|
+
[⬆ Back to Top](#delta-force-core)
|
|
1019
|
+
|
|
1020
|
+
</div>
|