volleyballsimtypes 0.0.451 → 0.0.452

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.
@@ -14,6 +14,14 @@ export declare const BlockInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -14,6 +14,14 @@ export declare const ReceptionInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -14,6 +14,14 @@ export declare const ServeInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -14,6 +14,14 @@ export declare const SetInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -14,6 +14,14 @@ export declare const SpikeInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -53,6 +53,14 @@ export declare const PlayerInputSchema: z.ZodObject<{
53
53
  GUARDIAN: TraitEnum.GUARDIAN;
54
54
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
55
55
  DEFENSIVE_SPECIALIST: TraitEnum.DEFENSIVE_SPECIALIST;
56
+ QUICK_LEARNER: TraitEnum.QUICK_LEARNER;
57
+ MOMENTUM_ADDICT: TraitEnum.MOMENTUM_ADDICT;
58
+ LOUDMOUTH: TraitEnum.LOUDMOUTH;
59
+ TRUE_LEADER: TraitEnum.TRUE_LEADER;
60
+ OVERACHIEVER: TraitEnum.OVERACHIEVER;
61
+ CRAFTY: TraitEnum.CRAFTY;
62
+ TENACIOUS: TraitEnum.TENACIOUS;
63
+ HUNTER: TraitEnum.HUNTER;
56
64
  }>>;
57
65
  rarity: z.ZodEnum<{
58
66
  COMMON: RarityEnum.COMMON;
@@ -5,6 +5,7 @@ interface TraitProps {
5
5
  readonly modifier?: number;
6
6
  readonly chance: number;
7
7
  readonly roles: Role[];
8
+ readonly maxRarity?: Rarity;
8
9
  }
9
10
  export declare enum TraitEnum {
10
11
  /**
@@ -45,9 +46,47 @@ export declare enum TraitEnum {
45
46
  /**
46
47
  * Gives the player a chance to perform a perfect reception.
47
48
  */
48
- DEFENSIVE_SPECIALIST = "DEFENSIVE_SPECIALIST"
49
+ DEFENSIVE_SPECIALIST = "DEFENSIVE_SPECIALIST",
50
+ /**
51
+ * Three good receptions/digs/sets in a row make the next reception/dig/set a guaranteed critical that
52
+ * cannot fail.
53
+ */
54
+ QUICK_LEARNER = "QUICK_LEARNER",
55
+ /**
56
+ * Each successful attack ramps up the spike, and a kill ramps it more. Starts with a small penalty and
57
+ * resets on an attacking error.
58
+ */
59
+ MOMENTUM_ADDICT = "MOMENTUM_ADDICT",
60
+ /**
61
+ * A front-row kill demoralizes the opponents who faced it, debuffing them for a few rallies.
62
+ */
63
+ LOUDMOUTH = "LOUDMOUTH",
64
+ /**
65
+ * When a teammate makes a non-block mistake, that teammate's next action cannot fail.
66
+ */
67
+ TRUE_LEADER = "TRUE_LEADER",
68
+ /**
69
+ * Reacting to a strong opponent action (block/receive), this player can rise to match it. Limited to
70
+ * Mythic rarity and below.
71
+ */
72
+ OVERACHIEVER = "OVERACHIEVER",
73
+ /**
74
+ * Opponents who interact with this player's serve or attack spend twice the energy (VIGOROUS is nullified).
75
+ */
76
+ CRAFTY = "CRAFTY",
77
+ /**
78
+ * When the team loses several points in a row, the whole on-court team gets a buff that grows with the
79
+ * streak and disappears the moment they win a point.
80
+ */
81
+ TENACIOUS = "TENACIOUS",
82
+ /**
83
+ * Serve trait, rolled before the ambient setter/opposite hunt: a chance to serve a precise target (the
84
+ * setter, opposite, or best back-row attacker, depending on serve type and rotation), bypassing GUARDIAN,
85
+ * with a slight serve bonus and reducing the hunted player's attack involvement that rally.
86
+ */
87
+ HUNTER = "HUNTER"
49
88
  }
50
- 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;
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;
51
90
  export declare function assignTraits(roles: Role[], rarity: Rarity, maxTraits?: boolean): Trait[];
52
91
  export declare const traitMap: Map<Trait, TraitProps>;
53
92
  export {};
@@ -10,6 +10,14 @@ const node_crypto_1 = require("node:crypto");
10
10
  const traits_json_1 = __importDefault(require("../../stat-config/traits.json"));
11
11
  const utils_1 = require("../utils");
12
12
  const traits = traits_json_1.default;
13
+ // Ascending rarity order, used by the maxRarity trait-eligibility gate in assignTraits.
14
+ const RARITY_RANK = {
15
+ [rarity_1.RarityEnum.COMMON]: 0,
16
+ [rarity_1.RarityEnum.RARE]: 1,
17
+ [rarity_1.RarityEnum.LEGENDARY]: 2,
18
+ [rarity_1.RarityEnum.MYTHIC]: 3,
19
+ [rarity_1.RarityEnum.SPECIAL]: 4
20
+ };
13
21
  var TraitEnum;
14
22
  (function (TraitEnum) {
15
23
  /**
@@ -51,6 +59,44 @@ var TraitEnum;
51
59
  * Gives the player a chance to perform a perfect reception.
52
60
  */
53
61
  TraitEnum["DEFENSIVE_SPECIALIST"] = "DEFENSIVE_SPECIALIST";
62
+ /**
63
+ * Three good receptions/digs/sets in a row make the next reception/dig/set a guaranteed critical that
64
+ * cannot fail.
65
+ */
66
+ TraitEnum["QUICK_LEARNER"] = "QUICK_LEARNER";
67
+ /**
68
+ * Each successful attack ramps up the spike, and a kill ramps it more. Starts with a small penalty and
69
+ * resets on an attacking error.
70
+ */
71
+ TraitEnum["MOMENTUM_ADDICT"] = "MOMENTUM_ADDICT";
72
+ /**
73
+ * A front-row kill demoralizes the opponents who faced it, debuffing them for a few rallies.
74
+ */
75
+ TraitEnum["LOUDMOUTH"] = "LOUDMOUTH";
76
+ /**
77
+ * When a teammate makes a non-block mistake, that teammate's next action cannot fail.
78
+ */
79
+ TraitEnum["TRUE_LEADER"] = "TRUE_LEADER";
80
+ /**
81
+ * Reacting to a strong opponent action (block/receive), this player can rise to match it. Limited to
82
+ * Mythic rarity and below.
83
+ */
84
+ TraitEnum["OVERACHIEVER"] = "OVERACHIEVER";
85
+ /**
86
+ * Opponents who interact with this player's serve or attack spend twice the energy (VIGOROUS is nullified).
87
+ */
88
+ TraitEnum["CRAFTY"] = "CRAFTY";
89
+ /**
90
+ * When the team loses several points in a row, the whole on-court team gets a buff that grows with the
91
+ * streak and disappears the moment they win a point.
92
+ */
93
+ TraitEnum["TENACIOUS"] = "TENACIOUS";
94
+ /**
95
+ * Serve trait, rolled before the ambient setter/opposite hunt: a chance to serve a precise target (the
96
+ * setter, opposite, or best back-row attacker, depending on serve type and rotation), bypassing GUARDIAN,
97
+ * with a slight serve bonus and reducing the hunted player's attack involvement that rally.
98
+ */
99
+ TraitEnum["HUNTER"] = "HUNTER";
54
100
  })(TraitEnum || (exports.TraitEnum = TraitEnum = {}));
55
101
  function assignTraits(roles, rarity, maxTraits) {
56
102
  let traitCount;
@@ -82,7 +128,9 @@ function assignTraits(roles, rarity, maxTraits) {
82
128
  return [];
83
129
  const filteredTraits = traits.filter((trait) => {
84
130
  const setA = new Set(trait.roles);
85
- return roles.some(el => setA.has(el));
131
+ const roleMatch = roles.some(el => setA.has(el));
132
+ const rarityOk = trait.maxRarity == null || RARITY_RANK[rarity] <= RARITY_RANK[trait.maxRarity];
133
+ return roleMatch && rarityOk;
86
134
  }).map(trait => trait.name);
87
135
  return (0, utils_1.shuffle)(filteredTraits).slice(0, traitCount);
88
136
  }
@@ -90,5 +90,79 @@
90
90
  "OUTSIDE_HITTER",
91
91
  "MIDDLE_BLOCKER"
92
92
  ]
93
+ },
94
+ {
95
+ "name": "QUICK_LEARNER",
96
+ "chance": 1,
97
+ "roles": [
98
+ "SETTER",
99
+ "LIBERO",
100
+ "OUTSIDE_HITTER"
101
+ ]
102
+ },
103
+ {
104
+ "name": "MOMENTUM_ADDICT",
105
+ "chance": 1,
106
+ "roles": [
107
+ "OUTSIDE_HITTER",
108
+ "OPPOSITE_HITTER",
109
+ "MIDDLE_BLOCKER"
110
+ ]
111
+ },
112
+ {
113
+ "name": "LOUDMOUTH",
114
+ "chance": 0.25,
115
+ "roles": [
116
+ "OUTSIDE_HITTER",
117
+ "OPPOSITE_HITTER",
118
+ "MIDDLE_BLOCKER"
119
+ ]
120
+ },
121
+ {
122
+ "name": "TRUE_LEADER",
123
+ "chance": 0.3,
124
+ "roles": [
125
+ "SETTER",
126
+ "LIBERO",
127
+ "OUTSIDE_HITTER"
128
+ ]
129
+ },
130
+ {
131
+ "name": "OVERACHIEVER",
132
+ "chance": 0.2,
133
+ "maxRarity": "MYTHIC",
134
+ "roles": [
135
+ "LIBERO",
136
+ "OUTSIDE_HITTER",
137
+ "MIDDLE_BLOCKER"
138
+ ]
139
+ },
140
+ {
141
+ "name": "CRAFTY",
142
+ "chance": 0.3,
143
+ "roles": [
144
+ "SETTER",
145
+ "OUTSIDE_HITTER",
146
+ "OPPOSITE_HITTER",
147
+ "MIDDLE_BLOCKER"
148
+ ]
149
+ },
150
+ {
151
+ "name": "TENACIOUS",
152
+ "chance": 1,
153
+ "roles": [
154
+ "SETTER",
155
+ "LIBERO",
156
+ "OUTSIDE_HITTER"
157
+ ]
158
+ },
159
+ {
160
+ "name": "HUNTER",
161
+ "chance": 0.15,
162
+ "roles": [
163
+ "SETTER",
164
+ "OPPOSITE_HITTER",
165
+ "OUTSIDE_HITTER"
166
+ ]
93
167
  }
94
168
  ]
@@ -14,6 +14,14 @@ export declare const BlockInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -14,6 +14,14 @@ export declare const ReceptionInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -14,6 +14,14 @@ export declare const ServeInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -14,6 +14,14 @@ export declare const SetInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -14,6 +14,14 @@ export declare const SpikeInputSchema: z.ZodObject<{
14
14
  GUARDIAN: TraitEnum.GUARDIAN;
15
15
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
16
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;
17
25
  }>>>;
18
26
  failure: z.ZodNumber;
19
27
  type: z.ZodNumber;
@@ -53,6 +53,14 @@ export declare const PlayerInputSchema: z.ZodObject<{
53
53
  GUARDIAN: TraitEnum.GUARDIAN;
54
54
  FLOAT_SERVE: TraitEnum.FLOAT_SERVE;
55
55
  DEFENSIVE_SPECIALIST: TraitEnum.DEFENSIVE_SPECIALIST;
56
+ QUICK_LEARNER: TraitEnum.QUICK_LEARNER;
57
+ MOMENTUM_ADDICT: TraitEnum.MOMENTUM_ADDICT;
58
+ LOUDMOUTH: TraitEnum.LOUDMOUTH;
59
+ TRUE_LEADER: TraitEnum.TRUE_LEADER;
60
+ OVERACHIEVER: TraitEnum.OVERACHIEVER;
61
+ CRAFTY: TraitEnum.CRAFTY;
62
+ TENACIOUS: TraitEnum.TENACIOUS;
63
+ HUNTER: TraitEnum.HUNTER;
56
64
  }>>;
57
65
  rarity: z.ZodEnum<{
58
66
  COMMON: RarityEnum.COMMON;
@@ -5,6 +5,7 @@ interface TraitProps {
5
5
  readonly modifier?: number;
6
6
  readonly chance: number;
7
7
  readonly roles: Role[];
8
+ readonly maxRarity?: Rarity;
8
9
  }
9
10
  export declare enum TraitEnum {
10
11
  /**
@@ -45,9 +46,47 @@ export declare enum TraitEnum {
45
46
  /**
46
47
  * Gives the player a chance to perform a perfect reception.
47
48
  */
48
- DEFENSIVE_SPECIALIST = "DEFENSIVE_SPECIALIST"
49
+ DEFENSIVE_SPECIALIST = "DEFENSIVE_SPECIALIST",
50
+ /**
51
+ * Three good receptions/digs/sets in a row make the next reception/dig/set a guaranteed critical that
52
+ * cannot fail.
53
+ */
54
+ QUICK_LEARNER = "QUICK_LEARNER",
55
+ /**
56
+ * Each successful attack ramps up the spike, and a kill ramps it more. Starts with a small penalty and
57
+ * resets on an attacking error.
58
+ */
59
+ MOMENTUM_ADDICT = "MOMENTUM_ADDICT",
60
+ /**
61
+ * A front-row kill demoralizes the opponents who faced it, debuffing them for a few rallies.
62
+ */
63
+ LOUDMOUTH = "LOUDMOUTH",
64
+ /**
65
+ * When a teammate makes a non-block mistake, that teammate's next action cannot fail.
66
+ */
67
+ TRUE_LEADER = "TRUE_LEADER",
68
+ /**
69
+ * Reacting to a strong opponent action (block/receive), this player can rise to match it. Limited to
70
+ * Mythic rarity and below.
71
+ */
72
+ OVERACHIEVER = "OVERACHIEVER",
73
+ /**
74
+ * Opponents who interact with this player's serve or attack spend twice the energy (VIGOROUS is nullified).
75
+ */
76
+ CRAFTY = "CRAFTY",
77
+ /**
78
+ * When the team loses several points in a row, the whole on-court team gets a buff that grows with the
79
+ * streak and disappears the moment they win a point.
80
+ */
81
+ TENACIOUS = "TENACIOUS",
82
+ /**
83
+ * Serve trait, rolled before the ambient setter/opposite hunt: a chance to serve a precise target (the
84
+ * setter, opposite, or best back-row attacker, depending on serve type and rotation), bypassing GUARDIAN,
85
+ * with a slight serve bonus and reducing the hunted player's attack involvement that rally.
86
+ */
87
+ HUNTER = "HUNTER"
49
88
  }
50
- 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;
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;
51
90
  export declare function assignTraits(roles: Role[], rarity: Rarity, maxTraits?: boolean): Trait[];
52
91
  export declare const traitMap: Map<Trait, TraitProps>;
53
92
  export {};
@@ -3,6 +3,14 @@ import { randomInt } from 'node:crypto';
3
3
  import rawTraits from '../../stat-config/traits.json';
4
4
  import { shuffle } from '../utils';
5
5
  const traits = rawTraits;
6
+ // Ascending rarity order, used by the maxRarity trait-eligibility gate in assignTraits.
7
+ const RARITY_RANK = {
8
+ [RarityEnum.COMMON]: 0,
9
+ [RarityEnum.RARE]: 1,
10
+ [RarityEnum.LEGENDARY]: 2,
11
+ [RarityEnum.MYTHIC]: 3,
12
+ [RarityEnum.SPECIAL]: 4
13
+ };
6
14
  export var TraitEnum;
7
15
  (function (TraitEnum) {
8
16
  /**
@@ -44,6 +52,44 @@ export var TraitEnum;
44
52
  * Gives the player a chance to perform a perfect reception.
45
53
  */
46
54
  TraitEnum["DEFENSIVE_SPECIALIST"] = "DEFENSIVE_SPECIALIST";
55
+ /**
56
+ * Three good receptions/digs/sets in a row make the next reception/dig/set a guaranteed critical that
57
+ * cannot fail.
58
+ */
59
+ TraitEnum["QUICK_LEARNER"] = "QUICK_LEARNER";
60
+ /**
61
+ * Each successful attack ramps up the spike, and a kill ramps it more. Starts with a small penalty and
62
+ * resets on an attacking error.
63
+ */
64
+ TraitEnum["MOMENTUM_ADDICT"] = "MOMENTUM_ADDICT";
65
+ /**
66
+ * A front-row kill demoralizes the opponents who faced it, debuffing them for a few rallies.
67
+ */
68
+ TraitEnum["LOUDMOUTH"] = "LOUDMOUTH";
69
+ /**
70
+ * When a teammate makes a non-block mistake, that teammate's next action cannot fail.
71
+ */
72
+ TraitEnum["TRUE_LEADER"] = "TRUE_LEADER";
73
+ /**
74
+ * Reacting to a strong opponent action (block/receive), this player can rise to match it. Limited to
75
+ * Mythic rarity and below.
76
+ */
77
+ TraitEnum["OVERACHIEVER"] = "OVERACHIEVER";
78
+ /**
79
+ * Opponents who interact with this player's serve or attack spend twice the energy (VIGOROUS is nullified).
80
+ */
81
+ TraitEnum["CRAFTY"] = "CRAFTY";
82
+ /**
83
+ * When the team loses several points in a row, the whole on-court team gets a buff that grows with the
84
+ * streak and disappears the moment they win a point.
85
+ */
86
+ TraitEnum["TENACIOUS"] = "TENACIOUS";
87
+ /**
88
+ * Serve trait, rolled before the ambient setter/opposite hunt: a chance to serve a precise target (the
89
+ * setter, opposite, or best back-row attacker, depending on serve type and rotation), bypassing GUARDIAN,
90
+ * with a slight serve bonus and reducing the hunted player's attack involvement that rally.
91
+ */
92
+ TraitEnum["HUNTER"] = "HUNTER";
47
93
  })(TraitEnum || (TraitEnum = {}));
48
94
  export function assignTraits(roles, rarity, maxTraits) {
49
95
  let traitCount;
@@ -75,7 +121,9 @@ export function assignTraits(roles, rarity, maxTraits) {
75
121
  return [];
76
122
  const filteredTraits = traits.filter((trait) => {
77
123
  const setA = new Set(trait.roles);
78
- return roles.some(el => setA.has(el));
124
+ const roleMatch = roles.some(el => setA.has(el));
125
+ const rarityOk = trait.maxRarity == null || RARITY_RANK[rarity] <= RARITY_RANK[trait.maxRarity];
126
+ return roleMatch && rarityOk;
79
127
  }).map(trait => trait.name);
80
128
  return shuffle(filteredTraits).slice(0, traitCount);
81
129
  }
@@ -90,5 +90,79 @@
90
90
  "OUTSIDE_HITTER",
91
91
  "MIDDLE_BLOCKER"
92
92
  ]
93
+ },
94
+ {
95
+ "name": "QUICK_LEARNER",
96
+ "chance": 1,
97
+ "roles": [
98
+ "SETTER",
99
+ "LIBERO",
100
+ "OUTSIDE_HITTER"
101
+ ]
102
+ },
103
+ {
104
+ "name": "MOMENTUM_ADDICT",
105
+ "chance": 1,
106
+ "roles": [
107
+ "OUTSIDE_HITTER",
108
+ "OPPOSITE_HITTER",
109
+ "MIDDLE_BLOCKER"
110
+ ]
111
+ },
112
+ {
113
+ "name": "LOUDMOUTH",
114
+ "chance": 0.25,
115
+ "roles": [
116
+ "OUTSIDE_HITTER",
117
+ "OPPOSITE_HITTER",
118
+ "MIDDLE_BLOCKER"
119
+ ]
120
+ },
121
+ {
122
+ "name": "TRUE_LEADER",
123
+ "chance": 0.3,
124
+ "roles": [
125
+ "SETTER",
126
+ "LIBERO",
127
+ "OUTSIDE_HITTER"
128
+ ]
129
+ },
130
+ {
131
+ "name": "OVERACHIEVER",
132
+ "chance": 0.2,
133
+ "maxRarity": "MYTHIC",
134
+ "roles": [
135
+ "LIBERO",
136
+ "OUTSIDE_HITTER",
137
+ "MIDDLE_BLOCKER"
138
+ ]
139
+ },
140
+ {
141
+ "name": "CRAFTY",
142
+ "chance": 0.3,
143
+ "roles": [
144
+ "SETTER",
145
+ "OUTSIDE_HITTER",
146
+ "OPPOSITE_HITTER",
147
+ "MIDDLE_BLOCKER"
148
+ ]
149
+ },
150
+ {
151
+ "name": "TENACIOUS",
152
+ "chance": 1,
153
+ "roles": [
154
+ "SETTER",
155
+ "LIBERO",
156
+ "OUTSIDE_HITTER"
157
+ ]
158
+ },
159
+ {
160
+ "name": "HUNTER",
161
+ "chance": 0.15,
162
+ "roles": [
163
+ "SETTER",
164
+ "OPPOSITE_HITTER",
165
+ "OUTSIDE_HITTER"
166
+ ]
93
167
  }
94
168
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.451",
3
+ "version": "0.0.452",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",