volleyballsimtypes 0.0.452 → 0.0.453

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 (37) hide show
  1. package/dist/cjs/src/service/event/event-types.d.ts +3 -2
  2. package/dist/cjs/src/service/event/free-ball.d.ts +17 -0
  3. package/dist/cjs/src/service/event/free-ball.js +47 -0
  4. package/dist/cjs/src/service/event/index.d.ts +1 -0
  5. package/dist/cjs/src/service/event/index.js +1 -0
  6. package/dist/cjs/src/service/event/rally-event.d.ts +3 -2
  7. package/dist/cjs/src/service/event/rally-event.js +1 -0
  8. package/dist/cjs/src/service/event/schemas/block.z.d.ts +1 -0
  9. package/dist/cjs/src/service/event/schemas/free-ball.z.d.ts +30 -0
  10. package/dist/cjs/src/service/event/schemas/free-ball.z.js +16 -0
  11. package/dist/cjs/src/service/event/schemas/reception.z.d.ts +1 -0
  12. package/dist/cjs/src/service/event/schemas/serve.z.d.ts +1 -0
  13. package/dist/cjs/src/service/event/schemas/set.z.d.ts +1 -0
  14. package/dist/cjs/src/service/event/schemas/spike.z.d.ts +1 -0
  15. package/dist/cjs/src/service/player/schemas/player.z.d.ts +1 -0
  16. package/dist/cjs/src/service/player/trait.d.ts +8 -2
  17. package/dist/cjs/src/service/player/trait.js +6 -0
  18. package/dist/cjs/src/stat-config/traits.json +24 -11
  19. package/dist/esm/src/service/event/event-types.d.ts +3 -2
  20. package/dist/esm/src/service/event/free-ball.d.ts +17 -0
  21. package/dist/esm/src/service/event/free-ball.js +43 -0
  22. package/dist/esm/src/service/event/index.d.ts +1 -0
  23. package/dist/esm/src/service/event/index.js +1 -0
  24. package/dist/esm/src/service/event/rally-event.d.ts +3 -2
  25. package/dist/esm/src/service/event/rally-event.js +1 -0
  26. package/dist/esm/src/service/event/schemas/block.z.d.ts +1 -0
  27. package/dist/esm/src/service/event/schemas/free-ball.z.d.ts +30 -0
  28. package/dist/esm/src/service/event/schemas/free-ball.z.js +13 -0
  29. package/dist/esm/src/service/event/schemas/reception.z.d.ts +1 -0
  30. package/dist/esm/src/service/event/schemas/serve.z.d.ts +1 -0
  31. package/dist/esm/src/service/event/schemas/set.z.d.ts +1 -0
  32. package/dist/esm/src/service/event/schemas/spike.z.d.ts +1 -0
  33. package/dist/esm/src/service/player/schemas/player.z.d.ts +1 -0
  34. package/dist/esm/src/service/player/trait.d.ts +8 -2
  35. package/dist/esm/src/service/player/trait.js +6 -0
  36. package/dist/esm/src/stat-config/traits.json +24 -11
  37. package/package.json +1 -1
@@ -1,7 +1,8 @@
1
1
  import type { BlockFailure, BlockType } from './block';
2
+ import type { FreeBallFailure, FreeBallType } from './free-ball';
2
3
  import type { ReceptionFailure, ReceptionType } from './reception';
3
4
  import type { ServeFailure, ServeType } from './serve';
4
5
  import type { SetFailure, SetType } from './set';
5
6
  import type { SpikeFailure, SpikeType } from './spike';
6
- export type EventSubType = BlockType | ReceptionType | ServeType | SetType | SpikeType;
7
- export type EventFailureType = BlockFailure | ReceptionFailure | ServeFailure | SetFailure | SpikeFailure;
7
+ export type EventSubType = BlockType | FreeBallType | ReceptionType | ServeType | SetType | SpikeType;
8
+ export type EventFailureType = BlockFailure | FreeBallFailure | ReceptionFailure | ServeFailure | SetFailure | SpikeFailure;
@@ -0,0 +1,17 @@
1
+ import { InPlayEvent } from './in-play-event';
2
+ export declare enum FreeBallTypeEnum {
3
+ OVER = 0,
4
+ STAY = 1
5
+ }
6
+ export type FreeBallType = FreeBallTypeEnum.OVER | FreeBallTypeEnum.STAY;
7
+ export declare enum FreeBallFailureEnum {
8
+ NO_FAILURE = 0
9
+ }
10
+ export type FreeBallFailure = FreeBallFailureEnum.NO_FAILURE;
11
+ export declare class FreeBall extends InPlayEvent<FreeBallFailure, FreeBallType> {
12
+ readonly failure: FreeBallFailure;
13
+ readonly type: FreeBallType;
14
+ static create(input: unknown): FreeBall;
15
+ private constructor();
16
+ toString(): string;
17
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FreeBall = exports.FreeBallFailureEnum = exports.FreeBallTypeEnum = void 0;
4
+ const rally_event_1 = require("./rally-event");
5
+ const in_play_event_1 = require("./in-play-event");
6
+ const free_ball_z_1 = require("./schemas/free-ball.z");
7
+ var FreeBallTypeEnum;
8
+ (function (FreeBallTypeEnum) {
9
+ // The save sent the ball over the net as a free ball -- the opponent plays it out.
10
+ FreeBallTypeEnum[FreeBallTypeEnum["OVER"] = 0] = "OVER";
11
+ // The save kept the ball on the team's side -- the team plays out its remaining touch(es).
12
+ FreeBallTypeEnum[FreeBallTypeEnum["STAY"] = 1] = "STAY";
13
+ })(FreeBallTypeEnum || (exports.FreeBallTypeEnum = FreeBallTypeEnum = {}));
14
+ var FreeBallFailureEnum;
15
+ (function (FreeBallFailureEnum) {
16
+ // A Last Resort save is guaranteed -- it always produces a free ball, never an error.
17
+ FreeBallFailureEnum[FreeBallFailureEnum["NO_FAILURE"] = 0] = "NO_FAILURE";
18
+ })(FreeBallFailureEnum || (exports.FreeBallFailureEnum = FreeBallFailureEnum = {}));
19
+ const eventType = rally_event_1.EventTypeEnum.FREE_BALL;
20
+ // A FREE_BALL event is a Last Resort save: the libero digs a ball that would otherwise have lost the rally and
21
+ // puts it back in play as a neutral free ball (over to the opponent, or staying on side). It is a real in-play
22
+ // event (score + target) so the next receiver handles it like any free ball.
23
+ class FreeBall extends in_play_event_1.InPlayEvent {
24
+ static create(input) {
25
+ const result = free_ball_z_1.FreeBallInputSchema.safeParse(input);
26
+ if (!result.success) {
27
+ throw new Error(`INVALID_FREE_BALL: ${result.error.message}. RECEIVED=${(() => { try {
28
+ return JSON.stringify(input);
29
+ }
30
+ catch {
31
+ return String(input);
32
+ } })()}`);
33
+ }
34
+ return new FreeBall(result.data);
35
+ }
36
+ constructor({ score, playerId, target, failure, type, activeTraits }) {
37
+ super({ score, playerId, target, activeTraits, eventType });
38
+ this.type = type;
39
+ this.failure = failure;
40
+ }
41
+ toString() {
42
+ const failure = `"failure":${this.failure}`;
43
+ const type = `"type":${this.type}`;
44
+ return `{${this._toString()},${failure},${type}}`;
45
+ }
46
+ }
47
+ exports.FreeBall = FreeBall;
@@ -1,5 +1,6 @@
1
1
  export * from './block';
2
2
  export * from './event-types';
3
+ export * from './free-ball';
3
4
  export * from './in-play-event';
4
5
  export * from './libero-replacement';
5
6
  export * from './rally-event';
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./block"), exports);
18
18
  __exportStar(require("./event-types"), exports);
19
+ __exportStar(require("./free-ball"), exports);
19
20
  __exportStar(require("./in-play-event"), exports);
20
21
  __exportStar(require("./libero-replacement"), exports);
21
22
  __exportStar(require("./rally-event"), exports);
@@ -5,9 +5,10 @@ export declare enum EventTypeEnum {
5
5
  RECEPTION = 3,
6
6
  SET = 4,
7
7
  SPIKE = 5,
8
- BLOCK = 6
8
+ BLOCK = 6,
9
+ FREE_BALL = 7
9
10
  }
10
- export type EventType = EventTypeEnum.LIBERO_REPLACEMENT | EventTypeEnum.SUBSTITUTION | EventTypeEnum.SERVE | EventTypeEnum.RECEPTION | EventTypeEnum.SET | EventTypeEnum.SPIKE | EventTypeEnum.BLOCK;
11
+ export type EventType = EventTypeEnum.LIBERO_REPLACEMENT | EventTypeEnum.SUBSTITUTION | EventTypeEnum.SERVE | EventTypeEnum.RECEPTION | EventTypeEnum.SET | EventTypeEnum.SPIKE | EventTypeEnum.BLOCK | EventTypeEnum.FREE_BALL;
11
12
  export interface RallyEventOpts {
12
13
  readonly playerId: string;
13
14
  readonly eventType: EventType;
@@ -10,6 +10,7 @@ var EventTypeEnum;
10
10
  EventTypeEnum[EventTypeEnum["SET"] = 4] = "SET";
11
11
  EventTypeEnum[EventTypeEnum["SPIKE"] = 5] = "SPIKE";
12
12
  EventTypeEnum[EventTypeEnum["BLOCK"] = 6] = "BLOCK";
13
+ EventTypeEnum[EventTypeEnum["FREE_BALL"] = 7] = "FREE_BALL";
13
14
  })(EventTypeEnum || (exports.EventTypeEnum = EventTypeEnum = {}));
14
15
  class RallyEvent {
15
16
  constructor({ eventType, playerId }) {
@@ -22,6 +22,7 @@ export declare const BlockInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+ import { TraitEnum } from '../../player';
3
+ export declare const FreeBallInputSchema: z.ZodObject<{
4
+ playerId: z.ZodUUID;
5
+ score: z.ZodNumber;
6
+ target: z.ZodNumber;
7
+ activeTraits: z.ZodDefault<z.ZodArray<z.ZodEnum<{
8
+ MASTER_MIND: TraitEnum.MASTER_MIND;
9
+ MOVING_WALL: TraitEnum.MOVING_WALL;
10
+ SURPRISE_ATTACK: TraitEnum.SURPRISE_ATTACK;
11
+ MARKSMAN: TraitEnum.MARKSMAN;
12
+ METEOR_SERVE: TraitEnum.METEOR_SERVE;
13
+ VIGOROUS: TraitEnum.VIGOROUS;
14
+ GUARDIAN: TraitEnum.GUARDIAN;
15
+ FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
+ DEFENSIVE_SPECIALIST: TraitEnum.DEFENSIVE_SPECIALIST;
17
+ QUICK_LEARNER: TraitEnum.QUICK_LEARNER;
18
+ MOMENTUM_ADDICT: TraitEnum.MOMENTUM_ADDICT;
19
+ LOUDMOUTH: TraitEnum.LOUDMOUTH;
20
+ TRUE_LEADER: TraitEnum.TRUE_LEADER;
21
+ OVERACHIEVER: TraitEnum.OVERACHIEVER;
22
+ CRAFTY: TraitEnum.CRAFTY;
23
+ TENACIOUS: TraitEnum.TENACIOUS;
24
+ HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
26
+ }>>>;
27
+ failure: z.ZodNumber;
28
+ type: z.ZodNumber;
29
+ }, z.core.$strip>;
30
+ export type FreeBallInput = z.infer<typeof FreeBallInputSchema>;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FreeBallInputSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const player_1 = require("../../player");
6
+ const freeBallTypeValues = [0, 1];
7
+ const freeBallFailureValues = [0];
8
+ const courtTargetValues = Array.from({ length: 13 }, (_, i) => i);
9
+ exports.FreeBallInputSchema = zod_1.z.object({
10
+ playerId: zod_1.z.uuid(),
11
+ score: zod_1.z.number().finite(),
12
+ target: zod_1.z.number().int().refine((v) => courtTargetValues.includes(v), { message: 'INVALID_COURT_TARGET' }),
13
+ activeTraits: zod_1.z.array(zod_1.z.enum(Object.values(player_1.TraitEnum))).default([]),
14
+ failure: zod_1.z.number().int().refine((v) => freeBallFailureValues.includes(v), { message: 'INVALID_FREE_BALL_FAILURE' }),
15
+ type: zod_1.z.number().int().refine((v) => freeBallTypeValues.includes(v), { message: 'INVALID_FREE_BALL_TYPE' })
16
+ });
@@ -22,6 +22,7 @@ export declare const ReceptionInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -22,6 +22,7 @@ export declare const ServeInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -22,6 +22,7 @@ export declare const SetInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -22,6 +22,7 @@ export declare const SpikeInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -61,6 +61,7 @@ export declare const PlayerInputSchema: z.ZodObject<{
61
61
  CRAFTY: TraitEnum.CRAFTY;
62
62
  TENACIOUS: TraitEnum.TENACIOUS;
63
63
  HUNTER: TraitEnum.HUNTER;
64
+ LAST_RESORT: TraitEnum.LAST_RESORT;
64
65
  }>>;
65
66
  rarity: z.ZodEnum<{
66
67
  COMMON: RarityEnum.COMMON;
@@ -84,9 +84,15 @@ export declare enum TraitEnum {
84
84
  * setter, opposite, or best back-row attacker, depending on serve type and rotation), bypassing GUARDIAN,
85
85
  * with a slight serve bonus and reducing the hunted player's attack involvement that rally.
86
86
  */
87
- HUNTER = "HUNTER"
87
+ HUNTER = "HUNTER",
88
+ /**
89
+ * Libero only. When a teammate's touch would lose the rally (a reception/dig error, a set error, or a failed
90
+ * dig of a blocked-back ball) and a save is still legal, a small chance the libero digs it into a neutral free
91
+ * ball, keeping the rally alive (over the net, or staying on side, depending on the touch).
92
+ */
93
+ LAST_RESORT = "LAST_RESORT"
88
94
  }
89
- export type Trait = TraitEnum.FLOAT_SERVE | TraitEnum.SURPRISE_ATTACK | TraitEnum.GUARDIAN | TraitEnum.MASTER_MIND | TraitEnum.MOVING_WALL | TraitEnum.MARKSMAN | TraitEnum.METEOR_SERVE | TraitEnum.VIGOROUS | TraitEnum.DEFENSIVE_SPECIALIST | TraitEnum.QUICK_LEARNER | TraitEnum.MOMENTUM_ADDICT | TraitEnum.LOUDMOUTH | TraitEnum.TRUE_LEADER | TraitEnum.OVERACHIEVER | TraitEnum.CRAFTY | TraitEnum.TENACIOUS | TraitEnum.HUNTER;
95
+ export type Trait = TraitEnum.FLOAT_SERVE | TraitEnum.SURPRISE_ATTACK | TraitEnum.GUARDIAN | TraitEnum.MASTER_MIND | TraitEnum.MOVING_WALL | TraitEnum.MARKSMAN | TraitEnum.METEOR_SERVE | TraitEnum.VIGOROUS | TraitEnum.DEFENSIVE_SPECIALIST | TraitEnum.QUICK_LEARNER | TraitEnum.MOMENTUM_ADDICT | TraitEnum.LOUDMOUTH | TraitEnum.TRUE_LEADER | TraitEnum.OVERACHIEVER | TraitEnum.CRAFTY | TraitEnum.TENACIOUS | TraitEnum.HUNTER | TraitEnum.LAST_RESORT;
90
96
  export declare function assignTraits(roles: Role[], rarity: Rarity, maxTraits?: boolean): Trait[];
91
97
  export declare const traitMap: Map<Trait, TraitProps>;
92
98
  export {};
@@ -97,6 +97,12 @@ var TraitEnum;
97
97
  * with a slight serve bonus and reducing the hunted player's attack involvement that rally.
98
98
  */
99
99
  TraitEnum["HUNTER"] = "HUNTER";
100
+ /**
101
+ * Libero only. When a teammate's touch would lose the rally (a reception/dig error, a set error, or a failed
102
+ * dig of a blocked-back ball) and a save is still legal, a small chance the libero digs it into a neutral free
103
+ * ball, keeping the rally alive (over the net, or staying on side, depending on the touch).
104
+ */
105
+ TraitEnum["LAST_RESORT"] = "LAST_RESORT";
100
106
  })(TraitEnum || (exports.TraitEnum = TraitEnum = {}));
101
107
  function assignTraits(roles, rarity, maxTraits) {
102
108
  let traitCount;
@@ -105,13 +105,12 @@
105
105
  "chance": 1,
106
106
  "roles": [
107
107
  "OUTSIDE_HITTER",
108
- "OPPOSITE_HITTER",
109
- "MIDDLE_BLOCKER"
108
+ "OPPOSITE_HITTER"
110
109
  ]
111
110
  },
112
111
  {
113
112
  "name": "LOUDMOUTH",
114
- "chance": 0.25,
113
+ "chance": 0.3333,
115
114
  "roles": [
116
115
  "OUTSIDE_HITTER",
117
116
  "OPPOSITE_HITTER",
@@ -123,8 +122,10 @@
123
122
  "chance": 0.3,
124
123
  "roles": [
125
124
  "SETTER",
126
- "LIBERO",
127
- "OUTSIDE_HITTER"
125
+ "OUTSIDE_HITTER",
126
+ "OPPOSITE_HITTER",
127
+ "MIDDLE_BLOCKER",
128
+ "LIBERO"
128
129
  ]
129
130
  },
130
131
  {
@@ -132,14 +133,16 @@
132
133
  "chance": 0.2,
133
134
  "maxRarity": "MYTHIC",
134
135
  "roles": [
135
- "LIBERO",
136
+ "SETTER",
136
137
  "OUTSIDE_HITTER",
137
- "MIDDLE_BLOCKER"
138
+ "OPPOSITE_HITTER",
139
+ "MIDDLE_BLOCKER",
140
+ "LIBERO"
138
141
  ]
139
142
  },
140
143
  {
141
144
  "name": "CRAFTY",
142
- "chance": 0.3,
145
+ "chance": 0.25,
143
146
  "roles": [
144
147
  "SETTER",
145
148
  "OUTSIDE_HITTER",
@@ -152,8 +155,10 @@
152
155
  "chance": 1,
153
156
  "roles": [
154
157
  "SETTER",
155
- "LIBERO",
156
- "OUTSIDE_HITTER"
158
+ "OUTSIDE_HITTER",
159
+ "OPPOSITE_HITTER",
160
+ "MIDDLE_BLOCKER",
161
+ "LIBERO"
157
162
  ]
158
163
  },
159
164
  {
@@ -161,8 +166,16 @@
161
166
  "chance": 0.15,
162
167
  "roles": [
163
168
  "SETTER",
169
+ "OUTSIDE_HITTER",
164
170
  "OPPOSITE_HITTER",
165
- "OUTSIDE_HITTER"
171
+ "MIDDLE_BLOCKER"
172
+ ]
173
+ },
174
+ {
175
+ "name": "LAST_RESORT",
176
+ "chance": 0.05,
177
+ "roles": [
178
+ "LIBERO"
166
179
  ]
167
180
  }
168
181
  ]
@@ -1,7 +1,8 @@
1
1
  import type { BlockFailure, BlockType } from './block';
2
+ import type { FreeBallFailure, FreeBallType } from './free-ball';
2
3
  import type { ReceptionFailure, ReceptionType } from './reception';
3
4
  import type { ServeFailure, ServeType } from './serve';
4
5
  import type { SetFailure, SetType } from './set';
5
6
  import type { SpikeFailure, SpikeType } from './spike';
6
- export type EventSubType = BlockType | ReceptionType | ServeType | SetType | SpikeType;
7
- export type EventFailureType = BlockFailure | ReceptionFailure | ServeFailure | SetFailure | SpikeFailure;
7
+ export type EventSubType = BlockType | FreeBallType | ReceptionType | ServeType | SetType | SpikeType;
8
+ export type EventFailureType = BlockFailure | FreeBallFailure | ReceptionFailure | ServeFailure | SetFailure | SpikeFailure;
@@ -0,0 +1,17 @@
1
+ import { InPlayEvent } from './in-play-event';
2
+ export declare enum FreeBallTypeEnum {
3
+ OVER = 0,
4
+ STAY = 1
5
+ }
6
+ export type FreeBallType = FreeBallTypeEnum.OVER | FreeBallTypeEnum.STAY;
7
+ export declare enum FreeBallFailureEnum {
8
+ NO_FAILURE = 0
9
+ }
10
+ export type FreeBallFailure = FreeBallFailureEnum.NO_FAILURE;
11
+ export declare class FreeBall extends InPlayEvent<FreeBallFailure, FreeBallType> {
12
+ readonly failure: FreeBallFailure;
13
+ readonly type: FreeBallType;
14
+ static create(input: unknown): FreeBall;
15
+ private constructor();
16
+ toString(): string;
17
+ }
@@ -0,0 +1,43 @@
1
+ import { EventTypeEnum } from './rally-event';
2
+ import { InPlayEvent } from './in-play-event';
3
+ import { FreeBallInputSchema } from './schemas/free-ball.z';
4
+ export var FreeBallTypeEnum;
5
+ (function (FreeBallTypeEnum) {
6
+ // The save sent the ball over the net as a free ball -- the opponent plays it out.
7
+ FreeBallTypeEnum[FreeBallTypeEnum["OVER"] = 0] = "OVER";
8
+ // The save kept the ball on the team's side -- the team plays out its remaining touch(es).
9
+ FreeBallTypeEnum[FreeBallTypeEnum["STAY"] = 1] = "STAY";
10
+ })(FreeBallTypeEnum || (FreeBallTypeEnum = {}));
11
+ export var FreeBallFailureEnum;
12
+ (function (FreeBallFailureEnum) {
13
+ // A Last Resort save is guaranteed -- it always produces a free ball, never an error.
14
+ FreeBallFailureEnum[FreeBallFailureEnum["NO_FAILURE"] = 0] = "NO_FAILURE";
15
+ })(FreeBallFailureEnum || (FreeBallFailureEnum = {}));
16
+ const eventType = EventTypeEnum.FREE_BALL;
17
+ // A FREE_BALL event is a Last Resort save: the libero digs a ball that would otherwise have lost the rally and
18
+ // puts it back in play as a neutral free ball (over to the opponent, or staying on side). It is a real in-play
19
+ // event (score + target) so the next receiver handles it like any free ball.
20
+ export class FreeBall extends InPlayEvent {
21
+ static create(input) {
22
+ const result = FreeBallInputSchema.safeParse(input);
23
+ if (!result.success) {
24
+ throw new Error(`INVALID_FREE_BALL: ${result.error.message}. RECEIVED=${(() => { try {
25
+ return JSON.stringify(input);
26
+ }
27
+ catch {
28
+ return String(input);
29
+ } })()}`);
30
+ }
31
+ return new FreeBall(result.data);
32
+ }
33
+ constructor({ score, playerId, target, failure, type, activeTraits }) {
34
+ super({ score, playerId, target, activeTraits, eventType });
35
+ this.type = type;
36
+ this.failure = failure;
37
+ }
38
+ toString() {
39
+ const failure = `"failure":${this.failure}`;
40
+ const type = `"type":${this.type}`;
41
+ return `{${this._toString()},${failure},${type}}`;
42
+ }
43
+ }
@@ -1,5 +1,6 @@
1
1
  export * from './block';
2
2
  export * from './event-types';
3
+ export * from './free-ball';
3
4
  export * from './in-play-event';
4
5
  export * from './libero-replacement';
5
6
  export * from './rally-event';
@@ -1,5 +1,6 @@
1
1
  export * from './block';
2
2
  export * from './event-types';
3
+ export * from './free-ball';
3
4
  export * from './in-play-event';
4
5
  export * from './libero-replacement';
5
6
  export * from './rally-event';
@@ -5,9 +5,10 @@ export declare enum EventTypeEnum {
5
5
  RECEPTION = 3,
6
6
  SET = 4,
7
7
  SPIKE = 5,
8
- BLOCK = 6
8
+ BLOCK = 6,
9
+ FREE_BALL = 7
9
10
  }
10
- export type EventType = EventTypeEnum.LIBERO_REPLACEMENT | EventTypeEnum.SUBSTITUTION | EventTypeEnum.SERVE | EventTypeEnum.RECEPTION | EventTypeEnum.SET | EventTypeEnum.SPIKE | EventTypeEnum.BLOCK;
11
+ export type EventType = EventTypeEnum.LIBERO_REPLACEMENT | EventTypeEnum.SUBSTITUTION | EventTypeEnum.SERVE | EventTypeEnum.RECEPTION | EventTypeEnum.SET | EventTypeEnum.SPIKE | EventTypeEnum.BLOCK | EventTypeEnum.FREE_BALL;
11
12
  export interface RallyEventOpts {
12
13
  readonly playerId: string;
13
14
  readonly eventType: EventType;
@@ -7,6 +7,7 @@ export var EventTypeEnum;
7
7
  EventTypeEnum[EventTypeEnum["SET"] = 4] = "SET";
8
8
  EventTypeEnum[EventTypeEnum["SPIKE"] = 5] = "SPIKE";
9
9
  EventTypeEnum[EventTypeEnum["BLOCK"] = 6] = "BLOCK";
10
+ EventTypeEnum[EventTypeEnum["FREE_BALL"] = 7] = "FREE_BALL";
10
11
  })(EventTypeEnum || (EventTypeEnum = {}));
11
12
  export class RallyEvent {
12
13
  constructor({ eventType, playerId }) {
@@ -22,6 +22,7 @@ export declare const BlockInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+ import { TraitEnum } from '../../player';
3
+ export declare const FreeBallInputSchema: z.ZodObject<{
4
+ playerId: z.ZodUUID;
5
+ score: z.ZodNumber;
6
+ target: z.ZodNumber;
7
+ activeTraits: z.ZodDefault<z.ZodArray<z.ZodEnum<{
8
+ MASTER_MIND: TraitEnum.MASTER_MIND;
9
+ MOVING_WALL: TraitEnum.MOVING_WALL;
10
+ SURPRISE_ATTACK: TraitEnum.SURPRISE_ATTACK;
11
+ MARKSMAN: TraitEnum.MARKSMAN;
12
+ METEOR_SERVE: TraitEnum.METEOR_SERVE;
13
+ VIGOROUS: TraitEnum.VIGOROUS;
14
+ GUARDIAN: TraitEnum.GUARDIAN;
15
+ FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
+ DEFENSIVE_SPECIALIST: TraitEnum.DEFENSIVE_SPECIALIST;
17
+ QUICK_LEARNER: TraitEnum.QUICK_LEARNER;
18
+ MOMENTUM_ADDICT: TraitEnum.MOMENTUM_ADDICT;
19
+ LOUDMOUTH: TraitEnum.LOUDMOUTH;
20
+ TRUE_LEADER: TraitEnum.TRUE_LEADER;
21
+ OVERACHIEVER: TraitEnum.OVERACHIEVER;
22
+ CRAFTY: TraitEnum.CRAFTY;
23
+ TENACIOUS: TraitEnum.TENACIOUS;
24
+ HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
26
+ }>>>;
27
+ failure: z.ZodNumber;
28
+ type: z.ZodNumber;
29
+ }, z.core.$strip>;
30
+ export type FreeBallInput = z.infer<typeof FreeBallInputSchema>;
@@ -0,0 +1,13 @@
1
+ import { z } from 'zod';
2
+ import { TraitEnum } from '../../player';
3
+ const freeBallTypeValues = [0, 1];
4
+ const freeBallFailureValues = [0];
5
+ const courtTargetValues = Array.from({ length: 13 }, (_, i) => i);
6
+ export const FreeBallInputSchema = z.object({
7
+ playerId: z.uuid(),
8
+ score: z.number().finite(),
9
+ target: z.number().int().refine((v) => courtTargetValues.includes(v), { message: 'INVALID_COURT_TARGET' }),
10
+ activeTraits: z.array(z.enum(Object.values(TraitEnum))).default([]),
11
+ failure: z.number().int().refine((v) => freeBallFailureValues.includes(v), { message: 'INVALID_FREE_BALL_FAILURE' }),
12
+ type: z.number().int().refine((v) => freeBallTypeValues.includes(v), { message: 'INVALID_FREE_BALL_TYPE' })
13
+ });
@@ -22,6 +22,7 @@ export declare const ReceptionInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -22,6 +22,7 @@ export declare const ServeInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -22,6 +22,7 @@ export declare const SetInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -22,6 +22,7 @@ export declare const SpikeInputSchema: z.ZodObject<{
22
22
  CRAFTY: TraitEnum.CRAFTY;
23
23
  TENACIOUS: TraitEnum.TENACIOUS;
24
24
  HUNTER: TraitEnum.HUNTER;
25
+ LAST_RESORT: TraitEnum.LAST_RESORT;
25
26
  }>>>;
26
27
  failure: z.ZodNumber;
27
28
  type: z.ZodNumber;
@@ -61,6 +61,7 @@ export declare const PlayerInputSchema: z.ZodObject<{
61
61
  CRAFTY: TraitEnum.CRAFTY;
62
62
  TENACIOUS: TraitEnum.TENACIOUS;
63
63
  HUNTER: TraitEnum.HUNTER;
64
+ LAST_RESORT: TraitEnum.LAST_RESORT;
64
65
  }>>;
65
66
  rarity: z.ZodEnum<{
66
67
  COMMON: RarityEnum.COMMON;
@@ -84,9 +84,15 @@ export declare enum TraitEnum {
84
84
  * setter, opposite, or best back-row attacker, depending on serve type and rotation), bypassing GUARDIAN,
85
85
  * with a slight serve bonus and reducing the hunted player's attack involvement that rally.
86
86
  */
87
- HUNTER = "HUNTER"
87
+ HUNTER = "HUNTER",
88
+ /**
89
+ * Libero only. When a teammate's touch would lose the rally (a reception/dig error, a set error, or a failed
90
+ * dig of a blocked-back ball) and a save is still legal, a small chance the libero digs it into a neutral free
91
+ * ball, keeping the rally alive (over the net, or staying on side, depending on the touch).
92
+ */
93
+ LAST_RESORT = "LAST_RESORT"
88
94
  }
89
- export type Trait = TraitEnum.FLOAT_SERVE | TraitEnum.SURPRISE_ATTACK | TraitEnum.GUARDIAN | TraitEnum.MASTER_MIND | TraitEnum.MOVING_WALL | TraitEnum.MARKSMAN | TraitEnum.METEOR_SERVE | TraitEnum.VIGOROUS | TraitEnum.DEFENSIVE_SPECIALIST | TraitEnum.QUICK_LEARNER | TraitEnum.MOMENTUM_ADDICT | TraitEnum.LOUDMOUTH | TraitEnum.TRUE_LEADER | TraitEnum.OVERACHIEVER | TraitEnum.CRAFTY | TraitEnum.TENACIOUS | TraitEnum.HUNTER;
95
+ export type Trait = TraitEnum.FLOAT_SERVE | TraitEnum.SURPRISE_ATTACK | TraitEnum.GUARDIAN | TraitEnum.MASTER_MIND | TraitEnum.MOVING_WALL | TraitEnum.MARKSMAN | TraitEnum.METEOR_SERVE | TraitEnum.VIGOROUS | TraitEnum.DEFENSIVE_SPECIALIST | TraitEnum.QUICK_LEARNER | TraitEnum.MOMENTUM_ADDICT | TraitEnum.LOUDMOUTH | TraitEnum.TRUE_LEADER | TraitEnum.OVERACHIEVER | TraitEnum.CRAFTY | TraitEnum.TENACIOUS | TraitEnum.HUNTER | TraitEnum.LAST_RESORT;
90
96
  export declare function assignTraits(roles: Role[], rarity: Rarity, maxTraits?: boolean): Trait[];
91
97
  export declare const traitMap: Map<Trait, TraitProps>;
92
98
  export {};
@@ -90,6 +90,12 @@ export var TraitEnum;
90
90
  * with a slight serve bonus and reducing the hunted player's attack involvement that rally.
91
91
  */
92
92
  TraitEnum["HUNTER"] = "HUNTER";
93
+ /**
94
+ * Libero only. When a teammate's touch would lose the rally (a reception/dig error, a set error, or a failed
95
+ * dig of a blocked-back ball) and a save is still legal, a small chance the libero digs it into a neutral free
96
+ * ball, keeping the rally alive (over the net, or staying on side, depending on the touch).
97
+ */
98
+ TraitEnum["LAST_RESORT"] = "LAST_RESORT";
93
99
  })(TraitEnum || (TraitEnum = {}));
94
100
  export function assignTraits(roles, rarity, maxTraits) {
95
101
  let traitCount;
@@ -105,13 +105,12 @@
105
105
  "chance": 1,
106
106
  "roles": [
107
107
  "OUTSIDE_HITTER",
108
- "OPPOSITE_HITTER",
109
- "MIDDLE_BLOCKER"
108
+ "OPPOSITE_HITTER"
110
109
  ]
111
110
  },
112
111
  {
113
112
  "name": "LOUDMOUTH",
114
- "chance": 0.25,
113
+ "chance": 0.3333,
115
114
  "roles": [
116
115
  "OUTSIDE_HITTER",
117
116
  "OPPOSITE_HITTER",
@@ -123,8 +122,10 @@
123
122
  "chance": 0.3,
124
123
  "roles": [
125
124
  "SETTER",
126
- "LIBERO",
127
- "OUTSIDE_HITTER"
125
+ "OUTSIDE_HITTER",
126
+ "OPPOSITE_HITTER",
127
+ "MIDDLE_BLOCKER",
128
+ "LIBERO"
128
129
  ]
129
130
  },
130
131
  {
@@ -132,14 +133,16 @@
132
133
  "chance": 0.2,
133
134
  "maxRarity": "MYTHIC",
134
135
  "roles": [
135
- "LIBERO",
136
+ "SETTER",
136
137
  "OUTSIDE_HITTER",
137
- "MIDDLE_BLOCKER"
138
+ "OPPOSITE_HITTER",
139
+ "MIDDLE_BLOCKER",
140
+ "LIBERO"
138
141
  ]
139
142
  },
140
143
  {
141
144
  "name": "CRAFTY",
142
- "chance": 0.3,
145
+ "chance": 0.25,
143
146
  "roles": [
144
147
  "SETTER",
145
148
  "OUTSIDE_HITTER",
@@ -152,8 +155,10 @@
152
155
  "chance": 1,
153
156
  "roles": [
154
157
  "SETTER",
155
- "LIBERO",
156
- "OUTSIDE_HITTER"
158
+ "OUTSIDE_HITTER",
159
+ "OPPOSITE_HITTER",
160
+ "MIDDLE_BLOCKER",
161
+ "LIBERO"
157
162
  ]
158
163
  },
159
164
  {
@@ -161,8 +166,16 @@
161
166
  "chance": 0.15,
162
167
  "roles": [
163
168
  "SETTER",
169
+ "OUTSIDE_HITTER",
164
170
  "OPPOSITE_HITTER",
165
- "OUTSIDE_HITTER"
171
+ "MIDDLE_BLOCKER"
172
+ ]
173
+ },
174
+ {
175
+ "name": "LAST_RESORT",
176
+ "chance": 0.05,
177
+ "roles": [
178
+ "LIBERO"
166
179
  ]
167
180
  }
168
181
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.452",
3
+ "version": "0.0.453",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",