volleyballsimtypes 0.0.380 → 0.0.382

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.
@@ -15,17 +15,17 @@ class GachaPityModel extends sequelize_1.Model {
15
15
  }
16
16
  },
17
17
  legendary_pity: {
18
- type: sequelize_1.DataTypes.FLOAT,
18
+ type: sequelize_1.DataTypes.INTEGER,
19
19
  allowNull: false,
20
20
  defaultValue: 0
21
21
  },
22
22
  mythic_pity: {
23
- type: sequelize_1.DataTypes.FLOAT,
23
+ type: sequelize_1.DataTypes.INTEGER,
24
24
  allowNull: false,
25
25
  defaultValue: 0
26
26
  },
27
27
  special_pity: {
28
- type: sequelize_1.DataTypes.FLOAT,
28
+ type: sequelize_1.DataTypes.INTEGER,
29
29
  allowNull: false,
30
30
  defaultValue: 0
31
31
  }
@@ -2,6 +2,11 @@ import { Rarity } from './rarity';
2
2
  import { Role } from './role';
3
3
  import { Country } from '../country';
4
4
  import { Player } from './player';
5
+ export declare const PITY_THRESHOLDS: {
6
+ legendary: number;
7
+ mythic: number;
8
+ special: number;
9
+ };
5
10
  export interface PityState {
6
11
  legendaryPity: number;
7
12
  mythicPity: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PlayerGenerator = exports.TOURNAMENT_PULL_CONFIG = exports.QUALIFIER_PULL_CONFIG = exports.NORMAL_PULL_CONFIG = void 0;
3
+ exports.PlayerGenerator = exports.TOURNAMENT_PULL_CONFIG = exports.QUALIFIER_PULL_CONFIG = exports.NORMAL_PULL_CONFIG = exports.PITY_THRESHOLDS = void 0;
4
4
  exports.rollRarity = rollRarity;
5
5
  exports.pickPlayerCountry = pickPlayerCountry;
6
6
  const uuid_1 = require("uuid");
@@ -14,9 +14,14 @@ const utils_1 = require("../utils");
14
14
  const player_1 = require("./player");
15
15
  const trait_1 = require("./trait");
16
16
  const decline_1 = require("./decline");
17
- const LEGENDARY_PITY_STEP = 0.004;
18
- const MYTHIC_PITY_STEP = 0.00001;
19
- const SPECIAL_PITY_STEP = 0.000005;
17
+ // Hard pity: each rarity's counter is the number of pulls since its last hit. Odds ramp linearly from
18
+ // the base rate to 1 (a guaranteed drop) as the counter climbs from 0 to its threshold, so the
19
+ // guarantee falls out for free once the counter reaches the threshold.
20
+ exports.PITY_THRESHOLDS = {
21
+ legendary: 25,
22
+ mythic: 200,
23
+ special: 575
24
+ };
20
25
  // Used for world/bot player generation — full rarity range
21
26
  const WORLD_PULL_CONFIG = {
22
27
  special: 0.0003,
@@ -69,11 +74,20 @@ exports.TOURNAMENT_PULL_CONFIG = {
69
74
  accumulateMythicPity: true,
70
75
  accumulateSpecialPity: true
71
76
  };
77
+ // Effective odds for a rarity: the base rate ramped linearly toward 1 (a guaranteed drop) as the
78
+ // integer pity counter climbs from 0 to its threshold. At count 0 it equals the base rate; at
79
+ // count === threshold it is 1, so the rarity is guaranteed. Returns the base rate unchanged when
80
+ // pity is not applied for this pull type.
81
+ function effectiveOdds(base, count, threshold, apply) {
82
+ if (!apply)
83
+ return base;
84
+ return Math.min(1, base + (count / threshold) * (1 - base));
85
+ }
72
86
  function rollRarity(pity, config = WORLD_PULL_CONFIG) {
73
87
  const roll = Math.random();
74
- const tSpecial = config.special + (config.applySpecialPity ? pity.specialPity : 0);
75
- const tMythic = tSpecial + config.mythic + (config.applyMythicPity ? pity.mythicPity : 0);
76
- const tLegendary = tMythic + config.legendary + (config.applyLegendaryPity ? pity.legendaryPity : 0);
88
+ const tSpecial = effectiveOdds(config.special, pity.specialPity, exports.PITY_THRESHOLDS.special, config.applySpecialPity);
89
+ const tMythic = tSpecial + effectiveOdds(config.mythic, pity.mythicPity, exports.PITY_THRESHOLDS.mythic, config.applyMythicPity);
90
+ const tLegendary = tMythic + effectiveOdds(config.legendary, pity.legendaryPity, exports.PITY_THRESHOLDS.legendary, config.applyLegendaryPity);
77
91
  const tRare = tLegendary + config.rare;
78
92
  let rarity;
79
93
  if (roll < tSpecial) {
@@ -93,16 +107,17 @@ function rollRarity(pity, config = WORLD_PULL_CONFIG) {
93
107
  }
94
108
  const hitLegendaryPlus = rarity === rarity_1.RarityEnum.LEGENDARY || rarity === rarity_1.RarityEnum.MYTHIC || rarity === rarity_1.RarityEnum.SPECIAL;
95
109
  const hitMythicPlus = rarity === rarity_1.RarityEnum.MYTHIC || rarity === rarity_1.RarityEnum.SPECIAL;
110
+ // Integer counters: reset to 0 on a hit of that rarity-or-better, otherwise +1.
96
111
  const updatedPity = {
97
112
  legendaryPity: !config.accumulateLegendaryPity
98
113
  ? pity.legendaryPity
99
- : hitLegendaryPlus ? 0 : pity.legendaryPity + LEGENDARY_PITY_STEP,
114
+ : hitLegendaryPlus ? 0 : pity.legendaryPity + 1,
100
115
  mythicPity: !config.accumulateMythicPity
101
116
  ? pity.mythicPity
102
- : hitMythicPlus ? 0 : pity.mythicPity + MYTHIC_PITY_STEP,
117
+ : hitMythicPlus ? 0 : pity.mythicPity + 1,
103
118
  specialPity: !config.accumulateSpecialPity
104
119
  ? pity.specialPity
105
- : rarity === rarity_1.RarityEnum.SPECIAL ? 0 : pity.specialPity + SPECIAL_PITY_STEP
120
+ : rarity === rarity_1.RarityEnum.SPECIAL ? 0 : pity.specialPity + 1
106
121
  };
107
122
  return { rarity, pity: updatedPity };
108
123
  }
@@ -12,17 +12,17 @@ export class GachaPityModel extends Model {
12
12
  }
13
13
  },
14
14
  legendary_pity: {
15
- type: DataTypes.FLOAT,
15
+ type: DataTypes.INTEGER,
16
16
  allowNull: false,
17
17
  defaultValue: 0
18
18
  },
19
19
  mythic_pity: {
20
- type: DataTypes.FLOAT,
20
+ type: DataTypes.INTEGER,
21
21
  allowNull: false,
22
22
  defaultValue: 0
23
23
  },
24
24
  special_pity: {
25
- type: DataTypes.FLOAT,
25
+ type: DataTypes.INTEGER,
26
26
  allowNull: false,
27
27
  defaultValue: 0
28
28
  }
@@ -2,6 +2,11 @@ import { Rarity } from './rarity';
2
2
  import { Role } from './role';
3
3
  import { Country } from '../country';
4
4
  import { Player } from './player';
5
+ export declare const PITY_THRESHOLDS: {
6
+ legendary: number;
7
+ mythic: number;
8
+ special: number;
9
+ };
5
10
  export interface PityState {
6
11
  legendaryPity: number;
7
12
  mythicPity: number;
@@ -9,9 +9,14 @@ import { shuffle, generatePlayerName } from '../utils';
9
9
  import { Player } from './player';
10
10
  import { assignTraits } from './trait';
11
11
  import { declineProfiles } from './decline';
12
- const LEGENDARY_PITY_STEP = 0.004;
13
- const MYTHIC_PITY_STEP = 0.00001;
14
- const SPECIAL_PITY_STEP = 0.000005;
12
+ // Hard pity: each rarity's counter is the number of pulls since its last hit. Odds ramp linearly from
13
+ // the base rate to 1 (a guaranteed drop) as the counter climbs from 0 to its threshold, so the
14
+ // guarantee falls out for free once the counter reaches the threshold.
15
+ export const PITY_THRESHOLDS = {
16
+ legendary: 25,
17
+ mythic: 200,
18
+ special: 575
19
+ };
15
20
  // Used for world/bot player generation — full rarity range
16
21
  const WORLD_PULL_CONFIG = {
17
22
  special: 0.0003,
@@ -64,11 +69,20 @@ export const TOURNAMENT_PULL_CONFIG = {
64
69
  accumulateMythicPity: true,
65
70
  accumulateSpecialPity: true
66
71
  };
72
+ // Effective odds for a rarity: the base rate ramped linearly toward 1 (a guaranteed drop) as the
73
+ // integer pity counter climbs from 0 to its threshold. At count 0 it equals the base rate; at
74
+ // count === threshold it is 1, so the rarity is guaranteed. Returns the base rate unchanged when
75
+ // pity is not applied for this pull type.
76
+ function effectiveOdds(base, count, threshold, apply) {
77
+ if (!apply)
78
+ return base;
79
+ return Math.min(1, base + (count / threshold) * (1 - base));
80
+ }
67
81
  export function rollRarity(pity, config = WORLD_PULL_CONFIG) {
68
82
  const roll = Math.random();
69
- const tSpecial = config.special + (config.applySpecialPity ? pity.specialPity : 0);
70
- const tMythic = tSpecial + config.mythic + (config.applyMythicPity ? pity.mythicPity : 0);
71
- const tLegendary = tMythic + config.legendary + (config.applyLegendaryPity ? pity.legendaryPity : 0);
83
+ const tSpecial = effectiveOdds(config.special, pity.specialPity, PITY_THRESHOLDS.special, config.applySpecialPity);
84
+ const tMythic = tSpecial + effectiveOdds(config.mythic, pity.mythicPity, PITY_THRESHOLDS.mythic, config.applyMythicPity);
85
+ const tLegendary = tMythic + effectiveOdds(config.legendary, pity.legendaryPity, PITY_THRESHOLDS.legendary, config.applyLegendaryPity);
72
86
  const tRare = tLegendary + config.rare;
73
87
  let rarity;
74
88
  if (roll < tSpecial) {
@@ -88,16 +102,17 @@ export function rollRarity(pity, config = WORLD_PULL_CONFIG) {
88
102
  }
89
103
  const hitLegendaryPlus = rarity === RarityEnum.LEGENDARY || rarity === RarityEnum.MYTHIC || rarity === RarityEnum.SPECIAL;
90
104
  const hitMythicPlus = rarity === RarityEnum.MYTHIC || rarity === RarityEnum.SPECIAL;
105
+ // Integer counters: reset to 0 on a hit of that rarity-or-better, otherwise +1.
91
106
  const updatedPity = {
92
107
  legendaryPity: !config.accumulateLegendaryPity
93
108
  ? pity.legendaryPity
94
- : hitLegendaryPlus ? 0 : pity.legendaryPity + LEGENDARY_PITY_STEP,
109
+ : hitLegendaryPlus ? 0 : pity.legendaryPity + 1,
95
110
  mythicPity: !config.accumulateMythicPity
96
111
  ? pity.mythicPity
97
- : hitMythicPlus ? 0 : pity.mythicPity + MYTHIC_PITY_STEP,
112
+ : hitMythicPlus ? 0 : pity.mythicPity + 1,
98
113
  specialPity: !config.accumulateSpecialPity
99
114
  ? pity.specialPity
100
- : rarity === RarityEnum.SPECIAL ? 0 : pity.specialPity + SPECIAL_PITY_STEP
115
+ : rarity === RarityEnum.SPECIAL ? 0 : pity.specialPity + 1
101
116
  };
102
117
  return { rarity, pity: updatedPity };
103
118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.380",
3
+ "version": "0.0.382",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",