1 Commits
Author SHA1 Message Date
okvdai 586fa32b69 v1.2.1 (#19)
* Update README.md

* Add global K/D calculation

* Display current and latest version in terminal #18
2023-05-03 18:25:19 +02:00
24 changed files with 467 additions and 301 deletions
+6 -35
View File
@@ -1,6 +1,6 @@
# pulse
# Pulse
**pulse** is a clientside mod for [TF|2 + Northstar](https://github.com/R2Northstar/Northstar) letting you view killstats collected by [the Tone API](https://toneapi.github.io/ToneAPI_webclient/) using the otherwise non-functional `Stats` tab.
Pulse is a clientside mod for [TF|2 + Northstar](https://github.com/R2Northstar/Northstar) letting you view killstats collected by [the Tone API](https://toneapi.github.io/ToneAPI_webclient/) using the otherwise non-functional `Stats` tab.
## Currently, features include:
- mostly functional `Overview` tab,
@@ -21,7 +21,7 @@ Found a bug? Make an issue on GitHub [here.](https://github.com/ToneAPI/pulse/is
- Most Kills - shows the weapon with most accumulated kills.
- Nemesis Weapon - shows the weapon that has killed you the most.
- Most Effective - shows weapon with the highest K/D ratio.
- Kill/Death Ratio - shows the overall K/D ratio of player compared to global K/D.
- Kill/Death Ratio - shows the overall K/D ratio of player. (the two line graphs "Lifetime Avg." and "Lifetime Avg. vs. Players" don't work.)
- Kills as Pilot - shows general kill data for player as Pilot, visualised in the table below:
| Name | Description |
@@ -31,7 +31,7 @@ Found a bug? Make an issue on GitHub [here.](https://github.com/ToneAPI/pulse/is
| AI kills |Non-functional, Tone API does not collect AI kill data.|
| Pilot melee kills |Shows only melee kills accumulated by player as Pilot.|
| Pilot executions |Shows only executions accumulated by player as Pilot.|
- Kills as Titan - shows general kill data for player as Titan, visualised in the table below:
| Name | Description |
@@ -73,37 +73,8 @@ Found a bug? Make an issue on GitHub [here.](https://github.com/ToneAPI/pulse/is
- Kills by Gamemode - piechart showing all kills (in percent) on chosen map by gamemode.
</details>
## DISCLAIMERS
## DISCLAIMER
The Tone API is NOT used by every server, view a list of supported servers [here.](https://tone.sleepycat.date/v2/client/servers)
**pulse** is very much a W.I.P as of right now, features may be missing/nonfunctional.
As of v2.1.0, **pulse** requires [loeb](https://github.com/okvdai/loeb)
## CHANGELOG
<details>
<summary> pulse v2.0.0 "Demeter" </summary>
- Switched to Thunderstore template on the GitHub site for easier development.
- General code rewrite - lots of improvements for easier development. Rewrite includes:
- common code file, for better code readability and ease of development,
- new parser, allowing for better expandability and faster data processing (and much simpler implementation, unlike the hellspawn that was the previous `getFromToneAPI` function),
- new request function, more compact and simple than previous iterations,
- other functions that simplify the code and make it easier to read / develop
- Localisation, currently available in:
- English,
- French,
- German,
- Italian,
- Polish. (Northstar isn't translated into Polish, but the game supports it.)
- Locking the Stats tab, avoiding situations where you could click too fast and see no stats. Also prevents the game from showing stats when the API is unreachable.
</details>
<details>
<summary> pulse v2.1.0 </summary>
- Changed endpoint
- Lots of bug fixes
- Uses new experimental loeb library
</details>
Pulse is very much a W.I.P as of right now, features may be missing/nonfunctional.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

-7
View File
@@ -1,7 +0,0 @@
{
"name": "Pulse",
"description": "Adds stats (collected by the Tone API) back to the Stats tab.",
"version_number": "2.1.1",
"website_url": "https://github.com/ToneAPI/pulse",
"dependencies": ["Okudai-loeb-1.0.1"]
}
+37
View File
@@ -0,0 +1,37 @@
{
"Name": "ToneAPI.pulse",
"Description": "Displays Tone API kill data in the Stats tab.",
"Version": "1.2.1",
"LoadPriority": 1,
"ConVars": [
{
"Name": "ToneURL",
"DefaultValue": "https://tone.sleepycat.date/v2/client"
},
{
"Name": "VersionURL",
"DefaultValue": "https://raw.githubusercontent.com/ToneAPI/pulse/main/version.json"
},
{
"Name": "MajorVersion",
"DefaultValue": "1"
},
{
"Name": "MinorVersion",
"DefaultValue": "2"
},
{
"Name": "PatchVersion",
"DefaultValue": "1"
}
],
"Scripts": [
{
"Path": "pulse.gnut",
"RunOn": "UI",
"UICallback": {
"After": "pulseInit"
}
}
]
}
@@ -532,7 +532,7 @@ resource/ui/menus/viewstats_pve.menu
visible 1
font Default_23
labelText "--"
allcaps 0
allcaps 1
textAlignment center
fgcolor_override "255 255 255 255"
//bgcolor_override "0 255 0 100"
@@ -323,7 +323,7 @@ resource/ui/menus/viewstats_overview.menu
tall 45
visible 1
font Default_31
labelText "#NEMESIS_WEAPON"
labelText "NEMESIS WEAPON"
allcaps 1
wrap 1
textAlignment west
@@ -345,7 +345,7 @@ resource/ui/menus/viewstats_weapons.menu
tall 36
visible 1
font Default_23
labelText "#DEATHS_WHILE_EQUIPPED"
labelText "DEATHS WITH WEAPON"
allcaps 1
textAlignment west
fgcolor_override "255 255 255 255"
+267
View File
@@ -0,0 +1,267 @@
global function pulseInit
global function GetWeaponStatsFromToneAPI
global function GetGlobalDataFromToneAPI
global function GetMapStatsFromToneAPI
global function GetGamemodeStatsFromToneAPI
global function getWeaponKillsFromToneAPI
global function getNemesisWeaponFromToneAPI
global function getDWEFromToneAPI
global function getMapKillFromToneAPI
global function getMapDeathFromToneAPI
global function getMapDistFromToneAPI
global function getMapMDistFromToneAPI
global function fetchGamemodeStatsFromToneAPI
global table globalToneAPIKillData = {}
global table globalToneAPIDeathData = {}
global table globalToneAPIDWEData = {}
global table globalToneAPIMapDeathData = {}
global table globalToneAPIMapDistData = {}
global table globalToneAPIMapKillData = {}
global table globalToneAPIMapMDistData = {}
global table globalToneAPIGamemodeData = {}
global table globalToneAPIAllPlayerKillData = {}
global table globalToneAPIAllPlayerDeathData = {}
global table< table > globalToneAPIGamemodeMapData = {}
string prefix = "default"
string HTTPrequestURL = "default"
string currentVersion = "default"
int weaponEntries = 0
int mapEntries = 0
int gamemodeEntries = 0
int mapGamemodeEntries = 0
void function pulseInit()
{
prefix = "\x1b[38;2;255;178;102m[PULSE]\x1b[0m "
HTTPrequestURL = GetConVarString("ToneURL")
currentVersion = "v" + GetConVarString("MajorVersion") + "." + GetConVarString("MinorVersion") + "." + GetConVarString("PatchVersion")
HttpRequest getVersion
getVersion.method = HttpRequestMethod.GET
getVersion.url = GetConVarString("VersionURL")
void functionref(HttpRequestResponse) onSuccess = void function(HttpRequestResponse response)
{
table JSONDecoded = DecodeJSON(response.body)
if (JSONDecoded["Major"] == GetConVarString("MajorVersion") && JSONDecoded["Minor"] == GetConVarString("MinorVersion") && JSONDecoded["Patch"] == GetConVarString("PatchVersion")) {
print(prefix + currentVersion + " has been loaded and is up to date.")
} else {
print(prefix + currentVersion + " has been loaded. Recommend updating to latest version: v" + JSONDecoded["Major"] + "." + JSONDecoded["Minor"] + "." + JSONDecoded["Patch"] + ".")
}
}
void functionref(HttpRequestFailure) onFailure = void function(HttpRequestFailure failure)
{
print(prefix + currentVersion + " has been loaded and has encountered an error getting latest version data.")
}
NSHttpRequest(getVersion, onSuccess, onFailure)
}
void function GetWeaponStatsFromToneAPI()
{
print(prefix + "Getting kill data...")
weaponEntries = 0
HttpRequest getWeaponStats
getWeaponStats.method = HttpRequestMethod.GET
getWeaponStats.url = HTTPrequestURL + "/weapons"
getWeaponStats.queryParameters["player"] <- [NSGetLocalPlayerUID()]
void functionref(HttpRequestResponse) onSuccess = void function(HttpRequestResponse response)
{
print(prefix + "Kill data received, processing...")
table JSONForConversion = DecodeJSON(response.body)
foreach (var key, var value in JSONForConversion) {
table test = expect table(value)
globalToneAPIKillData[string(key)] <- test.kills
globalToneAPIDeathData[string(key)] <- test.deaths
globalToneAPIDWEData[string(key)] <- test.deaths_while_equipped
weaponEntries += 1
}
print(prefix + "Kill data has been processed with a total of " + string(weaponEntries) + " entries.")
}
void functionref(HttpRequestFailure) onFailure = void function(HttpRequestFailure failure)
{
print(prefix + "Encountered an error getting kill data...")
}
NSHttpRequest(getWeaponStats, onSuccess, onFailure)
}
void function GetGlobalDataFromToneAPI()
{
print(prefix + "Getting global data...")
weaponEntries = 0
HttpRequest getGlobalStats
getGlobalStats.method = HttpRequestMethod.GET
getGlobalStats.url = HTTPrequestURL + "/weapons"
getGlobalStats.queryParameters["player"] <- ["!" + NSGetLocalPlayerUID()]
void functionref(HttpRequestResponse) onSuccess = void function(HttpRequestResponse response)
{
print(prefix + "Global data received, processing...")
table JSONForConversion = DecodeJSON(response.body)
foreach (var key, var value in JSONForConversion) {
table test = expect table(value)
globalToneAPIAllPlayerKillData[string(key)] <- test.kills
globalToneAPIAllPlayerDeathData[string(key)] <- test.deaths
weaponEntries += 1
}
print(prefix + "Global data has been processed with a total of " + string(weaponEntries) + " entries.")
}
void functionref(HttpRequestFailure) onFailure = void function(HttpRequestFailure failure)
{
print(prefix + "Encountered an error getting global data...")
}
NSHttpRequest(getGlobalStats, onSuccess, onFailure)
}
void function GetMapStatsFromToneAPI()
{
print(prefix + "Getting map data...")
mapEntries = 0
HttpRequest getMapStats
getMapStats.method = HttpRequestMethod.GET
getMapStats.url = HTTPrequestURL + "/maps"
getMapStats.queryParameters["player"] <- [NSGetLocalPlayerUID()]
void functionref(HttpRequestResponse) onSuccess = void function(HttpRequestResponse response)
{
print(prefix + "Map data received, processing...")
table JSONForConversion = DecodeJSON(response.body)
foreach (var key, var value in JSONForConversion) {
table test = expect table(value)
globalToneAPIMapKillData[string(key)] <- test.kills
globalToneAPIMapDeathData[string(key)] <- test.deaths
globalToneAPIMapDistData[string(key)] <- test.total_distance
globalToneAPIMapMDistData[string(key)] <- test.max_distance
mapEntries += 1
}
print(prefix + "Map data has been processed with a total of " + string(mapEntries) + " entries.")
}
void functionref(HttpRequestFailure) onFailure = void function(HttpRequestFailure failure)
{
print(prefix + "Encountered an error getting map data...")
}
NSHttpRequest(getMapStats, onSuccess, onFailure)
}
void function GetGamemodeStatsFromToneAPI()
{
print(prefix + "Getting gamemode data...")
gamemodeEntries = 0
HttpRequest getGamemodeStats
getGamemodeStats.method = HttpRequestMethod.GET
getGamemodeStats.url = HTTPrequestURL + "/gamemodes"
getGamemodeStats.queryParameters["player"] <- [NSGetLocalPlayerUID()]
void functionref(HttpRequestResponse) onSuccess = void function(HttpRequestResponse response)
{
print(prefix + "Gamemode data received, processing...")
table JSONForConversion = DecodeJSON(response.body)
foreach (var key, var value in JSONForConversion) {
table test = expect table(value)
globalToneAPIGamemodeData[string(key)] <- test.kills
gamemodeEntries += 1
}
print(prefix + "Gamemode data has been processed with a total of " + string(gamemodeEntries) + " entries.")
}
void functionref(HttpRequestFailure) onFailure = void function(HttpRequestFailure failure)
{
print(prefix + "Encountered an error getting gamemode data...")
}
NSHttpRequest(getGamemodeStats, onSuccess, onFailure)
}
void function fetchGamemodeStatsFromToneAPI(string mapName)
{
mapGamemodeEntries = 0
string mapNameSliced = mapName.slice(3)
HttpRequest getMapGamemodeStats
getMapGamemodeStats.method = HttpRequestMethod.GET
getMapGamemodeStats.url = HTTPrequestURL + "/gamemodes"
getMapGamemodeStats.queryParameters["map"] <- [mapNameSliced]
getMapGamemodeStats.queryParameters["player"] <- [NSGetLocalPlayerUID()]
void functionref(HttpRequestResponse) onSuccess = void function(HttpRequestResponse response):(mapName)
{
table JSONForConversion = DecodeJSON(response.body)
table mapData = {}
foreach (var gamemode, var value in JSONForConversion) {
table test = expect table(value)
mapData[string(gamemode)] <- test.kills
mapGamemodeEntries += 1
}
globalToneAPIGamemodeMapData[mapName] <- mapData
print(prefix + "Map gamemode data has been processed with a total of " + string(mapGamemodeEntries) + " entries.")
}
void functionref(HttpRequestFailure) onFailure = void function(HttpRequestFailure failure)
{
print(prefix + "Encountered an error getting map gamemode data...")
}
NSHttpRequest(getMapGamemodeStats, onSuccess, onFailure)
}
int function getWeaponKillsFromToneAPI(string weaponRef){
if(weaponRef in globalToneAPIKillData){
return expect int(globalToneAPIKillData[weaponRef])
}
return 0
}
int function getNemesisWeaponFromToneAPI(string weaponRef){
if(weaponRef in globalToneAPIDeathData){
return expect int(globalToneAPIDeathData[weaponRef])
}
return 0
}
int function getDWEFromToneAPI(string weaponRef){
if(weaponRef in globalToneAPIDWEData){
return expect int(globalToneAPIDWEData[weaponRef])
}
return 0
}
int function getMapKillFromToneAPI(string mapName){
mapName = mapName.slice(3)
if(mapName in globalToneAPIMapKillData){
return expect int(globalToneAPIMapKillData[mapName])
}
return 0
}
int function getMapDeathFromToneAPI(string mapName){
mapName = mapName.slice(3)
if(mapName in globalToneAPIMapDeathData){
return expect int(globalToneAPIMapDeathData[mapName])
}
return 0
}
int function getMapMDistFromToneAPI(string mapName){
mapName = mapName.slice(3)
if(mapName in globalToneAPIMapMDistData){
return expect int(globalToneAPIMapMDistData[mapName])
}
return 0
}
int function getMapDistFromToneAPI(string mapName){
mapName = mapName.slice(3)
if(mapName in globalToneAPIMapDistData){
return expect int(globalToneAPIMapDistData[mapName])
}
return 0
}
+56
View File
@@ -0,0 +1,56 @@
global function InitViewStatsMenu
struct{
array<string> allMaps
} file
void function InitViewStatsMenu()
{
var menu = GetMenu( "ViewStatsMenu" )
AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnViewStats_Open )
var button = Hud_GetChild( menu, "BtnOverview" )
SetButtonRuiText( button, Localize( "#STATS_OVERVIEW" ) )
AddButtonEventHandler( button, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ViewStats_Overview_Menu" ) ) )
button = Hud_GetChild( menu, "BtnTime" )
SetButtonRuiText( button, Localize( "#STATS_TIME" ) )
AddButtonEventHandler( button, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ViewStats_Time_Menu" ) ) )
button = Hud_GetChild( menu, "BtnPilotWeapons" )
SetButtonRuiText( button, Localize( "#STATS_PILOT_WEAPONS" ) )
AddButtonEventHandler( button, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ViewStats_Weapons_Menu" ) ) )
button = Hud_GetChild( menu, "BtnTitans" )
SetButtonRuiText( button, Localize( "#STATS_TITANS" ) )
AddButtonEventHandler( button, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ViewStats_Titans_Menu" ) ) )
button = Hud_GetChild( menu, "BtnMaps" )
SetButtonRuiText( button, Localize( "#STATS_MAPS" ) )
AddButtonEventHandler( button, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ViewStats_Maps_Menu" ) ) )
button = Hud_GetChild( menu, "BtnMisc" )
SetButtonRuiText( button, Localize( "#STATS_MISC" ) )
AddButtonEventHandler( button, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ViewStats_Misc_Menu" ) ) )
AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" )
AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
}
void function OnViewStats_Open()
{
foreach(elemNum in file.allMaps){
string mapName = expect string(file.allMaps[ elemNum ])
fetchGamemodeStatsFromToneAPI(mapName)
}
GetWeaponStatsFromToneAPI()
GetGlobalDataFromToneAPI()
GetMapStatsFromToneAPI()
GetGamemodeStatsFromToneAPI()
UI_SetPresentationType( ePresentationType.DEFAULT )
//UpdateViewStatsKillsMenu()
//UpdateViewStatsDistanceMenu()
}
@@ -140,6 +140,8 @@ void function UpdateStatsForMap( string mapName )
Hud_SetText( Hud_GetChild( file.menu, "WeaponName" ), GetMapDisplayName( mapName ) )
fetchGamemodeStatsFromToneAPI(mapName)
// Image
var imageElem = Hud_GetRui( Hud_GetChild( file.menu, "WeaponImageLarge" ) )
RuiSetImage( imageElem, "basicImage", GetMapImageForMapName( mapName ) )
@@ -152,20 +154,20 @@ void function UpdateStatsForMap( string mapName )
//SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat2" ), Localize( "#STATS_GAMES_PLAYED" ), gamesPlayed )
//SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat3" ), Localize( "#STATS_GAMES_PLAYED" ), gamesPlayed )
SetStatsLabelValue( file.menu, "KillsLabel0", Localize("#MAPS_KILLS") )
SetStatsLabelValue( file.menu, "KillsValue0", pulseParse("maps", mapName.slice(3), "kills") )
SetStatsLabelValue( file.menu, "KillsLabel0", "KILLS ON MAP" )
SetStatsLabelValue( file.menu, "KillsValue0", getMapKillFromToneAPI(mapName) )
SetStatsLabelValue( file.menu, "KillsLabel1", Localize("#MAPS_DEATHS") )
SetStatsLabelValue( file.menu, "KillsValue1", pulseParse("maps", mapName.slice(3), "deaths") )
SetStatsLabelValue( file.menu, "KillsLabel1", "DEATHS ON MAP" )
SetStatsLabelValue( file.menu, "KillsValue1", getMapDeathFromToneAPI(mapName) )
SetStatsLabelValue( file.menu, "KillsLabel2", Localize("#MAPS_TSD") )
SetStatsLabelValue( file.menu, "KillsValue2", HammerToMeterString(float(pulseParse("maps", mapName.slice(3), "total_distance"))))
SetStatsLabelValue( file.menu, "KillsLabel2", "TOTAL SHOT DISTANCE" )
SetStatsLabelValue( file.menu, "KillsValue2", string(int((1.905 * float(getMapDistFromToneAPI(mapName) ) ) )/100) + "m" )
SetStatsLabelValue( file.menu, "KillsLabel3", Localize("#MAPS_MSD") )
SetStatsLabelValue( file.menu, "KillsValue3", HammerToMeterString(float(pulseParse("maps", mapName.slice(3), "max_distance"))))
SetStatsLabelValue( file.menu, "KillsLabel3", "MAXIMUM SHOT DISTANCE" )
SetStatsLabelValue( file.menu, "KillsValue3", string(int((1.905 * float(getMapMDistFromToneAPI(mapName) ) ) )/100) + "m" )
SetStatsLabelValue( file.menu, "KillsLabel4", Localize("#MAPS_ASD") )
SetStatsLabelValue( file.menu, "KillsValue4", HammerToMeterString(float(pulseParse("maps", mapName.slice(3), "max_distance")) / float(pulseParse("maps", mapName.slice(3), "kills"))))
SetStatsLabelValue( file.menu, "KillsLabel4", "--" )
SetStatsLabelValue( file.menu, "KillsValue4", "--" )
//var anchorElem = Hud_GetChild( file.menu, "WeaponStatsBackground" )
//printt( Hud_GetX( anchorElem ) )
@@ -183,18 +185,13 @@ void function UpdateStatsForMap( string mapName )
fw = [147, 204, 57, 255],
gg = [14, 87, 132, 255]
}
table< string, string > customGamemodeNames = {
sns = Localize("#GAMEMODE_sns")
fw = Localize("#GAMEMODE_fw")
gg = Localize("#GAMEMODE_gg")
}
for ( int modeId = 0; modeId < enumCount; modeId++ )
{
string modeName = PersistenceGetEnumItemNameForIndex( "gameModes", modeId )
if (mapName.slice(3) in pulseData["gamemodesSeparated"])
if ( mapName in globalToneAPIGamemodeMapData && modeName in globalToneAPIGamemodeMapData[mapName] )
{
float modePlayedTime = 0
modePlayedTime = float(pulseParse("gamemodesSeparated", mapName.slice(3), modeName, "kills"))
modePlayedTime = float(globalToneAPIGamemodeMapData[mapName][modeName])
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, GameMode_GetName( modeName ), modePlayedTime, GetGameModeDisplayColor( modeName ) )
}
@@ -202,12 +199,12 @@ void function UpdateStatsForMap( string mapName )
}
foreach (string key, array<int> value in customGamemodeList)
{
if (mapName.slice(3) in pulseData["gamemodesSeparated"])
if ( mapName in globalToneAPIGamemodeMapData && key in globalToneAPIGamemodeMapData[mapName])
{
float modePlayedTime = 0
modePlayedTime = float(pulseParse("gamemodesSeparated", mapName.slice(3), key, "kills"))
modePlayedTime = float(globalToneAPIGamemodeMapData[mapName][key])
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, customGamemodeNames[key], modePlayedTime, value)
AddPieChartEntry( modes, key, modePlayedTime, value)
}
}
}
@@ -231,7 +228,7 @@ void function UpdateStatsForMap( string mapName )
PieChartData modesPlayedData
modesPlayedData.entries = modes
modesPlayedData.labelColor = [ 255, 255, 255, 255 ]
SetPieChartData( file.menu, "ModesPieChart", "#KILLS_GAMEMODE", modesPlayedData )
SetPieChartData( file.menu, "ModesPieChart", "KILLS BY GAMEMODE", modesPlayedData )
array<string> fdMaps = GetPlaylistMaps( "fd" )
@@ -6,13 +6,11 @@ struct
{
var menu
array<ItemDisplayData> allTitans
array<ItemDisplayData> allPilotWeapons
table<string, array<string> > titanStatLoadout
} file
const MAX_DOTS_ON_GRAPH = 10
table <string, int> titanKillData = {}
table <string, int> pilotKillData = {}
const IMAGE_TITAN_STRYDER = $"ui/menu/personal_stats/ps_titan_icon_stryder"
const IMAGE_TITAN_ATLAS = $"ui/menu/personal_stats/ps_titan_icon_atlas"
@@ -32,11 +30,11 @@ void function InitViewStatsOverviewMenu()
AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
}
void function GetTitanKills()
void function GetTitanKills( string titanName )
{
file.allTitans = GetVisibleItemsOfType( eItemTypes.TITAN )
var dataTable = GetDataTable( $"datatable/titan_properties.rpak" )
foreach ( titan in file.allTitans )
{
file.titanStatLoadout[ titan.ref ] <- []
@@ -50,28 +48,24 @@ void function GetTitanKills()
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "melee" ) ) )
}
foreach ( titan in file.allTitans)
foreach ( weaponRef in file.titanStatLoadout[ titanName ])
{
foreach ( weaponRef in file.titanStatLoadout[ titan.ref ])
{
titanKillData[weaponRef] <- pulseParse("weaponsLocal", weaponRef, "kills")
}
titanKillData[weaponRef] <- getWeaponKillsFromToneAPI(weaponRef)
}
}
void function GetAllPilotWeapons()
{
file.allPilotWeapons = GetVisibleItemsOfType( eItemTypes.PILOT_PRIMARY)
file.allPilotWeapons.extend(GetVisibleItemsOfType( eItemTypes.PILOT_SECONDARY) )
file.allPilotWeapons.extend(GetVisibleItemsOfType( eItemTypes.PILOT_ORDNANCE) )
file.allPilotWeapons.extend( GetVisibleItemsOfType( eItemTypes.PILOT_SPECIAL ) )
}
void function OnStatsOverview_Open()
{
UI_SetPresentationType( ePresentationType.NO_MODELS )
GetTitanKills()
GetTitanKills("ion")
GetTitanKills("scorch")
GetTitanKills("northstar")
GetTitanKills("ronin")
GetTitanKills("tone")
GetTitanKills("legion")
GetTitanKills("vanguard")
UpdateViewStatsOverviewMenu()
}
@@ -213,7 +207,7 @@ function UpdateViewStatsOverviewMenu()
Hud_Show( weaponImageElem )
Hud_SetText( weaponNameElem, nemesisWeapon.printName )
Hud_Show( weaponNameElem )
Hud_SetText( weaponDescElem, Localize("#NEMESIS_WEAPON_VALUE"), nemesisWeapon.val)
Hud_SetText( weaponDescElem, nemesisWeapon.val + " DEATHS BY WEAPON" )
Hud_Show( weaponDescElem )
Hud_Hide( noDataElem )
}
@@ -238,7 +232,7 @@ function UpdateViewStatsOverviewMenu()
Hud_Show( weaponImageElem )
Hud_SetText( weaponNameElem, highestKPMData.printName )
Hud_Show( weaponNameElem )
Hud_SetText( weaponDescElem, "%s1 K/D", highestKPMData.val)
Hud_SetText( weaponDescElem, highestKPMData.val + " K/D")
Hud_Show( weaponDescElem )
Hud_Hide( noDataElem )
}
@@ -294,34 +288,42 @@ function UpdateViewStatsOverviewMenu()
//#########################
// Lifetime
table playerweaponData = expect table(pulseData["weaponsLocal"])
table globalweaponData = expect table(pulseData["weaponsGlobal"])
var totalPilotKills = 0
var totalPilotDeaths = 0
foreach (var key, var value in playerweaponData) {
table values = expect table(value)
totalPilotKills += values["kills"]
totalPilotDeaths += values["deaths"]
foreach (var key, var value in globalToneAPIKillData) {
totalPilotKills += value
}
var totalGlobalKills = 0
var totalGlobalDeaths = 0
foreach (var key, var value in globalweaponData) {
table values = expect table(value)
totalGlobalKills += values["kills"]
totalGlobalDeaths += values["deaths"]
foreach (var key, var value in globalToneAPIAllPlayerKillData) {
totalGlobalKills += value
}
var totalGlobalDeaths = 0
foreach (var key, var value in globalToneAPIAllPlayerDeathData) {
totalGlobalDeaths += value
}
var totalPilotDeaths = 0
foreach (var key, var value in globalToneAPIDeathData) {
totalPilotDeaths += value
}
var killsAsPilot = 0
foreach (var key, var value in globalToneAPIKillData) {
if (key in titanKillData) {
continue
} else {
killsAsPilot += getWeaponKillsFromToneAPI(string(key))
}
}
var killsAsTitan = 0
var killsAsPilot = 0
foreach (var key, var value in playerweaponData) {
foreach (var key, var value in globalToneAPIKillData) {
if (key in titanKillData) {
killsAsTitan += titanKillData[string(key)]
} else {
killsAsPilot += pulseParse("weaponsLocal", string(key), "kills")
}
}
@@ -389,27 +391,27 @@ function UpdateViewStatsOverviewMenu()
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue0" ), string( killsAsPilot ) )
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue1" ), string( GetPlayerStatInt( player, "kills_stats", "titanKillsAsPilot" ) ) )
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue2" ), string( GetPlayerStatInt( player, "kills_stats", "totalNPC" ) ) )
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue3" ), string( pulseParse("weaponsLocal", "pilot_emptyhanded", "kills") + pulseParse("weaponsLocal", "melee_pilot_kunai", "kills") ) )
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue4" ), string( pulseParse("weaponsLocal", "human_execution", "kills") ) )
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue3" ), string( getWeaponKillsFromToneAPI("pilot_emptyhanded") ) )
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue4" ), string( getWeaponKillsFromToneAPI("human_execution") ) )
// Hud_SetText( GetElem( file.menu, "KillsAsPilotValue5" ), string( GetPlayerStatInt( player, "kills_stats", "titanFallKill" ) ) )
var titanMeleeKills = 0
titanMeleeKills += pulseParse("weaponsLocal", "titan_punch_ion", "kills")
titanMeleeKills += pulseParse("weaponsLocal", "titan_punch_scorch", "kills")
titanMeleeKills += pulseParse("weaponsLocal", "titan_punch_northstar", "kills")
titanMeleeKills += pulseParse("weaponsLocal", "titan_sword", "kills")
titanMeleeKills += pulseParse("weaponsLocal", "titan_punch_tone", "kills")
titanMeleeKills += pulseParse("weaponsLocal", "titan_punch_legion", "kills")
titanMeleeKills += pulseParse("weaponsLocal", "titan_punch_vanguard", "kills")
titanMeleeKills += pulseParse("weaponsLocal", "auto_titan_melee", "kills")
titanMeleeKills += getWeaponKillsFromToneAPI("titan_punch_ion")
titanMeleeKills += getWeaponKillsFromToneAPI("titan_punch_scorch")
titanMeleeKills += getWeaponKillsFromToneAPI("titan_punch_northstar")
titanMeleeKills += getWeaponKillsFromToneAPI("titan_sword")
titanMeleeKills += getWeaponKillsFromToneAPI("titan_punch_tone")
titanMeleeKills += getWeaponKillsFromToneAPI("titan_punch_legion")
titanMeleeKills += getWeaponKillsFromToneAPI("titan_punch_vanguard")
titanMeleeKills += getWeaponKillsFromToneAPI("auto_titan_melee")
var titanExecutions = pulseParse("weaponsLocal", "titan_execution", "kills")
var titanExecutions = getWeaponKillsFromToneAPI("titan_execution")
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue0" ), string( killsAsTitan ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue1" ), string( GetPlayerStatInt( player, "kills_stats", "titanKillsAsTitan" ) ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue2" ), string( titanExecutions ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue3" ), string( titanMeleeKills ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue4" ), string( pulseParse("weaponsLocal", "damagedef_titan_step", "kills") ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue4" ), string( getWeaponKillsFromToneAPI("damagedef_titan_step") ) )
}
function PlotKDPointsOnGraph( menu, graphIndex, values, dottedAverage )
@@ -49,7 +49,7 @@ float function GetTitanKills( string titanName)
float weaponKills = 0
foreach ( weaponRef in file.titanStatLoadout[ titanName ])
{
weaponKills += float(pulseParse("weaponsLocal", weaponRef, "kills"))
weaponKills += float(getWeaponKillsFromToneAPI(weaponRef))
}
return weaponKills
}
@@ -79,13 +79,11 @@ void function UpdateViewStatsTimeMenu()
//#########################################
// Time By Class Pie Chart
//#########################################
var totalPilotKills = 0
table playerweaponData = expect table(pulseData["weaponsLocal"])
foreach (var key, var value in playerweaponData) {
table values = expect table(value)
totalPilotKills += values["kills"]
foreach (var key, var value in globalToneAPIKillData) {
totalPilotKills += value
}
float hoursAsPilot = float(totalPilotKills)
float hoursAsTitan = killsAsTitan
@@ -103,7 +101,7 @@ void function UpdateViewStatsTimeMenu()
PieChartData classTimeData
classTimeData.entries = classes
classTimeData.labelColor = [ 255, 255, 255, 255 ]
SetPieChartData( file.menu, "ClassPieChart", Localize("#TIME_KILLS_CLASS"), classTimeData )
SetPieChartData( file.menu, "ClassPieChart", "KILLS BY CLASS", classTimeData )
//#########################################
// Time By Chassis Pie Chart
@@ -137,7 +135,7 @@ void function UpdateViewStatsTimeMenu()
PieChartData chassisTimeData
chassisTimeData.entries = titans
chassisTimeData.labelColor = [ 255, 255, 255, 255 ]
SetPieChartData( file.menu, "ChassisPieChart", Localize("#TIME_KILLS_TITAN"), chassisTimeData )
SetPieChartData( file.menu, "ChassisPieChart", "KILLS BY TITAN", chassisTimeData )
//#########################################
// Time By Mode Pie Chart
@@ -152,18 +150,13 @@ void function UpdateViewStatsTimeMenu()
fw = [147, 204, 57, 255],
gg = [14, 87, 132, 255]
}
table< string, string > customGamemodeNames = {
sns = Localize("#GAMEMODE_sns")
fw = Localize("#GAMEMODE_fw")
gg = Localize("#GAMEMODE_gg")
}
for ( int modeId = 0; modeId < enumCount; modeId++ )
{
string modeName = PersistenceGetEnumItemNameForIndex( "gameModes", modeId )
if ( pulseParse("gamemodesAll", modeName, "kills") != 0 )
if ( modeName in globalToneAPIGamemodeData )
{
float modePlayedTime = 0
modePlayedTime = float(pulseParse("gamemodesAll", modeName, "kills"))
modePlayedTime = float(globalToneAPIGamemodeData[modeName])
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, GameMode_GetName( modeName ), modePlayedTime, GetGameModeDisplayColor( modeName ) )
}
@@ -171,12 +164,12 @@ void function UpdateViewStatsTimeMenu()
}
foreach (string key, array<int> value in customGamemodeList)
{
if ( pulseParse("gamemodesAll", key, "kills") != 0 )
if ( key in globalToneAPIGamemodeData)
{
float modePlayedTime = 0
modePlayedTime = float(pulseParse("gamemodesAll", key, "kills"))
modePlayedTime = float(globalToneAPIGamemodeData[key])
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, customGamemodeNames[key], modePlayedTime, value)
AddPieChartEntry( modes, key, modePlayedTime, value)
}
}
}
@@ -184,7 +177,7 @@ void function UpdateViewStatsTimeMenu()
PieChartData modesPlayedData
modesPlayedData.entries = modes
modesPlayedData.labelColor = [ 255, 255, 255, 255 ]
SetPieChartData( file.menu, "ModesPieChart", Localize("#KILLS_GAMEMODE"), modesPlayedData )
SetPieChartData( file.menu, "ModesPieChart", "KILLS BY GAMEMODE", modesPlayedData )
//#########################################
// Time Stats
@@ -175,7 +175,7 @@ void function UpdateStatsForTitan( string titanRef, int loadoutIndex )
int aiKills
foreach ( weaponRef in file.titanStatLoadout[ titanRef ] )
{
totalKills += pulseParse("weaponsLocal", weaponRef, "kills")
totalKills += getWeaponKillsFromToneAPI(weaponRef)
pilotKills += GetPlayerStatInt( player, "weapon_kill_stats", "pilots", weaponRef )
titanKills += GetPlayerStatInt( player, "weapon_kill_stats", "titansTotal", weaponRef )
aiKills += GetPlayerStatInt( player, "weapon_kill_stats", "ai", weaponRef )
@@ -338,7 +338,7 @@ table<string, table> function GetOverviewWeaponData()
if ( !PersistenceEnumValueIsValid( "loadoutWeaponsAndAbilities", weaponName ) )
continue
int val = pulseParse("weaponsLocal", weaponName, "kills")
int val = getWeaponKillsFromToneAPI(weaponName)
if ( val > Table[ "most_kills" ].val )
{
Table[ "most_kills" ].ref = weaponName
@@ -346,7 +346,7 @@ table<string, table> function GetOverviewWeaponData()
Table[ "most_kills" ].val = val
}
int nval = pulseParse("weaponsLocal", weaponName, "deaths")
int nval = getNemesisWeaponFromToneAPI(weaponName)
if ( nval > Table[ "nemesis_weapon" ].val )
{
Table[ "nemesis_weapon" ].ref = weaponName
@@ -357,9 +357,9 @@ table<string, table> function GetOverviewWeaponData()
float kdval = 0
float kval = 0
float dval = 0
if( pulseParse("weaponsLocal", weaponName, "kills") != 0 && pulseParse("weaponsLocal", weaponName, "deaths_while_equipped") != 0){
kval = float(pulseParse("weaponsLocal", weaponName, "kills"))
dval = float(pulseParse("weaponsLocal", weaponName, "deaths_while_equipped"))
if( getWeaponKillsFromToneAPI(weaponName) != 0 && getDWEFromToneAPI(weaponName) != 0){
kval = float(getWeaponKillsFromToneAPI(weaponName))
dval = float(getDWEFromToneAPI(weaponName))
if (kval / dval > kdval){
kdval = kval / dval
}
@@ -180,8 +180,8 @@ void function UpdateStatsForWeapon( string weaponRef )
}
// Total Kills Stats
SetStatsLabelValue( file.menu, "KillsValue0", pulseParse("weaponsLocal", weaponRef, "kills") ) //Total kills
SetStatsLabelValue( file.menu, "KillsValue1", pulseParse("weaponsLocal", weaponRef, "kills") ) //Pilots
SetStatsLabelValue( file.menu, "KillsValue2", GetPlayerStatInt( player, "weapon_kill_stats", "titansTotal", weaponRef ) ) //Titans
SetStatsLabelValue( file.menu, "KillsValue3", pulseParse("weaponsLocal", weaponRef, "deaths_while_equipped")) // Deaths with weapon
SetStatsLabelValue( file.menu, "KillsValue0", getWeaponKillsFromToneAPI(weaponRef) )
SetStatsLabelValue( file.menu, "KillsValue1", getWeaponKillsFromToneAPI(weaponRef) )
SetStatsLabelValue( file.menu, "KillsValue2", GetPlayerStatInt( player, "weapon_kill_stats", "titansTotal", weaponRef ) )
SetStatsLabelValue( file.menu, "KillsValue3", getDWEFromToneAPI(weaponRef))
}
-28
View File
@@ -1,28 +0,0 @@
{
"Name": "ToneAPI.pulse",
"Description": "Displays Tone API kill data in the Stats tab.",
"Version": "2.1.1",
"LoadPriority": 1,
"ConVars": [
{
"Name": "ToneURL",
"DefaultValue": "https://toneapi.ovh/v2/client"
}
],
"Scripts": [
{
"Path":"pulse-common-func.gnut",
"RunOn":"UI"
},
{
"Path": "pulse.gnut",
"RunOn": "UI",
"UICallback": {
"After": "pulseInit"
}
}
],
"Localisation": [
"resource/pulse_%language%.txt"
]
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,95 +0,0 @@
globalize_all_functions
global enum ePulseDataType
{
WEAPON,
MAP,
GAMEMODE,
}
global struct pulseDataStruct
{
ePulseDataType dataType,
string dataName,
bool global,
int kills,
int deaths,
int max_distance,
int total_distance,
int deaths_while_equipped
}
global string pulsePrefix
void function pulsePrefixSet() //Sets our prefix
{
pulsePrefix = format("\x1b[38;2;%i;%i;%im[PULSE]\x1b[0m", 255, 178, 102)
}
void function pulsePrintt(string content) //Prints whatever we want printed with given prefix (by standard [PULSE]).
{
printt(format("%s " + content, pulsePrefix))
}
bool function pulseRequestData(string givenURL, table parameterTable, string tablepath) //Gets data from API (see ToneURL within mod.json) and puts it into one table for processing.
{
table<string, array<string> > requestTable
ePulseDataType requestedDataType
if ("weapon" in parameterTable)
{
requestedDataType = ePulseDataType.WEAPON
}
else if ("map" in parameterTable)
{
requestedDataType = ePulseDataType.MAP
}
else if ("gamemode" in parameterTable)
{
requestedDataType = ePulseDataType.GAMEMODE
}
void functionref (HttpRequestResponse) onSuccess = void function(HttpRequestResponse response) : (givenURL, parameterTable, requestTable, tablepath, requestedDataType)
{
if (NSIsSuccessHttpCode(respone.StatusCode))
{
table DecodedJSON = DecodeJSON(response.body)
foreach (var key in DecodedJSON) {
table dData = DecodedJSON[key]
pulseDataStruct data = {
dataType = requestedDataType,
dataName = string(key),
global = tablepath.find("Global") != null ? true : false;
int kills = "kills" in dData ? dData["kills"] : 0
int deaths = "deaths" in dData ? dData["deaths"] : 0
int max_distance = "max_distance" in dData ? dData["max_distance"] : 0
int total_distance = "total_distance" in dData ? dData["total_distance"] : 0
int deaths_while_equipped = "deaths_while_equipped" in dData ? dData["deaths_while_equipped"] : 0
}
pulseData.append(data)
}
} else {
pulsePrintt(format("%s, %s is unreachable.", response.statusCode, givenURL))
pulseLockStats()
}
}
void functionref (HttpRequestFailure) onFailure = void function(HttpRequestFailure failure) : (givenURL)
{
pulsePrintt(format("Something went wrong, %s is unreachable", givenURL))
pulseLockStats()
}
foreach (key, value in parameterTable)
{
requestTable[string(key)] <- [string(value)]
}
return NSHttpGet(givenURL, requestTable, onSuccess, onFailure)
}
void function pulseLockStats()
{
loebSetLockedButton(Localize("#MENU_TITLE_STATS"), true)
}
string function HammerToMeterString(float value)
{
return value > 0 && int((1.905 * value ))/100 > 0 ? string(int((1.905 * value ) )/100) + "m" : "0";
}
@@ -1,32 +0,0 @@
global function pulseInit
global function pulseGetData
global array<pulseDataStruct> pulseData = []
struct {
array<string> allMaps
} file
void function pulseInit()
{
pulsePrefixSet()
file.allMaps = GetPrivateMatchMaps()
pulsePrintt("Initialized.")
AddUICallback_OnLevelInit( pulseGetData )
}
void function pulseGetData()
{
print("data getter called")
string URL = GetConVarString("ToneURL")
array <string> URLpath = ["/weapons", "/weapons", "/gamemodes", "/gamemodes", "/maps"]
array <string> tablepath = ["weaponsLocal", "weaponsGlobal", "gamemodesAll", "gamemodesSeparated", "maps"]
pulseRequestData(URL + URLpath[0], {["player"] = NSGetLocalPlayerUID()}, tablepath[0])
pulseRequestData(URL + URLpath[1], {["player"] = "!" + NSGetLocalPlayerUID()}, tablepath[1])
pulseRequestData(URL + URLpath[2], {["player"] = NSGetLocalPlayerUID()}, tablepath[2])
foreach (map in file.allMaps)
{
pulseRequestData(URL + URLpath[3], {["player"] = NSGetLocalPlayerUID(), ["map"] = map.slice(3)}, tablepath[3])
}
pulseRequestData(URL + URLpath[4], {["player"] = NSGetLocalPlayerUID()}, tablepath[4])
}
+5
View File
@@ -0,0 +1,5 @@
{
"Major": "1",
"Minor": "2",
"Patch": "1"
}