32 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
okvdai fb6963f86e Update README.md 2023-05-01 21:48:43 +02:00
okvdai 4e0192d2ce Update menu_stats_overview.nut 2023-05-01 21:47:02 +02:00
okvdai 979f463367 Update README.md 2023-05-01 18:01:37 +02:00
okvdai 373c469abb Create viewstats_weapons.menu 2023-05-01 17:55:24 +02:00
okvdai 5c11623ecb Fix inaccurate K/D calculation 2023-05-01 17:51:45 +02:00
okvdai 47d91497dd Make use of "Time" tab #16 2023-05-01 17:23:07 +02:00
okvdai b28fb1e6c7 Update README.md 2023-04-30 22:49:58 +02:00
okvdai 3c28ab0fb3 Update README.md 2023-04-30 22:37:40 +02:00
okvdai 186692f198 Fix #17 2023-04-30 22:08:54 +02:00
okvdai 7287d0d1f2 Add menu_stats_time.nut 2023-04-30 21:32:29 +02:00
okvdai 890fffc7e3 Make use of pie chart #14 2023-04-30 17:39:47 +02:00
legonzaur 90bd196886 fix map data gamemode 2023-04-30 15:45:49 +02:00
okvdai db1d4d115c Fix custom gamemode function called multiple times #14 2023-04-30 12:38:37 +02:00
okvdai 44d4f3351f Update menu_stats_maps.nut #14 2023-04-29 22:01:25 +02:00
okvdai 33def04dda Initial #14 2023-04-29 19:13:33 +02:00
okvdai 2a7d5d3ac6 Fix typo in function name
to avoid future confusion
2023-04-29 17:13:43 +02:00
okvdai 354d23d991 Update mod.json 2023-04-29 15:57:47 +02:00
okvdai d2b5482e89 Convert Hammer units to meters #13 2023-04-29 15:39:20 +02:00
okvdai eefff5d5f3 Reduce terminal spam #15 2023-04-29 15:18:29 +02:00
okvdai dcc569ea44 Initial #15, continue #8 2023-04-29 14:56:29 +02:00
okvdai 3938b4830f Basic function #7 2023-04-28 18:46:09 +02:00
okvdai 326e39555d Finish #11, initial #7, #8. 2023-04-28 18:23:11 +02:00
okvdai 0b10707830 Real-time updates #11 2023-04-28 17:05:14 +02:00
okvdai 12233a4f8a Real-time updates #11 2023-04-28 17:03:26 +02:00
okvdai dbf3d84a83 Merge pull request #10 from ToneAPI/blade
Update pulse.gnut #9
2023-04-26 11:05:09 +02:00
okvdai 3976247376 Update pulse.gnut #9 2023-04-26 11:00:31 +02:00
okvdai e67df127f4 Update README.md 2023-04-25 11:08:41 +02:00
okvdai 707f469917 Integrate with v2 of the Tone API #4 2023-04-25 11:05:45 +02:00
okvdai a831471184 Update menu_stats_overview.nut 2023-04-24 23:45:27 +02:00
okvdai 4a50d26111 Fix K/D calculation 2023-04-24 22:42:46 +02:00
okvdai 79dbab8fcb Update pulse.gnut 2023-04-24 22:11:42 +02:00
13 changed files with 2730 additions and 91 deletions
+70 -5
View File
@@ -1,15 +1,80 @@
# Pulse
Pulse is a clientside mod for Titanfall 2 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:
- displaying kills in `Pilot Weapons`
- displaying kills and most used weapon (by kills) in `Overview`
## Currently, features include:
- mostly functional `Overview` tab,
- functional `Time` tab,
- Pilot weapon data displayed in `Pilot Weapons` tab,
- Titan kills displayed in `Titans` tab,
- functional `Maps` tab,
- real-time updates.
Want to know what we have planned for future updates? See [here.](https://github.com/ToneAPI/pulse/projects?query=is%3Aopen)
Found a bug? Make an issue on GitHub [here.](https://github.com/ToneAPI/pulse/issues/new)
<details>
<summary>Features, more in-depth:</summary>
### `Overview`
- 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. (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 |
|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Pilots |Shows **ALL KILLS** accumulated by player as Pilot. Differentiating Pilot and Titan kills will come in a later Tone API update.|
| Titans |Non-functional, see line above.|
| 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 |
|--------------------|------------------------------------------------------|
| Pilots |Shows **ALL KILLS** accumulated by player as Titan. Differentiating Pilot and Titan kills will come in a later Tone API update.|
| Titans |Non-functional, see line above.|
| Titan executions |Shows only executions accumulated by player as Titan.|
| Pilots meleed |Shows only melee kills accumulated by player as Titan.|
| Pilot roadkills |Shows only roadkills accumulated by player as Titan.|
- Upper statbox values have been zeroed out, these don't yet work and are set to 0 to avoid confusion.
### `Time`
- Kills by Class shows kills by Pilot and Titan on a piechart.
- Kills by Titan shows kills by all Titan classes on a piechart.
- Kills by Gamemode shows kills on each gamemode played on a piechart.
### `Pilot Weapons`
- shows total accumulated kills per weapon under Total Kills.
- shows deaths with given weapon equipped under Deaths with Weapon.
### `Titans`
- shows total accumulated kills per Titan under Total Kills.
### `Maps`
- Player Map Stats - shows general data for player on chosen map, visualised in the table below:
| Name | Description |
|-----------------------|------------------------------------------------------- |
| Kills on Map |Shows all kills accumulated by player on chosen map.|
| Deaths on Map |Shows all deaths accumulated by player on chosen map.|
| Total Shot Distance |Shows total distance of kills accumulated by player on chosen map.|
| Maximum Shot Distance |Shows highest distance kill by player on chosen map.|
- Kills by Gamemode - piechart showing all kills (in percent) on chosen map by gamemode.
</details>
## DISCLAIMER
The Tone API is NOT used by every server, view a list supported servers on [the webclient.](https://toneapi.github.io/ToneAPI_webclient/)
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.
+24 -2
View File
@@ -1,14 +1,36 @@
{
"Name": "ToneAPI.pulse",
"Description": "Displays Tone API kill data in the Stats tab.",
"Version": "1.1.0-prerelease",
"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": "GetStatsFromToneAPI"
"After": "pulseInit"
}
}
]
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,508 @@
resource/ui/menus/viewstats_weapons.menu
{
menu
{
ControlName Frame
xpos 0
ypos 0
zpos 3
wide f0
tall f0
autoResize 0
pinCorner 0
visible 1
enabled 1
PaintBackgroundType 0
infocus_bgcolor_overridep "0 0 0 0"
outoffocus_bgcolor_override "0 0 0 0"
Vignette
{
ControlName ImagePanel
InheritProperties MenuVignette
}
MenuTitle
{
ControlName Label
InheritProperties MenuTitle
labelText "#STATS_PILOT_WEAPONS"
}
MenuCommon
{
ControlName CNestedPanel
xpos 0
ypos 0
wide f0
tall f0
visible 1
controlSettingsFile "resource/ui/menus/panels/menu_common.res"
}
MatchmakingStatus
{
ControlName CNestedPanel
xpos 0
ypos 0
wide f0
tall f0
visible 1
controlSettingsFile "resource/ui/menus/panels/matchmaking_status.res"
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
GridPanel
{
ControlName CNestedPanel
xpos 96
ypos 193
zpos 99
wide 224
tall 702
visible 1
tabPosition 1
controlSettingsFile "Resource/UI/menus/panels/weapon_stats_grid.res"
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Screen
{
ControlName Label
xpos 0
ypos 0
wide f0
tall f0
labelText ""
//bgcolor_override "100 100 100 100"
//paintbackground 1
//visible 1
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
WeaponName
{
ControlName Label
xpos -516
ypos -366
zpos 101
auto_wide_tocontents 1
auto_tall_tocontents 1
visible 1
font DefaultBold_44
labelText "WEAPON NAME"
allcaps 1
fgcolor_override "255 255 255 255"
//bgcolor_override "0 255 0 100"
pin_to_sibling Screen
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner BOTTOM
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
KillsHeader
{
ControlName RuiPanel
rui "ui/stats_background.rpak"
zpos 101
wide 500
tall 194
visible 1
scaleImage 1
pin_to_sibling WeaponName
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner BOTTOM_LEFT
}
KillsHeaderLabel
{
ControlName Label
xpos -18
ypos -6
zpos 102
wide 400
tall 36
visible 1
font Default_31
labelText "#STATS_HEADER_KILL_HISTORY"
allcaps 1
textAlignment west
fgcolor_override "255 255 255 255"
//bgcolor_override "255 255 0 100"
pin_to_sibling KillsHeader
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner TOP_LEFT
}
KillsLineBackground0
{
ControlName RuiPanel
rui "ui/stats_line_background.rpak"
xpos 0
ypos -48
zpos 101
wide 500
tall 36
visible 1
scaleImage 1
pin_to_sibling KillsHeader
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner TOP_LEFT
}
KillsLabel0
{
ControlName Label
xpos -18
ypos 0
zpos 102
wide 308
tall 36
visible 1
font Default_23
labelText "#STATS_HEADER_TOTAL_KILLS"
allcaps 1
textAlignment west
fgcolor_override "255 255 255 255"
//bgcolor_override "255 255 0 100"
pin_to_sibling KillsLineBackground0
pin_corner_to_sibling LEFT
pin_to_sibling_corner LEFT
}
KillsValue0
{
ControlName Label
xpos 0
ypos 0
zpos 102
wide 94
tall 36
visible 1
font Default_23
labelText "--"
allcaps 1
textAlignment center
fgcolor_override "255 255 255 255"
//bgcolor_override "0 255 0 100"
pin_to_sibling KillsLineBackground0
pin_corner_to_sibling RIGHT
pin_to_sibling_corner RIGHT
}
KillsLineBackground1
{
ControlName RuiPanel
rui "ui/stats_line_background.rpak"
xpos 0
ypos 0
zpos 101
wide 500
tall 36
visible 0
scaleImage 1
pin_to_sibling KillsLineBackground0
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner BOTTOM_LEFT
}
KillsLabel1
{
ControlName Label
xpos -18
ypos 0
zpos 102
wide 308
tall 36
visible 1
font Default_23
labelText "#STATS_KILLS_PILOTS"
allcaps 1
textAlignment west
fgcolor_override "255 255 255 255"
//bgcolor_override "255 255 0 100"
pin_to_sibling KillsLineBackground1
pin_corner_to_sibling LEFT
pin_to_sibling_corner LEFT
}
KillsValue1
{
ControlName Label
xpos 0
ypos 0
zpos 102
wide 94
tall 36
visible 1
font Default_23
labelText "--"
allcaps 1
textAlignment center
fgcolor_override "255 255 255 255"
//bgcolor_override "0 255 0 100"
pin_to_sibling KillsLineBackground1
pin_corner_to_sibling RIGHT
pin_to_sibling_corner RIGHT
}
KillsLineBackground2
{
ControlName RuiPanel
rui "ui/stats_line_background.rpak"
xpos 0
ypos 0
zpos 101
wide 500
tall 36
visible 1
scaleImage 1
pin_to_sibling KillsLineBackground1
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner BOTTOM_LEFT
}
KillsLabel2
{
ControlName Label
xpos -18
ypos 0
zpos 102
wide 308
tall 36
visible 1
font Default_23
labelText "#STATS_KILLS_TITANS"
allcaps 1
textAlignment west
fgcolor_override "255 255 255 255"
//bgcolor_override "255 255 0 100"
pin_to_sibling KillsLineBackground2
pin_corner_to_sibling LEFT
pin_to_sibling_corner LEFT
}
KillsValue2
{
ControlName Label
xpos 0
ypos 0
zpos 102
wide 94
tall 36
visible 1
font Default_23
labelText "--"
allcaps 1
textAlignment center
fgcolor_override "255 255 255 255"
//bgcolor_override "0 255 0 100"
pin_to_sibling KillsLineBackground2
pin_corner_to_sibling RIGHT
pin_to_sibling_corner RIGHT
}
KillsLineBackground3
{
ControlName RuiPanel
rui "ui/stats_line_background.rpak"
xpos 0
ypos 0
zpos 101
wide 500
tall 36
visible 0
scaleImage 1
pin_to_sibling KillsLineBackground2
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner BOTTOM_LEFT
}
KillsLabel3
{
ControlName Label
xpos -18
ypos 0
zpos 102
wide 308
tall 36
visible 1
font Default_23
labelText "DEATHS WITH WEAPON"
allcaps 1
textAlignment west
fgcolor_override "255 255 255 255"
//bgcolor_override "255 255 0 100"
pin_to_sibling KillsLineBackground3
pin_corner_to_sibling LEFT
pin_to_sibling_corner LEFT
}
KillsValue3
{
ControlName Label
xpos 0
ypos 0
zpos 102
wide 94
tall 36
visible 1
font Default_23
labelText "--"
allcaps 1
textAlignment center
fgcolor_override "255 255 255 255"
//bgcolor_override "0 255 0 100"
pin_to_sibling KillsLineBackground3
pin_corner_to_sibling RIGHT
pin_to_sibling_corner RIGHT
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Stat0
{
ControlName RuiPanel
rui "ui/stat_box_e.rpak"
xpos 8
zpos 100
wide 210
tall 93
visible 1
pin_to_sibling KillsHeader
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner TOP_RIGHT
}
Stat1
{
ControlName RuiPanel
rui "ui/stat_box_e.rpak"
xpos 8
zpos 100
wide 210
tall 93
visible 1
pin_to_sibling Stat0
pin_corner_to_sibling LEFT
pin_to_sibling_corner RIGHT
}
Stat2
{
ControlName RuiPanel
rui "ui/stat_box_e.rpak"
ypos 8
zpos 100
wide 210
tall 93
visible 1
pin_to_sibling Stat0
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner BOTTOM_LEFT
}
Stat3
{
ControlName RuiPanel
rui "ui/stat_box_e.rpak"
xpos 8
zpos 100
wide 210
tall 93
visible 1
pin_to_sibling Stat2
pin_corner_to_sibling LEFT
pin_to_sibling_corner RIGHT
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
NextUnlock
{
ControlName RuiPanel
rui "ui/stats_next_unlock.rpak"
xpos 8
zpos 90
wide 356
tall 194
visible 1
scaleImage 1
pin_to_sibling Stat1
pin_corner_to_sibling TOP_LEFT
pin_to_sibling_corner TOP_RIGHT
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ModelRotateMouseCapture
{
ControlName CMouseMovementCapturePanel
xpos 580
zpos 12
wide 1340
tall %100
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
LblWeaponLocked
{
ControlName Label
classname LblWeaponLocked
xpos -650
ypos 142
zpos 102
wide 474
auto_tall_tocontents 1
visible 1
font Default_27_DropShadow
allcaps 1
textAlignment center
labelText "UNLOCK INFO"
fgcolor_override "153 61 61 255"
bgcolor_override "51 20 20 240"
pin_to_sibling KillsHeader
pin_corner_to_sibling BOTTOM
pin_to_sibling_corner TOP_LEFT
paintbackground 1
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FooterButtons
{
ControlName CNestedPanel
xpos 0
ypos r119
wide f0
tall 36
visible 1
controlSettingsFile "resource/ui/menus/panels/footer_buttons.res"
}
}
}
+219 -40
View File
@@ -1,61 +1,214 @@
global function GetStatsFromToneAPI
global function getWeaponKillsFromToneApi
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 = {}
void function GetStatsFromToneAPI()
string prefix = "default"
string HTTPrequestURL = "default"
string currentVersion = "default"
int weaponEntries = 0
int mapEntries = 0
int gamemodeEntries = 0
int mapGamemodeEntries = 0
void function pulseInit()
{
thread GetStatsFromToneAPI_threaded()
}
void function GetStatsFromToneAPI_threaded(){
while(true){
if(NSIsMasterServerAuthenticated()) break
WaitFrame()
}
//SetConVarString("ToneURL", "https://toneapi.sleepycat.date/v2_test")
print("[PULSE] Loaded, getting data...")
HttpRequest getStats
getStats.method = HttpRequestMethod.GET
getStats.url = "https://tone.sleepycat.date/v2_test/client/weapons"
getStats.queryParameters["player"] <- [NSGetLocalPlayerUID().tostring()]
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)
{
print("[PULSE] Kill data received, processing...")
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
print("[PULSE] " + key + " has been added.")
weaponEntries += 1
}
print("[PULSE] Kill data has been processed.")
print(prefix + "Kill data has been processed with a total of " + string(weaponEntries) + " entries.")
}
void functionref(HttpRequestFailure) onFailure = void function(HttpRequestFailure failure)
{
print("[PULSE] Encountered an error getting kill data...")
print(prefix + "Encountered an error getting kill data...")
}
bool result = NSHttpRequest(getStats, onSuccess, onFailure)
print("[PULSE] result is " + result)
NSHttpRequest(getWeaponStats, onSuccess, onFailure)
}
int function getWeaponKillsFromToneApi(string weaponRef){
if(weaponRef.find("mp_weapon") != null){
weaponRef = weaponRef.slice(10)
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){
print("[PULSE] Found matching weapon : " + weaponRef + " with " + globalToneAPIKillData[weaponRef] + " kills")
return expect int(globalToneAPIKillData[weaponRef])
}
return 0
@@ -63,12 +216,7 @@ int function getWeaponKillsFromToneApi(string weaponRef){
int function getNemesisWeaponFromToneAPI(string weaponRef){
if(weaponRef.find("mp_weapon") != null){
weaponRef = weaponRef.slice(10)
}
if(weaponRef in globalToneAPIDeathData){
print("[PULSE] Found matching weapon : " + weaponRef + " with " + globalToneAPIDeathData[weaponRef] + " nemesis weapon kills")
return expect int(globalToneAPIDeathData[weaponRef])
}
return 0
@@ -76,13 +224,44 @@ int function getNemesisWeaponFromToneAPI(string weaponRef){
int function getDWEFromToneAPI(string weaponRef){
if(weaponRef.find("mp_weapon") != null){
weaponRef = weaponRef.slice(10)
}
if(weaponRef in globalToneAPIDWEData){
print("[PULSE] Found matching weapon : " + weaponRef + " with " + globalToneAPIDeathData[weaponRef] + " deaths while equipped")
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()
}
+315
View File
@@ -0,0 +1,315 @@
global function InitViewStatsMapsMenu
global function setit
struct
{
var menu
GridMenuData gridData
bool isGridInitialized = false
array<string> allMaps
} file
void function InitViewStatsMapsMenu()
{
var menu = GetMenu( "ViewStats_Maps_Menu" )
file.menu = menu
Hud_SetText( Hud_GetChild( file.menu, "MenuTitle" ), "#STATS_MAPS" )
file.gridData.rows = 5
file.gridData.columns = 1
//file.gridData.numElements // Set in OnViewStatsWeapons_Open after itemdata exists
file.gridData.pageType = eGridPageType.VERTICAL
file.gridData.tileWidth = 224
file.gridData.tileHeight = 112
file.gridData.paddingVert = 6
file.gridData.paddingHorz = 6
Grid_AutoAspectSettings( menu, file.gridData )
file.gridData.initCallback = MapButton_Init
file.gridData.getFocusCallback = MapButton_GetFocus
file.gridData.clickCallback = MapButton_Activate
AddMenuEventHandler( file.menu, eUIEvent.MENU_OPEN, OnViewStatsWeapons_Open )
AddMenuFooterOption( file.menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
}
void function OnViewStatsWeapons_Open()
{
UI_SetPresentationType( ePresentationType.NO_MODELS )
file.allMaps = GetPrivateMatchMaps()
file.gridData.numElements = file.allMaps.len()
if ( !file.isGridInitialized )
{
GridMenuInit( file.menu, file.gridData )
file.isGridInitialized = true
}
file.gridData.currentPage = 0
Grid_InitPage( file.menu, file.gridData )
Hud_SetFocused( Grid_GetButtonForElementNumber( file.menu, 0 ) )
}
bool function MapButton_Init( var button, int elemNum )
{
string mapName = file.allMaps[ elemNum ]
UpdateStatsForMap( mapName )
asset mapImage = GetMapImageForMapName( mapName )
var rui = Hud_GetRui( button )
RuiSetImage( rui, "buttonImage", mapImage )
Hud_SetEnabled( button, true )
Hud_SetVisible( button, true )
return true
}
void function MapButton_GetFocus( var button, int elemNum )
{
if ( IsControllerModeActive() )
UpdateStatsForMap( file.allMaps[ elemNum ] )
}
void function MapButton_Activate( var button, int elemNum )
{
if ( !IsControllerModeActive() )
UpdateStatsForMap( file.allMaps[ elemNum ] )
}
int function GetGameStatForMapInt( string gameStat, string mapName )
{
array<string> privateMatchModes = GetPrivateMatchModes()
int totalStat = 0
int enumCount = PersistenceGetEnumCount( "gameModes" )
for ( int modeId = 0; modeId < enumCount; modeId++ )
{
string modeName = PersistenceGetEnumItemNameForIndex( "gameModes", modeId )
totalStat += GetGameStatForMapAndModeInt( gameStat, mapName, modeName )
}
return totalStat
}
int function GetGameStatForMapAndModeInt( string gameStat, string mapName, string modeName, string difficulty = "1" )
{
string statString = GetStatVar( "game_stats", gameStat, "" )
string persistentVar = Stats_GetFixedSaveVar( statString, mapName, modeName, difficulty )
return GetUIPlayer().GetPersistentVarAsInt( persistentVar )
}
float function GetGameStatForMapFloat( string gameStat, string mapName )
{
array<string> privateMatchModes = GetPrivateMatchModes()
float totalStat = 0
int enumCount = PersistenceGetEnumCount( "gameModes" )
for ( int modeId = 0; modeId < enumCount; modeId++ )
{
string modeName = PersistenceGetEnumItemNameForIndex( "gameModes", modeId )
totalStat += GetGameStatForMapAndModeFloat( gameStat, mapName, modeName )
}
return totalStat
}
float function GetGameStatForMapAndModeFloat( string gameStat, string mapName, string modeName )
{
string statString = GetStatVar( "game_stats", gameStat, "" )
string persistentVar = Stats_GetFixedSaveVar( statString, mapName, modeName, "1" )
return expect float( GetUIPlayer().GetPersistentVar( persistentVar ) )
}
void function UpdateStatsForMap( string mapName )
{
entity player = GetUIPlayer()
if ( player == null )
return
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 ) )
string timePlayed = "null"
string gamesPlayed = "null"
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat0" ), Localize( "#STATS_HEADER_TIME_PLAYED" ), timePlayed )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat1" ), Localize( "#STATS_GAMES_PLAYED" ), gamesPlayed )
//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", "KILLS ON MAP" )
SetStatsLabelValue( file.menu, "KillsValue0", getMapKillFromToneAPI(mapName) )
SetStatsLabelValue( file.menu, "KillsLabel1", "DEATHS ON MAP" )
SetStatsLabelValue( file.menu, "KillsValue1", getMapDeathFromToneAPI(mapName) )
SetStatsLabelValue( file.menu, "KillsLabel2", "TOTAL SHOT DISTANCE" )
SetStatsLabelValue( file.menu, "KillsValue2", string(int((1.905 * float(getMapDistFromToneAPI(mapName) ) ) )/100) + "m" )
SetStatsLabelValue( file.menu, "KillsLabel3", "MAXIMUM SHOT DISTANCE" )
SetStatsLabelValue( file.menu, "KillsValue3", string(int((1.905 * float(getMapMDistFromToneAPI(mapName) ) ) )/100) + "m" )
SetStatsLabelValue( file.menu, "KillsLabel4", "--" )
SetStatsLabelValue( file.menu, "KillsValue4", "--" )
//var anchorElem = Hud_GetChild( file.menu, "WeaponStatsBackground" )
//printt( Hud_GetX( anchorElem ) )
//printt( Hud_GetX( anchorElem ) )
//printt( Hud_GetX( anchorElem ) )
//printt( Hud_GetX( anchorElem ) )
//Hud_SetX( anchorElem, 0 )
//
array<string> gameModesArray = GetPersistenceEnumAsArray( "gameModes" )
array<PieChartEntry> modes
int enumCount = PersistenceGetEnumCount( "gameModes" )
table< string, array<int> > customGamemodeList = {
sns = [255, 178, 102, 255],
fw = [147, 204, 57, 255],
gg = [14, 87, 132, 255]
}
for ( int modeId = 0; modeId < enumCount; modeId++ )
{
string modeName = PersistenceGetEnumItemNameForIndex( "gameModes", modeId )
if ( mapName in globalToneAPIGamemodeMapData && modeName in globalToneAPIGamemodeMapData[mapName] )
{
float modePlayedTime = 0
modePlayedTime = float(globalToneAPIGamemodeMapData[mapName][modeName])
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, GameMode_GetName( modeName ), modePlayedTime, GetGameModeDisplayColor( modeName ) )
}
}
}
foreach (string key, array<int> value in customGamemodeList)
{
if ( mapName in globalToneAPIGamemodeMapData && key in globalToneAPIGamemodeMapData[mapName])
{
float modePlayedTime = 0
modePlayedTime = float(globalToneAPIGamemodeMapData[mapName][key])
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, key, modePlayedTime, value)
}
}
}
const MAX_MODE_ROWS = 8
if ( modes.len() > 0 )
{
modes.sort( ComparePieChartEntryValues )
if ( modes.len() > MAX_MODE_ROWS )
{
float otherValue
for ( int i = MAX_MODE_ROWS-1; i < modes.len() ; i++ )
otherValue += modes[i].numValue
modes.resize( MAX_MODE_ROWS-1 )
AddPieChartEntry( modes, "#GAMEMODE_OTHER", otherValue, [127, 127, 127, 255] )
}
}
PieChartData modesPlayedData
modesPlayedData.entries = modes
modesPlayedData.labelColor = [ 255, 255, 255, 255 ]
SetPieChartData( file.menu, "ModesPieChart", "KILLS BY GAMEMODE", modesPlayedData )
array<string> fdMaps = GetPlaylistMaps( "fd" )
if ( 0 == 1 ) // maybe work later on some FD servers
{
array<var> pveElems = GetElementsByClassname( file.menu, "PvEGroup" )
foreach ( elem in pveElems )
{
Hud_Show( elem )
}
vector perfectColor = TEAM_COLOR_FRIENDLY / 219.0
var iconLegendRui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIconLegend" ) )
RuiSetImage( iconLegendRui, "basicImage", $"rui/menu/gametype_select/playlist_fd_normal" )
RuiSetFloat3( iconLegendRui, "basicImageColor", perfectColor )
var icon0Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon0" ) )
RuiSetImage( icon0Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_easy" )
int easyWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "0" )
SetStatsLabelValue( file.menu, "PvELabel0", "#FD_DIFFICULTY_EASY" )
SetStatsLabelValue( file.menu, "PvEValueA0", easyWins )
if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "0" ) )
RuiSetFloat3( icon0Rui, "basicImageColor", perfectColor )
else
RuiSetFloat3( icon0Rui, "basicImageColor", easyWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> )
var icon1Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon1" ) )
RuiSetImage( icon1Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_normal" )
int normalWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "1" )
SetStatsLabelValue( file.menu, "PvELabel1", "#FD_DIFFICULTY_NORMAL" )
SetStatsLabelValue( file.menu, "PvEValueA1", normalWins )
if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "1" ) )
RuiSetFloat3( icon1Rui, "basicImageColor", perfectColor )
else
RuiSetFloat3( icon1Rui, "basicImageColor", normalWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> )
var icon2Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon2" ) )
RuiSetImage( icon2Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_hard" )
int hardWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "2" )
SetStatsLabelValue( file.menu, "PvELabel2", "#FD_DIFFICULTY_HARD" )
SetStatsLabelValue( file.menu, "PvEValueA2", hardWins )
if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "2" ) )
RuiSetFloat3( icon2Rui, "basicImageColor", perfectColor )
else
RuiSetFloat3( icon2Rui, "basicImageColor", hardWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> )
var icon3Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon3" ) )
RuiSetImage( icon3Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_master" )
int masterWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "3" )
SetStatsLabelValue( file.menu, "PvELabel3", "#FD_DIFFICULTY_MASTER" )
SetStatsLabelValue( file.menu, "PvEValueA3", masterWins )
if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "3" ) )
RuiSetFloat3( icon3Rui, "basicImageColor", perfectColor )
else
RuiSetFloat3( icon3Rui, "basicImageColor", masterWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> )
var icon4Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon4" ) )
RuiSetImage( icon4Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_insane" )
int insaneWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "4" )
SetStatsLabelValue( file.menu, "PvELabel4", "#FD_DIFFICULTY_INSANE" )
SetStatsLabelValue( file.menu, "PvEValueA4", insaneWins )
if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "4" ) )
RuiSetFloat3( icon4Rui, "basicImageColor", perfectColor )
else
RuiSetFloat3( icon4Rui, "basicImageColor", insaneWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> )
}
else
{
array<var> pveElems = GetElementsByClassname( file.menu, "PvEGroup" )
foreach ( elem in pveElems )
{
Hud_Hide( elem )
}
}
}
var function setit( vector color )
{
var iconLegendRui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIconLegend" ) )
RuiSetImage( iconLegendRui, "basicImage", $"rui/menu/gametype_select/playlist_fd_normal" )
RuiSetFloat3( iconLegendRui, "basicImageColor", color )
}
+91 -35
View File
@@ -5,9 +5,12 @@ global function InitViewStatsOverviewMenu
struct
{
var menu
array<ItemDisplayData> allTitans
table<string, array<string> > titanStatLoadout
} file
const MAX_DOTS_ON_GRAPH = 10
table <string, int> titanKillData = {}
const IMAGE_TITAN_STRYDER = $"ui/menu/personal_stats/ps_titan_icon_stryder"
const IMAGE_TITAN_ATLAS = $"ui/menu/personal_stats/ps_titan_icon_atlas"
@@ -27,10 +30,42 @@ void function InitViewStatsOverviewMenu()
AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
}
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 ] <- []
int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "titanRef" ), titan.ref )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "primary" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "ordnance" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "special" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "antirodeo" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "coreAbility" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "melee" ) ) )
}
foreach ( weaponRef in file.titanStatLoadout[ titanName ])
{
titanKillData[weaponRef] <- getWeaponKillsFromToneAPI(weaponRef)
}
}
void function OnStatsOverview_Open()
{
UI_SetPresentationType( ePresentationType.NO_MODELS )
GetTitanKills("ion")
GetTitanKills("scorch")
GetTitanKills("northstar")
GetTitanKills("ronin")
GetTitanKills("tone")
GetTitanKills("legion")
GetTitanKills("vanguard")
UpdateViewStatsOverviewMenu()
}
@@ -172,7 +207,7 @@ function UpdateViewStatsOverviewMenu()
Hud_Show( weaponImageElem )
Hud_SetText( weaponNameElem, nemesisWeapon.printName )
Hud_Show( weaponNameElem )
Hud_SetText( weaponDescElem, "#STATS_MOST_KILLS_VALUE", nemesisWeapon.val )
Hud_SetText( weaponDescElem, nemesisWeapon.val + " DEATHS BY WEAPON" )
Hud_Show( weaponDescElem )
Hud_Hide( noDataElem )
}
@@ -260,30 +295,49 @@ function UpdateViewStatsOverviewMenu()
totalPilotKills += value
}
var totalGlobalKills = 0
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 globalToneAPIDWEData) {
foreach (var key, var value in globalToneAPIDeathData) {
totalPilotDeaths += value
}
float kdval = float(totalPilotKills) / float(totalPilotDeaths)
var killsAsPilot = 0
foreach (var key, var value in globalToneAPIKillData) {
if (key in titanKillData) {
continue
} else {
killsAsPilot += getWeaponKillsFromToneAPI(string(key))
}
}
local lifetimeAverage = kdval
local formattedLifetimeAverage
if ( lifetimeAverage % 1 == 0 )
formattedLifetimeAverage = format( "%.0f", lifetimeAverage )
else
formattedLifetimeAverage = format( "%.1f", lifetimeAverage )
SetStatsLabelValue( file.menu, "LifetimeAverageValue", [ "#STATS_KD_VALUE", formattedLifetimeAverage ] )
var killsAsTitan = 0
foreach (var key, var value in globalToneAPIKillData) {
if (key in titanKillData) {
killsAsTitan += titanKillData[string(key)]
}
}
// Lifetime (PVP)
local lifetimeAveragePVP = player.GetPersistentVar( "kdratio_lifetime_pvp" ).tofloat()
local formattedLifetimeAveragePVP
if ( lifetimeAveragePVP % 1 == 0 )
formattedLifetimeAveragePVP = format( "%.0f", lifetimeAveragePVP )
else
formattedLifetimeAveragePVP = format( "%.1f", lifetimeAveragePVP )
SetStatsLabelValue( file.menu, "LifetimePVPAverageValue", [ "#STATS_KD_VALUE", formattedLifetimeAveragePVP ] )
float kval = float(totalPilotKills)
float dval = float(totalPilotDeaths)
float kdval = float(int((kval / dval)*100))/100
float gkval = float(totalGlobalKills)
float gdval = float(totalGlobalDeaths)
float gkdval = float(int((gkval / gdval)*100))/100
SetStatsLabelValue( file.menu, "LifetimeAverageValue", [ "#STATS_KD_VALUE", kdval ] )
SetStatsLabelValue( file.menu, "LifetimePVPAverageValue", [ "#STATS_KD_VALUE", gkdval ] )
bool last10GamesStatsVisible = gamesPlayed >= NUM_GAMES_TRACK_KDRATIO ? true : false
SetLast10GamesStatVisibility( file.menu, last10GamesStatsVisible )
@@ -313,7 +367,7 @@ function UpdateViewStatsOverviewMenu()
else
kdratio_match_average = format( "%.1f", kdratio_match_average )
SetStatsLabelValue( file.menu, "Last10GamesValue", [ "#STATS_KD_VALUE", kdratio_match_average ] )
PlotKDPointsOnGraph( file.menu, 0, kdratio_match, lifetimeAverage )
PlotKDPointsOnGraph( file.menu, 0, kdratio_match, kdval )
// Last 10 (PVP)
local kdratiopvp_match_sum = 0
@@ -331,31 +385,33 @@ function UpdateViewStatsOverviewMenu()
else
kdratiopvp_match_average = format( "%.1f", kdratiopvp_match_average )
SetStatsLabelValue( file.menu, "Last10GamesPVPValue", [ "#STATS_KD_VALUE", kdratiopvp_match_average ] )
PlotKDPointsOnGraph( file.menu, 1, kdratiopvp_match, lifetimeAveragePVP )
PlotKDPointsOnGraph( file.menu, 1, kdratiopvp_match, gkdval )
/////////////////////////
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue0" ), string( totalPilotKills ) )
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( getWeaponKillsFromToneApi("pilot_emptyhanded") ) )
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue4" ), string( getWeaponKillsFromToneApi("human_execution") ) )
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 += 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")
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")
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue0" ), string( GetPlayerStatInt( player, "kills_stats", "pilotKillsAsTitan" ) ) )
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( titanMeleeKills ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue3" ), string( GetPlayerStatInt( player, "kills_stats", "titanMeleePilot" ) ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue4" ), string( getWeaponKillsFromToneApi("damagedef_titan_step") ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue2" ), string( titanExecutions ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue3" ), string( titanMeleeKills ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue4" ), string( getWeaponKillsFromToneAPI("damagedef_titan_step") ) )
}
function PlotKDPointsOnGraph( menu, graphIndex, values, dottedAverage )
+199
View File
@@ -0,0 +1,199 @@
global function InitViewStatsTimeMenu
global function AddPieChartEntry
const MAX_MODE_ROWS = 8
struct
{
var menu
array<ItemDisplayData> allTitans
table<string, array<string> > titanStatLoadout
} file
void function InitViewStatsTimeMenu()
{
var menu = GetMenu( "ViewStats_Time_Menu" )
file.menu = menu
AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnStatsTime_Open )
AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
}
void function OnStatsTime_Open()
{
UI_SetPresentationType( ePresentationType.NO_MODELS )
file.allTitans = GetVisibleItemsOfType( eItemTypes.TITAN )
var dataTable = GetDataTable( $"datatable/titan_properties.rpak" )
foreach ( titan in file.allTitans )
{
file.titanStatLoadout[ titan.ref ] <- []
int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "titanRef" ), titan.ref )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "primary" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "ordnance" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "special" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "antirodeo" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "coreAbility" ) ) )
file.titanStatLoadout[ titan.ref ].append( GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "melee" ) ) )
}
UpdateViewStatsTimeMenu()
}
float function GetTitanKills( string titanName)
{
float weaponKills = 0
foreach ( weaponRef in file.titanStatLoadout[ titanName ])
{
weaponKills += float(getWeaponKillsFromToneAPI(weaponRef))
}
return weaponKills
}
void function UpdateViewStatsTimeMenu()
{
entity player = GetUIPlayer()
if ( player == null )
return
//#########################################
float killsAsTitan = 0
float killsAsIon = GetTitanKills( "ion" )
killsAsTitan += killsAsIon
float killsAsScorch = GetTitanKills( "scorch" )
killsAsTitan += killsAsScorch
float killsAsNorthstar = GetTitanKills( "northstar" )
killsAsTitan += killsAsNorthstar
float killsAsRonin = GetTitanKills( "ronin" )
killsAsTitan += killsAsRonin
float killsAsTone = GetTitanKills( "tone" )
killsAsTitan += killsAsTone
float killsAsLegion = GetTitanKills( "legion" )
killsAsTitan += killsAsLegion
float killsAsMonarch = GetTitanKills( "vanguard" )
killsAsTitan += killsAsMonarch
//#########################################
// Time By Class Pie Chart
//#########################################
var totalPilotKills = 0
foreach (var key, var value in globalToneAPIKillData) {
totalPilotKills += value
}
float hoursAsPilot = float(totalPilotKills)
float hoursAsTitan = killsAsTitan
array<PieChartEntry> classes
if ( hoursAsPilot > 0 )
AddPieChartEntry( classes, "#STATS_HEADER_PILOT", hoursAsPilot, [61, 117, 193, 255] )
if ( hoursAsTitan > 0 )
AddPieChartEntry( classes, "#STATS_HEADER_TITAN", hoursAsTitan, [223, 94, 0, 255] )
classes.sort( ComparePieChartEntryValues )
PieChartData classTimeData
classTimeData.entries = classes
classTimeData.labelColor = [ 255, 255, 255, 255 ]
SetPieChartData( file.menu, "ClassPieChart", "KILLS BY CLASS", classTimeData )
//#########################################
// Time By Chassis Pie Chart
//#########################################
array<PieChartEntry> titans
if ( killsAsIon > 0 )
AddPieChartEntry( titans, "#TITAN_ION", killsAsIon, [200, 40, 40, 255] )
if ( killsAsScorch > 0 )
AddPieChartEntry( titans, "#TITAN_SCORCH", killsAsScorch, [223, 94, 0, 255] )
if ( killsAsNorthstar > 0 )
AddPieChartEntry( titans, "#TITAN_NORTHSTAR", killsAsNorthstar, [61, 117, 193, 255] )
if ( killsAsRonin > 0 )
AddPieChartEntry( titans, "#TITAN_RONIN", killsAsRonin, [207, 191, 59, 255] )
if ( killsAsTone > 0 )
AddPieChartEntry( titans, "#TITAN_TONE", killsAsTone, [88, 172, 67, 255] )
if ( killsAsLegion > 0 )
AddPieChartEntry( titans, "#TITAN_LEGION", killsAsLegion, [46, 188, 180, 255] )
if ( killsAsMonarch > 0 )
AddPieChartEntry( titans, "#TITAN_VANGUARD", killsAsMonarch, [151, 71, 175, 255] )
titans.sort( ComparePieChartEntryValues )
PieChartData chassisTimeData
chassisTimeData.entries = titans
chassisTimeData.labelColor = [ 255, 255, 255, 255 ]
SetPieChartData( file.menu, "ChassisPieChart", "KILLS BY TITAN", chassisTimeData )
//#########################################
// Time By Mode Pie Chart
//#########################################
array<string> gameModesArray = GetPersistenceEnumAsArray( "gameModes" )
array<PieChartEntry> modes
int enumCount = PersistenceGetEnumCount( "gameModes" )
table< string, array<int> > customGamemodeList = {
sns = [255, 178, 102, 255],
fw = [147, 204, 57, 255],
gg = [14, 87, 132, 255]
}
for ( int modeId = 0; modeId < enumCount; modeId++ )
{
string modeName = PersistenceGetEnumItemNameForIndex( "gameModes", modeId )
if ( modeName in globalToneAPIGamemodeData )
{
float modePlayedTime = 0
modePlayedTime = float(globalToneAPIGamemodeData[modeName])
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, GameMode_GetName( modeName ), modePlayedTime, GetGameModeDisplayColor( modeName ) )
}
}
}
foreach (string key, array<int> value in customGamemodeList)
{
if ( key in globalToneAPIGamemodeData)
{
float modePlayedTime = 0
modePlayedTime = float(globalToneAPIGamemodeData[key])
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, key, modePlayedTime, value)
}
}
}
PieChartData modesPlayedData
modesPlayedData.entries = modes
modesPlayedData.labelColor = [ 255, 255, 255, 255 ]
SetPieChartData( file.menu, "ModesPieChart", "KILLS BY GAMEMODE", modesPlayedData )
//#########################################
// Time Stats
//#########################################
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat0" ), Localize( "#STATS_HEADER_TIME_PLAYED" ), StatToTimeString( "time_stats", "hours_total" ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat1" ), Localize( "#STATS_HEADER_TIME_IN_AIR" ), StatToTimeString( "time_stats", "hours_inAir" ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat2" ), Localize( "#STATS_HEADER_TIME_WALLRUNNING" ), StatToTimeString( "time_stats", "hours_wallrunning" ) )
}
void function AddPieChartEntry( array<PieChartEntry> entries, string displayName, float numValue, array<int> color )
{
PieChartEntry newEntry
newEntry.displayName = displayName
newEntry.numValue = numValue
newEntry.color = color
entries.append( newEntry )
}
@@ -175,7 +175,7 @@ void function UpdateStatsForTitan( string titanRef, int loadoutIndex )
int aiKills
foreach ( weaponRef in file.titanStatLoadout[ titanRef ] )
{
totalKills += getWeaponKillsFromToneApi(weaponRef)
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 = getWeaponKillsFromToneApi(weaponName)
int val = getWeaponKillsFromToneAPI(weaponName)
if ( val > Table[ "most_kills" ].val )
{
Table[ "most_kills" ].ref = weaponName
@@ -357,13 +357,15 @@ table<string, table> function GetOverviewWeaponData()
float kdval = 0
float kval = 0
float dval = 0
if( getWeaponKillsFromToneApi(weaponName) != 0 && getDWEFromToneAPI(weaponName) != 0){
kval = float(getWeaponKillsFromToneApi(weaponName))
if( getWeaponKillsFromToneAPI(weaponName) != 0 && getDWEFromToneAPI(weaponName) != 0){
kval = float(getWeaponKillsFromToneAPI(weaponName))
dval = float(getDWEFromToneAPI(weaponName))
if (kval / dval > kdval){
kdval = float(getWeaponKillsFromToneApi(weaponName) / getDWEFromToneAPI(weaponName))
kdval = kval / dval
}
}
int rnd= int(kdval*100)
kdval = float(rnd)/100
if ( kdval > Table[ "highest_kpm" ].val.tofloat() )
{
Table[ "highest_kpm" ].ref = weaponName
@@ -180,8 +180,8 @@ void function UpdateStatsForWeapon( string weaponRef )
}
// Total Kills Stats
SetStatsLabelValue( file.menu, "KillsValue0", getWeaponKillsFromToneApi(weaponRef) )
SetStatsLabelValue( file.menu, "KillsValue1", getWeaponKillsFromToneApi(weaponRef) )
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", GetPlayerStatInt( player, "weapon_kill_stats", "ai", weaponRef ) )
SetStatsLabelValue( file.menu, "KillsValue3", getDWEFromToneAPI(weaponRef))
}
+5
View File
@@ -0,0 +1,5 @@
{
"Major": "1",
"Minor": "2",
"Patch": "1"
}