Calculates unit stats for EA's Star Wars: Galaxy of Heroes based on player data.
Accepted data formats are those found in swgoh.help's API endpoints, specifically the 'player.roster' object from their /player
endpoint.
One additional data format is supported as well -- referred to as 'raw' in this documentation, it's a more 'pure' format based on the objects directly returned by the game's servers.
npm install swgoh-stat-calc
const statCalculator = require('swgoh-stat-calc');
statCalculator.setGameData( gameData );
The statCalculator.js
file is the complete calculator object, and has no dependencies on Node-specific packages.
It can run just as well in any browser/system with at least ES6 compatibility.
If used outside of npm, copy that file to a location your project can access, and adjust the require()
parameter to point to that file, such as:
const statCalculator = require('./statCalculator.js');
Examples below make use of the api-swgoh-help package (loaded into variable swapi
) to collect the raw data.
See it's documentation to learn more about how to use it to gather this data.
- .setGameData(gameData)
- .calcCharStats(char, options)
- .calcShipStats(ship, crew, options)
- .calcRosterStats(roster, options)
- .calcPlayerStats(player, options)
- .calcCharGP(char, options)
- .calcShipGP(ship, crew, options)
Tells the Stat Calculator what to use for the base Game Data. As hinted at in the Setup code above, this needs to be called before any stats can actually be calculated. Can also be used later to update / reassign the game data, if an update is detected and loaded externally.
gameData
Object
The Obect used by the Stat Calculator to read raw game data. It requires a specific format.
An example JSON file of the proper gameData
object can be found here.
That link should remain active and updated, and thus can be used directly to create the data object.
To create the object from swgoh.help's /data
endpoint, see the code in dataBuilder.js. (A separate package for this code will be created in the future, but for now, it's just hiding in that project).
None.
// uses 'node-fetch' for the GET request to retrieve the gameData object
const fetch = require('node-fetch');
const statCalculator = require('swgoh-stat-calc');
let gameData = await (await fetch('https://swgoh-stat-calc.glitch.me/gameData.json')).json();
statCalculator.setGameData( gameData );
Calculates stats for a single character.
char
Object
The character object to calculate stats for. Only a single character is allowed. See Object Formats
below for more info.
options
Object | Optional
Optional stat format flags/instructions. See Options
below for a breakdown.
The stats
object for the given char
. Does not affect char
itself.
// get Player roster from api.swgoh.help
let player = (await swapi.fetchPlayer({
allycode: 231686213,
language: "ENG_US",
project: {
roster: {
defId: 1,
nameKey: 1,
rarity: 1,
level: 1,
gear: 1,
equipped: 1,
combatType: 1,
skills: 1,
mods: 1,
relic: 1
}
}
}) ).result[0];
// pull Darth Sion out of roster as an example
let char = player.roster.find( unit => unit.defId == "DARTHSION" );
// get stats
char.stats = statCalculator.calcCharStats( char );
Calculates stats for a single ship.
ship
Object
The ship object to calculate stats for. Only a single character is allowed. See Object Formats
below for more info.
crew
Array
Array of crew members belonging to the ship. Each element is regular character object. See Object Formats
below for more info.
options
Object | Optional
Optional stat format flags/instructions. See Options
below for a breakdown.
The stats
object for the given ship
. Does not affect ship
itself.
// get Player roster from api.swgoh.help
let player = (await swapi.fetchPlayer({
allycode: 231686213,
language: "ENG_US",
project: {
roster: {
defId: 1,
nameKey: 1,
rarity: 1,
level: 1,
gear: 1,
equipped: 1,
combatType: 1,
skills: 1,
mods: 1,
relic: 1
}
}
}) ).result[0];
// pulls Hound's Tooth out of roster as an example
let ship = player.roster.find( unit => unit.defId == "HOUNDSTOOTH" );
// pulls Bossk out of roster for example crew
let crew = player.roster.find( unit => unit.defId == "BOSSK" );
// get stats
ship.stats = statCalculator.calcShipStats( ship, [crew] );
Calls .calcCharStats()
or .calcShipStats()
depending on each unit's combatType
in a roster.
units
Array
Array of unit objects to calculate stats for. Each element is regular unit object. See Object Formats
below for more info.
options
Object | Optional
Optional stat format flags/instructions. See Options
below for a breakdown.
The number of units that had stats calculated.
The original units
array has been altered such that each element now has a .stats
property with the calculated stats.
// get Player roster from api.swgoh.help
let player = (await swapi.fetchPlayer({
allycode: 231686213,
language: "ENG_US",
project: {
roster: {
defId: 1,
nameKey: 1,
rarity: 1,
level: 1,
gear: 1,
equipped: 1,
combatType: 1,
skills: 1,
mods: 1,
relic: 1
}
}
}) ).result[0];
// get stats for full roster
let count = statCalculator.calcRosterStats( player.roster );
Calls .calcRosterStats()
for each roster object in the player profile(s) submitted.
players
Object or Array
Full player profile(s). Either a single player or an array of players is accepted. See Object Formats
below for more info.
options
Object | Optional
Optional stat format flags/instructions. See Options
below for a breakdown.
The number of units that had stats calculated.
The original players
object/array has been altered such that each unit in each player.roster
object now has a .stats
property with the calculated stats.
// get Player roster from api.swgoh.help
let player = (await swapi.fetchPlayer({
allycode: 231686213,
language: "ENG_US",
project: {
roster: {
defId: 1,
nameKey: 1,
rarity: 1,
level: 1,
gear: 1,
equipped: 1,
combatType: 1,
skills: 1,
mods: 1,
relic: 1
}
}
}) ).result[0];
// get stats for full roster
let count = statCalculator.calcPlayerStats( player );
Calculates GP of the specified character.
char
Object
The character object to calculate stats for. Only a single character is allowed. See Object Formats
below for more info.
options
Object | Optional
Optional stat format flags/instructions. See Options
below for a breakdown.
The GP of submitted character.
// get Player roster from api.swgoh.help
let player = (await swapi.fetchPlayer({
allycode: 231686213,
language: "ENG_US",
project: {
roster: {
defId: 1,
nameKey: 1,
rarity: 1,
level: 1,
gear: 1,
equipped: 1,
combatType: 1,
skills: 1,
mods: 1,
relic: 1
}
}
}) ).result[0];
// pull Darth Sion out of roster as an example
let char = player.roster.find( unit => unit.defId == "DARTHSION" );
// get GP
char.gp = statCalculator.calcCharGP( char );
Calculates GP of the specified ship.
ship
Object
The ship object to calculate stats for. Only a single character is allowed. See Object Formats
below for more info.
crew
Array
Array of crew members belonging to the ship. Each element is regular character object. See Object Formats
below for more info.
options
Object | Optional
Optional stat format flags/instructions. See Options
below for a breakdown.
The GP of submitted ship.
// get Player roster from api.swgoh.help
let player = (await swapi.fetchPlayer({
allycode: 231686213,
language: "ENG_US",
project: {
roster: {
defId: 1,
nameKey: 1,
rarity: 1,
level: 1,
gear: 1,
equipped: 1,
combatType: 1,
skills: 1,
mods: 1,
relic: 1
}
}
}) ).result[0];
// pulls Hound's Tooth out of roster as an example
let ship = player.roster.find( unit => unit.defId == "HOUNDSTOOTH" );
// pulls Bossk out of roster for example crew
let crew = player.roster.find( unit => unit.defId == "BOSSK" );
// get stats
ship.gp = statCalculator.calcShipGP( ship, [crew] );
The options
parameter of all calculation methods is an object that can contain any of the following properties.
Any additional properties of the object will be ignored.
The Default explanations below are what is used when the related flag(s) are not used.
{ gameStyle: true, unscaled: true }
calcGP: true
Runs GP calculations along with stat calculations, and stores it's value in the unit's .gp
property.
Only evaluated by the .calcRosterStats()
and .calcPlayerStats()
method calls, when not using the /units
style objects.
onlyGP: true
Implies calcGP and only applicable in the same API calls as calcGP. Skips all stat calculations and only calculates the GP.
withoutModCalc: true
Speeds up character calculations by ignoring stats from mods.
Default - calculate mods stats for all characters that include them.
useValues: {Object}
Overrides unit parameters with specific values.
Object structure and total options are as defined below.
Parameters provided here can be missing in the original unit.
{
char: { // used when calculating character stats
rarity: 1-7,
level: 1-90,
gear: 1-12,
equipped: "all" || "none" || [1,2,3,4,5,6], // See Below
relic: 1-9 // 1='locked', 2='unlocked', 3=R1, 4=R2, ...9=R7
},
ship: { // used when calculating ship stats
rarity: 1-7,
level: 1-90
},
crew: { // used for characters when calculating ship stats
rarity: 1-7,
level: 1-90,
gear: 1-12,
equipped: "all" || "none" || [1,2,3,4,5,6] || 1-6, // See Below
skills: "max" || "maxNoZeta" || 1-8, // See Below
modRarity: 1-7,
modLevel: 1-15,
relic: 1-9 // 1='locked', 2='unlocked', 3=R1, 4=R2, ...9=R7
}
}
char.equipped
/crew.equipped
- gear currently equipped on characters/crew:
- "all" - all possible gear at the current level.
- "none" - no gear at the current level.
- Array - List of filled slots. Slots are numbered 1-6, left to right, starting at the top by in-game UI.
- Integer - Number, 1-6, of gear pieces equipped at current level. Only valid for crew.
char.relic
/crew.relic
- Relic 'Tier' to use
Used as therelic.currentTier
property in .help's data format.
Values of 1 and 2 are for 'locked' and 'unlocked', while values >2 are 2 more than the actual Relic Level.
crew.skills
- skill level to use for all crew members' abilities:
- "max" - Max possible level.
- "maxNoZeta" - Leaves zeta abilities at level 7, but uses max level for all others.
- Integer - Number, 1-8, to use for all abilities, if possible.
8 or higher is identical to "max".
Default - uses the values defined by the unit objects submitted.
This applies to each individual property of the useValues
object, not just the option as a whole.
percentVals: true
Converts internal flat values for Defense (Armor/Resistance) and Crit Chance (Special/Physical) to the percentages displayed in-game.
Uses the decimal form (i.e. 10% is returned as 0.1)
Default - return the flat values for above stats.
scaled: true
/ unscaled: true
Matches scaling status of values used internally to the game (as seen in portions of swgoh.help's /data
endpoint).\
scaled
- multiplies all values by 10,000. All non-modded stats should be integers at this scale.
unscaled
- multiplies all values by 100,000,000. All stats (including mods) fit as integers at this scale.
Default - Stats returned at the expected scale as seen in-game. Non-percent stats (like Speed) should be integers, all percent stats (like Potency) will be decimals
Default
The default Stats Object Style has the following properties:
base
all units - The base value of of the unit's stats without any stats from mods/gear/crew. For characters, these are the values used in mods with a percent bonus.gear
characters - Amount of stat granted by currently equipped gear (and unused within mod calculations).
mods
characters - Amount of stat granted by mods.
crew
ships - Amount of stat granted by crew rating.
gameStyle: true
Activates the percentVals
flag above, and also changes the Stats Object to have the following properties:
final
all units - Sums values from base, gear, mods, and/or crew into the total stat value.
gear
characters - Amount of stat granted by currently equipped gear (and unused within mod calculations).
mods
characters - Amount of stat granted by mods.
crew
ships - Amount of stat granted by crew rating.
language: {Object}
Tells the calculator to rename the stats using the submitted object.
Used mostly for localization.
Object must be such that options.language[ statID ]
is the stat name, i.e. {"1": "Health",...}
.
An example English localization can be seen here.
Note that a large enough array will also work, as can be seen here.
Note on language
keys: The object/array for options.language
does not need to be as complete as the above examples
(which cover all 60 possible stats in game code). Some statIDs that exist in game code are not used (such as id 59 - "UnitStat_Taunt"),
and even more are not returned by this API (such as id 57 - "Speed %" - which converted to the flat "Speed" value, id 5).
Any statIDs that are not in options.language
will remain indexed as that integer ID in the return object.
noSpace: true
Converts any stat name strings used in the language
option into standard camelCase with no spaces.
Only affects stat names defined in that parameter.
I.e. if the language[6]
is Physical Damage
, return object will use physicalDamage
as the name.
"Native" format -- swgoh.help's /player
Player profile object. Contains a .roster
property with an array of unit objects.
Full profile:
{
roster: [
{
defId: <String>,
rarity: <Integer>,
level: <Integer>,
gear: <Integer>,
equipped: [
{
equipmentId: <String>
},
... ],
skills: [ // skill list only required for crew members when calculating ship stats
{
tier: <Integer>,
id: <String> // id only needed for GP calculations
},
... ],
mods: [ // can be skipped if using `withoutModCalc` flag for characters only
{
pips: <Integer>,
set: <Integer>,
tier: <Integer>, // tier only needed for GP calculations
level: <Integer>,
primaryStat: {
unitStat: <Integer>,
value: <Number>
},
secondaryStat: [
{
unitStat: <Integer>,
value: <Number>
},
... ]
}
... ],
relic: {
currentTier: <Integer>
}
},
... ]
}
Used directly by .calcPlayerStats()
, which also accepts an array of these objects (and swgoh.help's /player
endpoint always returns an array)
player.roster
Used directly by .calcRosterStats()
Unit single element of player.roster
Used directly by .calcCharStats()
and .calcShipStats()
(for both the ship and the crew members).
"Units" format -- swgoh.help's /units
Object indexed by unit's base ID. Each such property is an array of unit objects.
Full Object:
{
<BaseID>: [
{
starLevel: <Integer>,
level: <Integer>,
gearLevel: <Integer>,
gear: [ <String>, ... ],
mods: [
{
set: <Integer>,
level: <Integer>,
stat: [
[ <Integer>, <Number> ],
... ]
}
... ]
},
... ],
<BaseID>: [ ... ],
... }
Only allowed by .calcRosterStats()
.
As skill info is not included in this format, ship stats cannot be processed.
Only characters will have their stats calculated.
Relic levels are not available in this format, so stats granted by relics will not be included.
Note: swgoh.help's /roster
endpoint is an array of these objects.
While that array is not directly accepted, each element in the array is a "Units" style object that is accepted as stated above.
Player profile object. Contains a .rosterUnit
property with an array of unit objects.
Full profile:
{
rosterUnit: [
{
definitionId: <String>,
currentRarity: <Integer>,
level: <Integer>,
currentTier: <Integer>,
equipment: [
{
equipmentId: <String>
},
... ],
skill: [ // skill list only required for crew members when calculating ship stats
{
tier: <Integer>,
id: <String> // id only needed for GP calculations
},
... ],
equippedStatMod: [ // can be skipped if using `withoutModCalc` flag for characters only
{
definitionId: <String>
level: <Integer>,
tier: <Integer>, // only needed for GP calculations
primaryStat: {
stat: {
unitStat: <Integer>,
unscaledDecimalValue: <Integer>
}
},
secondaryStat: [
{
stat: {
unitStatId: <Integer>,
unscaledDecimalValue: <Integer>
}
},
... ]
}
... ],
relic: {
currentTier: <Integer>
}
},
... ]
}
Used directly by .calcPlayerStats()
, which also accepts an array of these objects.
player.rosterUnit
Used directly by .calcRosterStats()
Unit single element of player.roster
Used directly by .calcCharStats()
and .calcShipStats()
(for both the ship and the crew members).
- Version 1.1.0
- Added support for a 'raw' format -- in line with the roster format sent directly by the game, not from swgoh.help.
- Exposed the endpoints for calculating GP so they can be called directly.
- Version 1.0.8
- A number of bug fixes
- Support for Relic stats (not available in .help's /units endpoint)
- Added GP calculations, available only with a
calcGP
flag using.calcRosterStats()
(and thus also.calcPlayerStats()
)
- Version 1.0.1
- 'Minor Text Fixes' to this README
- Version 1.0.0
- Initial Release