foundryvtt-mcp 0.11.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/LICENSE +21 -0
- package/README.md +142 -0
- package/dist/character/manager.d.ts +92 -0
- package/dist/character/manager.d.ts.map +1 -0
- package/dist/character/manager.js +208 -0
- package/dist/character/manager.js.map +1 -0
- package/dist/combat/manager.d.ts +94 -0
- package/dist/combat/manager.d.ts.map +1 -0
- package/dist/combat/manager.js +373 -0
- package/dist/combat/manager.js.map +1 -0
- package/dist/config/index.d.ts +114 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +177 -0
- package/dist/config/index.js.map +1 -0
- package/dist/diagnostics/client.d.ts +193 -0
- package/dist/diagnostics/client.d.ts.map +1 -0
- package/dist/diagnostics/client.js +314 -0
- package/dist/diagnostics/client.js.map +1 -0
- package/dist/diagnostics/types.d.ts +414 -0
- package/dist/diagnostics/types.d.ts.map +1 -0
- package/dist/diagnostics/types.js +94 -0
- package/dist/diagnostics/types.js.map +1 -0
- package/dist/foundry/auth.d.ts +19 -0
- package/dist/foundry/auth.d.ts.map +1 -0
- package/dist/foundry/auth.js +135 -0
- package/dist/foundry/auth.js.map +1 -0
- package/dist/foundry/client.d.ts +95 -0
- package/dist/foundry/client.d.ts.map +1 -0
- package/dist/foundry/client.js +692 -0
- package/dist/foundry/client.js.map +1 -0
- package/dist/foundry/types.d.ts +805 -0
- package/dist/foundry/types.d.ts.map +1 -0
- package/dist/foundry/types.js +13 -0
- package/dist/foundry/types.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +199 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/index.d.ts +3 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +93 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/tools/base.d.ts +80 -0
- package/dist/tools/base.d.ts.map +1 -0
- package/dist/tools/base.js +73 -0
- package/dist/tools/base.js.map +1 -0
- package/dist/tools/definitions.d.ts +414 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/definitions.js +429 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/handlers/actors.d.ts +31 -0
- package/dist/tools/handlers/actors.d.ts.map +1 -0
- package/dist/tools/handlers/actors.js +76 -0
- package/dist/tools/handlers/actors.js.map +1 -0
- package/dist/tools/handlers/chat.d.ts +13 -0
- package/dist/tools/handlers/chat.d.ts.map +1 -0
- package/dist/tools/handlers/chat.js +38 -0
- package/dist/tools/handlers/chat.js.map +1 -0
- package/dist/tools/handlers/combat.d.ts +11 -0
- package/dist/tools/handlers/combat.d.ts.map +1 -0
- package/dist/tools/handlers/combat.js +48 -0
- package/dist/tools/handlers/combat.js.map +1 -0
- package/dist/tools/handlers/diagnostics.d.ts +64 -0
- package/dist/tools/handlers/diagnostics.d.ts.map +1 -0
- package/dist/tools/handlers/diagnostics.js +182 -0
- package/dist/tools/handlers/diagnostics.js.map +1 -0
- package/dist/tools/handlers/dice.d.ts +39 -0
- package/dist/tools/handlers/dice.d.ts.map +1 -0
- package/dist/tools/handlers/dice.js +53 -0
- package/dist/tools/handlers/dice.js.map +1 -0
- package/dist/tools/handlers/generation.d.ts +44 -0
- package/dist/tools/handlers/generation.d.ts.map +1 -0
- package/dist/tools/handlers/generation.js +205 -0
- package/dist/tools/handlers/generation.js.map +1 -0
- package/dist/tools/handlers/items.d.ts +21 -0
- package/dist/tools/handlers/items.d.ts.map +1 -0
- package/dist/tools/handlers/items.js +50 -0
- package/dist/tools/handlers/items.js.map +1 -0
- package/dist/tools/handlers/journals.d.ts +22 -0
- package/dist/tools/handlers/journals.d.ts.map +1 -0
- package/dist/tools/handlers/journals.js +62 -0
- package/dist/tools/handlers/journals.js.map +1 -0
- package/dist/tools/handlers/resources.d.ts +13 -0
- package/dist/tools/handlers/resources.d.ts.map +1 -0
- package/dist/tools/handlers/resources.js +188 -0
- package/dist/tools/handlers/resources.js.map +1 -0
- package/dist/tools/handlers/scenes.d.ts +18 -0
- package/dist/tools/handlers/scenes.d.ts.map +1 -0
- package/dist/tools/handlers/scenes.js +34 -0
- package/dist/tools/handlers/scenes.js.map +1 -0
- package/dist/tools/handlers/users.d.ts +11 -0
- package/dist/tools/handlers/users.d.ts.map +1 -0
- package/dist/tools/handlers/users.js +34 -0
- package/dist/tools/handlers/users.js.map +1 -0
- package/dist/tools/handlers/utils.d.ts +11 -0
- package/dist/tools/handlers/utils.d.ts.map +1 -0
- package/dist/tools/handlers/utils.js +24 -0
- package/dist/tools/handlers/utils.js.map +1 -0
- package/dist/tools/handlers/world.d.ts +26 -0
- package/dist/tools/handlers/world.d.ts.map +1 -0
- package/dist/tools/handlers/world.js +92 -0
- package/dist/tools/handlers/world.js.map +1 -0
- package/dist/tools/index.d.ts +19 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +22 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/new-router.d.ts +29 -0
- package/dist/tools/new-router.d.ts.map +1 -0
- package/dist/tools/new-router.js +97 -0
- package/dist/tools/new-router.js.map +1 -0
- package/dist/tools/registry.d.ts +51 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +79 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/resources.d.ts +16 -0
- package/dist/tools/resources.d.ts.map +1 -0
- package/dist/tools/resources.js +63 -0
- package/dist/tools/resources.js.map +1 -0
- package/dist/tools/router.d.ts +22 -0
- package/dist/tools/router.d.ts.map +1 -0
- package/dist/tools/router.js +128 -0
- package/dist/tools/router.js.map +1 -0
- package/dist/utils/cache-instance.d.ts +25 -0
- package/dist/utils/cache-instance.d.ts.map +1 -0
- package/dist/utils/cache-instance.js +30 -0
- package/dist/utils/cache-instance.js.map +1 -0
- package/dist/utils/cache.d.ts +80 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +205 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/diagnostics.d.ts +114 -0
- package/dist/utils/diagnostics.d.ts.map +1 -0
- package/dist/utils/diagnostics.js +330 -0
- package/dist/utils/diagnostics.js.map +1 -0
- package/dist/utils/logger.d.ts +137 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +158 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { logger } from '../utils/logger.js';
|
|
3
|
+
export class CombatManager extends EventEmitter {
|
|
4
|
+
foundryClient;
|
|
5
|
+
currentCombat = null;
|
|
6
|
+
combatHistory = [];
|
|
7
|
+
turnTimer;
|
|
8
|
+
TURN_WARNING_TIME = 30000; // 30 seconds
|
|
9
|
+
constructor(foundryClient) {
|
|
10
|
+
super();
|
|
11
|
+
this.foundryClient = foundryClient;
|
|
12
|
+
this.setupEventHandlers();
|
|
13
|
+
}
|
|
14
|
+
setupEventHandlers() {
|
|
15
|
+
this.on('combat_start', this.handleCombatStart.bind(this));
|
|
16
|
+
this.on('turn_start', this.handleTurnStart.bind(this));
|
|
17
|
+
this.on('turn_end', this.handleTurnEnd.bind(this));
|
|
18
|
+
this.on('round_end', this.handleRoundEnd.bind(this));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Destroy the combat manager and release resources
|
|
22
|
+
*/
|
|
23
|
+
destroy() {
|
|
24
|
+
if (this.turnTimer) {
|
|
25
|
+
clearTimeout(this.turnTimer);
|
|
26
|
+
this.turnTimer = undefined;
|
|
27
|
+
}
|
|
28
|
+
this.removeAllListeners();
|
|
29
|
+
this.currentCombat = null;
|
|
30
|
+
this.combatHistory = [];
|
|
31
|
+
logger.info('Combat manager destroyed');
|
|
32
|
+
}
|
|
33
|
+
// Public API Methods
|
|
34
|
+
getCurrentCombat() {
|
|
35
|
+
return this.currentCombat;
|
|
36
|
+
}
|
|
37
|
+
getCombatHistory(limit = 50) {
|
|
38
|
+
return this.combatHistory.slice(-limit);
|
|
39
|
+
}
|
|
40
|
+
async startCombat(combatants) {
|
|
41
|
+
logger.info('Starting new combat encounter');
|
|
42
|
+
const combat = {
|
|
43
|
+
id: this.generateCombatId(),
|
|
44
|
+
round: 1,
|
|
45
|
+
turn: 0,
|
|
46
|
+
active: true,
|
|
47
|
+
started: false,
|
|
48
|
+
combatants: await this.initializeCombatants(combatants),
|
|
49
|
+
turnStartTime: new Date(),
|
|
50
|
+
roundStartTime: new Date(),
|
|
51
|
+
};
|
|
52
|
+
// Sort by initiative
|
|
53
|
+
combat.combatants.sort((a, b) => (b.initiative || 0) - (a.initiative || 0));
|
|
54
|
+
this.currentCombat = combat;
|
|
55
|
+
this.emitCombatEvent('combat_start', combat);
|
|
56
|
+
return combat;
|
|
57
|
+
}
|
|
58
|
+
async rollInitiative(combatantId) {
|
|
59
|
+
if (!this.currentCombat) {
|
|
60
|
+
throw new Error('No active combat');
|
|
61
|
+
}
|
|
62
|
+
const results = {};
|
|
63
|
+
const combatants = combatantId
|
|
64
|
+
? this.currentCombat.combatants.filter((c) => c.id === combatantId)
|
|
65
|
+
: this.currentCombat.combatants;
|
|
66
|
+
for (const combatant of combatants) {
|
|
67
|
+
// Roll 1d20 + initiative modifier (simplified)
|
|
68
|
+
const roll = Math.floor(Math.random() * 20) + 1;
|
|
69
|
+
const modifier = this.getInitiativeModifier(combatant);
|
|
70
|
+
const total = roll + modifier;
|
|
71
|
+
combatant.initiative = total;
|
|
72
|
+
results[combatant.name] = total;
|
|
73
|
+
logger.debug(`${combatant.name} rolled initiative: ${total} (${roll} + ${modifier})`);
|
|
74
|
+
}
|
|
75
|
+
// Re-sort combatants by initiative
|
|
76
|
+
this.currentCombat.combatants.sort((a, b) => (b.initiative || 0) - (a.initiative || 0));
|
|
77
|
+
this.emitCombatEvent('initiative_changed', this.currentCombat, results);
|
|
78
|
+
return results;
|
|
79
|
+
}
|
|
80
|
+
async nextTurn() {
|
|
81
|
+
if (!this.currentCombat || !this.currentCombat.active) {
|
|
82
|
+
throw new Error('No active combat');
|
|
83
|
+
}
|
|
84
|
+
// End current turn
|
|
85
|
+
if (this.currentCombat.currentCombatant) {
|
|
86
|
+
this.emitCombatEvent('turn_end', this.currentCombat);
|
|
87
|
+
}
|
|
88
|
+
// Clear turn timer
|
|
89
|
+
if (this.turnTimer) {
|
|
90
|
+
clearTimeout(this.turnTimer);
|
|
91
|
+
}
|
|
92
|
+
// Advance to next combatant
|
|
93
|
+
this.currentCombat.turn++;
|
|
94
|
+
// Check if we need to start a new round
|
|
95
|
+
if (this.currentCombat.turn >= this.currentCombat.combatants.length) {
|
|
96
|
+
this.currentCombat.turn = 0;
|
|
97
|
+
this.currentCombat.round++;
|
|
98
|
+
this.emitCombatEvent('round_end', this.currentCombat);
|
|
99
|
+
// Reset turn actions for all combatants
|
|
100
|
+
this.currentCombat.combatants.forEach((c) => {
|
|
101
|
+
c.turnTaken = false;
|
|
102
|
+
c.actions = {
|
|
103
|
+
action: false,
|
|
104
|
+
bonus: false,
|
|
105
|
+
movement: 0,
|
|
106
|
+
reaction: false,
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// Set current combatant
|
|
111
|
+
const combatant = this.currentCombat.combatants[this.currentCombat.turn];
|
|
112
|
+
if (combatant) {
|
|
113
|
+
this.currentCombat.currentCombatant = combatant;
|
|
114
|
+
}
|
|
115
|
+
this.currentCombat.turnStartTime = new Date();
|
|
116
|
+
if (!this.currentCombat.started) {
|
|
117
|
+
this.currentCombat.started = true;
|
|
118
|
+
}
|
|
119
|
+
this.emitCombatEvent('turn_start', this.currentCombat);
|
|
120
|
+
return this.currentCombat.currentCombatant || null;
|
|
121
|
+
}
|
|
122
|
+
async applyDamage(combatantId, damage, damageType) {
|
|
123
|
+
if (!this.currentCombat) {
|
|
124
|
+
throw new Error('No active combat');
|
|
125
|
+
}
|
|
126
|
+
const combatant = this.currentCombat.combatants.find((c) => c.id === combatantId);
|
|
127
|
+
if (!combatant) {
|
|
128
|
+
throw new Error(`Combatant ${combatantId} not found`);
|
|
129
|
+
}
|
|
130
|
+
// Apply damage to temp HP first, then regular HP
|
|
131
|
+
let remainingDamage = damage;
|
|
132
|
+
if (combatant.hp.temp && combatant.hp.temp > 0) {
|
|
133
|
+
const tempDamage = Math.min(remainingDamage, combatant.hp.temp);
|
|
134
|
+
combatant.hp.temp -= tempDamage;
|
|
135
|
+
remainingDamage -= tempDamage;
|
|
136
|
+
}
|
|
137
|
+
combatant.hp.current = Math.max(0, combatant.hp.current - remainingDamage);
|
|
138
|
+
// Check if combatant is defeated
|
|
139
|
+
if (combatant.hp.current === 0) {
|
|
140
|
+
combatant.defeated = true;
|
|
141
|
+
}
|
|
142
|
+
this.emitCombatEvent('damage_dealt', this.currentCombat, {
|
|
143
|
+
combatantId,
|
|
144
|
+
damage,
|
|
145
|
+
damageType,
|
|
146
|
+
newHP: combatant.hp.current,
|
|
147
|
+
defeated: combatant.defeated,
|
|
148
|
+
});
|
|
149
|
+
logger.info(`${combatant.name} took ${damage} ${damageType || 'damage'}, HP: ${combatant.hp.current}/${combatant.hp.max}`);
|
|
150
|
+
return combatant;
|
|
151
|
+
}
|
|
152
|
+
async healCombatant(combatantId, healing) {
|
|
153
|
+
if (!this.currentCombat) {
|
|
154
|
+
throw new Error('No active combat');
|
|
155
|
+
}
|
|
156
|
+
const combatant = this.currentCombat.combatants.find((c) => c.id === combatantId);
|
|
157
|
+
if (!combatant) {
|
|
158
|
+
throw new Error(`Combatant ${combatantId} not found`);
|
|
159
|
+
}
|
|
160
|
+
combatant.hp.current = Math.min(combatant.hp.max, combatant.hp.current + healing);
|
|
161
|
+
if (combatant.hp.current > 0) {
|
|
162
|
+
combatant.defeated = false;
|
|
163
|
+
}
|
|
164
|
+
logger.info(`${combatant.name} healed for ${healing}, HP: ${combatant.hp.current}/${combatant.hp.max}`);
|
|
165
|
+
return combatant;
|
|
166
|
+
}
|
|
167
|
+
async applyCondition(combatantId, condition, duration) {
|
|
168
|
+
if (!this.currentCombat) {
|
|
169
|
+
throw new Error('No active combat');
|
|
170
|
+
}
|
|
171
|
+
const combatant = this.currentCombat.combatants.find((c) => c.id === combatantId);
|
|
172
|
+
if (!combatant) {
|
|
173
|
+
throw new Error(`Combatant ${combatantId} not found`);
|
|
174
|
+
}
|
|
175
|
+
if (!combatant.conditions.includes(condition)) {
|
|
176
|
+
combatant.conditions.push(condition);
|
|
177
|
+
this.emitCombatEvent('condition_applied', this.currentCombat, {
|
|
178
|
+
combatantId,
|
|
179
|
+
condition,
|
|
180
|
+
duration,
|
|
181
|
+
});
|
|
182
|
+
logger.info(`Applied ${condition} to ${combatant.name}`);
|
|
183
|
+
}
|
|
184
|
+
return combatant;
|
|
185
|
+
}
|
|
186
|
+
async removeCondition(combatantId, condition) {
|
|
187
|
+
if (!this.currentCombat) {
|
|
188
|
+
throw new Error('No active combat');
|
|
189
|
+
}
|
|
190
|
+
const combatant = this.currentCombat.combatants.find((c) => c.id === combatantId);
|
|
191
|
+
if (!combatant) {
|
|
192
|
+
throw new Error(`Combatant ${combatantId} not found`);
|
|
193
|
+
}
|
|
194
|
+
const index = combatant.conditions.indexOf(condition);
|
|
195
|
+
if (index > -1) {
|
|
196
|
+
combatant.conditions.splice(index, 1);
|
|
197
|
+
logger.info(`Removed ${condition} from ${combatant.name}`);
|
|
198
|
+
}
|
|
199
|
+
return combatant;
|
|
200
|
+
}
|
|
201
|
+
async endCombat() {
|
|
202
|
+
if (!this.currentCombat) {
|
|
203
|
+
throw new Error('No active combat');
|
|
204
|
+
}
|
|
205
|
+
this.currentCombat.active = false;
|
|
206
|
+
if (this.turnTimer) {
|
|
207
|
+
clearTimeout(this.turnTimer);
|
|
208
|
+
}
|
|
209
|
+
const endedCombat = { ...this.currentCombat };
|
|
210
|
+
this.emitCombatEvent('combat_end', endedCombat);
|
|
211
|
+
logger.info('Combat ended');
|
|
212
|
+
this.currentCombat = null;
|
|
213
|
+
return endedCombat;
|
|
214
|
+
}
|
|
215
|
+
// Event Handlers
|
|
216
|
+
handleCombatStart(event) {
|
|
217
|
+
logger.info(`Combat started with ${event.combat.combatants.length} combatants`);
|
|
218
|
+
}
|
|
219
|
+
handleTurnStart(event) {
|
|
220
|
+
const combatant = event.combat.currentCombatant;
|
|
221
|
+
if (combatant) {
|
|
222
|
+
logger.info(`Turn ${event.combat.turn + 1}, Round ${event.combat.round}: ${combatant.name}'s turn`);
|
|
223
|
+
// Set turn timer
|
|
224
|
+
this.turnTimer = setTimeout(() => {
|
|
225
|
+
this.emit('turn_warning', combatant);
|
|
226
|
+
}, this.TURN_WARNING_TIME);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
handleTurnEnd(event) {
|
|
230
|
+
const combatant = event.combat.currentCombatant;
|
|
231
|
+
if (combatant) {
|
|
232
|
+
combatant.turnTaken = true;
|
|
233
|
+
logger.debug(`${combatant.name} ended their turn`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
handleRoundEnd(event) {
|
|
237
|
+
logger.info(`Round ${event.combat.round - 1} ended, starting Round ${event.combat.round}`);
|
|
238
|
+
}
|
|
239
|
+
// Helper Methods
|
|
240
|
+
async initializeCombatants(combatantData) {
|
|
241
|
+
const combatants = [];
|
|
242
|
+
for (const data of combatantData) {
|
|
243
|
+
const combatant = {
|
|
244
|
+
id: data.id || this.generateCombatantId(),
|
|
245
|
+
name: data.name || 'Unknown',
|
|
246
|
+
initiative: data.initiative || 0,
|
|
247
|
+
hp: data.hp || { current: 1, max: 1 },
|
|
248
|
+
ac: data.ac || 10,
|
|
249
|
+
conditions: data.conditions || [],
|
|
250
|
+
defeated: data.defeated || false,
|
|
251
|
+
hidden: data.hidden || false,
|
|
252
|
+
actorId: data.actorId || '',
|
|
253
|
+
tokenId: data.tokenId || '',
|
|
254
|
+
turnTaken: false,
|
|
255
|
+
actions: {
|
|
256
|
+
action: false,
|
|
257
|
+
bonus: false,
|
|
258
|
+
movement: 0,
|
|
259
|
+
reaction: false,
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
combatants.push(combatant);
|
|
263
|
+
}
|
|
264
|
+
return combatants;
|
|
265
|
+
}
|
|
266
|
+
getInitiativeModifier(_combatant) {
|
|
267
|
+
// Simplified initiative modifier calculation
|
|
268
|
+
// In a real implementation, this would pull from the actual character sheet
|
|
269
|
+
return Math.floor(Math.random() * 6) - 1; // -1 to +4
|
|
270
|
+
}
|
|
271
|
+
generateCombatId() {
|
|
272
|
+
return `combat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
273
|
+
}
|
|
274
|
+
generateCombatantId() {
|
|
275
|
+
return `combatant_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
276
|
+
}
|
|
277
|
+
emitCombatEvent(type, combat, data) {
|
|
278
|
+
const event = {
|
|
279
|
+
type,
|
|
280
|
+
timestamp: new Date(),
|
|
281
|
+
combat: { ...combat }, // Deep copy to prevent mutations
|
|
282
|
+
data,
|
|
283
|
+
};
|
|
284
|
+
this.combatHistory.push(event);
|
|
285
|
+
// Keep history manageable
|
|
286
|
+
if (this.combatHistory.length > 1000) {
|
|
287
|
+
this.combatHistory = this.combatHistory.slice(-500);
|
|
288
|
+
}
|
|
289
|
+
this.emit(type, event);
|
|
290
|
+
this.emit('combat_event', event);
|
|
291
|
+
}
|
|
292
|
+
// Analysis Methods
|
|
293
|
+
getCombatStatistics() {
|
|
294
|
+
if (!this.currentCombat) {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
const stats = {
|
|
298
|
+
totalRounds: this.currentCombat.round,
|
|
299
|
+
totalTurns: this.currentCombat.round * this.currentCombat.combatants.length + this.currentCombat.turn,
|
|
300
|
+
averageTurnTime: this.calculateAverageTurnTime(),
|
|
301
|
+
combatants: this.currentCombat.combatants.map((c) => ({
|
|
302
|
+
name: c.name,
|
|
303
|
+
initiative: c.initiative || 0,
|
|
304
|
+
hp: { current: c.hp.current, max: c.hp.max },
|
|
305
|
+
status: c.conditions,
|
|
306
|
+
})),
|
|
307
|
+
activeEffects: this.currentCombat.combatants.reduce((acc, c) => acc + c.conditions.length, 0),
|
|
308
|
+
};
|
|
309
|
+
return stats;
|
|
310
|
+
}
|
|
311
|
+
calculateAverageTurnTime() {
|
|
312
|
+
const turnEvents = this.combatHistory.filter((e) => e.type === 'turn_start');
|
|
313
|
+
if (turnEvents.length < 2) {
|
|
314
|
+
return 0;
|
|
315
|
+
}
|
|
316
|
+
let totalTime = 0;
|
|
317
|
+
for (let i = 1; i < turnEvents.length; i++) {
|
|
318
|
+
const currentEvent = turnEvents[i];
|
|
319
|
+
const previousEvent = turnEvents[i - 1];
|
|
320
|
+
if (currentEvent && previousEvent) {
|
|
321
|
+
totalTime += currentEvent.timestamp.getTime() - previousEvent.timestamp.getTime();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return Math.round(totalTime / (turnEvents.length - 1) / 1000); // seconds
|
|
325
|
+
}
|
|
326
|
+
suggestTacticalActions(combatantId) {
|
|
327
|
+
if (!this.currentCombat) {
|
|
328
|
+
return ['No active combat'];
|
|
329
|
+
}
|
|
330
|
+
const combatant = this.currentCombat.combatants.find((c) => c.id === combatantId);
|
|
331
|
+
if (!combatant) {
|
|
332
|
+
return ['Combatant not found'];
|
|
333
|
+
}
|
|
334
|
+
const suggestions = [];
|
|
335
|
+
// HP-based suggestions
|
|
336
|
+
const hpPercent = (combatant.hp.current / combatant.hp.max) * 100;
|
|
337
|
+
if (hpPercent < 25) {
|
|
338
|
+
suggestions.push('Consider healing or retreating - HP critically low');
|
|
339
|
+
suggestions.push('Use defensive actions like Dodge or Shield');
|
|
340
|
+
}
|
|
341
|
+
else if (hpPercent < 50) {
|
|
342
|
+
suggestions.push('Monitor HP carefully - consider healing');
|
|
343
|
+
}
|
|
344
|
+
// Condition-based suggestions
|
|
345
|
+
if (combatant.conditions.includes('poisoned')) {
|
|
346
|
+
suggestions.push('Remove poison condition if possible');
|
|
347
|
+
}
|
|
348
|
+
if (combatant.conditions.includes('prone')) {
|
|
349
|
+
suggestions.push('Use movement to stand up from prone');
|
|
350
|
+
}
|
|
351
|
+
if (combatant.conditions.includes('grappled')) {
|
|
352
|
+
suggestions.push('Attempt to escape grapple with Athletics or Acrobatics');
|
|
353
|
+
}
|
|
354
|
+
// Action economy suggestions
|
|
355
|
+
if (!combatant.actions.action) {
|
|
356
|
+
suggestions.push('Use your Action for Attack, Cast a Spell, or other actions');
|
|
357
|
+
}
|
|
358
|
+
if (!combatant.actions.bonus) {
|
|
359
|
+
suggestions.push('Check for available Bonus Actions');
|
|
360
|
+
}
|
|
361
|
+
// Enemy analysis
|
|
362
|
+
const enemies = this.currentCombat.combatants.filter((c) => c.id !== combatantId && !c.defeated);
|
|
363
|
+
const lowHpEnemies = enemies.filter((e) => e.hp.current / e.hp.max < 0.3);
|
|
364
|
+
if (lowHpEnemies.length > 0) {
|
|
365
|
+
suggestions.push(`Focus fire on low HP enemies: ${lowHpEnemies.map((e) => e.name).join(', ')}`);
|
|
366
|
+
}
|
|
367
|
+
if (suggestions.length === 0) {
|
|
368
|
+
suggestions.push('Assess battlefield and choose optimal action');
|
|
369
|
+
}
|
|
370
|
+
return suggestions;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/combat/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Configuration management for FoundryVTT MCP Server
|
|
3
|
+
*
|
|
4
|
+
* This module handles loading and validating configuration from environment variables
|
|
5
|
+
* using Zod schemas for type safety and runtime validation.
|
|
6
|
+
*
|
|
7
|
+
* @version 0.1.0
|
|
8
|
+
* @author FoundryVTT MCP Team
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
/**
|
|
12
|
+
* Zod schema for validating server configuration
|
|
13
|
+
*
|
|
14
|
+
* Defines the structure and validation rules for all configuration options,
|
|
15
|
+
* including server settings, FoundryVTT connection details, and caching options.
|
|
16
|
+
*/
|
|
17
|
+
declare const ConfigSchema: z.ZodObject<{
|
|
18
|
+
serverName: z.ZodDefault<z.ZodString>;
|
|
19
|
+
serverVersion: z.ZodDefault<z.ZodString>;
|
|
20
|
+
logLevel: z.ZodDefault<z.ZodEnum<{
|
|
21
|
+
debug: "debug";
|
|
22
|
+
info: "info";
|
|
23
|
+
warn: "warn";
|
|
24
|
+
error: "error";
|
|
25
|
+
}>>;
|
|
26
|
+
nodeEnv: z.ZodDefault<z.ZodEnum<{
|
|
27
|
+
development: "development";
|
|
28
|
+
production: "production";
|
|
29
|
+
test: "test";
|
|
30
|
+
}>>;
|
|
31
|
+
foundry: z.ZodObject<{
|
|
32
|
+
url: z.ZodString;
|
|
33
|
+
apiKey: z.ZodOptional<z.ZodString>;
|
|
34
|
+
username: z.ZodOptional<z.ZodString>;
|
|
35
|
+
password: z.ZodOptional<z.ZodString>;
|
|
36
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
37
|
+
socketPath: z.ZodDefault<z.ZodString>;
|
|
38
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
39
|
+
retryAttempts: z.ZodDefault<z.ZodNumber>;
|
|
40
|
+
retryDelay: z.ZodDefault<z.ZodNumber>;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
cache: z.ZodObject<{
|
|
43
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
44
|
+
ttlSeconds: z.ZodDefault<z.ZodNumber>;
|
|
45
|
+
maxSize: z.ZodDefault<z.ZodNumber>;
|
|
46
|
+
}, z.core.$strip>;
|
|
47
|
+
}, z.core.$strip>;
|
|
48
|
+
/**
|
|
49
|
+
* TypeScript type derived from the ConfigSchema
|
|
50
|
+
*
|
|
51
|
+
* This type provides compile-time type checking for configuration objects
|
|
52
|
+
* and ensures consistency between the schema and type definitions.
|
|
53
|
+
*/
|
|
54
|
+
type Config = z.infer<typeof ConfigSchema>;
|
|
55
|
+
/**
|
|
56
|
+
* Gets the global configuration instance
|
|
57
|
+
*
|
|
58
|
+
* This loads and caches the configuration on first access, allowing tests
|
|
59
|
+
* to set environment variables before triggering configuration validation.
|
|
60
|
+
*
|
|
61
|
+
* @returns Validated configuration object
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* import { config } from './config/index.js';
|
|
65
|
+
*
|
|
66
|
+
* console.log(`Connecting to ${config.foundry.url}`);
|
|
67
|
+
* if (config.foundry.apiKey) {
|
|
68
|
+
* console.log('Using local REST API module with API key');
|
|
69
|
+
* } else {
|
|
70
|
+
* console.log('Using WebSocket connection with username/password');
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare const config: {
|
|
75
|
+
serverName: string;
|
|
76
|
+
serverVersion: string;
|
|
77
|
+
logLevel: "debug" | "info" | "warn" | "error";
|
|
78
|
+
nodeEnv: "development" | "production" | "test";
|
|
79
|
+
foundry: {
|
|
80
|
+
url: string;
|
|
81
|
+
socketPath: string;
|
|
82
|
+
timeout: number;
|
|
83
|
+
retryAttempts: number;
|
|
84
|
+
retryDelay: number;
|
|
85
|
+
apiKey?: string | undefined;
|
|
86
|
+
username?: string | undefined;
|
|
87
|
+
password?: string | undefined;
|
|
88
|
+
userId?: string | undefined;
|
|
89
|
+
};
|
|
90
|
+
cache: {
|
|
91
|
+
enabled: boolean;
|
|
92
|
+
ttlSeconds: number;
|
|
93
|
+
maxSize: number;
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Resets the cached configuration - used for testing
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
100
|
+
export declare function resetConfig(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Export the Config type for use in other modules
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* import type { Config } from './config/index.js';
|
|
107
|
+
*
|
|
108
|
+
* function processConfig(cfg: Config) {
|
|
109
|
+
* // Process configuration
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export type { Config };
|
|
114
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AACH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDhB,CAAC;AAEH;;;;;GAKG;AACH,KAAK,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAyF3C;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;CAOjB,CAAC;AAEH;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED;;;;;;;;;;;GAWG;AACH,YAAY,EAAE,MAAM,EAAE,CAAC"}
|