@its-not-rocket-science/ananke 0.1.0

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 (311) hide show
  1. package/CHANGELOG.md +135 -0
  2. package/LICENSE +21 -0
  3. package/README.md +2199 -0
  4. package/STABLE_API.md +266 -0
  5. package/dist/src/anatomy/anatomy-compiler.d.ts +14 -0
  6. package/dist/src/anatomy/anatomy-compiler.js +277 -0
  7. package/dist/src/anatomy/anatomy-contracts.d.ts +94 -0
  8. package/dist/src/anatomy/anatomy-contracts.js +1 -0
  9. package/dist/src/anatomy/anatomy-helpers.d.ts +82 -0
  10. package/dist/src/anatomy/anatomy-helpers.js +233 -0
  11. package/dist/src/anatomy/anatomy-schema.d.ts +28 -0
  12. package/dist/src/anatomy/anatomy-schema.js +388 -0
  13. package/dist/src/anatomy/index.d.ts +4 -0
  14. package/dist/src/anatomy/index.js +4 -0
  15. package/dist/src/archetypes.d.ts +87 -0
  16. package/dist/src/archetypes.js +285 -0
  17. package/dist/src/arena.d.ts +173 -0
  18. package/dist/src/arena.js +695 -0
  19. package/dist/src/bridge/bridge-engine.d.ts +46 -0
  20. package/dist/src/bridge/bridge-engine.js +252 -0
  21. package/dist/src/bridge/index.d.ts +4 -0
  22. package/dist/src/bridge/index.js +5 -0
  23. package/dist/src/bridge/interpolation.d.ts +64 -0
  24. package/dist/src/bridge/interpolation.js +130 -0
  25. package/dist/src/bridge/mapping.d.ts +33 -0
  26. package/dist/src/bridge/mapping.js +54 -0
  27. package/dist/src/bridge/types.d.ts +94 -0
  28. package/dist/src/bridge/types.js +2 -0
  29. package/dist/src/campaign.d.ts +141 -0
  30. package/dist/src/campaign.js +235 -0
  31. package/dist/src/channels.d.ts +15 -0
  32. package/dist/src/channels.js +20 -0
  33. package/dist/src/chronicle.d.ts +124 -0
  34. package/dist/src/chronicle.js +232 -0
  35. package/dist/src/collective-activities.d.ts +154 -0
  36. package/dist/src/collective-activities.js +247 -0
  37. package/dist/src/competence/acoustic.d.ts +101 -0
  38. package/dist/src/competence/acoustic.js +242 -0
  39. package/dist/src/competence/catalogue.d.ts +30 -0
  40. package/dist/src/competence/catalogue.js +241 -0
  41. package/dist/src/competence/crafting.d.ts +35 -0
  42. package/dist/src/competence/crafting.js +88 -0
  43. package/dist/src/competence/engineering.d.ts +53 -0
  44. package/dist/src/competence/engineering.js +108 -0
  45. package/dist/src/competence/framework.d.ts +68 -0
  46. package/dist/src/competence/framework.js +694 -0
  47. package/dist/src/competence/index.d.ts +12 -0
  48. package/dist/src/competence/index.js +13 -0
  49. package/dist/src/competence/interspecies.d.ts +81 -0
  50. package/dist/src/competence/interspecies.js +108 -0
  51. package/dist/src/competence/language.d.ts +79 -0
  52. package/dist/src/competence/language.js +115 -0
  53. package/dist/src/competence/naturalist.d.ts +97 -0
  54. package/dist/src/competence/naturalist.js +187 -0
  55. package/dist/src/competence/navigation.d.ts +24 -0
  56. package/dist/src/competence/navigation.js +48 -0
  57. package/dist/src/competence/performance.d.ts +125 -0
  58. package/dist/src/competence/performance.js +210 -0
  59. package/dist/src/competence/teaching.d.ts +64 -0
  60. package/dist/src/competence/teaching.js +121 -0
  61. package/dist/src/competence/willpower.d.ts +74 -0
  62. package/dist/src/competence/willpower.js +114 -0
  63. package/dist/src/crafting/index.d.ts +55 -0
  64. package/dist/src/crafting/index.js +229 -0
  65. package/dist/src/crafting/manufacturing.d.ts +83 -0
  66. package/dist/src/crafting/manufacturing.js +165 -0
  67. package/dist/src/crafting/materials.d.ts +53 -0
  68. package/dist/src/crafting/materials.js +120 -0
  69. package/dist/src/crafting/recipes.d.ts +75 -0
  70. package/dist/src/crafting/recipes.js +233 -0
  71. package/dist/src/crafting/workshops.d.ts +61 -0
  72. package/dist/src/crafting/workshops.js +170 -0
  73. package/dist/src/debug.d.ts +86 -0
  74. package/dist/src/debug.js +76 -0
  75. package/dist/src/derive.d.ts +21 -0
  76. package/dist/src/derive.js +88 -0
  77. package/dist/src/describe.d.ts +29 -0
  78. package/dist/src/describe.js +276 -0
  79. package/dist/src/dialogue.d.ts +122 -0
  80. package/dist/src/dialogue.js +266 -0
  81. package/dist/src/dist.d.ts +20 -0
  82. package/dist/src/dist.js +39 -0
  83. package/dist/src/downtime.d.ts +89 -0
  84. package/dist/src/downtime.js +391 -0
  85. package/dist/src/economy.d.ts +116 -0
  86. package/dist/src/economy.js +182 -0
  87. package/dist/src/emotional-contagion.d.ts +142 -0
  88. package/dist/src/emotional-contagion.js +274 -0
  89. package/dist/src/equipment.d.ts +206 -0
  90. package/dist/src/equipment.js +598 -0
  91. package/dist/src/faction.d.ts +102 -0
  92. package/dist/src/faction.js +237 -0
  93. package/dist/src/generate.d.ts +35 -0
  94. package/dist/src/generate.js +166 -0
  95. package/dist/src/index.d.ts +42 -0
  96. package/dist/src/index.js +54 -0
  97. package/dist/src/inheritance.d.ts +69 -0
  98. package/dist/src/inheritance.js +136 -0
  99. package/dist/src/inventory.d.ts +194 -0
  100. package/dist/src/inventory.js +637 -0
  101. package/dist/src/item-durability.d.ts +69 -0
  102. package/dist/src/item-durability.js +308 -0
  103. package/dist/src/legend.d.ts +97 -0
  104. package/dist/src/legend.js +269 -0
  105. package/dist/src/lod.d.ts +9 -0
  106. package/dist/src/lod.js +84 -0
  107. package/dist/src/metrics.d.ts +51 -0
  108. package/dist/src/metrics.js +91 -0
  109. package/dist/src/model3d.d.ts +138 -0
  110. package/dist/src/model3d.js +214 -0
  111. package/dist/src/mythology.d.ts +101 -0
  112. package/dist/src/mythology.js +308 -0
  113. package/dist/src/narrative-render.d.ts +42 -0
  114. package/dist/src/narrative-render.js +194 -0
  115. package/dist/src/narrative-stress.d.ts +123 -0
  116. package/dist/src/narrative-stress.js +183 -0
  117. package/dist/src/narrative.d.ts +44 -0
  118. package/dist/src/narrative.js +257 -0
  119. package/dist/src/party.d.ts +70 -0
  120. package/dist/src/party.js +226 -0
  121. package/dist/src/polity.d.ts +262 -0
  122. package/dist/src/polity.js +398 -0
  123. package/dist/src/presets.d.ts +42 -0
  124. package/dist/src/presets.js +170 -0
  125. package/dist/src/progression.d.ts +170 -0
  126. package/dist/src/progression.js +256 -0
  127. package/dist/src/quest-generators.d.ts +76 -0
  128. package/dist/src/quest-generators.js +534 -0
  129. package/dist/src/quest.d.ts +239 -0
  130. package/dist/src/quest.js +520 -0
  131. package/dist/src/relationships-effects.d.ts +75 -0
  132. package/dist/src/relationships-effects.js +219 -0
  133. package/dist/src/relationships.d.ts +104 -0
  134. package/dist/src/relationships.js +347 -0
  135. package/dist/src/replay.d.ts +47 -0
  136. package/dist/src/replay.js +82 -0
  137. package/dist/src/rng.d.ts +9 -0
  138. package/dist/src/rng.js +37 -0
  139. package/dist/src/settlement-services.d.ts +67 -0
  140. package/dist/src/settlement-services.js +267 -0
  141. package/dist/src/settlement.d.ts +143 -0
  142. package/dist/src/settlement.js +419 -0
  143. package/dist/src/sim/action.d.ts +28 -0
  144. package/dist/src/sim/action.js +12 -0
  145. package/dist/src/sim/aging.d.ts +95 -0
  146. package/dist/src/sim/aging.js +243 -0
  147. package/dist/src/sim/ai/decide.d.ts +10 -0
  148. package/dist/src/sim/ai/decide.js +267 -0
  149. package/dist/src/sim/ai/perception.d.ts +12 -0
  150. package/dist/src/sim/ai/perception.js +54 -0
  151. package/dist/src/sim/ai/personality.d.ts +54 -0
  152. package/dist/src/sim/ai/personality.js +202 -0
  153. package/dist/src/sim/ai/presets.d.ts +2 -0
  154. package/dist/src/sim/ai/presets.js +28 -0
  155. package/dist/src/sim/ai/system.d.ts +6 -0
  156. package/dist/src/sim/ai/system.js +13 -0
  157. package/dist/src/sim/ai/targeting.d.ts +8 -0
  158. package/dist/src/sim/ai/targeting.js +42 -0
  159. package/dist/src/sim/ai/types.d.ts +14 -0
  160. package/dist/src/sim/ai/types.js +1 -0
  161. package/dist/src/sim/body.d.ts +9 -0
  162. package/dist/src/sim/body.js +32 -0
  163. package/dist/src/sim/bodyplan.d.ts +161 -0
  164. package/dist/src/sim/bodyplan.js +677 -0
  165. package/dist/src/sim/capability.d.ts +135 -0
  166. package/dist/src/sim/capability.js +8 -0
  167. package/dist/src/sim/combat.d.ts +21 -0
  168. package/dist/src/sim/combat.js +77 -0
  169. package/dist/src/sim/commandBuilders.d.ts +11 -0
  170. package/dist/src/sim/commandBuilders.js +39 -0
  171. package/dist/src/sim/commands.d.ts +71 -0
  172. package/dist/src/sim/commands.js +8 -0
  173. package/dist/src/sim/condition.d.ts +35 -0
  174. package/dist/src/sim/condition.js +21 -0
  175. package/dist/src/sim/cone.d.ts +40 -0
  176. package/dist/src/sim/cone.js +44 -0
  177. package/dist/src/sim/context.d.ts +68 -0
  178. package/dist/src/sim/context.js +1 -0
  179. package/dist/src/sim/density.d.ts +14 -0
  180. package/dist/src/sim/density.js +33 -0
  181. package/dist/src/sim/disease.d.ts +141 -0
  182. package/dist/src/sim/disease.js +353 -0
  183. package/dist/src/sim/entity.d.ts +251 -0
  184. package/dist/src/sim/entity.js +19 -0
  185. package/dist/src/sim/events.d.ts +25 -0
  186. package/dist/src/sim/events.js +5 -0
  187. package/dist/src/sim/explosion.d.ts +40 -0
  188. package/dist/src/sim/explosion.js +40 -0
  189. package/dist/src/sim/formation-unit.d.ts +138 -0
  190. package/dist/src/sim/formation-unit.js +197 -0
  191. package/dist/src/sim/formation.d.ts +12 -0
  192. package/dist/src/sim/formation.js +54 -0
  193. package/dist/src/sim/frontage.d.ts +30 -0
  194. package/dist/src/sim/frontage.js +84 -0
  195. package/dist/src/sim/grapple.d.ts +100 -0
  196. package/dist/src/sim/grapple.js +480 -0
  197. package/dist/src/sim/hazard.d.ts +104 -0
  198. package/dist/src/sim/hazard.js +201 -0
  199. package/dist/src/sim/hydrostatic.d.ts +58 -0
  200. package/dist/src/sim/hydrostatic.js +117 -0
  201. package/dist/src/sim/impairment.d.ts +20 -0
  202. package/dist/src/sim/impairment.js +162 -0
  203. package/dist/src/sim/indexing.d.ts +7 -0
  204. package/dist/src/sim/indexing.js +7 -0
  205. package/dist/src/sim/injury.d.ts +54 -0
  206. package/dist/src/sim/injury.js +66 -0
  207. package/dist/src/sim/intent.d.ts +26 -0
  208. package/dist/src/sim/intent.js +7 -0
  209. package/dist/src/sim/kernel.d.ts +45 -0
  210. package/dist/src/sim/kernel.js +1992 -0
  211. package/dist/src/sim/kinds.d.ts +64 -0
  212. package/dist/src/sim/kinds.js +56 -0
  213. package/dist/src/sim/knockback.d.ts +50 -0
  214. package/dist/src/sim/knockback.js +82 -0
  215. package/dist/src/sim/limb.d.ts +48 -0
  216. package/dist/src/sim/limb.js +78 -0
  217. package/dist/src/sim/medical.d.ts +32 -0
  218. package/dist/src/sim/medical.js +33 -0
  219. package/dist/src/sim/morale.d.ts +69 -0
  220. package/dist/src/sim/morale.js +92 -0
  221. package/dist/src/sim/mount.d.ts +150 -0
  222. package/dist/src/sim/mount.js +225 -0
  223. package/dist/src/sim/nutrition.d.ts +74 -0
  224. package/dist/src/sim/nutrition.js +168 -0
  225. package/dist/src/sim/occlusion.d.ts +8 -0
  226. package/dist/src/sim/occlusion.js +71 -0
  227. package/dist/src/sim/push.d.ts +11 -0
  228. package/dist/src/sim/push.js +79 -0
  229. package/dist/src/sim/ranged.d.ts +44 -0
  230. package/dist/src/sim/ranged.js +69 -0
  231. package/dist/src/sim/seeds.d.ts +3 -0
  232. package/dist/src/sim/seeds.js +16 -0
  233. package/dist/src/sim/sensory-extended.d.ts +103 -0
  234. package/dist/src/sim/sensory-extended.js +181 -0
  235. package/dist/src/sim/sensory.d.ts +38 -0
  236. package/dist/src/sim/sensory.js +109 -0
  237. package/dist/src/sim/skills.d.ts +70 -0
  238. package/dist/src/sim/skills.js +69 -0
  239. package/dist/src/sim/sleep.d.ts +107 -0
  240. package/dist/src/sim/sleep.js +215 -0
  241. package/dist/src/sim/spatial.d.ts +8 -0
  242. package/dist/src/sim/spatial.js +59 -0
  243. package/dist/src/sim/step/capability.d.ts +8 -0
  244. package/dist/src/sim/step/capability.js +77 -0
  245. package/dist/src/sim/step/concentration.d.ts +9 -0
  246. package/dist/src/sim/step/concentration.js +25 -0
  247. package/dist/src/sim/step/effects.d.ts +17 -0
  248. package/dist/src/sim/step/effects.js +96 -0
  249. package/dist/src/sim/step/energy.d.ts +3 -0
  250. package/dist/src/sim/step/energy.js +31 -0
  251. package/dist/src/sim/step/hazards.d.ts +4 -0
  252. package/dist/src/sim/step/hazards.js +19 -0
  253. package/dist/src/sim/step/injury.d.ts +10 -0
  254. package/dist/src/sim/step/injury.js +353 -0
  255. package/dist/src/sim/step/morale.d.ts +11 -0
  256. package/dist/src/sim/step/morale.js +130 -0
  257. package/dist/src/sim/step/movement.d.ts +5 -0
  258. package/dist/src/sim/step/movement.js +172 -0
  259. package/dist/src/sim/step/push.d.ts +11 -0
  260. package/dist/src/sim/step/push.js +79 -0
  261. package/dist/src/sim/step/substances.d.ts +3 -0
  262. package/dist/src/sim/step/substances.js +75 -0
  263. package/dist/src/sim/substance.d.ts +38 -0
  264. package/dist/src/sim/substance.js +57 -0
  265. package/dist/src/sim/systemic-toxicology.d.ts +109 -0
  266. package/dist/src/sim/systemic-toxicology.js +263 -0
  267. package/dist/src/sim/team.d.ts +9 -0
  268. package/dist/src/sim/team.js +37 -0
  269. package/dist/src/sim/tech.d.ts +36 -0
  270. package/dist/src/sim/tech.js +46 -0
  271. package/dist/src/sim/terrain.d.ts +121 -0
  272. package/dist/src/sim/terrain.js +141 -0
  273. package/dist/src/sim/testing.d.ts +13 -0
  274. package/dist/src/sim/testing.js +100 -0
  275. package/dist/src/sim/thermoregulation.d.ts +77 -0
  276. package/dist/src/sim/thermoregulation.js +161 -0
  277. package/dist/src/sim/tick.d.ts +3 -0
  278. package/dist/src/sim/tick.js +3 -0
  279. package/dist/src/sim/toxicology.d.ts +52 -0
  280. package/dist/src/sim/toxicology.js +104 -0
  281. package/dist/src/sim/trace.d.ts +141 -0
  282. package/dist/src/sim/trace.js +1 -0
  283. package/dist/src/sim/tuning.d.ts +16 -0
  284. package/dist/src/sim/tuning.js +42 -0
  285. package/dist/src/sim/vec3.d.ts +14 -0
  286. package/dist/src/sim/vec3.js +31 -0
  287. package/dist/src/sim/weapon_dynamics.d.ts +102 -0
  288. package/dist/src/sim/weapon_dynamics.js +142 -0
  289. package/dist/src/sim/weather.d.ts +95 -0
  290. package/dist/src/sim/weather.js +105 -0
  291. package/dist/src/sim/world.d.ts +52 -0
  292. package/dist/src/sim/world.js +1 -0
  293. package/dist/src/sim/wound-aging.d.ts +120 -0
  294. package/dist/src/sim/wound-aging.js +223 -0
  295. package/dist/src/species.d.ts +106 -0
  296. package/dist/src/species.js +664 -0
  297. package/dist/src/story-arcs.d.ts +17 -0
  298. package/dist/src/story-arcs.js +276 -0
  299. package/dist/src/tech-diffusion.d.ts +80 -0
  300. package/dist/src/tech-diffusion.js +185 -0
  301. package/dist/src/traits.d.ts +25 -0
  302. package/dist/src/traits.js +178 -0
  303. package/dist/src/types.d.ts +117 -0
  304. package/dist/src/types.js +1 -0
  305. package/dist/src/units.d.ts +41 -0
  306. package/dist/src/units.js +64 -0
  307. package/dist/src/weapons.d.ts +20 -0
  308. package/dist/src/weapons.js +824 -0
  309. package/dist/src/world-generation.d.ts +52 -0
  310. package/dist/src/world-generation.js +301 -0
  311. package/package.json +74 -0
@@ -0,0 +1,824 @@
1
+ /**
2
+ * Phase 17: Historical weapons database
3
+ * Spans six eras with realistic physical properties calibrated to archaeological and
4
+ * biomechanics literature. All units follow the project SI fixed-point conventions.
5
+ */
6
+ import { q, to } from "./units.js";
7
+ // ─── Shared damage profiles ────────────────────────────────────────────────────
8
+ const dmg = (surfF, intF, strF, bleed, pen) => ({
9
+ surfaceFrac: q(surfF),
10
+ internalFrac: q(intF),
11
+ structuralFrac: q(strF),
12
+ bleedFactor: q(bleed),
13
+ penetrationBias: q(pen),
14
+ });
15
+ // Shared projectile profiles
16
+ const ARROW_DMG = dmg(0.20, 0.65, 0.15, 0.90, 0.70); // bodkin arrow
17
+ const BULLET_DMG = dmg(0.20, 0.60, 0.20, 0.70, 0.65); // generic bullet
18
+ const RIFLE_DMG = dmg(0.15, 0.65, 0.20, 0.65, 0.75); // jacketed rifle bullet
19
+ const THROWN_DMG = dmg(0.30, 0.50, 0.20, 0.60, 0.45); // thrown spear / javelin
20
+ // ─── PREHISTORIC MELEE ─────────────────────────────────────────────────────────
21
+ export const PREHISTORIC_MELEE = [
22
+ {
23
+ id: "wpn_hand_axe",
24
+ kind: "weapon",
25
+ name: "Hand Axe",
26
+ mass_kg: to.kg(0.50),
27
+ bulk: q(1.0),
28
+ reach_m: to.m(0.25),
29
+ handedness: "oneHand",
30
+ momentArm_m: to.m(0.18),
31
+ readyTime_s: to.s(0.50),
32
+ damage: dmg(0.55, 0.35, 0.10, 0.80, 0.15),
33
+ },
34
+ {
35
+ id: "wpn_war_club",
36
+ kind: "weapon",
37
+ name: "War Club",
38
+ mass_kg: to.kg(1.00),
39
+ bulk: q(1.3),
40
+ reach_m: to.m(0.55),
41
+ handedness: "oneHand",
42
+ momentArm_m: to.m(0.22),
43
+ readyTime_s: to.s(0.55),
44
+ damage: dmg(0.25, 0.25, 0.50, 0.15, 0.05),
45
+ },
46
+ {
47
+ id: "wpn_flint_knife",
48
+ kind: "weapon",
49
+ name: "Flint Knife",
50
+ mass_kg: to.kg(0.15),
51
+ bulk: q(0.9),
52
+ reach_m: to.m(0.18),
53
+ handedness: "oneHand",
54
+ momentArm_m: to.m(0.12),
55
+ readyTime_s: to.s(0.30),
56
+ damage: dmg(0.55, 0.35, 0.10, 0.85, 0.20),
57
+ },
58
+ {
59
+ id: "wpn_flint_spear",
60
+ kind: "weapon",
61
+ name: "Flint-tipped Spear",
62
+ mass_kg: to.kg(0.90),
63
+ bulk: q(1.4),
64
+ reach_m: to.m(1.90),
65
+ handedness: "twoHand",
66
+ momentArm_m: to.m(0.65),
67
+ readyTime_s: to.s(0.45),
68
+ damage: dmg(0.25, 0.60, 0.15, 0.65, 0.55),
69
+ },
70
+ {
71
+ id: "wpn_bone_dagger",
72
+ kind: "weapon",
73
+ name: "Bone Dagger",
74
+ mass_kg: to.kg(0.12),
75
+ bulk: q(0.8),
76
+ reach_m: to.m(0.15),
77
+ handedness: "oneHand",
78
+ momentArm_m: to.m(0.10),
79
+ readyTime_s: to.s(0.28),
80
+ damage: dmg(0.45, 0.40, 0.15, 0.70, 0.30),
81
+ },
82
+ ];
83
+ // ─── CLASSICAL MELEE ──────────────────────────────────────────────────────────
84
+ export const CLASSICAL_MELEE = [
85
+ {
86
+ id: "wpn_pugio",
87
+ kind: "weapon",
88
+ name: "Pugio",
89
+ mass_kg: to.kg(0.30),
90
+ bulk: q(0.9),
91
+ reach_m: to.m(0.22),
92
+ handedness: "oneHand",
93
+ momentArm_m: to.m(0.14),
94
+ readyTime_s: to.s(0.32),
95
+ damage: dmg(0.35, 0.50, 0.15, 0.75, 0.60),
96
+ },
97
+ {
98
+ id: "wpn_gladius",
99
+ kind: "weapon",
100
+ name: "Gladius",
101
+ mass_kg: to.kg(0.90),
102
+ bulk: q(1.2),
103
+ reach_m: to.m(0.55),
104
+ handedness: "oneHand",
105
+ momentArm_m: to.m(0.35),
106
+ readyTime_s: to.s(0.48),
107
+ damage: dmg(0.40, 0.45, 0.15, 0.70, 0.45),
108
+ },
109
+ {
110
+ id: "wpn_xiphos",
111
+ kind: "weapon",
112
+ name: "Xiphos",
113
+ mass_kg: to.kg(0.80),
114
+ bulk: q(1.2),
115
+ reach_m: to.m(0.62),
116
+ handedness: "oneHand",
117
+ momentArm_m: to.m(0.38),
118
+ readyTime_s: to.s(0.50),
119
+ damage: dmg(0.45, 0.40, 0.15, 0.70, 0.35),
120
+ },
121
+ {
122
+ id: "wpn_kopis",
123
+ kind: "weapon",
124
+ name: "Kopis",
125
+ mass_kg: to.kg(0.75),
126
+ bulk: q(1.2),
127
+ reach_m: to.m(0.62),
128
+ handedness: "oneHand",
129
+ momentArm_m: to.m(0.32),
130
+ readyTime_s: to.s(0.52),
131
+ damage: dmg(0.60, 0.30, 0.10, 0.75, 0.10),
132
+ },
133
+ {
134
+ id: "wpn_spatha",
135
+ kind: "weapon",
136
+ name: "Spatha",
137
+ mass_kg: to.kg(1.10),
138
+ bulk: q(1.4),
139
+ reach_m: to.m(0.90),
140
+ handedness: "oneHand",
141
+ momentArm_m: to.m(0.45),
142
+ readyTime_s: to.s(0.58),
143
+ damage: dmg(0.45, 0.40, 0.15, 0.65, 0.30),
144
+ },
145
+ {
146
+ id: "wpn_dory",
147
+ kind: "weapon",
148
+ name: "Dory",
149
+ mass_kg: to.kg(0.80),
150
+ bulk: q(1.5),
151
+ reach_m: to.m(2.20),
152
+ handedness: "twoHand",
153
+ momentArm_m: to.m(0.70),
154
+ readyTime_s: to.s(0.45),
155
+ damage: dmg(0.20, 0.65, 0.15, 0.60, 0.60),
156
+ },
157
+ {
158
+ id: "wpn_sarissa",
159
+ kind: "weapon",
160
+ name: "Sarissa",
161
+ mass_kg: to.kg(1.50),
162
+ bulk: q(2.0),
163
+ reach_m: to.m(5.50),
164
+ handedness: "twoHand",
165
+ momentArm_m: to.m(0.85),
166
+ readyTime_s: to.s(0.90),
167
+ damage: dmg(0.20, 0.65, 0.15, 0.55, 0.65),
168
+ },
169
+ {
170
+ id: "wpn_pilum",
171
+ kind: "weapon",
172
+ name: "Pilum",
173
+ mass_kg: to.kg(1.00),
174
+ bulk: q(1.4),
175
+ reach_m: to.m(0.45),
176
+ handedness: "oneHand",
177
+ momentArm_m: to.m(0.28),
178
+ readyTime_s: to.s(0.55),
179
+ damage: dmg(0.20, 0.65, 0.15, 0.55, 0.65),
180
+ },
181
+ ];
182
+ // ─── MEDIEVAL MELEE ───────────────────────────────────────────────────────────
183
+ export const MEDIEVAL_MELEE = [
184
+ {
185
+ id: "wpn_arming_sword",
186
+ kind: "weapon",
187
+ name: "Arming Sword",
188
+ mass_kg: to.kg(1.10),
189
+ bulk: q(1.3),
190
+ reach_m: to.m(0.85),
191
+ handedness: "oneHand",
192
+ momentArm_m: to.m(0.45),
193
+ readyTime_s: to.s(0.50),
194
+ damage: dmg(0.40, 0.45, 0.15, 0.65, 0.30),
195
+ },
196
+ {
197
+ id: "wpn_dane_axe",
198
+ kind: "weapon",
199
+ name: "Dane Axe",
200
+ mass_kg: to.kg(1.30),
201
+ bulk: q(1.6),
202
+ reach_m: to.m(1.15),
203
+ handedness: "twoHand",
204
+ momentArm_m: to.m(0.55),
205
+ readyTime_s: to.s(0.65),
206
+ damage: dmg(0.55, 0.30, 0.15, 0.75, 0.15),
207
+ },
208
+ {
209
+ id: "wpn_battle_axe",
210
+ kind: "weapon",
211
+ name: "Battle Axe",
212
+ mass_kg: to.kg(1.50),
213
+ bulk: q(1.5),
214
+ reach_m: to.m(0.65),
215
+ handedness: "oneHand",
216
+ momentArm_m: to.m(0.38),
217
+ readyTime_s: to.s(0.60),
218
+ damage: dmg(0.60, 0.25, 0.15, 0.70, 0.15),
219
+ },
220
+ {
221
+ id: "wpn_flanged_mace",
222
+ kind: "weapon",
223
+ name: "Flanged Mace",
224
+ mass_kg: to.kg(1.20),
225
+ bulk: q(1.4),
226
+ reach_m: to.m(0.58),
227
+ handedness: "oneHand",
228
+ momentArm_m: to.m(0.32),
229
+ readyTime_s: to.s(0.55),
230
+ damage: dmg(0.15, 0.30, 0.55, 0.10, 0.05),
231
+ },
232
+ {
233
+ id: "wpn_war_flail",
234
+ kind: "weapon",
235
+ name: "War Flail",
236
+ mass_kg: to.kg(1.50),
237
+ bulk: q(1.6),
238
+ reach_m: to.m(0.75),
239
+ handedness: "oneHand",
240
+ momentArm_m: to.m(0.35),
241
+ readyTime_s: to.s(0.65),
242
+ shieldBypassQ: q(0.55),
243
+ damage: dmg(0.25, 0.35, 0.40, 0.20, 0.10),
244
+ },
245
+ {
246
+ id: "wpn_morning_star",
247
+ kind: "weapon",
248
+ name: "Morning Star",
249
+ mass_kg: to.kg(1.40),
250
+ bulk: q(1.5),
251
+ reach_m: to.m(0.62),
252
+ handedness: "oneHand",
253
+ momentArm_m: to.m(0.30),
254
+ readyTime_s: to.s(0.60),
255
+ shieldBypassQ: q(0.40),
256
+ damage: dmg(0.25, 0.30, 0.45, 0.25, 0.20),
257
+ },
258
+ {
259
+ id: "wpn_military_pick",
260
+ kind: "weapon",
261
+ name: "Military Pick",
262
+ mass_kg: to.kg(1.30),
263
+ bulk: q(1.4),
264
+ reach_m: to.m(0.60),
265
+ handedness: "oneHand",
266
+ momentArm_m: to.m(0.32),
267
+ readyTime_s: to.s(0.60),
268
+ damage: dmg(0.10, 0.20, 0.70, 0.05, 0.70),
269
+ },
270
+ {
271
+ id: "wpn_warhammer_med",
272
+ kind: "weapon",
273
+ name: "War Hammer",
274
+ mass_kg: to.kg(1.50),
275
+ bulk: q(1.5),
276
+ reach_m: to.m(0.65),
277
+ handedness: "oneHand",
278
+ momentArm_m: to.m(0.35),
279
+ readyTime_s: to.s(0.60),
280
+ damage: dmg(0.10, 0.30, 0.60, 0.05, 0.05),
281
+ },
282
+ {
283
+ id: "wpn_halberd",
284
+ kind: "weapon",
285
+ name: "Halberd",
286
+ mass_kg: to.kg(2.50),
287
+ bulk: q(2.0),
288
+ reach_m: to.m(1.80),
289
+ handedness: "twoHand",
290
+ momentArm_m: to.m(0.70),
291
+ readyTime_s: to.s(0.75),
292
+ damage: dmg(0.45, 0.35, 0.20, 0.60, 0.35),
293
+ },
294
+ {
295
+ id: "wpn_glaive",
296
+ kind: "weapon",
297
+ name: "Glaive",
298
+ mass_kg: to.kg(2.00),
299
+ bulk: q(1.9),
300
+ reach_m: to.m(1.75),
301
+ handedness: "twoHand",
302
+ momentArm_m: to.m(0.65),
303
+ readyTime_s: to.s(0.70),
304
+ damage: dmg(0.60, 0.25, 0.15, 0.70, 0.10),
305
+ },
306
+ {
307
+ id: "wpn_bastard_sword",
308
+ kind: "weapon",
309
+ name: "Bastard Sword",
310
+ mass_kg: to.kg(1.60),
311
+ bulk: q(1.6),
312
+ reach_m: to.m(1.00),
313
+ handedness: "oneHand",
314
+ momentArm_m: to.m(0.50),
315
+ readyTime_s: to.s(0.60),
316
+ damage: dmg(0.40, 0.45, 0.15, 0.65, 0.35),
317
+ },
318
+ {
319
+ id: "wpn_zweihander",
320
+ kind: "weapon",
321
+ name: "Zweihänder",
322
+ mass_kg: to.kg(3.00),
323
+ bulk: q(2.2),
324
+ reach_m: to.m(1.45),
325
+ handedness: "twoHand",
326
+ momentArm_m: to.m(0.65),
327
+ readyTime_s: to.s(0.85),
328
+ damage: dmg(0.50, 0.30, 0.20, 0.65, 0.10),
329
+ },
330
+ ];
331
+ // ─── RENAISSANCE MELEE ────────────────────────────────────────────────────────
332
+ export const RENAISSANCE_MELEE = [
333
+ {
334
+ id: "wpn_rapier",
335
+ kind: "weapon",
336
+ name: "Rapier",
337
+ mass_kg: to.kg(1.00),
338
+ bulk: q(1.2),
339
+ reach_m: to.m(1.02),
340
+ handedness: "oneHand",
341
+ momentArm_m: to.m(0.48),
342
+ readyTime_s: to.s(0.45),
343
+ damage: dmg(0.15, 0.70, 0.15, 0.60, 0.80),
344
+ },
345
+ {
346
+ id: "wpn_sidesword",
347
+ kind: "weapon",
348
+ name: "Sidesword",
349
+ mass_kg: to.kg(1.20),
350
+ bulk: q(1.3),
351
+ reach_m: to.m(0.88),
352
+ handedness: "oneHand",
353
+ momentArm_m: to.m(0.44),
354
+ readyTime_s: to.s(0.48),
355
+ damage: dmg(0.35, 0.50, 0.15, 0.60, 0.45),
356
+ },
357
+ {
358
+ id: "wpn_estoc",
359
+ kind: "weapon",
360
+ name: "Estoc",
361
+ mass_kg: to.kg(1.40),
362
+ bulk: q(1.4),
363
+ reach_m: to.m(1.10),
364
+ handedness: "oneHand",
365
+ momentArm_m: to.m(0.50),
366
+ readyTime_s: to.s(0.50),
367
+ damage: dmg(0.05, 0.80, 0.15, 0.30, 0.95),
368
+ },
369
+ {
370
+ id: "wpn_main_gauche",
371
+ kind: "weapon",
372
+ name: "Main Gauche",
373
+ mass_kg: to.kg(0.35),
374
+ bulk: q(0.9),
375
+ reach_m: to.m(0.32),
376
+ handedness: "oneHand",
377
+ momentArm_m: to.m(0.18),
378
+ readyTime_s: to.s(0.30),
379
+ damage: dmg(0.20, 0.65, 0.15, 0.50, 0.50),
380
+ },
381
+ {
382
+ id: "wpn_pike_ren",
383
+ kind: "weapon",
384
+ name: "Infantry Pike",
385
+ mass_kg: to.kg(1.50),
386
+ bulk: q(2.0),
387
+ reach_m: to.m(4.50),
388
+ handedness: "twoHand",
389
+ momentArm_m: to.m(0.80),
390
+ readyTime_s: to.s(0.85),
391
+ damage: dmg(0.15, 0.70, 0.15, 0.50, 0.65),
392
+ },
393
+ {
394
+ id: "wpn_poleaxe",
395
+ kind: "weapon",
396
+ name: "Poleaxe",
397
+ mass_kg: to.kg(2.50),
398
+ bulk: q(2.1),
399
+ reach_m: to.m(1.75),
400
+ handedness: "twoHand",
401
+ momentArm_m: to.m(0.68),
402
+ readyTime_s: to.s(0.75),
403
+ damage: dmg(0.30, 0.35, 0.35, 0.45, 0.40),
404
+ },
405
+ ];
406
+ // ─── EARLY MODERN MELEE ───────────────────────────────────────────────────────
407
+ export const EARLY_MODERN_MELEE = [
408
+ {
409
+ id: "wpn_cavalry_saber",
410
+ kind: "weapon",
411
+ name: "Cavalry Saber",
412
+ mass_kg: to.kg(1.00),
413
+ bulk: q(1.2),
414
+ reach_m: to.m(0.90),
415
+ handedness: "oneHand",
416
+ momentArm_m: to.m(0.45),
417
+ readyTime_s: to.s(0.48),
418
+ damage: dmg(0.55, 0.35, 0.10, 0.75, 0.15),
419
+ },
420
+ {
421
+ id: "wpn_smallsword",
422
+ kind: "weapon",
423
+ name: "Smallsword",
424
+ mass_kg: to.kg(0.70),
425
+ bulk: q(1.1),
426
+ reach_m: to.m(0.90),
427
+ handedness: "oneHand",
428
+ momentArm_m: to.m(0.42),
429
+ readyTime_s: to.s(0.40),
430
+ damage: dmg(0.15, 0.70, 0.15, 0.55, 0.70),
431
+ },
432
+ {
433
+ id: "wpn_socket_bayonet",
434
+ kind: "weapon",
435
+ name: "Socket Bayonet",
436
+ mass_kg: to.kg(0.40),
437
+ bulk: q(0.9),
438
+ reach_m: to.m(0.28),
439
+ handedness: "oneHand",
440
+ momentArm_m: to.m(0.16),
441
+ readyTime_s: to.s(0.35),
442
+ damage: dmg(0.20, 0.65, 0.15, 0.60, 0.60),
443
+ },
444
+ {
445
+ id: "wpn_entrenching_tool",
446
+ kind: "weapon",
447
+ name: "Entrenching Tool",
448
+ mass_kg: to.kg(0.90),
449
+ bulk: q(1.2),
450
+ reach_m: to.m(0.38),
451
+ handedness: "oneHand",
452
+ momentArm_m: to.m(0.22),
453
+ readyTime_s: to.s(0.45),
454
+ damage: dmg(0.45, 0.30, 0.25, 0.45, 0.25),
455
+ },
456
+ ];
457
+ // ─── CONTEMPORARY MELEE ───────────────────────────────────────────────────────
458
+ export const CONTEMPORARY_MELEE = [
459
+ {
460
+ id: "wpn_combat_knife",
461
+ kind: "weapon",
462
+ name: "Combat Knife",
463
+ mass_kg: to.kg(0.30),
464
+ bulk: q(0.9),
465
+ reach_m: to.m(0.22),
466
+ handedness: "oneHand",
467
+ momentArm_m: to.m(0.14),
468
+ readyTime_s: to.s(0.28),
469
+ damage: dmg(0.30, 0.55, 0.15, 0.80, 0.65),
470
+ },
471
+ {
472
+ id: "wpn_tactical_tomahawk",
473
+ kind: "weapon",
474
+ name: "Tactical Tomahawk",
475
+ mass_kg: to.kg(0.70),
476
+ bulk: q(1.1),
477
+ reach_m: to.m(0.45),
478
+ handedness: "oneHand",
479
+ momentArm_m: to.m(0.28),
480
+ readyTime_s: to.s(0.40),
481
+ damage: dmg(0.55, 0.30, 0.15, 0.70, 0.20),
482
+ },
483
+ {
484
+ id: "wpn_riot_baton",
485
+ kind: "weapon",
486
+ name: "Riot Baton",
487
+ mass_kg: to.kg(0.80),
488
+ bulk: q(1.1),
489
+ reach_m: to.m(0.55),
490
+ handedness: "oneHand",
491
+ momentArm_m: to.m(0.30),
492
+ readyTime_s: to.s(0.40),
493
+ damage: dmg(0.20, 0.35, 0.45, 0.05, 0.05),
494
+ },
495
+ ];
496
+ // ─── PREHISTORIC RANGED ───────────────────────────────────────────────────────
497
+ export const PREHISTORIC_RANGED = [
498
+ {
499
+ id: "rng_atlatl_dart",
500
+ kind: "ranged",
501
+ name: "Atlatl Dart",
502
+ category: "bow",
503
+ mass_kg: to.kg(0.5),
504
+ bulk: q(1.2),
505
+ launchEnergy_J: 180,
506
+ projectileMass_kg: to.kg(0.040),
507
+ dragCoeff_perM: q(0.008),
508
+ dispersionQ: q(0.014),
509
+ recycleTime_s: to.s(3.0),
510
+ damage: THROWN_DMG,
511
+ },
512
+ {
513
+ id: "rng_simple_selfbow",
514
+ kind: "ranged",
515
+ name: "Simple Selfbow",
516
+ category: "bow",
517
+ mass_kg: to.kg(0.6),
518
+ bulk: q(1.2),
519
+ launchEnergy_J: 20,
520
+ projectileMass_kg: to.kg(0.025),
521
+ dragCoeff_perM: q(0.010),
522
+ dispersionQ: q(0.018),
523
+ recycleTime_s: to.s(2.5),
524
+ damage: ARROW_DMG,
525
+ },
526
+ ];
527
+ // ─── CLASSICAL RANGED ─────────────────────────────────────────────────────────
528
+ export const CLASSICAL_RANGED = [
529
+ {
530
+ id: "rng_javelin_light",
531
+ kind: "ranged",
532
+ name: "Light Javelin",
533
+ category: "thrown",
534
+ mass_kg: to.kg(0.8),
535
+ bulk: q(1.3),
536
+ launchEnergy_J: 0,
537
+ projectileMass_kg: to.kg(0.400),
538
+ dragCoeff_perM: q(0.004),
539
+ dispersionQ: q(0.016),
540
+ recycleTime_s: to.s(4.0),
541
+ damage: THROWN_DMG,
542
+ },
543
+ {
544
+ id: "rng_pilum_throw",
545
+ kind: "ranged",
546
+ name: "Pilum (Thrown)",
547
+ category: "thrown",
548
+ mass_kg: to.kg(1.2),
549
+ bulk: q(1.5),
550
+ launchEnergy_J: 0,
551
+ projectileMass_kg: to.kg(1.000),
552
+ dragCoeff_perM: q(0.005),
553
+ dispersionQ: q(0.020),
554
+ recycleTime_s: to.s(5.0),
555
+ damage: THROWN_DMG,
556
+ },
557
+ {
558
+ id: "rng_composite_bow",
559
+ kind: "ranged",
560
+ name: "Composite Bow",
561
+ category: "bow",
562
+ mass_kg: to.kg(0.9),
563
+ bulk: q(1.3),
564
+ launchEnergy_J: 80,
565
+ projectileMass_kg: to.kg(0.025),
566
+ dragCoeff_perM: q(0.007),
567
+ dispersionQ: q(0.010),
568
+ recycleTime_s: to.s(1.8),
569
+ damage: dmg(0.25, 0.60, 0.15, 0.80, 0.55),
570
+ },
571
+ {
572
+ id: "rng_warbow",
573
+ kind: "ranged",
574
+ name: "English Warbow",
575
+ category: "bow",
576
+ mass_kg: to.kg(1.1),
577
+ bulk: q(1.6),
578
+ launchEnergy_J: 120,
579
+ projectileMass_kg: to.kg(0.030),
580
+ dragCoeff_perM: q(0.005),
581
+ dispersionQ: q(0.008),
582
+ recycleTime_s: to.s(2.2),
583
+ damage: ARROW_DMG,
584
+ },
585
+ ];
586
+ // ─── MEDIEVAL RANGED ──────────────────────────────────────────────────────────
587
+ export const MEDIEVAL_RANGED = [
588
+ {
589
+ id: "rng_arbalest",
590
+ kind: "ranged",
591
+ name: "Arbalest",
592
+ category: "bow",
593
+ mass_kg: to.kg(5.0),
594
+ bulk: q(2.2),
595
+ launchEnergy_J: 350,
596
+ projectileMass_kg: to.kg(0.045),
597
+ dragCoeff_perM: q(0.004),
598
+ dispersionQ: q(0.005),
599
+ recycleTime_s: to.s(12.0),
600
+ damage: dmg(0.15, 0.70, 0.15, 0.75, 0.80),
601
+ },
602
+ {
603
+ id: "rng_hand_cannon",
604
+ kind: "ranged",
605
+ name: "Hand Cannon",
606
+ category: "firearm",
607
+ mass_kg: to.kg(3.5),
608
+ bulk: q(2.0),
609
+ launchEnergy_J: 300,
610
+ projectileMass_kg: to.kg(0.030),
611
+ dragCoeff_perM: q(0.003),
612
+ dispersionQ: q(0.022),
613
+ recycleTime_s: to.s(40.0),
614
+ damage: dmg(0.25, 0.55, 0.20, 0.65, 0.55),
615
+ },
616
+ {
617
+ id: "rng_arquebus",
618
+ kind: "ranged",
619
+ name: "Arquebus",
620
+ category: "firearm",
621
+ mass_kg: to.kg(4.5),
622
+ bulk: q(2.2),
623
+ launchEnergy_J: 250,
624
+ projectileMass_kg: to.kg(0.028),
625
+ dragCoeff_perM: q(0.003),
626
+ dispersionQ: q(0.018),
627
+ recycleTime_s: to.s(30.0),
628
+ damage: dmg(0.25, 0.55, 0.20, 0.65, 0.55),
629
+ },
630
+ ];
631
+ // ─── RENAISSANCE RANGED ───────────────────────────────────────────────────────
632
+ export const RENAISSANCE_RANGED = [
633
+ {
634
+ id: "rng_wheellock_pistol",
635
+ kind: "ranged",
636
+ name: "Wheellock Pistol",
637
+ category: "firearm",
638
+ mass_kg: to.kg(1.8),
639
+ bulk: q(1.5),
640
+ launchEnergy_J: 250,
641
+ projectileMass_kg: to.kg(0.015),
642
+ dragCoeff_perM: q(0.003),
643
+ dispersionQ: q(0.020),
644
+ recycleTime_s: to.s(20.0),
645
+ damage: BULLET_DMG,
646
+ },
647
+ {
648
+ id: "rng_flintlock_rifle",
649
+ kind: "ranged",
650
+ name: "Flintlock Rifle",
651
+ category: "firearm",
652
+ mass_kg: to.kg(4.2),
653
+ bulk: q(2.0),
654
+ launchEnergy_J: 900,
655
+ projectileMass_kg: to.kg(0.028),
656
+ dragCoeff_perM: q(0.002),
657
+ dispersionQ: q(0.008),
658
+ recycleTime_s: to.s(20.0),
659
+ damage: RIFLE_DMG,
660
+ },
661
+ ];
662
+ // ─── EARLY MODERN RANGED ──────────────────────────────────────────────────────
663
+ export const EARLY_MODERN_RANGED = [
664
+ {
665
+ id: "rng_percussion_rifle",
666
+ kind: "ranged",
667
+ name: "Percussion Rifle",
668
+ category: "firearm",
669
+ mass_kg: to.kg(4.0),
670
+ bulk: q(2.0),
671
+ launchEnergy_J: 1200,
672
+ projectileMass_kg: to.kg(0.028),
673
+ dragCoeff_perM: q(0.002),
674
+ dispersionQ: q(0.006),
675
+ recycleTime_s: to.s(12.0),
676
+ damage: RIFLE_DMG,
677
+ },
678
+ {
679
+ id: "rng_early_revolver",
680
+ kind: "ranged",
681
+ name: "Early Revolver",
682
+ category: "firearm",
683
+ mass_kg: to.kg(1.4),
684
+ bulk: q(1.3),
685
+ launchEnergy_J: 350,
686
+ projectileMass_kg: to.kg(0.012),
687
+ dragCoeff_perM: q(0.002),
688
+ dispersionQ: q(0.015),
689
+ recycleTime_s: to.s(20.0),
690
+ magCapacity: 6,
691
+ shotInterval_s: to.s(0.8),
692
+ damage: BULLET_DMG,
693
+ },
694
+ {
695
+ id: "rng_breech_rifle",
696
+ kind: "ranged",
697
+ name: "Breech-Loading Rifle",
698
+ category: "firearm",
699
+ mass_kg: to.kg(4.2),
700
+ bulk: q(2.0),
701
+ launchEnergy_J: 1400,
702
+ projectileMass_kg: to.kg(0.028),
703
+ dragCoeff_perM: q(0.002),
704
+ dispersionQ: q(0.005),
705
+ recycleTime_s: to.s(8.0),
706
+ damage: RIFLE_DMG,
707
+ },
708
+ {
709
+ id: "rng_handgun_9mm",
710
+ kind: "ranged",
711
+ name: "Handgun 9mm",
712
+ category: "firearm",
713
+ mass_kg: to.kg(0.8),
714
+ bulk: q(1.1),
715
+ launchEnergy_J: 520,
716
+ projectileMass_kg: to.kg(0.008),
717
+ dragCoeff_perM: q(0.002),
718
+ dispersionQ: q(0.004),
719
+ recycleTime_s: to.s(2.5),
720
+ magCapacity: 15,
721
+ shotInterval_s: to.s(0.2),
722
+ damage: BULLET_DMG,
723
+ },
724
+ ];
725
+ // ─── CONTEMPORARY RANGED ─────────────────────────────────────────────────────
726
+ export const CONTEMPORARY_RANGED = [
727
+ {
728
+ id: "rng_assault_rifle",
729
+ kind: "ranged",
730
+ name: "Assault Rifle",
731
+ category: "firearm",
732
+ mass_kg: to.kg(3.5),
733
+ bulk: q(1.8),
734
+ launchEnergy_J: 1760,
735
+ projectileMass_kg: to.kg(0.004),
736
+ dragCoeff_perM: q(0.001),
737
+ dispersionQ: q(0.003),
738
+ recycleTime_s: to.s(3.0),
739
+ magCapacity: 30,
740
+ shotInterval_s: to.s(0.1),
741
+ damage: dmg(0.10, 0.75, 0.15, 0.55, 0.85),
742
+ },
743
+ {
744
+ id: "rng_battle_rifle",
745
+ kind: "ranged",
746
+ name: "Battle Rifle",
747
+ category: "firearm",
748
+ mass_kg: to.kg(4.3),
749
+ bulk: q(1.9),
750
+ launchEnergy_J: 3300,
751
+ projectileMass_kg: to.kg(0.0097),
752
+ dragCoeff_perM: q(0.001),
753
+ dispersionQ: q(0.003),
754
+ recycleTime_s: to.s(3.5),
755
+ magCapacity: 20,
756
+ shotInterval_s: to.s(0.2),
757
+ damage: dmg(0.10, 0.75, 0.15, 0.50, 0.85),
758
+ },
759
+ {
760
+ id: "rng_sniper_rifle",
761
+ kind: "ranged",
762
+ name: "Sniper Rifle",
763
+ category: "firearm",
764
+ mass_kg: to.kg(6.5),
765
+ bulk: q(2.2),
766
+ launchEnergy_J: 3300,
767
+ projectileMass_kg: to.kg(0.0097),
768
+ dragCoeff_perM: q(0.001),
769
+ dispersionQ: q(0.002),
770
+ recycleTime_s: to.s(8.0),
771
+ magCapacity: 10,
772
+ shotInterval_s: to.s(2.5),
773
+ damage: dmg(0.05, 0.80, 0.15, 0.40, 0.90),
774
+ },
775
+ {
776
+ id: "rng_shotgun_12g",
777
+ kind: "ranged",
778
+ name: "Shotgun 12-Gauge",
779
+ category: "firearm",
780
+ mass_kg: to.kg(3.4),
781
+ bulk: q(1.8),
782
+ launchEnergy_J: 1800,
783
+ projectileMass_kg: to.kg(0.032),
784
+ dragCoeff_perM: q(0.003),
785
+ dispersionQ: q(0.035),
786
+ recycleTime_s: to.s(8.0),
787
+ magCapacity: 6,
788
+ shotInterval_s: to.s(0.5),
789
+ damage: dmg(0.65, 0.25, 0.10, 0.80, 0.05),
790
+ },
791
+ {
792
+ id: "rng_submachine_gun",
793
+ kind: "ranged",
794
+ name: "Submachine Gun",
795
+ category: "firearm",
796
+ mass_kg: to.kg(2.8),
797
+ bulk: q(1.5),
798
+ launchEnergy_J: 520,
799
+ projectileMass_kg: to.kg(0.008),
800
+ dragCoeff_perM: q(0.002),
801
+ dispersionQ: q(0.007),
802
+ recycleTime_s: to.s(2.5),
803
+ magCapacity: 30,
804
+ shotInterval_s: to.s(0.1),
805
+ damage: dmg(0.25, 0.60, 0.15, 0.65, 0.55),
806
+ },
807
+ ];
808
+ // ─── Aggregate exports ────────────────────────────────────────────────────────
809
+ export const ALL_HISTORICAL_MELEE = [
810
+ ...PREHISTORIC_MELEE,
811
+ ...CLASSICAL_MELEE,
812
+ ...MEDIEVAL_MELEE,
813
+ ...RENAISSANCE_MELEE,
814
+ ...EARLY_MODERN_MELEE,
815
+ ...CONTEMPORARY_MELEE,
816
+ ];
817
+ export const ALL_HISTORICAL_RANGED = [
818
+ ...PREHISTORIC_RANGED,
819
+ ...CLASSICAL_RANGED,
820
+ ...MEDIEVAL_RANGED,
821
+ ...RENAISSANCE_RANGED,
822
+ ...EARLY_MODERN_RANGED,
823
+ ...CONTEMPORARY_RANGED,
824
+ ];