mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-30 23:27:55 -05:00
Analyzer core structure
This commit is contained in:
5
app/modules/analyzer/index.ts
Normal file
5
app/modules/analyzer/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export type {
|
||||
DistanceDamage,
|
||||
MainWeaponParams,
|
||||
SubWeaponParams,
|
||||
} from "./types";
|
||||
599
app/modules/analyzer/params.json
Normal file
599
app/modules/analyzer/params.json
Normal file
@@ -0,0 +1,599 @@
|
||||
{
|
||||
"mainWeapons": {
|
||||
"0": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 6,
|
||||
"specialWeaponId": 11,
|
||||
"internalName": "Shooter_Short",
|
||||
"InkConsume": 0.008
|
||||
},
|
||||
"10": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 0,
|
||||
"specialWeaponId": 2,
|
||||
"internalName": "Shooter_First",
|
||||
"InkConsume": 0.0043
|
||||
},
|
||||
"20": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 2,
|
||||
"specialWeaponId": 12,
|
||||
"internalName": "Shooter_Precision",
|
||||
"InkConsume": 0.008
|
||||
},
|
||||
"30": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 5,
|
||||
"specialWeaponId": 13,
|
||||
"internalName": "Shooter_Blaze",
|
||||
"InkConsume": 0.0055
|
||||
},
|
||||
"40": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 1,
|
||||
"specialWeaponId": 1,
|
||||
"internalName": "Shooter_Normal",
|
||||
"InkConsume": 0.0092
|
||||
},
|
||||
"50": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 4,
|
||||
"specialWeaponId": 9,
|
||||
"internalName": "Shooter_Gravity",
|
||||
"InkConsume": 0.013
|
||||
},
|
||||
"60": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 1,
|
||||
"specialWeaponId": 15,
|
||||
"internalName": "Shooter_QuickMiddle",
|
||||
"InkConsume": 0.008
|
||||
},
|
||||
"70": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 12,
|
||||
"specialWeaponId": 12,
|
||||
"internalName": "Shooter_Expert",
|
||||
"InkConsume": 0.02
|
||||
},
|
||||
"80": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 3,
|
||||
"specialWeaponId": 8,
|
||||
"internalName": "Shooter_Heavy",
|
||||
"InkConsume": 0.025
|
||||
},
|
||||
"90": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 12,
|
||||
"specialWeaponId": 8,
|
||||
"internalName": "Shooter_Long",
|
||||
"InkConsume": 0.016
|
||||
},
|
||||
"200": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 0,
|
||||
"specialWeaponId": 3,
|
||||
"internalName": "Blaster_Short",
|
||||
"InkConsume": 0.075
|
||||
},
|
||||
"210": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 7,
|
||||
"specialWeaponId": 2,
|
||||
"internalName": "Blaster_Middle",
|
||||
"InkConsume": 0.1
|
||||
},
|
||||
"220": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 1,
|
||||
"specialWeaponId": 7,
|
||||
"internalName": "Blaster_Long",
|
||||
"InkConsume": 0.11
|
||||
},
|
||||
"230": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 0,
|
||||
"specialWeaponId": 1,
|
||||
"internalName": "Blaster_LightShort",
|
||||
"InkConsume": 0.04
|
||||
},
|
||||
"240": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 10,
|
||||
"specialWeaponId": 14,
|
||||
"internalName": "Blaster_Light",
|
||||
"InkConsume": 0.07
|
||||
},
|
||||
"250": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 11,
|
||||
"specialWeaponId": 8,
|
||||
"internalName": "Blaster_LightLong",
|
||||
"InkConsume": 0.08
|
||||
},
|
||||
"300": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 6,
|
||||
"specialWeaponId": 12,
|
||||
"internalName": "Shooter_TripleQuick",
|
||||
"InkConsume": 0.0115
|
||||
},
|
||||
"310": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 9,
|
||||
"specialWeaponId": 15,
|
||||
"internalName": "Shooter_TripleMiddle",
|
||||
"InkConsume": 0.0225
|
||||
},
|
||||
"400": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 4,
|
||||
"specialWeaponId": 1,
|
||||
"internalName": "Shooter_Flash",
|
||||
"InkConsume": 0.022
|
||||
},
|
||||
"1000": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 7,
|
||||
"specialWeaponId": 3,
|
||||
"internalName": "Roller_Compact",
|
||||
"InkConsumeMaxPerFrame_WeaponRollParam": 0.001,
|
||||
"InkConsumeMinPerFrame_WeaponRollParam": 0.0002,
|
||||
"InkConsume_WeaponVerticalSwingParam": 0.0396,
|
||||
"InkConsume_WeaponWideSwingParam": 0.0396
|
||||
},
|
||||
"1010": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 6,
|
||||
"specialWeaponId": 2,
|
||||
"internalName": "Roller_Normal",
|
||||
"InkConsumeMaxPerFrame_WeaponRollParam": 0.001,
|
||||
"InkConsumeMinPerFrame_WeaponRollParam": 0.0002,
|
||||
"InkConsume_WeaponVerticalSwingParam": 0.085,
|
||||
"InkConsume_WeaponWideSwingParam": 0.085
|
||||
},
|
||||
"1020": {
|
||||
"SpecialPoint": 190,
|
||||
"subWeaponId": 3,
|
||||
"specialWeaponId": 15,
|
||||
"internalName": "Roller_Heavy",
|
||||
"InkConsumeMaxPerFrame_WeaponRollParam": 0.001,
|
||||
"InkConsumeMinPerFrame_WeaponRollParam": 0.0002,
|
||||
"InkConsume_WeaponVerticalSwingParam": 0.18,
|
||||
"InkConsume_WeaponWideSwingParam": 0.18
|
||||
},
|
||||
"1030": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 10,
|
||||
"specialWeaponId": 4,
|
||||
"internalName": "Roller_Hunter",
|
||||
"InkConsumeMaxPerFrame_WeaponRollParam": 0.001,
|
||||
"InkConsumeMinPerFrame_WeaponRollParam": 0.0002,
|
||||
"InkConsume_WeaponVerticalSwingParam": 0.12,
|
||||
"InkConsume_WeaponWideSwingParam": 0.08
|
||||
},
|
||||
"1100": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 0,
|
||||
"specialWeaponId": 9,
|
||||
"internalName": "Brush_Mini",
|
||||
"InkConsume_WeaponSwingParam": 0.02,
|
||||
"InkConsumeMaxPerFrame_WeaponRollParam": 0.00135,
|
||||
"InkConsumeMinPerFrame_WeaponRollParam": 0.00135
|
||||
},
|
||||
"1110": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 1,
|
||||
"specialWeaponId": 3,
|
||||
"internalName": "Brush_Normal",
|
||||
"InkConsume_WeaponSwingParam": 0.032,
|
||||
"InkConsumeMaxPerFrame_WeaponRollParam": 0.00162,
|
||||
"InkConsumeMinPerFrame_WeaponRollParam": 0.00162
|
||||
},
|
||||
"2000": {
|
||||
"SpecialPoint": 190,
|
||||
"subWeaponId": 9,
|
||||
"specialWeaponId": 2,
|
||||
"internalName": "Charger_Quick",
|
||||
"InkConsumeFullCharge": 0.105,
|
||||
"InkConsumeMinCharge": 0.018667
|
||||
},
|
||||
"2010": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 0,
|
||||
"specialWeaponId": 8,
|
||||
"internalName": "Charger_Normal",
|
||||
"InkConsumeFullCharge": 0.18,
|
||||
"InkConsumeMinCharge": 0.0225
|
||||
},
|
||||
"2020": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 0,
|
||||
"specialWeaponId": 8,
|
||||
"internalName": "Charger_NormalScope",
|
||||
"InkConsumeFullCharge": 0.18,
|
||||
"InkConsumeMinCharge": 0.0225
|
||||
},
|
||||
"2030": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 10,
|
||||
"specialWeaponId": 7,
|
||||
"internalName": "Charger_Long",
|
||||
"InkConsumeFullCharge": 0.25,
|
||||
"InkConsumeMinCharge": 0.0225
|
||||
},
|
||||
"2040": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 10,
|
||||
"specialWeaponId": 7,
|
||||
"internalName": "Charger_LongScope",
|
||||
"InkConsumeFullCharge": 0.25,
|
||||
"InkConsumeMinCharge": 0.0225
|
||||
},
|
||||
"2050": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 7,
|
||||
"specialWeaponId": 9,
|
||||
"internalName": "Charger_Light",
|
||||
"InkConsumeFullCharge": 0.084,
|
||||
"InkConsumeMinCharge": 0.0336
|
||||
},
|
||||
"2060": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 13,
|
||||
"specialWeaponId": 4,
|
||||
"internalName": "Charger_Keeper",
|
||||
"InkConsumeFullCharge": 0.15,
|
||||
"InkConsumeMinCharge": 0.02
|
||||
},
|
||||
"3000": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 0,
|
||||
"specialWeaponId": 14,
|
||||
"internalName": "Slosher_Strong",
|
||||
"InkConsume": 0.07
|
||||
},
|
||||
"3010": {
|
||||
"SpecialPoint": 190,
|
||||
"subWeaponId": 11,
|
||||
"specialWeaponId": 10,
|
||||
"internalName": "Slosher_Diffusion",
|
||||
"InkConsume": 0.06
|
||||
},
|
||||
"3020": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 5,
|
||||
"specialWeaponId": 6,
|
||||
"internalName": "Slosher_Launcher",
|
||||
"InkConsume": 0.084
|
||||
},
|
||||
"3030": {
|
||||
"SpecialPoint": 190,
|
||||
"subWeaponId": 3,
|
||||
"specialWeaponId": 5,
|
||||
"internalName": "Slosher_Bathtub",
|
||||
"InkConsume": 0.08
|
||||
},
|
||||
"3040": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 9,
|
||||
"specialWeaponId": 5,
|
||||
"internalName": "Slosher_Washtub",
|
||||
"InkConsume": 0.117
|
||||
},
|
||||
"4000": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 2,
|
||||
"specialWeaponId": 11,
|
||||
"internalName": "Spinner_Quick",
|
||||
"InkConsume": 0.1725
|
||||
},
|
||||
"4010": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 3,
|
||||
"specialWeaponId": 7,
|
||||
"internalName": "Spinner_Standard",
|
||||
"InkConsume": 0.225
|
||||
},
|
||||
"4020": {
|
||||
"SpecialPoint": 190,
|
||||
"subWeaponId": 7,
|
||||
"specialWeaponId": 6,
|
||||
"internalName": "Spinner_Hyper",
|
||||
"InkConsume": 0.35
|
||||
},
|
||||
"4030": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 5,
|
||||
"specialWeaponId": 10,
|
||||
"internalName": "Spinner_Downpour",
|
||||
"InkConsume": 0.25
|
||||
},
|
||||
"4040": {
|
||||
"SpecialPoint": 190,
|
||||
"subWeaponId": 9,
|
||||
"specialWeaponId": 5,
|
||||
"internalName": "Spinner_Serein",
|
||||
"InkConsume": 0.15
|
||||
},
|
||||
"5000": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 8,
|
||||
"specialWeaponId": 15,
|
||||
"internalName": "Maneuver_Short",
|
||||
"InkConsume": 0.00663,
|
||||
"InkConsume_SideStepParam": 0.05
|
||||
},
|
||||
"5010": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 1,
|
||||
"specialWeaponId": 12,
|
||||
"internalName": "Maneuver_Normal",
|
||||
"InkConsume": 0.0072,
|
||||
"InkConsume_SideStepParam": 0.07
|
||||
},
|
||||
"5020": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 4,
|
||||
"specialWeaponId": 6,
|
||||
"internalName": "Maneuver_Gallon",
|
||||
"InkConsume": 0.014,
|
||||
"InkConsume_SideStepParam": 0.08
|
||||
},
|
||||
"5030": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 0,
|
||||
"specialWeaponId": 7,
|
||||
"internalName": "Maneuver_Dual",
|
||||
"InkConsume": 0.012,
|
||||
"InkConsume_SideStepParam": 0.08
|
||||
},
|
||||
"5040": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 7,
|
||||
"specialWeaponId": 13,
|
||||
"internalName": "Maneuver_Stepper",
|
||||
"InkConsume": 0.008,
|
||||
"InkConsume_SideStepParam": 0.03
|
||||
},
|
||||
"6000": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 3,
|
||||
"specialWeaponId": 14,
|
||||
"internalName": "Shelter_Normal",
|
||||
"InkConsumeUmbrella_WeaponShelterCanopyParam": 0.3
|
||||
},
|
||||
"6010": {
|
||||
"SpecialPoint": 190,
|
||||
"subWeaponId": 8,
|
||||
"specialWeaponId": 8,
|
||||
"internalName": "Shelter_Wide",
|
||||
"InkConsumeUmbrella_WeaponShelterCanopyParam": 0.3,
|
||||
"InkConsume_WeaponShelterShotgunParam": 0.11
|
||||
},
|
||||
"6020": {
|
||||
"SpecialPoint": 180,
|
||||
"subWeaponId": 10,
|
||||
"specialWeaponId": 13,
|
||||
"internalName": "Shelter_Compact",
|
||||
"InkConsumeUmbrella_WeaponShelterCanopyParam": 0,
|
||||
"InkConsume_WeaponShelterShotgunParam": 0.04
|
||||
},
|
||||
"7010": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 11,
|
||||
"specialWeaponId": 9,
|
||||
"internalName": "Stringer_Normal",
|
||||
"InkConsumeFullCharge_ChargeParam": 0.085,
|
||||
"InkConsumeMinCharge_ChargeParam": 0.05
|
||||
},
|
||||
"8000": {
|
||||
"SpecialPoint": 200,
|
||||
"subWeaponId": 2,
|
||||
"specialWeaponId": 3,
|
||||
"internalName": "Saber_Normal",
|
||||
"InkConsume_SwingParam": 0.04,
|
||||
"InkConsumeFullCharge_ChargeParam": 0.09,
|
||||
"InkConsumeMinCharge_ChargeParam": 0.035
|
||||
}
|
||||
},
|
||||
"subWeapons": {
|
||||
"0": {
|
||||
"internalName": "Bomb_Splash",
|
||||
"InkRecoverStop": 60,
|
||||
"DistanceDamage": [
|
||||
{
|
||||
"Damage": 1800,
|
||||
"Distance": 3.6
|
||||
},
|
||||
{
|
||||
"Damage": 300,
|
||||
"Distance": 7
|
||||
}
|
||||
]
|
||||
},
|
||||
"1": {
|
||||
"internalName": "Bomb_Suction",
|
||||
"InkRecoverStop": 60,
|
||||
"DistanceDamage": [
|
||||
{
|
||||
"Damage": 1800,
|
||||
"Distance": 4.6
|
||||
},
|
||||
{
|
||||
"Damage": 300,
|
||||
"Distance": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
"2": {
|
||||
"internalName": "Bomb_Quick",
|
||||
"SubInkSaveLv": 0,
|
||||
"InkConsume": 0.4,
|
||||
"InkRecoverStop": 50,
|
||||
"DistanceDamage": [
|
||||
{
|
||||
"Damage": 350,
|
||||
"Distance": 2.8
|
||||
},
|
||||
{
|
||||
"Damage": 250,
|
||||
"Distance": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"3": {
|
||||
"internalName": "Sprinkler",
|
||||
"SubInkSaveLv": 3,
|
||||
"InkConsume": 0.6,
|
||||
"InkRecoverStop": 60
|
||||
},
|
||||
"4": {
|
||||
"internalName": "Shield",
|
||||
"InkConsume": 0.6,
|
||||
"InkRecoverStop": 85
|
||||
},
|
||||
"5": {
|
||||
"internalName": "Bomb_Fizzy",
|
||||
"SubInkSaveLv": 1,
|
||||
"InkConsume": 0.6,
|
||||
"InkRecoverStop": 70,
|
||||
"DistanceDamage_BlastParamArray": [
|
||||
[
|
||||
{
|
||||
"Damage": 500,
|
||||
"Distance": 1.6
|
||||
},
|
||||
{
|
||||
"Damage": 350,
|
||||
"Distance": 3.8
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"Damage": 500,
|
||||
"Distance": 1.95
|
||||
},
|
||||
{
|
||||
"Damage": 350,
|
||||
"Distance": 4.5
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"Damage": 500,
|
||||
"Distance": 2.6
|
||||
},
|
||||
{
|
||||
"Damage": 350,
|
||||
"Distance": 5.45
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"6": {
|
||||
"internalName": "Bomb_Curling",
|
||||
"InkRecoverStop": 70,
|
||||
"DistanceDamage_BlastParamMaxCharge": [
|
||||
{
|
||||
"Damage": 1800,
|
||||
"Distance": 4.6
|
||||
},
|
||||
{
|
||||
"Damage": 300,
|
||||
"Distance": 8
|
||||
}
|
||||
],
|
||||
"DistanceDamage_BlastParamMinCharge": [
|
||||
{
|
||||
"Damage": 1800,
|
||||
"Distance": 1.6
|
||||
},
|
||||
{
|
||||
"Damage": 300,
|
||||
"Distance": 5
|
||||
}
|
||||
],
|
||||
"DirectDamage": 200
|
||||
},
|
||||
"7": {
|
||||
"internalName": "Bomb_Robot",
|
||||
"SubInkSaveLv": 1,
|
||||
"InkConsume": 0.55,
|
||||
"InkRecoverStop": 85,
|
||||
"DistanceDamage": [
|
||||
{
|
||||
"Damage": 1800,
|
||||
"Distance": 2.85
|
||||
},
|
||||
{
|
||||
"Damage": 300,
|
||||
"Distance": 6.5
|
||||
}
|
||||
]
|
||||
},
|
||||
"8": {
|
||||
"internalName": "Beacon",
|
||||
"SubInkSaveLv": 3,
|
||||
"InkConsume": 0.75,
|
||||
"InkRecoverStop": 0
|
||||
},
|
||||
"9": {
|
||||
"internalName": "PointSensor",
|
||||
"SubInkSaveLv": 1,
|
||||
"InkConsume": 0.45,
|
||||
"InkRecoverStop": 75
|
||||
},
|
||||
"10": {
|
||||
"internalName": "Trap",
|
||||
"SubInkSaveLv": 3,
|
||||
"InkConsume": 0.6,
|
||||
"InkRecoverStop": 0,
|
||||
"DistanceDamage": [
|
||||
{
|
||||
"Damage": 450,
|
||||
"Distance": 3.6
|
||||
},
|
||||
{
|
||||
"Damage": 350,
|
||||
"Distance": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
"11": {
|
||||
"internalName": "PoisonMist",
|
||||
"SubInkSaveLv": 1,
|
||||
"InkConsume": 0.6,
|
||||
"InkRecoverStop": 75
|
||||
},
|
||||
"12": {
|
||||
"internalName": "LineMarker",
|
||||
"SubInkSaveLv": 0,
|
||||
"InkConsume": 0.4,
|
||||
"InkRecoverStop": 50,
|
||||
"DirectDamage": 300
|
||||
},
|
||||
"13": {
|
||||
"internalName": "Bomb_Torpedo",
|
||||
"InkConsume": 0.65,
|
||||
"InkRecoverStop": 88,
|
||||
"DistanceDamage_BlastParamChase": [
|
||||
{
|
||||
"Damage": 600,
|
||||
"Distance": 2.6
|
||||
},
|
||||
{
|
||||
"Damage": 350,
|
||||
"Distance": 6
|
||||
}
|
||||
],
|
||||
"DistanceDamage_SplashBlastParam": [
|
||||
{
|
||||
"Damage": 120,
|
||||
"Distance": 2.6
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
61
app/modules/analyzer/stats.ts
Normal file
61
app/modules/analyzer/stats.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import type { BuildAbilitiesTupleWithUnknown } from "~/modules/in-game-lists";
|
||||
import type { BuildWeapon } from "~/db/types";
|
||||
import type { AnalyzedBuild, StatFunctionInput } from "./types";
|
||||
import invariant from "tiny-invariant";
|
||||
import { buildToAbilityPoints, params } from "./utils";
|
||||
|
||||
export function buildStats({
|
||||
build,
|
||||
weaponSplId,
|
||||
}: {
|
||||
build: BuildAbilitiesTupleWithUnknown;
|
||||
weaponSplId: BuildWeapon["weaponSplId"];
|
||||
}): AnalyzedBuild {
|
||||
const mainWeaponParams = params().mainWeapons[weaponSplId];
|
||||
invariant(mainWeaponParams, `Weapon with splId ${weaponSplId} not found`);
|
||||
|
||||
const subWeaponParams = params().subWeapons[mainWeaponParams.subWeaponId];
|
||||
invariant(
|
||||
subWeaponParams,
|
||||
`Sub weapon with splId ${mainWeaponParams.subWeaponId} not found`
|
||||
);
|
||||
|
||||
const input: StatFunctionInput = {
|
||||
mainWeaponParams,
|
||||
subWeaponParams,
|
||||
abilityPoints: buildToAbilityPoints(build),
|
||||
};
|
||||
|
||||
return {
|
||||
weapon: {
|
||||
specialWeaponSplId: mainWeaponParams.specialWeaponId,
|
||||
subWeaponSplId: mainWeaponParams.subWeaponId,
|
||||
},
|
||||
stats: {
|
||||
shotsPerInkTank: shotsPerInkTank(input),
|
||||
inkCost: inkCost(input),
|
||||
specialPoint: specialPoint(input),
|
||||
subWeaponWhiteInkFrames: subWeaponParams.InkRecoverStop,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function shotsPerInkTank(
|
||||
args: StatFunctionInput
|
||||
): AnalyzedBuild["stats"]["shotsPerInkTank"] {
|
||||
return {};
|
||||
}
|
||||
|
||||
function specialPoint(
|
||||
args: StatFunctionInput
|
||||
): AnalyzedBuild["stats"]["specialPoint"] {
|
||||
return {
|
||||
baseValue: args.mainWeaponParams.SpecialPoint,
|
||||
modifiedBy: "SCU",
|
||||
value: args.mainWeaponParams.SpecialPoint, // xxx:
|
||||
};
|
||||
}
|
||||
|
||||
function inkCost(args: StatFunctionInput): AnalyzedBuild["stats"]["inkCost"] {
|
||||
return {};
|
||||
}
|
||||
117
app/modules/analyzer/types.ts
Normal file
117
app/modules/analyzer/types.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import type { Ability } from "~/modules/in-game-lists";
|
||||
|
||||
export interface MainWeaponParams {
|
||||
subWeaponId: number;
|
||||
specialWeaponId: number;
|
||||
internalName: string;
|
||||
SpecialPoint: number;
|
||||
/** How much ink one shot consumes? InkConsume = 0.5 means 2 shots per full tank */
|
||||
InkConsume?: number;
|
||||
/** How much ink one fully charged shot consumes? */
|
||||
InkConsumeFullCharge?: number;
|
||||
/** How much ink one tap shot consumes? */
|
||||
InkConsumeMinCharge?: number;
|
||||
// xxx: morph with another swing one below
|
||||
/** How much ink one swing of brush consumes? */
|
||||
InkConsume_WeaponSwingParam?: number;
|
||||
/** Lower bound of ink consumed per frame when rolling with roller/brush */
|
||||
InkConsumeMaxPerFrame_WeaponRollParam?: number;
|
||||
/** Upper bound of ink consumed per frame when rolling with roller/brush */
|
||||
InkConsumeMinPerFrame_WeaponRollParam?: number;
|
||||
/** How much ink one vertical swing of roller consumes? */
|
||||
InkConsume_WeaponVerticalSwingParam?: number;
|
||||
/** How much ink one horizontal swing of roller consumes? */
|
||||
InkConsume_WeaponWideSwingParam?: number;
|
||||
/** How much ink one swing of splatana consumes? */
|
||||
InkConsume_SwingParam?: number;
|
||||
/** How much ink brella shield launch consumes? */
|
||||
InkConsumeUmbrella_WeaponShelterCanopyParam?: number;
|
||||
// xxx: splat brella missing this - are we missing extend?
|
||||
/** How much ink one brella shot consumes? */
|
||||
InkConsume_WeaponShelterShotgunParam?: number;
|
||||
/** How much ink a dualie dodge roll consumes? */
|
||||
InkConsume_SideStepParam?: number;
|
||||
// xxx: some explanations... the below two are for splatana/bow
|
||||
InkConsumeFullCharge_ChargeParam?: number;
|
||||
InkConsumeMinCharge_ChargeParam?: number;
|
||||
//InkConsumeMidCharge_ChargeParam?: number;
|
||||
// xxx: what are these?
|
||||
// SpeedInkConsumeMax_WeaponRollParam?: number;
|
||||
// SpeedInkConsumeMin_WeaponRollParam?: number;
|
||||
}
|
||||
|
||||
export interface DistanceDamage {
|
||||
damage: number;
|
||||
distance: number;
|
||||
}
|
||||
|
||||
export interface SubWeaponParams {
|
||||
internalName: string;
|
||||
SubInkSaveLv: number;
|
||||
/** How much ink one usage of the sub consumes */
|
||||
InkConsume: number;
|
||||
/** Amount of frames white ink (=no ink recovery during this time) takes */
|
||||
InkRecoverStop: number;
|
||||
/** Damage dealt at different radiuses */
|
||||
DistanceDamage?: Array<DistanceDamage>;
|
||||
/** Damage dealt by explosion at different radiuses (curling bomb charged all the way) */
|
||||
DistanceDamage_BlastParamMaxCharge?: Array<DistanceDamage>;
|
||||
/** Damage dealt by explosion at different radiuses (curling bomb not charged) */
|
||||
DistanceDamage_BlastParamMinCharge?: Array<DistanceDamage>;
|
||||
/** Damage dealt by explosion at different radiuses (fizzy bomb bounces) */
|
||||
DistanceDamage_BlastParamArray?: Array<DistanceDamage>;
|
||||
// xxx: verify torpedo
|
||||
/** Damage dealt by explosion at different radiuses (torpedo explosion air to ground) */
|
||||
DistanceDamage_BlastParamChase?: Array<DistanceDamage>;
|
||||
/** Damage dealt by explosion at different radiuses (rolling torpedo) */
|
||||
DistanceDamage_SplashBlastParam?: Array<DistanceDamage>;
|
||||
/** Damage dealt by direct hit */
|
||||
DirectDamage?: number;
|
||||
}
|
||||
|
||||
export type ParamsJson = {
|
||||
mainWeapons: Record<number, MainWeaponParams>;
|
||||
subWeapons: Record<number, SubWeaponParams>;
|
||||
};
|
||||
|
||||
interface Stat {
|
||||
value: number;
|
||||
baseValue: number;
|
||||
modifiedBy: Ability;
|
||||
}
|
||||
|
||||
export type AbilityPoints = Map<Ability, number>;
|
||||
|
||||
export interface StatFunctionInput {
|
||||
mainWeaponParams: MainWeaponParams;
|
||||
subWeaponParams: SubWeaponParams;
|
||||
abilityPoints: AbilityPoints;
|
||||
}
|
||||
|
||||
type InkConsumeShotType =
|
||||
| "NORMAL"
|
||||
| "SWING"
|
||||
| "VERTICAL_SWING"
|
||||
| "HORIZONTAL_SWING"
|
||||
| "TAP_SHOT"
|
||||
| "FULL_CHARGE";
|
||||
|
||||
type InkConsumePercentageType =
|
||||
| "SHIELD_LAUNCH"
|
||||
| "DUALIE_ROLL"
|
||||
| "ROLL_MIN"
|
||||
| "ROLL_MAX";
|
||||
|
||||
export interface AnalyzedBuild {
|
||||
weapon: {
|
||||
subWeaponSplId: number;
|
||||
specialWeaponSplId: number;
|
||||
};
|
||||
stats: {
|
||||
specialPoint: Stat;
|
||||
shotsPerInkTank: Partial<Record<InkConsumeShotType, Stat>>;
|
||||
/** How much action costs (% of ink tank) */
|
||||
inkCost?: Partial<Record<InkConsumePercentageType, Stat>>;
|
||||
subWeaponWhiteInkFrames?: number;
|
||||
};
|
||||
}
|
||||
23
app/modules/analyzer/utils.ts
Normal file
23
app/modules/analyzer/utils.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { BuildAbilitiesTupleWithUnknown } from "../in-game-lists";
|
||||
import paramsJson from "./params.json";
|
||||
import type { AbilityPoints, ParamsJson } from "./types";
|
||||
|
||||
export function params(): ParamsJson {
|
||||
return paramsJson as ParamsJson;
|
||||
}
|
||||
|
||||
export function buildToAbilityPoints(build: BuildAbilitiesTupleWithUnknown) {
|
||||
const result: AbilityPoints = new Map();
|
||||
|
||||
for (const abilityRow of build) {
|
||||
for (const [i, ability] of abilityRow.entries()) {
|
||||
if (ability === "UNKNOWN") continue;
|
||||
|
||||
const aps = i === 0 ? 10 : 3;
|
||||
|
||||
result.set(ability, (result.get(ability) ?? 0) + aps);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -3,4 +3,11 @@ export { modes, modesShort } from "./modes";
|
||||
export { weaponIds } from "./weapon-ids";
|
||||
export { headGearIds, clothesGearIds, shoesGearIds } from "./gear-ids";
|
||||
export { abilitiesShort, abilities } from "./abilities";
|
||||
export type { Ability, AbilityType, ModeShort, Stage } from "./types";
|
||||
export type {
|
||||
Ability,
|
||||
AbilityType,
|
||||
ModeShort,
|
||||
Stage,
|
||||
BuildAbilitiesTuple,
|
||||
BuildAbilitiesTupleWithUnknown,
|
||||
} from "./types";
|
||||
|
||||
7
app/routes/analyzer.tsx
Normal file
7
app/routes/analyzer.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Main } from "~/components/Main";
|
||||
|
||||
export default function BuildAnalyzerPage() {
|
||||
if (process.env.NODE_ENV === "production") return <Main>Coming soon :)</Main>;
|
||||
|
||||
return <Main>hellou</Main>;
|
||||
}
|
||||
@@ -12,85 +12,17 @@ import specialWeapons from "./dicts/WeaponInfoSpecial.json";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import invariant from "tiny-invariant";
|
||||
import type { MainWeaponParams, SubWeaponParams } from "~/modules/analyzer";
|
||||
import type { ParamsJson } from "~/modules/analyzer/types";
|
||||
|
||||
const CURRENT_SEASON = 0;
|
||||
|
||||
type MainWeapon = typeof weapons[number];
|
||||
type SubWeapon = typeof subWeapons[number];
|
||||
|
||||
interface MainWeaponParams {
|
||||
id: number;
|
||||
subWeaponId: number;
|
||||
specialWeaponId: number;
|
||||
internalName: string;
|
||||
SpecialPoint: number;
|
||||
/** How much ink one shot consumes? InkConsume = 0.5 means 2 shots per full tank */
|
||||
InkConsume?: number;
|
||||
/** How much ink one fully charged shot consumes? */
|
||||
InkConsumeFullCharge?: number;
|
||||
/** How much ink one tap shot consumes? */
|
||||
InkConsumeMinCharge?: number;
|
||||
/** How much ink one swing of brush consumes? */
|
||||
InkConsume_WeaponSwingParam?: number;
|
||||
/** Lower bound of ink consumed per frame when rolling with roller/brush */
|
||||
InkConsumeMaxPerFrame_WeaponRollParam?: number;
|
||||
/** Upper bound of ink consumed per frame when rolling with roller/brush */
|
||||
InkConsumeMinPerFrame_WeaponRollParam?: number;
|
||||
/** How much ink one vertical swing of roller consumes? */
|
||||
InkConsume_WeaponVerticalSwingParam?: number;
|
||||
/** How much ink one horizontal swing of roller consumes? */
|
||||
InkConsume_WeaponWideSwingParam?: number;
|
||||
/** How much ink one swing of splatana consumes? */
|
||||
InkConsume_SwingParam?: number;
|
||||
/** How much ink brella shield launch consumes? */
|
||||
InkConsumeUmbrella_WeaponShelterCanopyParam?: number;
|
||||
// xxx: splat brella missing this - are we missing extend?
|
||||
/** How much ink one brella shot consumes? */
|
||||
InkConsume_WeaponShelterShotgunParam?: number;
|
||||
/** How much ink a dualie dodge roll consumes? */
|
||||
InkConsume_SideStepParam?: number;
|
||||
// xxx: some explanations... the below two are for splatana/bow
|
||||
InkConsumeFullCharge_ChargeParam?: number;
|
||||
InkConsumeMinCharge_ChargeParam?: number;
|
||||
//InkConsumeMidCharge_ChargeParam?: number;
|
||||
// xxx: what are these?
|
||||
// SpeedInkConsumeMax_WeaponRollParam?: number;
|
||||
// SpeedInkConsumeMin_WeaponRollParam?: number;
|
||||
}
|
||||
|
||||
interface DistanceDamage {
|
||||
damage: number;
|
||||
distance: number;
|
||||
}
|
||||
|
||||
interface SubWeaponParams {
|
||||
id: number;
|
||||
internalName: string;
|
||||
SubInkSaveLv: number;
|
||||
/** How much ink one usage of the sub consumes */
|
||||
InkConsume: number;
|
||||
/** Amount of frames white ink (=no ink recovery during this time) takes */
|
||||
InkRecoverStop: number;
|
||||
/** Damage dealt at different radiuses */
|
||||
DistanceDamage?: Array<DistanceDamage>;
|
||||
/** Damage dealt by explosion at different radiuses (curling bomb charged all the way) */
|
||||
DistanceDamage_BlastParamMaxCharge?: Array<DistanceDamage>;
|
||||
/** Damage dealt by explosion at different radiuses (curling bomb not charged) */
|
||||
DistanceDamage_BlastParamMinCharge?: Array<DistanceDamage>;
|
||||
/** Damage dealt by explosion at different radiuses (fizzy bomb bounces) */
|
||||
DistanceDamage_BlastParamArray?: Array<DistanceDamage>;
|
||||
// xxx: verify torpedo
|
||||
/** Damage dealt by explosion at different radiuses (torpedo explosion air to ground) */
|
||||
DistanceDamage_BlastParamChase?: Array<DistanceDamage>;
|
||||
/** Damage dealt by explosion at different radiuses (rolling torpedo) */
|
||||
DistanceDamage_SplashBlastParam?: Array<DistanceDamage>;
|
||||
/** Damage dealt by direct hit */
|
||||
DirectDamage?: number;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const mainWeaponsResult: Array<MainWeaponParams> = [];
|
||||
const subWeaponsResult: Array<SubWeaponParams> = [];
|
||||
const mainWeaponsResult: Record<number, MainWeaponParams> = {};
|
||||
const subWeaponsResult: Record<number, SubWeaponParams> = {};
|
||||
|
||||
for (const weapon of weapons) {
|
||||
if (mainWeaponShouldBeSkipped(weapon)) continue;
|
||||
@@ -98,7 +30,7 @@ function main() {
|
||||
const rawParams = loadWeaponParamsObject(weapon);
|
||||
const params = parametersToMainWeaponResult(weapon, rawParams);
|
||||
|
||||
mainWeaponsResult.push(params);
|
||||
mainWeaponsResult[weapon.Id] = params;
|
||||
}
|
||||
|
||||
for (const subWeapon of subWeapons) {
|
||||
@@ -107,10 +39,10 @@ function main() {
|
||||
const rawParams = loadWeaponParamsObject(subWeapon);
|
||||
const params = parametersToSubWeaponResult(subWeapon, rawParams);
|
||||
|
||||
subWeaponsResult.push(params);
|
||||
subWeaponsResult[subWeapon.Id] = params;
|
||||
}
|
||||
|
||||
const toFile = {
|
||||
const toFile: ParamsJson = {
|
||||
mainWeapons: mainWeaponsResult,
|
||||
subWeapons: subWeaponsResult,
|
||||
};
|
||||
@@ -126,7 +58,6 @@ function parametersToMainWeaponResult(
|
||||
params: any
|
||||
): MainWeaponParams {
|
||||
return {
|
||||
id: weapon.Id,
|
||||
SpecialPoint: weapon.SpecialPoint,
|
||||
subWeaponId: resolveSubWeaponId(weapon),
|
||||
specialWeaponId: resolveSpecialWeaponId(weapon),
|
||||
@@ -172,7 +103,6 @@ function parametersToSubWeaponResult(
|
||||
params: any
|
||||
): SubWeaponParams {
|
||||
return {
|
||||
id: subWeapon.Id,
|
||||
internalName: subWeapon.__RowId,
|
||||
// xxx: not every sub has this, why? e.g. Splash Wall
|
||||
SubInkSaveLv: params["SubWeaponSetting"]?.["SubInkSaveLv"],
|
||||
|
||||
Reference in New Issue
Block a user