@lippelt/srd-dnd5e-2014 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.
- package/dist/index.cjs +217 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +28 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +187 -0
- package/dist/index.js.map +1 -0
- package/package.json +44 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
abilityMod: () => abilityMod,
|
|
24
|
+
dnd5e2014: () => dnd5e2014,
|
|
25
|
+
resetRoller: () => resetRoller,
|
|
26
|
+
setRoller: () => setRoller,
|
|
27
|
+
spellAttackBonus: () => spellAttackBonus,
|
|
28
|
+
spellSaveDC: () => spellSaveDC
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
var roller = (sides) => Math.floor(Math.random() * sides) + 1;
|
|
32
|
+
function setRoller(fn) {
|
|
33
|
+
roller = fn;
|
|
34
|
+
}
|
|
35
|
+
function resetRoller() {
|
|
36
|
+
roller = (sides) => Math.floor(Math.random() * sides) + 1;
|
|
37
|
+
}
|
|
38
|
+
function roll(sides, count = 1) {
|
|
39
|
+
const out = [];
|
|
40
|
+
for (let i = 0; i < count; i++) out.push(roller(sides));
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
var DICE_PRESETS = [
|
|
44
|
+
{ id: "d20", label: "d20", notation: "1d20", category: "check" },
|
|
45
|
+
{ id: "d20-adv", label: "d20 (adv.)", notation: "advantage", category: "check", description: "Rola 2d20 e pega o maior." },
|
|
46
|
+
{ id: "d20-dis", label: "d20 (desv.)", notation: "disadvantage", category: "check", description: "Rola 2d20 e pega o menor." },
|
|
47
|
+
{ id: "d4", label: "d4", notation: "1d4", category: "damage" },
|
|
48
|
+
{ id: "d6", label: "d6", notation: "1d6", category: "damage" },
|
|
49
|
+
{ id: "d8", label: "d8", notation: "1d8", category: "damage" },
|
|
50
|
+
{ id: "d10", label: "d10", notation: "1d10", category: "damage" },
|
|
51
|
+
{ id: "d12", label: "d12", notation: "1d12", category: "damage" },
|
|
52
|
+
{ id: "d100", label: "d100", notation: "1d100", category: "special" }
|
|
53
|
+
];
|
|
54
|
+
var CONDITIONS = [
|
|
55
|
+
{ id: "blinded", label: "Blinded", summary: "Cego: falha em testes que exigem vis\xE3o; atacantes t\xEAm vantagem; o cego tem desvantagem." },
|
|
56
|
+
{ id: "charmed", label: "Charmed", summary: "Enfeiti\xE7ado: n\xE3o pode atacar o encantador nem usar habilidades nocivas contra ele." },
|
|
57
|
+
{ id: "deafened", label: "Deafened", summary: "Surdo: falha em testes que dependem de audi\xE7\xE3o." },
|
|
58
|
+
{ id: "exhaustion-1", label: "Exhaustion 1", summary: "Exaust\xE3o 1: desvantagem em testes de habilidade." },
|
|
59
|
+
{ id: "exhaustion-2", label: "Exhaustion 2", summary: "Exaust\xE3o 2: velocidade reduzida pela metade." },
|
|
60
|
+
{ id: "exhaustion-3", label: "Exhaustion 3", summary: "Exaust\xE3o 3: desvantagem em ataques e jogadas de resist\xEAncia." },
|
|
61
|
+
{ id: "exhaustion-4", label: "Exhaustion 4", summary: "Exaust\xE3o 4: m\xE1ximo de HP reduzido pela metade." },
|
|
62
|
+
{ id: "exhaustion-5", label: "Exhaustion 5", summary: "Exaust\xE3o 5: velocidade reduzida a 0." },
|
|
63
|
+
{ id: "exhaustion-6", label: "Exhaustion 6", summary: "Exaust\xE3o 6: morte." },
|
|
64
|
+
{ id: "frightened", label: "Frightened", summary: "Amedrontado: desvantagem se a fonte do medo estiver \xE0 vista; n\xE3o pode se mover para perto dela." },
|
|
65
|
+
{ id: "grappled", label: "Grappled", summary: "Agarrado: velocidade 0; termina se o agarrador ficar incapacitado." },
|
|
66
|
+
{ id: "incapacitated", label: "Incapacitated", summary: "Incapacitado: n\xE3o pode tomar a\xE7\xF5es nem rea\xE7\xF5es." },
|
|
67
|
+
{ id: "invisible", label: "Invisible", summary: "Invis\xEDvel: vantagem em ataques; atacantes t\xEAm desvantagem." },
|
|
68
|
+
{ id: "paralyzed", label: "Paralyzed", summary: "Paralisado: incapacitado, n\xE3o pode se mover/falar; ataques a at\xE9 1,5m s\xE3o autom\xE1ticos cr\xEDticos." },
|
|
69
|
+
{ id: "petrified", label: "Petrified", summary: "Petrificado: transformado em subst\xE2ncia s\xF3lida; resist\xEAncia a todo dano; imune a venenos e doen\xE7as." },
|
|
70
|
+
{ id: "poisoned", label: "Poisoned", summary: "Envenenado: desvantagem em ataques e testes de habilidade." },
|
|
71
|
+
{ id: "prone", label: "Prone", summary: "Ca\xEDdo: desvantagem em ataques; ataques corpo-a-corpo contra o alvo t\xEAm vantagem; \xE0 dist\xE2ncia t\xEAm desvantagem." },
|
|
72
|
+
{ id: "restrained", label: "Restrained", summary: "Contido: velocidade 0; desvantagem em ataques e Dex saves; atacantes t\xEAm vantagem." },
|
|
73
|
+
{ id: "stunned", label: "Stunned", summary: "Atordoado: incapacitado; falha automaticamente em Str/Dex saves; atacantes t\xEAm vantagem." },
|
|
74
|
+
{ id: "unconscious", label: "Unconscious", summary: "Inconsciente: incapacitado, ca\xEDdo; ataques a at\xE9 1,5m s\xE3o cr\xEDticos autom\xE1ticos." }
|
|
75
|
+
];
|
|
76
|
+
var TRACKER_FIELDS = [
|
|
77
|
+
{
|
|
78
|
+
key: "ac",
|
|
79
|
+
label: "CA",
|
|
80
|
+
kind: "integer",
|
|
81
|
+
min: 1,
|
|
82
|
+
max: 30,
|
|
83
|
+
default: 10,
|
|
84
|
+
description: "Classe de Armadura \u2014 DC para ser atingido por ataques."
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
key: "deathSuccesses",
|
|
88
|
+
label: "M\u2713",
|
|
89
|
+
kind: "integer",
|
|
90
|
+
min: 0,
|
|
91
|
+
max: 3,
|
|
92
|
+
default: 0,
|
|
93
|
+
description: "Sucessos em testes de resist\xEAncia \xE0 morte (3 = estabilizado)."
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
key: "deathFailures",
|
|
97
|
+
label: "M\u2717",
|
|
98
|
+
kind: "integer",
|
|
99
|
+
min: 0,
|
|
100
|
+
max: 3,
|
|
101
|
+
default: 0,
|
|
102
|
+
description: "Falhas em testes de resist\xEAncia \xE0 morte (3 = morte)."
|
|
103
|
+
}
|
|
104
|
+
];
|
|
105
|
+
function abilityMod(score) {
|
|
106
|
+
return Math.floor((score - 10) / 2);
|
|
107
|
+
}
|
|
108
|
+
function spellSaveDC(proficiency, casterMod) {
|
|
109
|
+
return 8 + proficiency + casterMod;
|
|
110
|
+
}
|
|
111
|
+
function spellAttackBonus(proficiency, casterMod) {
|
|
112
|
+
return proficiency + casterMod;
|
|
113
|
+
}
|
|
114
|
+
function rollD20({ modifier = 0, advantage = false, disadvantage = false }) {
|
|
115
|
+
const cancelled = advantage && disadvantage;
|
|
116
|
+
const useAdv = advantage && !cancelled;
|
|
117
|
+
const useDis = disadvantage && !cancelled;
|
|
118
|
+
const count = useAdv || useDis ? 2 : 1;
|
|
119
|
+
const dice = roll(20, count);
|
|
120
|
+
const picked = useAdv ? Math.max(...dice) : useDis ? Math.min(...dice) : dice[0];
|
|
121
|
+
const total = picked + modifier;
|
|
122
|
+
const notes = [];
|
|
123
|
+
if (cancelled) notes.push("vantagem/desvantagem se cancelaram");
|
|
124
|
+
else if (useAdv) notes.push("vantagem");
|
|
125
|
+
else if (useDis) notes.push("desvantagem");
|
|
126
|
+
if (picked === 20) notes.push("cr\xEDtico natural");
|
|
127
|
+
if (picked === 1) notes.push("falha cr\xEDtica");
|
|
128
|
+
const modStr = modifier === 0 ? "" : modifier > 0 ? `+${modifier}` : `${modifier}`;
|
|
129
|
+
const dStr = count === 2 ? `2d20${useAdv ? "kh1" : "kl1"}` : "1d20";
|
|
130
|
+
return { rolls: dice, modifier, total, notation: `${dStr}${modStr}`, notes };
|
|
131
|
+
}
|
|
132
|
+
function rollAttack(params) {
|
|
133
|
+
const result = rollD20(params);
|
|
134
|
+
const d20 = result.rolls[result.rolls.length === 2 ? params.advantage && !params.disadvantage ? result.rolls[0] >= result.rolls[1] ? 0 : 1 : result.rolls[0] <= result.rolls[1] ? 0 : 1 : 0];
|
|
135
|
+
const notes = [...result.notes ?? []];
|
|
136
|
+
if (params.targetAC !== void 0) {
|
|
137
|
+
const natural20 = d20 === 20;
|
|
138
|
+
const natural1 = d20 === 1;
|
|
139
|
+
const hit = natural20 || !natural1 && result.total >= params.targetAC;
|
|
140
|
+
notes.push(hit ? natural20 ? "acerto cr\xEDtico" : "acertou" : natural1 ? "erro cr\xEDtico" : "errou");
|
|
141
|
+
}
|
|
142
|
+
return { ...result, notes };
|
|
143
|
+
}
|
|
144
|
+
function rollSave(params) {
|
|
145
|
+
const result = rollD20(params);
|
|
146
|
+
const notes = [...result.notes ?? []];
|
|
147
|
+
notes.push(result.total >= params.dc ? "sucesso" : "falha");
|
|
148
|
+
return { ...result, notes: notes.concat([`DC ${params.dc}`]) };
|
|
149
|
+
}
|
|
150
|
+
function rollDamage({ count, sides, modifier = 0, critical = false }) {
|
|
151
|
+
const totalDice = critical ? count * 2 : count;
|
|
152
|
+
const dice = roll(sides, totalDice);
|
|
153
|
+
const sum = dice.reduce((a, b) => a + b, 0);
|
|
154
|
+
const total = Math.max(0, sum + modifier);
|
|
155
|
+
const modStr = modifier === 0 ? "" : modifier > 0 ? `+${modifier}` : `${modifier}`;
|
|
156
|
+
return {
|
|
157
|
+
rolls: dice,
|
|
158
|
+
modifier,
|
|
159
|
+
total,
|
|
160
|
+
notation: `${totalDice}d${sides}${modStr}${critical ? " (crit)" : ""}`,
|
|
161
|
+
notes: critical ? ["dano cr\xEDtico \u2014 dados dobrados"] : []
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function applyDndDamage(incoming, ctx) {
|
|
165
|
+
const t = ctx.target;
|
|
166
|
+
const type = ctx.type;
|
|
167
|
+
if (!type || !t) return { final: Math.max(0, incoming), notes: [] };
|
|
168
|
+
if (t.immunity?.includes(type)) return { final: 0, notes: [`imune a ${type}`] };
|
|
169
|
+
if (t.resistance?.includes(type)) {
|
|
170
|
+
return { final: Math.floor(incoming / 2), notes: [`resist\xEAncia a ${type} (metade)`] };
|
|
171
|
+
}
|
|
172
|
+
if (t.vulnerability?.includes(type)) {
|
|
173
|
+
return { final: incoming * 2, notes: [`vulnerabilidade a ${type} (dobro)`] };
|
|
174
|
+
}
|
|
175
|
+
return { final: Math.max(0, incoming), notes: [] };
|
|
176
|
+
}
|
|
177
|
+
var RULES = {
|
|
178
|
+
roll(kind, params) {
|
|
179
|
+
switch (kind) {
|
|
180
|
+
case "d20":
|
|
181
|
+
case "check":
|
|
182
|
+
case "ability":
|
|
183
|
+
return rollD20(params);
|
|
184
|
+
case "attack":
|
|
185
|
+
return rollAttack(params);
|
|
186
|
+
case "save":
|
|
187
|
+
return rollSave(params);
|
|
188
|
+
case "damage":
|
|
189
|
+
return rollDamage(params);
|
|
190
|
+
default:
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
applyDamage(incoming, target) {
|
|
195
|
+
return applyDndDamage(incoming, target);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
var dnd5e2014 = {
|
|
199
|
+
id: "dnd5e-2014",
|
|
200
|
+
name: "Dungeons & Dragons 5e (2014)",
|
|
201
|
+
ruleVersion: "SRD 5.1",
|
|
202
|
+
attribution: "Contains material from the System Reference Document 5.1 by Wizards of the Coast LLC, licensed under CC-BY 4.0.",
|
|
203
|
+
dicePresets: DICE_PRESETS,
|
|
204
|
+
conditions: CONDITIONS,
|
|
205
|
+
trackerFields: TRACKER_FIELDS,
|
|
206
|
+
rules: RULES
|
|
207
|
+
};
|
|
208
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
209
|
+
0 && (module.exports = {
|
|
210
|
+
abilityMod,
|
|
211
|
+
dnd5e2014,
|
|
212
|
+
resetRoller,
|
|
213
|
+
setRoller,
|
|
214
|
+
spellAttackBonus,
|
|
215
|
+
spellSaveDC
|
|
216
|
+
});
|
|
217
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Dungeons & Dragons 5th Edition (2014).\n *\n * Conteúdo de regras (condições, ability scores, escala de DC) deriva do\n * System Reference Document 5.1, publicado pela Wizards of the Coast LLC\n * sob a Creative Commons Attribution 4.0 International License:\n * https://creativecommons.org/licenses/by/4.0/legalcode\n *\n * Esta implementação é original (não copia código de implementações\n * existentes). Referência conceitual: foundryvtt/dnd5e (MIT).\n */\n\nimport type {\n ConditionDef,\n DicePreset,\n RollResult,\n System,\n SystemRules,\n TrackerField,\n} from '@lippelt/srd-core'\n\n// ============================================================================\n// Random helper — extraído pra que os testes possam injetar uma fonte\n// determinística via `setRoller`.\n// ============================================================================\n\ntype Roller = (sides: number) => number\n\nlet roller: Roller = (sides: number) => Math.floor(Math.random() * sides) + 1\n\n/** Substitui o gerador de dados (use em testes). Restaurar com `resetRoller`. */\nexport function setRoller(fn: Roller): void {\n roller = fn\n}\n\n/** Restaura o gerador padrão (Math.random). */\nexport function resetRoller(): void {\n roller = (sides: number) => Math.floor(Math.random() * sides) + 1\n}\n\nfunction roll(sides: number, count = 1): number[] {\n const out: number[] = []\n for (let i = 0; i < count; i++) out.push(roller(sides))\n return out\n}\n\n// ============================================================================\n// Presets de dados — botões rápidos da UI\n// ============================================================================\n\nconst DICE_PRESETS: DicePreset[] = [\n { id: 'd20', label: 'd20', notation: '1d20', category: 'check' },\n { id: 'd20-adv', label: 'd20 (adv.)', notation: 'advantage', category: 'check', description: 'Rola 2d20 e pega o maior.' },\n { id: 'd20-dis', label: 'd20 (desv.)', notation: 'disadvantage', category: 'check', description: 'Rola 2d20 e pega o menor.' },\n { id: 'd4', label: 'd4', notation: '1d4', category: 'damage' },\n { id: 'd6', label: 'd6', notation: '1d6', category: 'damage' },\n { id: 'd8', label: 'd8', notation: '1d8', category: 'damage' },\n { id: 'd10', label: 'd10', notation: '1d10', category: 'damage' },\n { id: 'd12', label: 'd12', notation: '1d12', category: 'damage' },\n { id: 'd100', label: 'd100', notation: '1d100', category: 'special' },\n]\n\n// ============================================================================\n// Condições — SRD 5.1 (CC-BY 4.0)\n// ============================================================================\n\nconst CONDITIONS: ConditionDef[] = [\n { id: 'blinded', label: 'Blinded', summary: 'Cego: falha em testes que exigem visão; atacantes têm vantagem; o cego tem desvantagem.' },\n { id: 'charmed', label: 'Charmed', summary: 'Enfeitiçado: não pode atacar o encantador nem usar habilidades nocivas contra ele.' },\n { id: 'deafened', label: 'Deafened', summary: 'Surdo: falha em testes que dependem de audição.' },\n { id: 'exhaustion-1', label: 'Exhaustion 1', summary: 'Exaustão 1: desvantagem em testes de habilidade.' },\n { id: 'exhaustion-2', label: 'Exhaustion 2', summary: 'Exaustão 2: velocidade reduzida pela metade.' },\n { id: 'exhaustion-3', label: 'Exhaustion 3', summary: 'Exaustão 3: desvantagem em ataques e jogadas de resistência.' },\n { id: 'exhaustion-4', label: 'Exhaustion 4', summary: 'Exaustão 4: máximo de HP reduzido pela metade.' },\n { id: 'exhaustion-5', label: 'Exhaustion 5', summary: 'Exaustão 5: velocidade reduzida a 0.' },\n { id: 'exhaustion-6', label: 'Exhaustion 6', summary: 'Exaustão 6: morte.' },\n { id: 'frightened', label: 'Frightened', summary: 'Amedrontado: desvantagem se a fonte do medo estiver à vista; não pode se mover para perto dela.' },\n { id: 'grappled', label: 'Grappled', summary: 'Agarrado: velocidade 0; termina se o agarrador ficar incapacitado.' },\n { id: 'incapacitated', label: 'Incapacitated', summary: 'Incapacitado: não pode tomar ações nem reações.' },\n { id: 'invisible', label: 'Invisible', summary: 'Invisível: vantagem em ataques; atacantes têm desvantagem.' },\n { id: 'paralyzed', label: 'Paralyzed', summary: 'Paralisado: incapacitado, não pode se mover/falar; ataques a até 1,5m são automáticos críticos.' },\n { id: 'petrified', label: 'Petrified', summary: 'Petrificado: transformado em substância sólida; resistência a todo dano; imune a venenos e doenças.' },\n { id: 'poisoned', label: 'Poisoned', summary: 'Envenenado: desvantagem em ataques e testes de habilidade.' },\n { id: 'prone', label: 'Prone', summary: 'Caído: desvantagem em ataques; ataques corpo-a-corpo contra o alvo têm vantagem; à distância têm desvantagem.' },\n { id: 'restrained', label: 'Restrained', summary: 'Contido: velocidade 0; desvantagem em ataques e Dex saves; atacantes têm vantagem.' },\n { id: 'stunned', label: 'Stunned', summary: 'Atordoado: incapacitado; falha automaticamente em Str/Dex saves; atacantes têm vantagem.' },\n { id: 'unconscious', label: 'Unconscious', summary: 'Inconsciente: incapacitado, caído; ataques a até 1,5m são críticos automáticos.' },\n]\n\n// ============================================================================\n// Tracker fields — AC e death saves além de initiative/hp genéricos\n// ============================================================================\n\nconst TRACKER_FIELDS: TrackerField[] = [\n {\n key: 'ac',\n label: 'CA',\n kind: 'integer',\n min: 1,\n max: 30,\n default: 10,\n description: 'Classe de Armadura — DC para ser atingido por ataques.',\n },\n {\n key: 'deathSuccesses',\n label: 'M✓',\n kind: 'integer',\n min: 0,\n max: 3,\n default: 0,\n description: 'Sucessos em testes de resistência à morte (3 = estabilizado).',\n },\n {\n key: 'deathFailures',\n label: 'M✗',\n kind: 'integer',\n min: 0,\n max: 3,\n default: 0,\n description: 'Falhas em testes de resistência à morte (3 = morte).',\n },\n]\n\n// ============================================================================\n// Regras automatizadas\n// ============================================================================\n\n/** Modificador derivado da ability score: floor((score - 10) / 2). */\nexport function abilityMod(score: number): number {\n return Math.floor((score - 10) / 2)\n}\n\n/** DC de feitiço: 8 + proficiency + ability modifier. */\nexport function spellSaveDC(proficiency: number, casterMod: number): number {\n return 8 + proficiency + casterMod\n}\n\n/** Bônus de ataque por feitiço: proficiency + ability modifier. */\nexport function spellAttackBonus(proficiency: number, casterMod: number): number {\n return proficiency + casterMod\n}\n\ninterface D20Params {\n modifier?: number\n advantage?: boolean\n disadvantage?: boolean\n}\n\n/** Rola um d20 com possível advantage/disadvantage e modificador. */\nfunction rollD20({ modifier = 0, advantage = false, disadvantage = false }: D20Params): RollResult {\n // Vantagem e desvantagem se cancelam mutuamente (SRD 5.1).\n const cancelled = advantage && disadvantage\n const useAdv = advantage && !cancelled\n const useDis = disadvantage && !cancelled\n const count = useAdv || useDis ? 2 : 1\n const dice = roll(20, count)\n const picked = useAdv ? Math.max(...dice) : useDis ? Math.min(...dice) : dice[0]!\n const total = picked + modifier\n const notes: string[] = []\n if (cancelled) notes.push('vantagem/desvantagem se cancelaram')\n else if (useAdv) notes.push('vantagem')\n else if (useDis) notes.push('desvantagem')\n if (picked === 20) notes.push('crítico natural')\n if (picked === 1) notes.push('falha crítica')\n const modStr = modifier === 0 ? '' : modifier > 0 ? `+${modifier}` : `${modifier}`\n const dStr = count === 2 ? `2d20${useAdv ? 'kh1' : 'kl1'}` : '1d20'\n return { rolls: dice, modifier, total, notation: `${dStr}${modStr}`, notes }\n}\n\ninterface AttackParams {\n modifier?: number\n targetAC?: number\n advantage?: boolean\n disadvantage?: boolean\n}\n\n/**\n * Rolagem de ataque contra AC. Se `targetAC` for fornecido, anota se acertou.\n * Crítico natural 20 sempre acerta; 1 sempre erra (SRD 5.1).\n */\nfunction rollAttack(params: AttackParams): RollResult {\n const result = rollD20(params)\n const d20 = result.rolls[result.rolls.length === 2\n ? (params.advantage && !params.disadvantage ? (result.rolls[0]! >= result.rolls[1]! ? 0 : 1) : (result.rolls[0]! <= result.rolls[1]! ? 0 : 1))\n : 0]!\n const notes = [...(result.notes ?? [])]\n if (params.targetAC !== undefined) {\n const natural20 = d20 === 20\n const natural1 = d20 === 1\n const hit = natural20 || (!natural1 && result.total >= params.targetAC)\n notes.push(hit ? (natural20 ? 'acerto crítico' : 'acertou') : (natural1 ? 'erro crítico' : 'errou'))\n }\n return { ...result, notes }\n}\n\ninterface SaveParams {\n modifier?: number\n dc: number\n advantage?: boolean\n disadvantage?: boolean\n}\n\n/** Saving throw vs DC. Anota success/failure. */\nfunction rollSave(params: SaveParams): RollResult {\n const result = rollD20(params)\n const notes = [...(result.notes ?? [])]\n notes.push(result.total >= params.dc ? 'sucesso' : 'falha')\n return { ...result, notes: notes.concat([`DC ${params.dc}`]) }\n}\n\ninterface DamageParams {\n count: number\n sides: number\n modifier?: number\n critical?: boolean\n}\n\n/**\n * Rolagem de dano: NdM+K, com opção de crítico (rola o dobro dos dados,\n * mantém o modificador uma única vez — SRD 5.1).\n */\nfunction rollDamage({ count, sides, modifier = 0, critical = false }: DamageParams): RollResult {\n const totalDice = critical ? count * 2 : count\n const dice = roll(sides, totalDice)\n const sum = dice.reduce((a, b) => a + b, 0)\n const total = Math.max(0, sum + modifier)\n const modStr = modifier === 0 ? '' : modifier > 0 ? `+${modifier}` : `${modifier}`\n return {\n rolls: dice,\n modifier,\n total,\n notation: `${totalDice}d${sides}${modStr}${critical ? ' (crit)' : ''}`,\n notes: critical ? ['dano crítico — dados dobrados'] : [],\n }\n}\n\ninterface DamageTarget {\n resistance?: string[]\n vulnerability?: string[]\n immunity?: string[]\n}\n\ninterface ApplyDamageInput {\n type?: string\n target?: DamageTarget\n}\n\n/**\n * Reduz dano pelas propriedades do alvo. Ordem (SRD 5.1):\n * 1. Imunidade zera o dano.\n * 2. Resistência metade (arredondar pra baixo).\n * 3. Vulnerabilidade dobra.\n * Se uma criatura tem múltiplas categorias para o mesmo tipo, apenas uma se aplica\n * (mas combinadas com outras categorias podem coexistir — aqui assumimos exclusividade).\n */\nfunction applyDndDamage(incoming: number, ctx: ApplyDamageInput): { final: number; notes: string[] } {\n const t = ctx.target\n const type = ctx.type\n if (!type || !t) return { final: Math.max(0, incoming), notes: [] }\n if (t.immunity?.includes(type)) return { final: 0, notes: [`imune a ${type}`] }\n if (t.resistance?.includes(type)) {\n return { final: Math.floor(incoming / 2), notes: [`resistência a ${type} (metade)`] }\n }\n if (t.vulnerability?.includes(type)) {\n return { final: incoming * 2, notes: [`vulnerabilidade a ${type} (dobro)`] }\n }\n return { final: Math.max(0, incoming), notes: [] }\n}\n\n// ============================================================================\n// Bundle do sistema\n// ============================================================================\n\nconst RULES: SystemRules = {\n roll(kind, params) {\n switch (kind) {\n case 'd20':\n case 'check':\n case 'ability':\n return rollD20(params as unknown as D20Params)\n case 'attack':\n return rollAttack(params as unknown as AttackParams)\n case 'save':\n return rollSave(params as unknown as SaveParams)\n case 'damage':\n return rollDamage(params as unknown as DamageParams)\n default:\n return null\n }\n },\n applyDamage(incoming, target) {\n return applyDndDamage(incoming, target as ApplyDamageInput)\n },\n}\n\nexport const dnd5e2014: System = {\n id: 'dnd5e-2014',\n name: 'Dungeons & Dragons 5e (2014)',\n ruleVersion: 'SRD 5.1',\n attribution:\n 'Contains material from the System Reference Document 5.1 by Wizards of the Coast LLC, licensed under CC-BY 4.0.',\n dicePresets: DICE_PRESETS,\n conditions: CONDITIONS,\n trackerFields: TRACKER_FIELDS,\n rules: RULES,\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { System } from '@lippelt/srd-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dungeons & Dragons 5th Edition (2014).
|
|
5
|
+
*
|
|
6
|
+
* Conteúdo de regras (condições, ability scores, escala de DC) deriva do
|
|
7
|
+
* System Reference Document 5.1, publicado pela Wizards of the Coast LLC
|
|
8
|
+
* sob a Creative Commons Attribution 4.0 International License:
|
|
9
|
+
* https://creativecommons.org/licenses/by/4.0/legalcode
|
|
10
|
+
*
|
|
11
|
+
* Esta implementação é original (não copia código de implementações
|
|
12
|
+
* existentes). Referência conceitual: foundryvtt/dnd5e (MIT).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
type Roller = (sides: number) => number;
|
|
16
|
+
/** Substitui o gerador de dados (use em testes). Restaurar com `resetRoller`. */
|
|
17
|
+
declare function setRoller(fn: Roller): void;
|
|
18
|
+
/** Restaura o gerador padrão (Math.random). */
|
|
19
|
+
declare function resetRoller(): void;
|
|
20
|
+
/** Modificador derivado da ability score: floor((score - 10) / 2). */
|
|
21
|
+
declare function abilityMod(score: number): number;
|
|
22
|
+
/** DC de feitiço: 8 + proficiency + ability modifier. */
|
|
23
|
+
declare function spellSaveDC(proficiency: number, casterMod: number): number;
|
|
24
|
+
/** Bônus de ataque por feitiço: proficiency + ability modifier. */
|
|
25
|
+
declare function spellAttackBonus(proficiency: number, casterMod: number): number;
|
|
26
|
+
declare const dnd5e2014: System;
|
|
27
|
+
|
|
28
|
+
export { abilityMod, dnd5e2014, resetRoller, setRoller, spellAttackBonus, spellSaveDC };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { System } from '@lippelt/srd-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dungeons & Dragons 5th Edition (2014).
|
|
5
|
+
*
|
|
6
|
+
* Conteúdo de regras (condições, ability scores, escala de DC) deriva do
|
|
7
|
+
* System Reference Document 5.1, publicado pela Wizards of the Coast LLC
|
|
8
|
+
* sob a Creative Commons Attribution 4.0 International License:
|
|
9
|
+
* https://creativecommons.org/licenses/by/4.0/legalcode
|
|
10
|
+
*
|
|
11
|
+
* Esta implementação é original (não copia código de implementações
|
|
12
|
+
* existentes). Referência conceitual: foundryvtt/dnd5e (MIT).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
type Roller = (sides: number) => number;
|
|
16
|
+
/** Substitui o gerador de dados (use em testes). Restaurar com `resetRoller`. */
|
|
17
|
+
declare function setRoller(fn: Roller): void;
|
|
18
|
+
/** Restaura o gerador padrão (Math.random). */
|
|
19
|
+
declare function resetRoller(): void;
|
|
20
|
+
/** Modificador derivado da ability score: floor((score - 10) / 2). */
|
|
21
|
+
declare function abilityMod(score: number): number;
|
|
22
|
+
/** DC de feitiço: 8 + proficiency + ability modifier. */
|
|
23
|
+
declare function spellSaveDC(proficiency: number, casterMod: number): number;
|
|
24
|
+
/** Bônus de ataque por feitiço: proficiency + ability modifier. */
|
|
25
|
+
declare function spellAttackBonus(proficiency: number, casterMod: number): number;
|
|
26
|
+
declare const dnd5e2014: System;
|
|
27
|
+
|
|
28
|
+
export { abilityMod, dnd5e2014, resetRoller, setRoller, spellAttackBonus, spellSaveDC };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var roller = (sides) => Math.floor(Math.random() * sides) + 1;
|
|
3
|
+
function setRoller(fn) {
|
|
4
|
+
roller = fn;
|
|
5
|
+
}
|
|
6
|
+
function resetRoller() {
|
|
7
|
+
roller = (sides) => Math.floor(Math.random() * sides) + 1;
|
|
8
|
+
}
|
|
9
|
+
function roll(sides, count = 1) {
|
|
10
|
+
const out = [];
|
|
11
|
+
for (let i = 0; i < count; i++) out.push(roller(sides));
|
|
12
|
+
return out;
|
|
13
|
+
}
|
|
14
|
+
var DICE_PRESETS = [
|
|
15
|
+
{ id: "d20", label: "d20", notation: "1d20", category: "check" },
|
|
16
|
+
{ id: "d20-adv", label: "d20 (adv.)", notation: "advantage", category: "check", description: "Rola 2d20 e pega o maior." },
|
|
17
|
+
{ id: "d20-dis", label: "d20 (desv.)", notation: "disadvantage", category: "check", description: "Rola 2d20 e pega o menor." },
|
|
18
|
+
{ id: "d4", label: "d4", notation: "1d4", category: "damage" },
|
|
19
|
+
{ id: "d6", label: "d6", notation: "1d6", category: "damage" },
|
|
20
|
+
{ id: "d8", label: "d8", notation: "1d8", category: "damage" },
|
|
21
|
+
{ id: "d10", label: "d10", notation: "1d10", category: "damage" },
|
|
22
|
+
{ id: "d12", label: "d12", notation: "1d12", category: "damage" },
|
|
23
|
+
{ id: "d100", label: "d100", notation: "1d100", category: "special" }
|
|
24
|
+
];
|
|
25
|
+
var CONDITIONS = [
|
|
26
|
+
{ id: "blinded", label: "Blinded", summary: "Cego: falha em testes que exigem vis\xE3o; atacantes t\xEAm vantagem; o cego tem desvantagem." },
|
|
27
|
+
{ id: "charmed", label: "Charmed", summary: "Enfeiti\xE7ado: n\xE3o pode atacar o encantador nem usar habilidades nocivas contra ele." },
|
|
28
|
+
{ id: "deafened", label: "Deafened", summary: "Surdo: falha em testes que dependem de audi\xE7\xE3o." },
|
|
29
|
+
{ id: "exhaustion-1", label: "Exhaustion 1", summary: "Exaust\xE3o 1: desvantagem em testes de habilidade." },
|
|
30
|
+
{ id: "exhaustion-2", label: "Exhaustion 2", summary: "Exaust\xE3o 2: velocidade reduzida pela metade." },
|
|
31
|
+
{ id: "exhaustion-3", label: "Exhaustion 3", summary: "Exaust\xE3o 3: desvantagem em ataques e jogadas de resist\xEAncia." },
|
|
32
|
+
{ id: "exhaustion-4", label: "Exhaustion 4", summary: "Exaust\xE3o 4: m\xE1ximo de HP reduzido pela metade." },
|
|
33
|
+
{ id: "exhaustion-5", label: "Exhaustion 5", summary: "Exaust\xE3o 5: velocidade reduzida a 0." },
|
|
34
|
+
{ id: "exhaustion-6", label: "Exhaustion 6", summary: "Exaust\xE3o 6: morte." },
|
|
35
|
+
{ id: "frightened", label: "Frightened", summary: "Amedrontado: desvantagem se a fonte do medo estiver \xE0 vista; n\xE3o pode se mover para perto dela." },
|
|
36
|
+
{ id: "grappled", label: "Grappled", summary: "Agarrado: velocidade 0; termina se o agarrador ficar incapacitado." },
|
|
37
|
+
{ id: "incapacitated", label: "Incapacitated", summary: "Incapacitado: n\xE3o pode tomar a\xE7\xF5es nem rea\xE7\xF5es." },
|
|
38
|
+
{ id: "invisible", label: "Invisible", summary: "Invis\xEDvel: vantagem em ataques; atacantes t\xEAm desvantagem." },
|
|
39
|
+
{ id: "paralyzed", label: "Paralyzed", summary: "Paralisado: incapacitado, n\xE3o pode se mover/falar; ataques a at\xE9 1,5m s\xE3o autom\xE1ticos cr\xEDticos." },
|
|
40
|
+
{ id: "petrified", label: "Petrified", summary: "Petrificado: transformado em subst\xE2ncia s\xF3lida; resist\xEAncia a todo dano; imune a venenos e doen\xE7as." },
|
|
41
|
+
{ id: "poisoned", label: "Poisoned", summary: "Envenenado: desvantagem em ataques e testes de habilidade." },
|
|
42
|
+
{ id: "prone", label: "Prone", summary: "Ca\xEDdo: desvantagem em ataques; ataques corpo-a-corpo contra o alvo t\xEAm vantagem; \xE0 dist\xE2ncia t\xEAm desvantagem." },
|
|
43
|
+
{ id: "restrained", label: "Restrained", summary: "Contido: velocidade 0; desvantagem em ataques e Dex saves; atacantes t\xEAm vantagem." },
|
|
44
|
+
{ id: "stunned", label: "Stunned", summary: "Atordoado: incapacitado; falha automaticamente em Str/Dex saves; atacantes t\xEAm vantagem." },
|
|
45
|
+
{ id: "unconscious", label: "Unconscious", summary: "Inconsciente: incapacitado, ca\xEDdo; ataques a at\xE9 1,5m s\xE3o cr\xEDticos autom\xE1ticos." }
|
|
46
|
+
];
|
|
47
|
+
var TRACKER_FIELDS = [
|
|
48
|
+
{
|
|
49
|
+
key: "ac",
|
|
50
|
+
label: "CA",
|
|
51
|
+
kind: "integer",
|
|
52
|
+
min: 1,
|
|
53
|
+
max: 30,
|
|
54
|
+
default: 10,
|
|
55
|
+
description: "Classe de Armadura \u2014 DC para ser atingido por ataques."
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
key: "deathSuccesses",
|
|
59
|
+
label: "M\u2713",
|
|
60
|
+
kind: "integer",
|
|
61
|
+
min: 0,
|
|
62
|
+
max: 3,
|
|
63
|
+
default: 0,
|
|
64
|
+
description: "Sucessos em testes de resist\xEAncia \xE0 morte (3 = estabilizado)."
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
key: "deathFailures",
|
|
68
|
+
label: "M\u2717",
|
|
69
|
+
kind: "integer",
|
|
70
|
+
min: 0,
|
|
71
|
+
max: 3,
|
|
72
|
+
default: 0,
|
|
73
|
+
description: "Falhas em testes de resist\xEAncia \xE0 morte (3 = morte)."
|
|
74
|
+
}
|
|
75
|
+
];
|
|
76
|
+
function abilityMod(score) {
|
|
77
|
+
return Math.floor((score - 10) / 2);
|
|
78
|
+
}
|
|
79
|
+
function spellSaveDC(proficiency, casterMod) {
|
|
80
|
+
return 8 + proficiency + casterMod;
|
|
81
|
+
}
|
|
82
|
+
function spellAttackBonus(proficiency, casterMod) {
|
|
83
|
+
return proficiency + casterMod;
|
|
84
|
+
}
|
|
85
|
+
function rollD20({ modifier = 0, advantage = false, disadvantage = false }) {
|
|
86
|
+
const cancelled = advantage && disadvantage;
|
|
87
|
+
const useAdv = advantage && !cancelled;
|
|
88
|
+
const useDis = disadvantage && !cancelled;
|
|
89
|
+
const count = useAdv || useDis ? 2 : 1;
|
|
90
|
+
const dice = roll(20, count);
|
|
91
|
+
const picked = useAdv ? Math.max(...dice) : useDis ? Math.min(...dice) : dice[0];
|
|
92
|
+
const total = picked + modifier;
|
|
93
|
+
const notes = [];
|
|
94
|
+
if (cancelled) notes.push("vantagem/desvantagem se cancelaram");
|
|
95
|
+
else if (useAdv) notes.push("vantagem");
|
|
96
|
+
else if (useDis) notes.push("desvantagem");
|
|
97
|
+
if (picked === 20) notes.push("cr\xEDtico natural");
|
|
98
|
+
if (picked === 1) notes.push("falha cr\xEDtica");
|
|
99
|
+
const modStr = modifier === 0 ? "" : modifier > 0 ? `+${modifier}` : `${modifier}`;
|
|
100
|
+
const dStr = count === 2 ? `2d20${useAdv ? "kh1" : "kl1"}` : "1d20";
|
|
101
|
+
return { rolls: dice, modifier, total, notation: `${dStr}${modStr}`, notes };
|
|
102
|
+
}
|
|
103
|
+
function rollAttack(params) {
|
|
104
|
+
const result = rollD20(params);
|
|
105
|
+
const d20 = result.rolls[result.rolls.length === 2 ? params.advantage && !params.disadvantage ? result.rolls[0] >= result.rolls[1] ? 0 : 1 : result.rolls[0] <= result.rolls[1] ? 0 : 1 : 0];
|
|
106
|
+
const notes = [...result.notes ?? []];
|
|
107
|
+
if (params.targetAC !== void 0) {
|
|
108
|
+
const natural20 = d20 === 20;
|
|
109
|
+
const natural1 = d20 === 1;
|
|
110
|
+
const hit = natural20 || !natural1 && result.total >= params.targetAC;
|
|
111
|
+
notes.push(hit ? natural20 ? "acerto cr\xEDtico" : "acertou" : natural1 ? "erro cr\xEDtico" : "errou");
|
|
112
|
+
}
|
|
113
|
+
return { ...result, notes };
|
|
114
|
+
}
|
|
115
|
+
function rollSave(params) {
|
|
116
|
+
const result = rollD20(params);
|
|
117
|
+
const notes = [...result.notes ?? []];
|
|
118
|
+
notes.push(result.total >= params.dc ? "sucesso" : "falha");
|
|
119
|
+
return { ...result, notes: notes.concat([`DC ${params.dc}`]) };
|
|
120
|
+
}
|
|
121
|
+
function rollDamage({ count, sides, modifier = 0, critical = false }) {
|
|
122
|
+
const totalDice = critical ? count * 2 : count;
|
|
123
|
+
const dice = roll(sides, totalDice);
|
|
124
|
+
const sum = dice.reduce((a, b) => a + b, 0);
|
|
125
|
+
const total = Math.max(0, sum + modifier);
|
|
126
|
+
const modStr = modifier === 0 ? "" : modifier > 0 ? `+${modifier}` : `${modifier}`;
|
|
127
|
+
return {
|
|
128
|
+
rolls: dice,
|
|
129
|
+
modifier,
|
|
130
|
+
total,
|
|
131
|
+
notation: `${totalDice}d${sides}${modStr}${critical ? " (crit)" : ""}`,
|
|
132
|
+
notes: critical ? ["dano cr\xEDtico \u2014 dados dobrados"] : []
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function applyDndDamage(incoming, ctx) {
|
|
136
|
+
const t = ctx.target;
|
|
137
|
+
const type = ctx.type;
|
|
138
|
+
if (!type || !t) return { final: Math.max(0, incoming), notes: [] };
|
|
139
|
+
if (t.immunity?.includes(type)) return { final: 0, notes: [`imune a ${type}`] };
|
|
140
|
+
if (t.resistance?.includes(type)) {
|
|
141
|
+
return { final: Math.floor(incoming / 2), notes: [`resist\xEAncia a ${type} (metade)`] };
|
|
142
|
+
}
|
|
143
|
+
if (t.vulnerability?.includes(type)) {
|
|
144
|
+
return { final: incoming * 2, notes: [`vulnerabilidade a ${type} (dobro)`] };
|
|
145
|
+
}
|
|
146
|
+
return { final: Math.max(0, incoming), notes: [] };
|
|
147
|
+
}
|
|
148
|
+
var RULES = {
|
|
149
|
+
roll(kind, params) {
|
|
150
|
+
switch (kind) {
|
|
151
|
+
case "d20":
|
|
152
|
+
case "check":
|
|
153
|
+
case "ability":
|
|
154
|
+
return rollD20(params);
|
|
155
|
+
case "attack":
|
|
156
|
+
return rollAttack(params);
|
|
157
|
+
case "save":
|
|
158
|
+
return rollSave(params);
|
|
159
|
+
case "damage":
|
|
160
|
+
return rollDamage(params);
|
|
161
|
+
default:
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
applyDamage(incoming, target) {
|
|
166
|
+
return applyDndDamage(incoming, target);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
var dnd5e2014 = {
|
|
170
|
+
id: "dnd5e-2014",
|
|
171
|
+
name: "Dungeons & Dragons 5e (2014)",
|
|
172
|
+
ruleVersion: "SRD 5.1",
|
|
173
|
+
attribution: "Contains material from the System Reference Document 5.1 by Wizards of the Coast LLC, licensed under CC-BY 4.0.",
|
|
174
|
+
dicePresets: DICE_PRESETS,
|
|
175
|
+
conditions: CONDITIONS,
|
|
176
|
+
trackerFields: TRACKER_FIELDS,
|
|
177
|
+
rules: RULES
|
|
178
|
+
};
|
|
179
|
+
export {
|
|
180
|
+
abilityMod,
|
|
181
|
+
dnd5e2014,
|
|
182
|
+
resetRoller,
|
|
183
|
+
setRoller,
|
|
184
|
+
spellAttackBonus,
|
|
185
|
+
spellSaveDC
|
|
186
|
+
};
|
|
187
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Dungeons & Dragons 5th Edition (2014).\n *\n * Conteúdo de regras (condições, ability scores, escala de DC) deriva do\n * System Reference Document 5.1, publicado pela Wizards of the Coast LLC\n * sob a Creative Commons Attribution 4.0 International License:\n * https://creativecommons.org/licenses/by/4.0/legalcode\n *\n * Esta implementação é original (não copia código de implementações\n * existentes). Referência conceitual: foundryvtt/dnd5e (MIT).\n */\n\nimport type {\n ConditionDef,\n DicePreset,\n RollResult,\n System,\n SystemRules,\n TrackerField,\n} from '@lippelt/srd-core'\n\n// ============================================================================\n// Random helper — extraído pra que os testes possam injetar uma fonte\n// determinística via `setRoller`.\n// ============================================================================\n\ntype Roller = (sides: number) => number\n\nlet roller: Roller = (sides: number) => Math.floor(Math.random() * sides) + 1\n\n/** Substitui o gerador de dados (use em testes). Restaurar com `resetRoller`. */\nexport function setRoller(fn: Roller): void {\n roller = fn\n}\n\n/** Restaura o gerador padrão (Math.random). */\nexport function resetRoller(): void {\n roller = (sides: number) => Math.floor(Math.random() * sides) + 1\n}\n\nfunction roll(sides: number, count = 1): number[] {\n const out: number[] = []\n for (let i = 0; i < count; i++) out.push(roller(sides))\n return out\n}\n\n// ============================================================================\n// Presets de dados — botões rápidos da UI\n// ============================================================================\n\nconst DICE_PRESETS: DicePreset[] = [\n { id: 'd20', label: 'd20', notation: '1d20', category: 'check' },\n { id: 'd20-adv', label: 'd20 (adv.)', notation: 'advantage', category: 'check', description: 'Rola 2d20 e pega o maior.' },\n { id: 'd20-dis', label: 'd20 (desv.)', notation: 'disadvantage', category: 'check', description: 'Rola 2d20 e pega o menor.' },\n { id: 'd4', label: 'd4', notation: '1d4', category: 'damage' },\n { id: 'd6', label: 'd6', notation: '1d6', category: 'damage' },\n { id: 'd8', label: 'd8', notation: '1d8', category: 'damage' },\n { id: 'd10', label: 'd10', notation: '1d10', category: 'damage' },\n { id: 'd12', label: 'd12', notation: '1d12', category: 'damage' },\n { id: 'd100', label: 'd100', notation: '1d100', category: 'special' },\n]\n\n// ============================================================================\n// Condições — SRD 5.1 (CC-BY 4.0)\n// ============================================================================\n\nconst CONDITIONS: ConditionDef[] = [\n { id: 'blinded', label: 'Blinded', summary: 'Cego: falha em testes que exigem visão; atacantes têm vantagem; o cego tem desvantagem.' },\n { id: 'charmed', label: 'Charmed', summary: 'Enfeitiçado: não pode atacar o encantador nem usar habilidades nocivas contra ele.' },\n { id: 'deafened', label: 'Deafened', summary: 'Surdo: falha em testes que dependem de audição.' },\n { id: 'exhaustion-1', label: 'Exhaustion 1', summary: 'Exaustão 1: desvantagem em testes de habilidade.' },\n { id: 'exhaustion-2', label: 'Exhaustion 2', summary: 'Exaustão 2: velocidade reduzida pela metade.' },\n { id: 'exhaustion-3', label: 'Exhaustion 3', summary: 'Exaustão 3: desvantagem em ataques e jogadas de resistência.' },\n { id: 'exhaustion-4', label: 'Exhaustion 4', summary: 'Exaustão 4: máximo de HP reduzido pela metade.' },\n { id: 'exhaustion-5', label: 'Exhaustion 5', summary: 'Exaustão 5: velocidade reduzida a 0.' },\n { id: 'exhaustion-6', label: 'Exhaustion 6', summary: 'Exaustão 6: morte.' },\n { id: 'frightened', label: 'Frightened', summary: 'Amedrontado: desvantagem se a fonte do medo estiver à vista; não pode se mover para perto dela.' },\n { id: 'grappled', label: 'Grappled', summary: 'Agarrado: velocidade 0; termina se o agarrador ficar incapacitado.' },\n { id: 'incapacitated', label: 'Incapacitated', summary: 'Incapacitado: não pode tomar ações nem reações.' },\n { id: 'invisible', label: 'Invisible', summary: 'Invisível: vantagem em ataques; atacantes têm desvantagem.' },\n { id: 'paralyzed', label: 'Paralyzed', summary: 'Paralisado: incapacitado, não pode se mover/falar; ataques a até 1,5m são automáticos críticos.' },\n { id: 'petrified', label: 'Petrified', summary: 'Petrificado: transformado em substância sólida; resistência a todo dano; imune a venenos e doenças.' },\n { id: 'poisoned', label: 'Poisoned', summary: 'Envenenado: desvantagem em ataques e testes de habilidade.' },\n { id: 'prone', label: 'Prone', summary: 'Caído: desvantagem em ataques; ataques corpo-a-corpo contra o alvo têm vantagem; à distância têm desvantagem.' },\n { id: 'restrained', label: 'Restrained', summary: 'Contido: velocidade 0; desvantagem em ataques e Dex saves; atacantes têm vantagem.' },\n { id: 'stunned', label: 'Stunned', summary: 'Atordoado: incapacitado; falha automaticamente em Str/Dex saves; atacantes têm vantagem.' },\n { id: 'unconscious', label: 'Unconscious', summary: 'Inconsciente: incapacitado, caído; ataques a até 1,5m são críticos automáticos.' },\n]\n\n// ============================================================================\n// Tracker fields — AC e death saves além de initiative/hp genéricos\n// ============================================================================\n\nconst TRACKER_FIELDS: TrackerField[] = [\n {\n key: 'ac',\n label: 'CA',\n kind: 'integer',\n min: 1,\n max: 30,\n default: 10,\n description: 'Classe de Armadura — DC para ser atingido por ataques.',\n },\n {\n key: 'deathSuccesses',\n label: 'M✓',\n kind: 'integer',\n min: 0,\n max: 3,\n default: 0,\n description: 'Sucessos em testes de resistência à morte (3 = estabilizado).',\n },\n {\n key: 'deathFailures',\n label: 'M✗',\n kind: 'integer',\n min: 0,\n max: 3,\n default: 0,\n description: 'Falhas em testes de resistência à morte (3 = morte).',\n },\n]\n\n// ============================================================================\n// Regras automatizadas\n// ============================================================================\n\n/** Modificador derivado da ability score: floor((score - 10) / 2). */\nexport function abilityMod(score: number): number {\n return Math.floor((score - 10) / 2)\n}\n\n/** DC de feitiço: 8 + proficiency + ability modifier. */\nexport function spellSaveDC(proficiency: number, casterMod: number): number {\n return 8 + proficiency + casterMod\n}\n\n/** Bônus de ataque por feitiço: proficiency + ability modifier. */\nexport function spellAttackBonus(proficiency: number, casterMod: number): number {\n return proficiency + casterMod\n}\n\ninterface D20Params {\n modifier?: number\n advantage?: boolean\n disadvantage?: boolean\n}\n\n/** Rola um d20 com possível advantage/disadvantage e modificador. */\nfunction rollD20({ modifier = 0, advantage = false, disadvantage = false }: D20Params): RollResult {\n // Vantagem e desvantagem se cancelam mutuamente (SRD 5.1).\n const cancelled = advantage && disadvantage\n const useAdv = advantage && !cancelled\n const useDis = disadvantage && !cancelled\n const count = useAdv || useDis ? 2 : 1\n const dice = roll(20, count)\n const picked = useAdv ? Math.max(...dice) : useDis ? Math.min(...dice) : dice[0]!\n const total = picked + modifier\n const notes: string[] = []\n if (cancelled) notes.push('vantagem/desvantagem se cancelaram')\n else if (useAdv) notes.push('vantagem')\n else if (useDis) notes.push('desvantagem')\n if (picked === 20) notes.push('crítico natural')\n if (picked === 1) notes.push('falha crítica')\n const modStr = modifier === 0 ? '' : modifier > 0 ? `+${modifier}` : `${modifier}`\n const dStr = count === 2 ? `2d20${useAdv ? 'kh1' : 'kl1'}` : '1d20'\n return { rolls: dice, modifier, total, notation: `${dStr}${modStr}`, notes }\n}\n\ninterface AttackParams {\n modifier?: number\n targetAC?: number\n advantage?: boolean\n disadvantage?: boolean\n}\n\n/**\n * Rolagem de ataque contra AC. Se `targetAC` for fornecido, anota se acertou.\n * Crítico natural 20 sempre acerta; 1 sempre erra (SRD 5.1).\n */\nfunction rollAttack(params: AttackParams): RollResult {\n const result = rollD20(params)\n const d20 = result.rolls[result.rolls.length === 2\n ? (params.advantage && !params.disadvantage ? (result.rolls[0]! >= result.rolls[1]! ? 0 : 1) : (result.rolls[0]! <= result.rolls[1]! ? 0 : 1))\n : 0]!\n const notes = [...(result.notes ?? [])]\n if (params.targetAC !== undefined) {\n const natural20 = d20 === 20\n const natural1 = d20 === 1\n const hit = natural20 || (!natural1 && result.total >= params.targetAC)\n notes.push(hit ? (natural20 ? 'acerto crítico' : 'acertou') : (natural1 ? 'erro crítico' : 'errou'))\n }\n return { ...result, notes }\n}\n\ninterface SaveParams {\n modifier?: number\n dc: number\n advantage?: boolean\n disadvantage?: boolean\n}\n\n/** Saving throw vs DC. Anota success/failure. */\nfunction rollSave(params: SaveParams): RollResult {\n const result = rollD20(params)\n const notes = [...(result.notes ?? [])]\n notes.push(result.total >= params.dc ? 'sucesso' : 'falha')\n return { ...result, notes: notes.concat([`DC ${params.dc}`]) }\n}\n\ninterface DamageParams {\n count: number\n sides: number\n modifier?: number\n critical?: boolean\n}\n\n/**\n * Rolagem de dano: NdM+K, com opção de crítico (rola o dobro dos dados,\n * mantém o modificador uma única vez — SRD 5.1).\n */\nfunction rollDamage({ count, sides, modifier = 0, critical = false }: DamageParams): RollResult {\n const totalDice = critical ? count * 2 : count\n const dice = roll(sides, totalDice)\n const sum = dice.reduce((a, b) => a + b, 0)\n const total = Math.max(0, sum + modifier)\n const modStr = modifier === 0 ? '' : modifier > 0 ? `+${modifier}` : `${modifier}`\n return {\n rolls: dice,\n modifier,\n total,\n notation: `${totalDice}d${sides}${modStr}${critical ? ' (crit)' : ''}`,\n notes: critical ? ['dano crítico — dados dobrados'] : [],\n }\n}\n\ninterface DamageTarget {\n resistance?: string[]\n vulnerability?: string[]\n immunity?: string[]\n}\n\ninterface ApplyDamageInput {\n type?: string\n target?: DamageTarget\n}\n\n/**\n * Reduz dano pelas propriedades do alvo. Ordem (SRD 5.1):\n * 1. Imunidade zera o dano.\n * 2. Resistência metade (arredondar pra baixo).\n * 3. Vulnerabilidade dobra.\n * Se uma criatura tem múltiplas categorias para o mesmo tipo, apenas uma se aplica\n * (mas combinadas com outras categorias podem coexistir — aqui assumimos exclusividade).\n */\nfunction applyDndDamage(incoming: number, ctx: ApplyDamageInput): { final: number; notes: string[] } {\n const t = ctx.target\n const type = ctx.type\n if (!type || !t) return { final: Math.max(0, incoming), notes: [] }\n if (t.immunity?.includes(type)) return { final: 0, notes: [`imune a ${type}`] }\n if (t.resistance?.includes(type)) {\n return { final: Math.floor(incoming / 2), notes: [`resistência a ${type} (metade)`] }\n }\n if (t.vulnerability?.includes(type)) {\n return { final: incoming * 2, notes: [`vulnerabilidade a ${type} (dobro)`] }\n }\n return { final: Math.max(0, incoming), notes: [] }\n}\n\n// ============================================================================\n// Bundle do sistema\n// ============================================================================\n\nconst RULES: SystemRules = {\n roll(kind, params) {\n switch (kind) {\n case 'd20':\n case 'check':\n case 'ability':\n return rollD20(params as unknown as D20Params)\n case 'attack':\n return rollAttack(params as unknown as AttackParams)\n case 'save':\n return rollSave(params as unknown as SaveParams)\n case 'damage':\n return rollDamage(params as unknown as DamageParams)\n default:\n return null\n }\n },\n applyDamage(incoming, target) {\n return applyDndDamage(incoming, target as ApplyDamageInput)\n },\n}\n\nexport const dnd5e2014: System = {\n id: 'dnd5e-2014',\n name: 'Dungeons & Dragons 5e (2014)',\n ruleVersion: 'SRD 5.1',\n attribution:\n 'Contains material from the System Reference Document 5.1 by Wizards of the Coast LLC, licensed under CC-BY 4.0.',\n dicePresets: DICE_PRESETS,\n conditions: CONDITIONS,\n trackerFields: TRACKER_FIELDS,\n rules: RULES,\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lippelt/srd-dnd5e-2014",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "D&D 5e (2014) system module for @lippelt/srd-core — SRD 5.1, CC-BY 4.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"lint": "eslint .",
|
|
29
|
+
"test": "vitest run",
|
|
30
|
+
"test:watch": "vitest"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/flippelt/gmcr-srd-systems.git",
|
|
36
|
+
"directory": "packages/dnd5e-2014"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@lippelt/srd-core": "^0.1.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@lippelt/srd-core": "*"
|
|
43
|
+
}
|
|
44
|
+
}
|