127 Commits
Author SHA1 Message Date
okvdai 47e4cd949c Begin #37 2023-10-23 20:19:30 +02:00
okvdai ca2ef84d55 Merge branch 'dev' of https://github.com/ToneAPI/pulse into dev 2023-10-23 18:32:39 +02:00
okvdai 02ba70198f Update version numbers 2023-10-13 19:04:54 +02:00
okvdai f959f7dd91 Prepare for release v2.1.0 2023-10-03 23:37:41 +02:00
okvdai 7aa6c9476f Fix stats loading only after reloading mods 2023-09-03 15:20:57 +02:00
okvdai 0f0d89c9c3 Merge pulse-loeb-component.nut into pulse-common-func.gnut 2023-09-03 15:15:33 +02:00
okvdai d56b2878a2 Update ToneURL convar 2023-09-03 14:16:16 +02:00
okvdai 5a5591d7b4 Update pulse-loeb-component.nut 2023-07-31 22:58:52 +02:00
okvdai 48c415c9ba Dependency info 2023-07-07 18:41:31 +02:00
okvdai 11ae2bac90 Integrate with loeb #35 2023-07-07 18:30:26 +02:00
okvdai f7e4588f80 Update localisation 2023-06-21 14:44:04 +02:00
okvdai b8879c3560 Update viewstats_maps.menu 2023-06-21 14:37:50 +02:00
okvdai 1c5ab1514b Average kill distance calculation, better Hammer conversion 2023-06-21 14:36:41 +02:00
okvdai c538dd44f3 Hotfixes 2023-06-20 20:25:31 +02:00
okvdai df4ee8fb0c Rename pulseSuccessBool to pulseFailure 2023-06-20 20:21:49 +02:00
okvdai ba0c4d11c7 Change request failure message 2023-06-20 20:20:55 +02:00
okvdai c1cd3a6fc7 Format code 2023-06-20 20:17:52 +02:00
okvdai a8bbd9ea39 Fix typo in english localisation 2023-06-20 20:16:17 +02:00
okvdai ff06daefae Use NsIsSuccessHttpCode() for status code checking 2023-06-20 20:15:47 +02:00
okvdai e1d5801d9a Add melee_pilot_kunai into the melee kill stat 2023-06-20 16:30:02 +02:00
okvdai d4efc94e7d Add missing comma 2023-06-19 13:42:18 +02:00
okvdai 81b1b4f928 Cleanup in menu_stats_overview.nut 2023-06-15 19:22:06 +02:00
okvdai 1d6b09537f Add status code checking to request function
"Borrowed" from the servermod
2023-06-15 19:02:54 +02:00
okvdai 8501955cea Update README.md 2023-06-13 20:06:51 +02:00
okvdai aa979e6bb4 Lock Stats tab until data has been gathered #27 2023-06-13 19:38:32 +02:00
okvdai e81bd9c49d Clean up formatting of shown text #30 2023-06-13 18:27:44 +02:00
okvdai bd6c98a59a Update README.md 2023-06-13 17:27:22 +02:00
okvdai 66eaaf472b Delete README.md 2023-06-13 17:23:31 +02:00
okvdaiandLegonzaur e361f4c543 Update pulse_french.txt #30
Co-Authored-By: Legonzaur <34353603+Legonzaur@users.noreply.github.com>
2023-06-12 22:39:52 +02:00
okvdai aff50542f9 Update pulse_polish.txt #30 2023-06-12 22:10:10 +02:00
okvdaiandLegonzaur 58a31f6b67 French localisation #30
Courtesy of @Legonzaur

Co-Authored-By: Legonzaur <34353603+Legonzaur@users.noreply.github.com>
2023-06-12 21:55:25 +02:00
okvdai 16ef610d57 Fix typo in polish localisation filename 2023-06-11 18:46:01 +02:00
okvdai fa061048f4 Italian localisation #30
Courtesy of 4lready-taken
(4lready-taken in-game)
2023-06-11 18:28:46 +02:00
okvdai 52387afe33 Polish localisation #30 2023-06-11 18:18:59 +02:00
okvdai 283134f455 German localisation #30
Courtesy of NoCatt
https://github.com/NoCatt
2023-06-11 17:57:16 +02:00
okvdai 64f22ff648 Update pulse_english.txt 2023-06-11 17:52:28 +02:00
okvdai f2b09667e7 English localisation #30 2023-06-11 17:33:31 +02:00
okvdai ffe6fec939 Remove testing code snippet 2023-06-10 15:38:20 +02:00
okvdai d372ecaff1 Simplify description in manifest.json 2023-06-10 14:03:23 +02:00
okvdai 96b7aaaa07 Change typography to lowercase 2023-06-10 11:11:08 +02:00
okvdai 3485cc783a v2.0.0 #24
Prepare for v2.0.0 release
2023-06-10 10:40:10 +02:00
okvdai 9b732b2f5e Merge branch 'v2_dev' of https://github.com/ToneAPI/pulse into v2_dev 2023-06-08 15:06:11 +02:00
okvdai aee8c91670 Update README.md 2023-06-08 15:06:19 +02:00
okvdai a18c59931f Clean up remaining test code 2023-06-08 15:06:07 +02:00
okvdai 40f1af931e Bug fixes 2023-06-08 13:43:27 +02:00
okvdai b2cb958673 Fix map piecharts 2023-06-08 12:56:38 +02:00
okvdai 2a15573826 Thread pulseGetData function 2023-06-08 12:33:23 +02:00
okvdai d74c57ec2b Update pulse-common-func.gnut 2023-06-08 12:33:06 +02:00
okvdai 908a875f6d Work on making map piecharts function
again...
2023-06-07 22:28:01 +02:00
okvdai 1109be0ece Parser rewrite 2023-06-07 21:18:35 +02:00
okvdai ddfb34a9f8 Change to Thunderstore template
For easier publishing to both platforms
2023-06-07 19:15:14 +02:00
okvdai 739b265fab Fix missing Kills by Gamemode piechart data 2023-06-02 16:58:11 +02:00
okvdai a262c7ff45 Fix arbitrary data display 2023-06-02 16:51:40 +02:00
okvdai da25a4dd29 Bug fixes 2023-06-02 16:40:52 +02:00
okvdai 84ab278d92 Update nut files to work with refactor 2023-06-02 14:48:40 +02:00
okvdai c41173ad13 Delete menu_stats.nut 2023-06-02 14:05:00 +02:00
okvdai 2fdcf288d4 Create menu_lobby.nut 2023-06-02 14:03:43 +02:00
okvdai 3985b3dd5c pulseGetData() function 2023-06-02 14:00:38 +02:00
okvdai ae963b245f Remove version.json and version ConVars 2023-06-02 13:55:36 +02:00
okvdai 30be7f5bf5 Remove version check
Is unnecessary
2023-06-02 13:48:16 +02:00
okvdai 1a0b074816 Get current and latest version as string 2023-06-02 13:21:01 +02:00
okvdai 42f8c0d0f4 Globalise prefix to avoid future issues 2023-06-02 13:12:26 +02:00
okvdai 5735e67c2f Copy getFromToneAPI to common file as pulseParse 2023-06-02 13:06:32 +02:00
okvdai 2d2d456a85 Replace NSHttpRequest with NSHttpGet 2023-06-02 12:58:35 +02:00
okvdai a5844b6be4 Initial function for getting data 2023-06-02 12:57:19 +02:00
okvdai 6f4425872b Move prefix definition to common file 2023-06-02 12:29:29 +02:00
okvdai 748981160a Add comment descriptions to pulse-common-func.gnut 2023-06-02 12:03:54 +02:00
okvdai 90401c8567 Begin porting common functions to common file
For easier readability and expandability
2023-06-02 11:58:02 +02:00
okvdai 1b914dc5cf Bump version number 2023-06-02 11:08:37 +02:00
okvdai 413d9f6cf3 Globalise prefix 2023-05-14 13:55:31 +02:00
okvdai 240a07d9fa Add clearer gamemode names to "Maps" and "Time" 2023-05-14 13:48:49 +02:00
okvdai 550c899323 Complete refactor #8 2023-05-14 12:53:04 +02:00
okvdai 2466febd4e Refactoring #8 2023-05-06 14:10:47 +02:00
okvdai aedfc9afc0 Rework request functions into GetStatsFromToneAPI #8 2023-05-05 23:19:28 +02:00
okvdai cdd00dc2b7 Rework get functions into getFromToneAPI #8 2023-05-05 22:01:51 +02:00
okvdai 4ce976cc88 Delete .gitignore 2023-05-04 20:48:07 +02:00
okvdai 687819e604 Create .gitignore 2023-05-04 20:46:03 +02:00
okvdai 2395d3d99b Update README.md 2023-05-03 18:33:11 +02:00
okvdai d23d020e6a Complete #18 2023-05-03 17:50:40 +02:00
okvdai e51386252d Remove unnecessary brackets 2023-05-03 17:42:03 +02:00
okvdai 54d26f568b Display current and latest version in terminal #18 2023-05-03 17:39:59 +02:00
okvdai 53fb421662 Create version.json for #18 testing 2023-05-03 17:06:18 +02:00
okvdai e6aaebef5f Add global K/D calculation 2023-05-03 15:02:11 +02:00
okvdai 9798a5ff76 Update README.md 2023-05-02 15:55:05 +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
okvdai b2df433810 Update menu_stats_overview.nut 2023-04-24 20:28:11 +02:00
okvdai 0f80026a94 Add best K/D calculation 2023-04-24 19:52:19 +02:00
okvdai 9701fa5559 Create menu_stats_titans.nut 2023-04-24 18:37:16 +02:00
okvdai 1c2244e10d Prepare for v1.1.0
- Add viewstats_overview.menu
- Add NEMESIS WEAPON to Overview tab
- Add pilot melee kills, executions, roadkills and Titan executions to Overview tab
2023-04-24 18:29:48 +02:00
okvdai f71255e55b Update mod.json
Add description, update version number
2023-04-21 16:10:08 +02:00
okvdai 3268f5b75c Update README.md 2023-04-21 16:07:14 +02:00
legonzaur 7dce384024 force tone to fetch data after masterserver auth 2023-04-21 13:14:04 +02:00
okvdai 4c45bc233a Update README.md 2023-04-20 19:48:07 +02:00
okvdai a18faecd0a Update README.md 2023-04-20 19:00:01 +02:00
okvdai 5bfe63f1c5 Update README.md 2023-04-20 18:59:39 +02:00
okvdai 66dfb9d53a Update README.md 2023-04-20 18:59:11 +02:00
okvdaiandlegonzaur e8cbfeb3cc Prepare for v1.0.0 release (#2)
* Replace sh_stats.gnut with pulse.gnut

* Add menu_stats_utility.nut

* Add menu_stats_overview.nut

---------

Co-authored-by: legonzaur <legonzaur@live.fr>
2023-04-20 18:54:49 +02:00
22 changed files with 5072 additions and 152 deletions
+102 -8
View File
@@ -1,15 +1,109 @@
# Pulse # 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: ## Currently, features include:
- displaying kills in `Pilot Weapons` - mostly functional `Overview` tab,
- displaying kills and most used weapon (by kills) in `Overview` - 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) Want to know what we have planned for future updates? See [here.](https://github.com/ToneAPI/pulse/projects?query=is%3Aopen)
## DISCLAIMER Found a bug? Make an issue on GitHub [here.](https://github.com/ToneAPI/pulse/issues/new)
The Tone API is NOT used by every server, view a list supported servers on [the webclient.](https://toneapi.github.io/ToneAPI_webclient/) <details>
<summary>Features, more in-depth:</summary>
Pulse is very much a W.I.P as of right now, features may be missing/nonfunctional. ### `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 compared to global K/D.
- 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>
## DISCLAIMERS
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>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

+7
View File
@@ -0,0 +1,7 @@
{
"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"]
}
-15
View File
@@ -1,15 +0,0 @@
{
"Name": "ToneAPI.pulse",
"Description": "placeholder text",
"Version": "0.0.1",
"LoadPriority": 1,
"Scripts": [
{
"Path": "pulse.gnut",
"RunOn": "UI",
"UICallback": {
"After": "GetStatsFromToneAPI"
}
}
]
}
-55
View File
@@ -1,55 +0,0 @@
global function GetStatsFromToneAPI
global function getWeaponKillsFromToneApi
global table globalToneAPIKillData = {}
void function GetStatsFromToneAPI()
{
//SetConVarString("ToneURL", "https://toneapi.sleepycat.date/v1")
print("[PULSE] Loaded, getting data...")
HttpRequest getStats
getStats.method = HttpRequestMethod.GET
getStats.url = "https://tone.sleepycat.date/v1/client/weapons"
getStats.queryParameters["player"] <- [NSGetLocalPlayerUID().tostring()]
void functionref(HttpRequestResponse) onSuccess = void function(HttpRequestResponse response)
{
print("[PULSE] Kill data received, processing...")
table JSONForConversion = DecodeJSON(response.body)
foreach (var key, var value in JSONForConversion) {
table test = expect table(value)
//this won't work on v2 since kills will be an integer already
string kills = expect string(test.kills)
globalToneAPIKillData[string(key)] <- kills.tointeger()
print("[PULSE] " + key + " has been added.")
}
print("[PULSE] Kill data has been processed.")
}
void functionref(HttpRequestFailure) onFailure = void function(HttpRequestFailure failure)
{
print("[PULSE] Encountered an error getting kill data...")
}
bool result = NSHttpRequest(getStats, onSuccess, onFailure)
print("[PULSE] result is " + result)
}
int function getWeaponKillsFromToneApi(string weaponRef){
//Sliced names are to be removed afterwards
print("[PULSE]" + weaponRef)
if(weaponRef.find("mp_weapon") != null){
weaponRef = weaponRef.slice(10)
}
foreach (var key, var value in globalToneAPIKillData) {
print(key)
print(value)
}
if(weaponRef in globalToneAPIKillData){
print("found!")
print(globalToneAPIKillData[weaponRef])
return expect int(globalToneAPIKillData[weaponRef])
}
return 0
}
+28
View File
@@ -0,0 +1,28 @@
{
"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.
File diff suppressed because it is too large Load Diff
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_WHILE_EQUIPPED"
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"
}
}
}
@@ -0,0 +1,95 @@
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";
}
@@ -0,0 +1,32 @@
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])
}
@@ -0,0 +1,318 @@
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 ) )
// 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", Localize("#MAPS_KILLS") )
SetStatsLabelValue( file.menu, "KillsValue0", pulseParse("maps", mapName.slice(3), "kills") )
SetStatsLabelValue( file.menu, "KillsLabel1", Localize("#MAPS_DEATHS") )
SetStatsLabelValue( file.menu, "KillsValue1", pulseParse("maps", mapName.slice(3), "deaths") )
SetStatsLabelValue( file.menu, "KillsLabel2", Localize("#MAPS_TSD") )
SetStatsLabelValue( file.menu, "KillsValue2", HammerToMeterString(float(pulseParse("maps", mapName.slice(3), "total_distance"))))
SetStatsLabelValue( file.menu, "KillsLabel3", Localize("#MAPS_MSD") )
SetStatsLabelValue( file.menu, "KillsValue3", HammerToMeterString(float(pulseParse("maps", mapName.slice(3), "max_distance"))))
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"))))
//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]
}
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"])
{
float modePlayedTime = 0
modePlayedTime = float(pulseParse("gamemodesSeparated", mapName.slice(3), modeName, "kills"))
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, GameMode_GetName( modeName ), modePlayedTime, GetGameModeDisplayColor( modeName ) )
}
}
}
foreach (string key, array<int> value in customGamemodeList)
{
if (mapName.slice(3) in pulseData["gamemodesSeparated"])
{
float modePlayedTime = 0
modePlayedTime = float(pulseParse("gamemodesSeparated", mapName.slice(3), key, "kills"))
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, customGamemodeNames[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_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 )
}
@@ -5,9 +5,14 @@ global function InitViewStatsOverviewMenu
struct struct
{ {
var menu var menu
array<ItemDisplayData> allTitans
array<ItemDisplayData> allPilotWeapons
table<string, array<string> > titanStatLoadout
} file } file
const MAX_DOTS_ON_GRAPH = 10 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_STRYDER = $"ui/menu/personal_stats/ps_titan_icon_stryder"
const IMAGE_TITAN_ATLAS = $"ui/menu/personal_stats/ps_titan_icon_atlas" const IMAGE_TITAN_ATLAS = $"ui/menu/personal_stats/ps_titan_icon_atlas"
@@ -27,10 +32,46 @@ void function InitViewStatsOverviewMenu()
AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
} }
void function GetTitanKills()
{
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 ( titan in file.allTitans)
{
foreach ( weaponRef in file.titanStatLoadout[ titan.ref ])
{
titanKillData[weaponRef] <- pulseParse("weaponsLocal", weaponRef, "kills")
}
}
}
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() void function OnStatsOverview_Open()
{ {
UI_SetPresentationType( ePresentationType.NO_MODELS ) UI_SetPresentationType( ePresentationType.NO_MODELS )
GetTitanKills()
UpdateViewStatsOverviewMenu() UpdateViewStatsOverviewMenu()
} }
@@ -51,12 +92,19 @@ function UpdateViewStatsOverviewMenu()
int timesMVP = GetPlayerStatInt( player, "game_stats", "mvp_total" ) int timesMVP = GetPlayerStatInt( player, "game_stats", "mvp_total" )
int timesTop3 = GetPlayerStat_AllCompetitiveModesAndMapsInt( player, "game_stats", "top3OnTeam" ) int timesTop3 = GetPlayerStat_AllCompetitiveModesAndMapsInt( player, "game_stats", "top3OnTeam" )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat0" ), Localize( "#STATS_HEADER_TIME_PLAYED" ), timePlayed ) //SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat0" ), Localize( "#STATS_HEADER_TIME_PLAYED" ), timePlayed )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat1" ), Localize( "#STATS_GAMES_PLAYED" ), string( gamesPlayed ) ) //SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat1" ), Localize( "#STATS_GAMES_PLAYED" ), string( gamesPlayed ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat2" ), Localize( "#STATS_GAMES_WON" ), string( gamesWon ) ) //SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat2" ), Localize( "#STATS_GAMES_WON" ), string( gamesWon ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat3" ), Localize( "#STATS_GAMES_WIN_PERCENT" ), Localize( "#STATS_PERCENTAGE", winPercent ) ) //SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat3" ), Localize( "#STATS_GAMES_WIN_PERCENT" ), Localize( "#STATS_PERCENTAGE", winPercent ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat4" ), Localize( "#STATS_GAMES_MVP" ), string( timesMVP ) ) //SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat4" ), Localize( "#STATS_GAMES_MVP" ), string( timesMVP ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat5" ), Localize( "#STATS_GAMES_TOP3" ), string( timesTop3 ) ) //SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat5" ), Localize( "#STATS_GAMES_TOP3" ), string( timesTop3 ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat0" ), Localize( "#STATS_HEADER_TIME_PLAYED" ), string( 0 ))
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat1" ), Localize( "#STATS_GAMES_PLAYED" ), string( 0 ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat2" ), Localize( "#STATS_GAMES_WON" ), string( 0 ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat3" ), Localize( "#STATS_GAMES_WIN_PERCENT" ), string( 0 ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat4" ), Localize( "#STATS_GAMES_MVP" ), string( 0 ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat5" ), Localize( "#STATS_GAMES_TOP3" ), string( 0 ) )
//######################### //#########################
// Modes // Modes
@@ -118,7 +166,7 @@ function UpdateViewStatsOverviewMenu()
table<string, table> weaponData = GetOverviewWeaponData() table<string, table> weaponData = GetOverviewWeaponData()
table mostKillsData = weaponData[ "most_kills" ] table mostKillsData = weaponData[ "most_kills" ]
table mostUsedData = weaponData[ "most_used" ] table nemesisWeapon = weaponData[ "nemesis_weapon" ]
table highestKPMData = weaponData[ "highest_kpm" ] table highestKPMData = weaponData[ "highest_kpm" ]
var weaponImageElem var weaponImageElem
@@ -158,14 +206,14 @@ function UpdateViewStatsOverviewMenu()
weaponNameElem = Hud_GetChild( file.menu, "WeaponName1" ) weaponNameElem = Hud_GetChild( file.menu, "WeaponName1" )
weaponDescElem = Hud_GetChild( file.menu, "WeaponDesc1" ) weaponDescElem = Hud_GetChild( file.menu, "WeaponDesc1" )
noDataElem = Hud_GetChild( file.menu, "WeaponImageTextOverlay1" ) noDataElem = Hud_GetChild( file.menu, "WeaponImageTextOverlay1" )
if ( mostUsedData.ref != "" ) if ( nemesisWeapon.ref != "" )
{ {
SetItemImageWidth( weaponImageElem, expect string( mostUsedData.ref ) ) SetItemImageWidth( weaponImageElem, expect string( nemesisWeapon.ref ) )
RuiSetImage( weaponRui, "buttonImage", GetItemImage( expect string( mostUsedData.ref ) ) ) RuiSetImage( weaponRui, "buttonImage", GetItemImage( expect string( nemesisWeapon.ref ) ) )
Hud_Show( weaponImageElem ) Hud_Show( weaponImageElem )
Hud_SetText( weaponNameElem, mostUsedData.printName ) Hud_SetText( weaponNameElem, nemesisWeapon.printName )
Hud_Show( weaponNameElem ) Hud_Show( weaponNameElem )
SetStatsLabelValue( file.menu, "WeaponDesc1", HoursToTimeString( expect float( mostUsedData.val ) ) ) Hud_SetText( weaponDescElem, Localize("#NEMESIS_WEAPON_VALUE"), nemesisWeapon.val)
Hud_Show( weaponDescElem ) Hud_Show( weaponDescElem )
Hud_Hide( noDataElem ) Hud_Hide( noDataElem )
} }
@@ -190,7 +238,7 @@ function UpdateViewStatsOverviewMenu()
Hud_Show( weaponImageElem ) Hud_Show( weaponImageElem )
Hud_SetText( weaponNameElem, highestKPMData.printName ) Hud_SetText( weaponNameElem, highestKPMData.printName )
Hud_Show( weaponNameElem ) Hud_Show( weaponNameElem )
Hud_SetText( weaponDescElem, "#STATS_MOST_EFFICIENT_VALUE", highestKPMData.val ) Hud_SetText( weaponDescElem, "%s1 K/D", highestKPMData.val)
Hud_Show( weaponDescElem ) Hud_Show( weaponDescElem )
Hud_Hide( noDataElem ) Hud_Hide( noDataElem )
} }
@@ -246,22 +294,48 @@ function UpdateViewStatsOverviewMenu()
//######################### //#########################
// Lifetime // Lifetime
local lifetimeAverage = player.GetPersistentVar( "kdratio_lifetime" ).tofloat() table playerweaponData = expect table(pulseData["weaponsLocal"])
local formattedLifetimeAverage table globalweaponData = expect table(pulseData["weaponsGlobal"])
if ( lifetimeAverage % 1 == 0 )
formattedLifetimeAverage = format( "%.0f", lifetimeAverage )
else
formattedLifetimeAverage = format( "%.1f", lifetimeAverage )
SetStatsLabelValue( file.menu, "LifetimeAverageValue", [ "#STATS_KD_VALUE", formattedLifetimeAverage ] )
// Lifetime (PVP)
local lifetimeAveragePVP = player.GetPersistentVar( "kdratio_lifetime_pvp" ).tofloat() var totalPilotKills = 0
local formattedLifetimeAveragePVP var totalPilotDeaths = 0
if ( lifetimeAveragePVP % 1 == 0 ) foreach (var key, var value in playerweaponData) {
formattedLifetimeAveragePVP = format( "%.0f", lifetimeAveragePVP ) table values = expect table(value)
else totalPilotKills += values["kills"]
formattedLifetimeAveragePVP = format( "%.1f", lifetimeAveragePVP ) totalPilotDeaths += values["deaths"]
SetStatsLabelValue( file.menu, "LifetimePVPAverageValue", [ "#STATS_KD_VALUE", formattedLifetimeAveragePVP ] ) }
var totalGlobalKills = 0
var totalGlobalDeaths = 0
foreach (var key, var value in globalweaponData) {
table values = expect table(value)
totalGlobalKills += values["kills"]
totalGlobalDeaths += values["deaths"]
}
var killsAsTitan = 0
var killsAsPilot = 0
foreach (var key, var value in playerweaponData) {
if (key in titanKillData) {
killsAsTitan += titanKillData[string(key)]
} else {
killsAsPilot += pulseParse("weaponsLocal", string(key), "kills")
}
}
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 bool last10GamesStatsVisible = gamesPlayed >= NUM_GAMES_TRACK_KDRATIO ? true : false
SetLast10GamesStatVisibility( file.menu, last10GamesStatsVisible ) SetLast10GamesStatVisibility( file.menu, last10GamesStatsVisible )
@@ -291,7 +365,7 @@ function UpdateViewStatsOverviewMenu()
else else
kdratio_match_average = format( "%.1f", kdratio_match_average ) kdratio_match_average = format( "%.1f", kdratio_match_average )
SetStatsLabelValue( file.menu, "Last10GamesValue", [ "#STATS_KD_VALUE", 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) // Last 10 (PVP)
local kdratiopvp_match_sum = 0 local kdratiopvp_match_sum = 0
@@ -309,38 +383,33 @@ function UpdateViewStatsOverviewMenu()
else else
kdratiopvp_match_average = format( "%.1f", kdratiopvp_match_average ) kdratiopvp_match_average = format( "%.1f", kdratiopvp_match_average )
SetStatsLabelValue( file.menu, "Last10GamesPVPValue", [ "#STATS_KD_VALUE", 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 )
var totalPilotKills = 0
foreach (var key, var value in globalToneAPIKillData) {
totalPilotKills += value
}
///////////////////////// /////////////////////////
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, "KillsAsPilotValue1" ), string( GetPlayerStatInt( player, "kills_stats", "titanKillsAsPilot" ) ) )
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue2" ), string( GetPlayerStatInt( player, "kills_stats", "totalNPC" ) ) ) Hud_SetText( GetElem( file.menu, "KillsAsPilotValue2" ), string( GetPlayerStatInt( player, "kills_stats", "totalNPC" ) ) )
Hud_SetText( GetElem( file.menu, "KillsAsPilotValue3" ), string( GetPlayerStatInt( player, "kills_stats", "pilotKickMeleePilot" ) ) ) 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( GetPlayerStatInt( player, "kills_stats", "pilotExecutePilot" ) ) ) Hud_SetText( GetElem( file.menu, "KillsAsPilotValue4" ), string( pulseParse("weaponsLocal", "human_execution", "kills") ) )
// Hud_SetText( GetElem( file.menu, "KillsAsPilotValue5" ), string( GetPlayerStatInt( player, "kills_stats", "titanFallKill" ) ) ) // 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")
var titanExecutions = pulseParse("weaponsLocal", "titan_execution", "kills")
int totalTitanExecutions = 0 Hud_SetText( GetElem( file.menu, "KillsAsTitanValue0" ), string( killsAsTitan ) )
totalTitanExecutions += GetPlayerStatInt( player, "kills_stats", "titanExocutionIon" )
totalTitanExecutions += GetPlayerStatInt( player, "kills_stats", "titanExocutionScorch" )
totalTitanExecutions += GetPlayerStatInt( player, "kills_stats", "titanExocutionNorthstar" )
totalTitanExecutions += GetPlayerStatInt( player, "kills_stats", "titanExocutionRonin" )
totalTitanExecutions += GetPlayerStatInt( player, "kills_stats", "titanExocutionTone" )
totalTitanExecutions += GetPlayerStatInt( player, "kills_stats", "titanExocutionLegion" )
totalTitanExecutions += GetPlayerStatInt( player, "kills_stats", "titanExocutionVanguard" )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue0" ), string( GetPlayerStatInt( player, "kills_stats", "pilotKillsAsTitan" ) ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue1" ), string( GetPlayerStatInt( player, "kills_stats", "titanKillsAsTitan" ) ) ) Hud_SetText( GetElem( file.menu, "KillsAsTitanValue1" ), string( GetPlayerStatInt( player, "kills_stats", "titanKillsAsTitan" ) ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue2" ), string( totalTitanExecutions ) ) Hud_SetText( GetElem( file.menu, "KillsAsTitanValue2" ), string( titanExecutions ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue3" ), string( GetPlayerStatInt( player, "kills_stats", "titanMeleePilot" ) ) ) Hud_SetText( GetElem( file.menu, "KillsAsTitanValue3" ), string( titanMeleeKills ) )
Hud_SetText( GetElem( file.menu, "KillsAsTitanValue4" ), string( GetPlayerStatInt( player, "kills_stats", "titanStepCrushPilot" ) ) ) Hud_SetText( GetElem( file.menu, "KillsAsTitanValue4" ), string( pulseParse("weaponsLocal", "damagedef_titan_step", "kills") ) )
} }
function PlotKDPointsOnGraph( menu, graphIndex, values, dottedAverage ) function PlotKDPointsOnGraph( menu, graphIndex, values, dottedAverage )
@@ -0,0 +1,206 @@
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(pulseParse("weaponsLocal", weaponRef, "kills"))
}
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
table playerweaponData = expect table(pulseData["weaponsLocal"])
foreach (var key, var value in playerweaponData) {
table values = expect table(value)
totalPilotKills += values["kills"]
}
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", Localize("#TIME_KILLS_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", Localize("#TIME_KILLS_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]
}
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 )
{
float modePlayedTime = 0
modePlayedTime = float(pulseParse("gamemodesAll", modeName, "kills"))
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, GameMode_GetName( modeName ), modePlayedTime, GetGameModeDisplayColor( modeName ) )
}
}
}
foreach (string key, array<int> value in customGamemodeList)
{
if ( pulseParse("gamemodesAll", key, "kills") != 0 )
{
float modePlayedTime = 0
modePlayedTime = float(pulseParse("gamemodesAll", key, "kills"))
if ( modePlayedTime > 0 ) {
AddPieChartEntry( modes, customGamemodeNames[key], modePlayedTime, value)
}
}
}
PieChartData modesPlayedData
modesPlayedData.entries = modes
modesPlayedData.labelColor = [ 255, 255, 255, 255 ]
SetPieChartData( file.menu, "ModesPieChart", Localize("#KILLS_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 )
}
@@ -0,0 +1,227 @@
//TODO: Kills Per Minute stat
global function InitViewStatsTitansMenu
struct
{
var menu
var[NUM_PERSISTENT_TITAN_LOADOUTS] buttons
array<ItemDisplayData> allTitans
table<string, array<string> > titanStatLoadout
} file
void function InitViewStatsTitansMenu()
{
var menu = GetMenu( "ViewStats_Titans_Menu" )
file.menu = menu
Hud_SetText( Hud_GetChild( file.menu, "MenuTitle" ), "#STATS_TITANS" )
AddMenuEventHandler( file.menu, eUIEvent.MENU_OPEN, OnViewStatsTitans_Open )
for ( int i = 0; i < NUM_PERSISTENT_TITAN_LOADOUTS; i++ )
{
var button = Hud_GetChild( menu, "Button" + i )
//button.s.rowIndex <- i
//Hud_AddEventHandler( button, UIE_CLICK, OnButton_Activate )
Hud_AddEventHandler( button, UIE_GET_FOCUS, OnButton_Focused )
file.buttons[i] = button
}
AddMenuFooterOption( file.menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
}
void function OnViewStatsTitans_Open()
{
UI_SetPresentationType( ePresentationType.STORE_PRIME_TITANS )
RunMenuClientFunction( "UpdateTitanModel", 0 )
// Get Titan list
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" ) ) )
}
UpdateButtons( 0, file.buttons )
UpdateStatsForTitan( file.allTitans[ 0 ].ref, 0 )
}
void function UpdateButtons( int selectedIndex, var[NUM_PERSISTENT_TITAN_LOADOUTS] buttons )
{
foreach ( index, button in buttons )
{
TitanLoadoutDef loadout = GetCachedTitanLoadout( index )
RHud_SetText( button, GetTitanLoadoutName( loadout ) )
Hud_SetEnabled( button, true )
Hud_SetVisible( button, true )
}
}
//void function OnButton_Activate( var button )
//{
// int id = int( Hud_GetScriptID( button ) )
// if ( !IsControllerModeActive() )
// UpdateStatsForTitan( file.allTitans[ id ].ref, id )
//}
void function OnButton_Focused( var button )
{
int id = int( Hud_GetScriptID( button ) )
//if ( IsControllerModeActive() )
UpdateStatsForTitan( file.allTitans[ id ].ref, id )
}
void function UpdateStatsForTitan( string titanRef, int loadoutIndex )
{
entity player = GetUIPlayer()
if ( player == null )
return
RunMenuClientFunction( "UpdateTitanModel", loadoutIndex )
RunMenuClientFunction( "UpdateStorePrimeBg", loadoutIndex )
// Name
Hud_SetText( Hud_GetChild( file.menu, "TitanName" ), GetItemName( titanRef ) )
// Locked info
var lockLabel = GetElementsByClassname( file.menu, "LblTitanLocked" )[0]
if ( IsItemLocked( player, titanRef ) )
{
Hud_SetText( lockLabel, "#LOUADOUT_UNLOCK_REQUIREMENT_LEVEL", GetUnlockLevelReq( titanRef ) )
Hud_Show( lockLabel )
}
else
{
Hud_Hide( lockLabel )
}
string timeUsed = StatToTimeString( "time_stats", "hours_as_titan_" + titanRef )
int shotsHit
foreach ( weaponRef in file.titanStatLoadout[ titanRef ] )
shotsHit += GetPlayerStatInt( player, "weapon_stats", "shotsHit", weaponRef )
int coresEarned = GetPlayerStatInt( player, "titan_stats", "coresEarned", titanRef )
int crits
bool critsApplicable = false
foreach ( weaponRef in file.titanStatLoadout[ titanRef ] )
{
if ( GetWeaponInfoFileKeyField_Global( weaponRef, "critical_hit" ) == true )
{
critsApplicable = true
crits += GetPlayerStatInt( player, "weapon_stats", "critHits", weaponRef )
}
}
string critHitsValue = Localize( "#STATS_NOT_APPLICABLE" )
if ( critsApplicable )
critHitsValue = string( crits )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat0" ), Localize( "#STATS_HEADER_TIME_USED" ), timeUsed )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat1" ), Localize( "#STATS_HEADER_SHOTS_HIT" ), string( shotsHit ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat2" ), Localize( "#STATS_HEADER_CORES_EARNED" ), string( coresEarned ) )
SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat3" ), Localize( "#STATS_HEADER_CRITICAL_HITS" ), critHitsValue )
string nextUnlockRef = GetNextUnlockForTitanLevel( player, titanRef, TitanGetRawLevel( player, titanRef ) + 1 )
if ( nextUnlockRef != "" )
{
var rui = Hud_GetRui( Hud_GetChild( file.menu, "NextUnlock" ) )
if ( nextUnlockRef == "random" )
{
RuiSetString( rui, "unlockName", "" )
RuiSetImage( rui, "unlockImage", $"rui/menu/common/unlock_random" )
}
else
{
ItemDisplayData displayData
if ( IsSubItemType( GetItemType( nextUnlockRef ) ) )
displayData = GetItemDisplayData( nextUnlockRef, titanRef )
else
displayData = GetItemDisplayData( nextUnlockRef )
RuiSetString( rui, "unlockName", displayData.name )
RuiSetImage( rui, "unlockImage", displayData.image )
vector aspect = GetItemImageAspect( nextUnlockRef )
float mult = 1.0
if ( aspect.x > aspect.y )
mult = 120.0 / aspect.x
else
mult = 120.0 / aspect.y
aspect.x *= mult
aspect.y *= mult
RuiSetFloat2( rui, "unlockImageSize", aspect )
}
}
int totalKills
int pilotKills
int titanKills
int aiKills
foreach ( weaponRef in file.titanStatLoadout[ titanRef ] )
{
totalKills += pulseParse("weaponsLocal", weaponRef, "kills")
pilotKills += GetPlayerStatInt( player, "weapon_kill_stats", "pilots", weaponRef )
titanKills += GetPlayerStatInt( player, "weapon_kill_stats", "titansTotal", weaponRef )
aiKills += GetPlayerStatInt( player, "weapon_kill_stats", "ai", weaponRef )
}
// Total Kills Stats
SetStatsLabelValue( file.menu, "KillsValue0", totalKills )
SetStatsLabelValue( file.menu, "KillsValue1", pilotKills )
SetStatsLabelValue( file.menu, "KillsValue2", titanKills )
SetStatsLabelValue( file.menu, "KillsValue3", aiKills )
}
asset function GetTitanStatImage( string titanRef )
{
asset image
switch ( titanRef )
{
case "ion":
image = $"r2_ui/menus/loadout_icons/titans/ion_icon"
break
case "scorch":
image = $"r2_ui/menus/loadout_icons/titans/scorch_icon"
break
case "northstar":
image = $"r2_ui/menus/loadout_icons/titans/northstar_icon"
break
case "ronin":
image = $"r2_ui/menus/loadout_icons/titans/ronin_icon"
break
case "tone":
image = $"r2_ui/menus/loadout_icons/titans/tone_icon"
break
case "legion":
image = $"r2_ui/menus/loadout_icons/titans/legion_icon"
break
case "vanguard":
image = $"r2_ui/menus/loadout_icons/titans/vanguard_icon"
break
}
return image
}
@@ -306,10 +306,10 @@ table<string, table> function GetOverviewWeaponData()
Table[ "most_kills" ].ref <- "" Table[ "most_kills" ].ref <- ""
Table[ "most_kills" ].printName <- "" Table[ "most_kills" ].printName <- ""
Table[ "most_kills" ].val <- 0 Table[ "most_kills" ].val <- 0
Table[ "most_used" ] <- {} Table[ "nemesis_weapon" ] <- {}
Table[ "most_used" ].ref <- "" Table[ "nemesis_weapon" ].ref <- ""
Table[ "most_used" ].printName <- "" Table[ "nemesis_weapon" ].printName <- ""
Table[ "most_used" ].val <- 0 Table[ "nemesis_weapon" ].val <- 0
Table[ "highest_kpm" ] <- {} Table[ "highest_kpm" ] <- {}
Table[ "highest_kpm" ].ref <- "" Table[ "highest_kpm" ].ref <- ""
Table[ "highest_kpm" ].printName <- "" Table[ "highest_kpm" ].printName <- ""
@@ -338,7 +338,7 @@ table<string, table> function GetOverviewWeaponData()
if ( !PersistenceEnumValueIsValid( "loadoutWeaponsAndAbilities", weaponName ) ) if ( !PersistenceEnumValueIsValid( "loadoutWeaponsAndAbilities", weaponName ) )
continue continue
int val = getWeaponKillsFromToneApi(weaponName) int val = pulseParse("weaponsLocal", weaponName, "kills")
if ( val > Table[ "most_kills" ].val ) if ( val > Table[ "most_kills" ].val )
{ {
Table[ "most_kills" ].ref = weaponName Table[ "most_kills" ].ref = weaponName
@@ -346,24 +346,31 @@ table<string, table> function GetOverviewWeaponData()
Table[ "most_kills" ].val = val Table[ "most_kills" ].val = val
} }
float fVal = GetPlayerStatFloat( player, "weapon_stats", "hoursUsed", weaponName ) int nval = pulseParse("weaponsLocal", weaponName, "deaths")
if ( fVal > Table[ "most_used" ].val ) if ( nval > Table[ "nemesis_weapon" ].val )
{ {
Table[ "most_used" ].ref = weaponName Table[ "nemesis_weapon" ].ref = weaponName
Table[ "most_used" ].printName = weaponDisplayName Table[ "nemesis_weapon" ].printName = weaponDisplayName
Table[ "most_used" ].val = fVal Table[ "nemesis_weapon" ].val = nval
} }
local killsPerMinute = 0 float kdval = 0
local hoursEquipped = GetPlayerStatFloat( player, "weapon_stats", "hoursEquipped", weaponName ) float kval = 0
local killCount = GetPlayerStatInt( player, "weapon_kill_stats", "total", weaponName ) float dval = 0
if ( hoursEquipped > 0 ) if( pulseParse("weaponsLocal", weaponName, "kills") != 0 && pulseParse("weaponsLocal", weaponName, "deaths_while_equipped") != 0){
killsPerMinute = format( "%.2f", ( killCount / ( hoursEquipped * 60.0 ) ).tofloat() ) kval = float(pulseParse("weaponsLocal", weaponName, "kills"))
if ( killsPerMinute.tofloat() > Table[ "highest_kpm" ].val.tofloat() ) dval = float(pulseParse("weaponsLocal", weaponName, "deaths_while_equipped"))
if (kval / dval > kdval){
kdval = kval / dval
}
}
int rnd= int(kdval*100)
kdval = float(rnd)/100
if ( kdval > Table[ "highest_kpm" ].val.tofloat() )
{ {
Table[ "highest_kpm" ].ref = weaponName Table[ "highest_kpm" ].ref = weaponName
Table[ "highest_kpm" ].printName = weaponDisplayName Table[ "highest_kpm" ].printName = weaponDisplayName
Table[ "highest_kpm" ].val = killsPerMinute Table[ "highest_kpm" ].val = kdval
} }
} }
@@ -180,8 +180,8 @@ void function UpdateStatsForWeapon( string weaponRef )
} }
// Total Kills Stats // Total Kills Stats
SetStatsLabelValue( file.menu, "KillsValue0", getWeaponKillsFromToneApi(weaponRef) ) SetStatsLabelValue( file.menu, "KillsValue0", pulseParse("weaponsLocal", weaponRef, "kills") ) //Total kills
SetStatsLabelValue( file.menu, "KillsValue1", getWeaponKillsFromToneApi(weaponRef) ) SetStatsLabelValue( file.menu, "KillsValue1", pulseParse("weaponsLocal", weaponRef, "kills") ) //Pilots
SetStatsLabelValue( file.menu, "KillsValue2", GetPlayerStatInt( player, "weapon_kill_stats", "titansTotal", weaponRef ) ) SetStatsLabelValue( file.menu, "KillsValue2", GetPlayerStatInt( player, "weapon_kill_stats", "titansTotal", weaponRef ) ) //Titans
SetStatsLabelValue( file.menu, "KillsValue3", GetPlayerStatInt( player, "weapon_kill_stats", "ai", weaponRef ) ) SetStatsLabelValue( file.menu, "KillsValue3", pulseParse("weaponsLocal", weaponRef, "deaths_while_equipped")) // Deaths with weapon
} }