@rpgjs/action-battle 5.0.0-beta.5 → 5.0.0-beta.7

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 (66) hide show
  1. package/README.md +161 -22
  2. package/dist/ai.server.d.ts +55 -4
  3. package/dist/client/index.js +13 -8
  4. package/dist/client/index10.js +54 -136
  5. package/dist/client/index11.js +52 -23
  6. package/dist/client/index12.js +101 -1217
  7. package/dist/client/index13.js +139 -42
  8. package/dist/client/index14.js +23 -8
  9. package/dist/client/index15.js +68 -444
  10. package/dist/client/index16.js +1343 -0
  11. package/dist/client/index17.js +13 -0
  12. package/dist/client/index18.js +60 -0
  13. package/dist/client/index19.js +10 -0
  14. package/dist/client/index2.js +25 -87
  15. package/dist/client/index20.js +504 -0
  16. package/dist/client/index3.js +45 -83
  17. package/dist/client/index4.js +98 -297
  18. package/dist/client/index5.js +81 -33
  19. package/dist/client/index6.js +284 -78
  20. package/dist/client/index7.js +33 -74
  21. package/dist/client/index8.js +95 -55
  22. package/dist/client/index9.js +75 -96
  23. package/dist/core/attack-profile.d.ts +9 -0
  24. package/dist/core/attack-runtime.d.ts +20 -0
  25. package/dist/core/enemy-attack-profiles.d.ts +6 -0
  26. package/dist/core/equipment.d.ts +2 -0
  27. package/dist/core/hit-reaction.d.ts +5 -0
  28. package/dist/index.d.ts +7 -2
  29. package/dist/server/index.js +12 -7
  30. package/dist/server/index10.js +1340 -8
  31. package/dist/server/index11.js +37 -0
  32. package/dist/server/index12.js +60 -0
  33. package/dist/server/index13.js +13 -0
  34. package/dist/server/index14.js +503 -0
  35. package/dist/server/index15.js +10 -0
  36. package/dist/server/index2.js +1 -1
  37. package/dist/server/index3.js +25 -87
  38. package/dist/server/index4.js +45 -141
  39. package/dist/server/index5.js +104 -21
  40. package/dist/server/index6.js +137 -1215
  41. package/dist/server/index7.js +22 -34
  42. package/dist/server/index8.js +70 -44
  43. package/dist/server/index9.js +44 -437
  44. package/dist/server.d.ts +8 -2
  45. package/dist/ui/state.d.ts +5 -5
  46. package/package.json +5 -5
  47. package/src/ai.server.spec.ts +120 -0
  48. package/src/ai.server.ts +362 -56
  49. package/src/client.ts +21 -12
  50. package/src/config.ts +17 -2
  51. package/src/core/attack-profile.spec.ts +118 -0
  52. package/src/core/attack-profile.ts +100 -0
  53. package/src/core/attack-runtime.spec.ts +103 -0
  54. package/src/core/attack-runtime.ts +83 -0
  55. package/src/core/contracts.ts +3 -0
  56. package/src/core/enemy-attack-profiles.spec.ts +35 -0
  57. package/src/core/enemy-attack-profiles.ts +103 -0
  58. package/src/core/equipment.spec.ts +37 -0
  59. package/src/core/equipment.ts +17 -0
  60. package/src/core/hit-reaction.spec.ts +43 -0
  61. package/src/core/hit-reaction.ts +70 -0
  62. package/src/core/hit.spec.ts +54 -1
  63. package/src/core/hit.ts +26 -0
  64. package/src/index.ts +48 -1
  65. package/src/server.ts +192 -34
  66. package/src/types.ts +62 -6
@@ -0,0 +1,13 @@
1
+ //#region src/core/equipment.ts
2
+ var resolveItemId = (item) => item?.id?.() ?? item?.id;
3
+ function resolveActionBattleWeaponAttackProfile(entity) {
4
+ const equipments = entity?.equipments?.() || [];
5
+ for (const item of equipments) {
6
+ const itemId = resolveItemId(item);
7
+ const itemData = entity?.databaseById?.(itemId);
8
+ if (itemData?._type === "weapon" && itemData.attackProfile) return itemData.attackProfile;
9
+ }
10
+ return null;
11
+ }
12
+ //#endregion
13
+ export { resolveActionBattleWeaponAttackProfile };
@@ -0,0 +1,60 @@
1
+ import { isActionBattleEntityInvincible, setActionBattleInvincibility } from "./index2.js";
2
+ //#region src/core/hit.ts
3
+ var applyActionBattleHit = (system, context) => {
4
+ let hitContext = { ...context };
5
+ const before = system.hooks?.beforeHit?.(hitContext);
6
+ if (before === false) return {
7
+ damage: 0,
8
+ knockbackForce: 0,
9
+ knockbackDuration: 0,
10
+ defeated: false,
11
+ attacker: hitContext.attacker,
12
+ target: hitContext.target,
13
+ cancelled: true,
14
+ metadata: hitContext.metadata
15
+ };
16
+ if (before) hitContext = before;
17
+ if (isActionBattleEntityInvincible(hitContext.target)) return {
18
+ damage: 0,
19
+ knockbackForce: 0,
20
+ knockbackDuration: 0,
21
+ defeated: false,
22
+ attacker: hitContext.attacker,
23
+ target: hitContext.target,
24
+ cancelled: true,
25
+ metadata: hitContext.metadata,
26
+ reaction: hitContext.reaction
27
+ };
28
+ const damage = hitContext.damage ?? system.resolveDamage({
29
+ attacker: hitContext.attacker,
30
+ target: hitContext.target,
31
+ skill: hitContext.skill,
32
+ pattern: hitContext.pattern
33
+ });
34
+ hitContext.damage = damage;
35
+ const afterDamage = system.hooks?.afterDamage?.(hitContext);
36
+ if (afterDamage) hitContext = afterDamage;
37
+ const knockback = hitContext.knockback ?? system.resolveKnockback({
38
+ attacker: hitContext.attacker,
39
+ target: hitContext.target,
40
+ damage
41
+ });
42
+ hitContext.knockback = knockback;
43
+ if (!damage.defeated && knockback.force > 0 && knockback.direction) hitContext.target.knockback?.(knockback.direction, knockback.force, knockback.duration);
44
+ if (!damage.defeated && hitContext.reaction?.invincibilityMs) setActionBattleInvincibility(hitContext.target, hitContext.reaction.invincibilityMs);
45
+ const result = {
46
+ damage: damage.damage,
47
+ knockbackForce: knockback.force,
48
+ knockbackDuration: knockback.duration,
49
+ defeated: damage.defeated,
50
+ attacker: hitContext.attacker,
51
+ target: hitContext.target,
52
+ rawDamage: damage.raw,
53
+ reaction: hitContext.reaction,
54
+ metadata: hitContext.metadata
55
+ };
56
+ system.hooks?.afterHit?.(result);
57
+ return result;
58
+ };
59
+ //#endregion
60
+ export { applyActionBattleHit };
@@ -0,0 +1,10 @@
1
+ //#region src/enemies/factory.ts
2
+ var BattleAi = null;
3
+ var createActionEnemy = (event, presetOrOptions, presets = {}) => {
4
+ const options = typeof presetOrOptions === "string" ? presets[presetOrOptions] : presetOrOptions;
5
+ if (!options) throw new Error(`Action battle enemy preset not found: ${presetOrOptions}`);
6
+ options.stats?.(event);
7
+ return new BattleAi(event, options);
8
+ };
9
+ //#endregion
10
+ export { createActionEnemy };
@@ -1,94 +1,32 @@
1
- //#region src/config.ts
2
- var DEFAULT_ACTION_BATTLE_OPTIONS = {
3
- ui: {
4
- actionBar: {
5
- enabled: false,
6
- autoOpen: false,
7
- mode: "both"
8
- },
9
- targeting: {
10
- enabled: true,
11
- showGrid: true,
12
- colors: {
13
- area: 3120887,
14
- edge: 1796760,
15
- cursor: 16765286
16
- }
17
- }
18
- },
19
- skills: { defaultAoeMask: ["#"] },
20
- targeting: {
21
- affects: "events",
22
- allowEmptyTarget: true
23
- },
24
- attack: {
25
- lockMovement: true,
26
- lockDurationMs: 350,
27
- showPreview: true,
28
- previewDurationMs: 180,
29
- previewColor: 16774064,
30
- previewAccentColor: 16777215
31
- },
32
- animations: {}
1
+ //#region src/core/hit-reaction.ts
2
+ var DEFAULT_ACTION_BATTLE_HIT_REACTION = {
3
+ invincibilityMs: 250,
4
+ hitstunMs: 150,
5
+ staggerPower: 1
33
6
  };
34
- var currentActionBattleOptions = DEFAULT_ACTION_BATTLE_OPTIONS;
35
- function normalizeActionBattleOptions(options = {}) {
7
+ var STATE_KEY = "__actionBattleHitReaction";
8
+ var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
9
+ var nonNegativeMs = (value, fallback) => isFiniteNumber(value) ? Math.max(0, value) : fallback;
10
+ var nonNegativeValue = (value, fallback) => isFiniteNumber(value) ? Math.max(0, value) : fallback;
11
+ var getRuntimeState = (entity) => {
12
+ if (!entity[STATE_KEY]) entity[STATE_KEY] = { invincibleUntil: 0 };
13
+ return entity[STATE_KEY];
14
+ };
15
+ function normalizeActionBattleHitReaction(reaction, defaults = DEFAULT_ACTION_BATTLE_HIT_REACTION) {
36
16
  return {
37
- ui: {
38
- actionBar: {
39
- ...DEFAULT_ACTION_BATTLE_OPTIONS.ui?.actionBar,
40
- ...options.ui?.actionBar
41
- },
42
- targeting: {
43
- ...DEFAULT_ACTION_BATTLE_OPTIONS.ui?.targeting,
44
- ...options.ui?.targeting,
45
- colors: {
46
- ...DEFAULT_ACTION_BATTLE_OPTIONS.ui?.targeting?.colors,
47
- ...options.ui?.targeting?.colors
48
- }
49
- }
50
- },
51
- skills: {
52
- ...DEFAULT_ACTION_BATTLE_OPTIONS.skills,
53
- ...options.skills
54
- },
55
- targeting: {
56
- ...DEFAULT_ACTION_BATTLE_OPTIONS.targeting,
57
- ...options.targeting
58
- },
59
- attack: {
60
- ...DEFAULT_ACTION_BATTLE_OPTIONS.attack,
61
- ...options.attack
62
- },
63
- animations: {
64
- ...DEFAULT_ACTION_BATTLE_OPTIONS.animations,
65
- ...options.animations
66
- },
67
- systems: {
68
- combat: {
69
- ...DEFAULT_ACTION_BATTLE_OPTIONS.systems?.combat,
70
- ...options.systems?.combat,
71
- hooks: {
72
- ...DEFAULT_ACTION_BATTLE_OPTIONS.systems?.combat?.hooks,
73
- ...options.systems?.combat?.hooks
74
- }
75
- },
76
- ai: {
77
- ...DEFAULT_ACTION_BATTLE_OPTIONS.systems?.ai,
78
- ...options.systems?.ai,
79
- behaviors: {
80
- ...DEFAULT_ACTION_BATTLE_OPTIONS.systems?.ai?.behaviors,
81
- ...options.systems?.ai?.behaviors
82
- }
83
- }
84
- }
17
+ invincibilityMs: nonNegativeMs(reaction?.invincibilityMs, defaults.invincibilityMs),
18
+ hitstunMs: nonNegativeMs(reaction?.hitstunMs, defaults.hitstunMs),
19
+ staggerPower: nonNegativeValue(reaction?.staggerPower, defaults.staggerPower)
85
20
  };
86
21
  }
87
- function setActionBattleOptions(options) {
88
- currentActionBattleOptions = options;
22
+ function isActionBattleEntityInvincible(entity, now = Date.now()) {
23
+ if (!entity) return false;
24
+ return getRuntimeState(entity).invincibleUntil > now;
89
25
  }
90
- function getActionBattleOptions() {
91
- return currentActionBattleOptions;
26
+ function setActionBattleInvincibility(entity, durationMs, now = Date.now()) {
27
+ if (!entity || durationMs <= 0) return;
28
+ const state = getRuntimeState(entity);
29
+ state.invincibleUntil = Math.max(state.invincibleUntil, now + durationMs);
92
30
  }
93
31
  //#endregion
94
- export { DEFAULT_ACTION_BATTLE_OPTIONS, getActionBattleOptions, normalizeActionBattleOptions, setActionBattleOptions };
32
+ export { DEFAULT_ACTION_BATTLE_HIT_REACTION, isActionBattleEntityInvincible, normalizeActionBattleHitReaction, setActionBattleInvincibility };