Files
ToneAPI_servermod/mod/scripts/vscripts/matchstat.nut
T
2023-09-07 00:33:58 +02:00

226 lines
8.7 KiB
Plaintext

global function matchstat_Init
typedef playerSpecificStats table < string, var >
typedef playerStats table < string, playerSpecificStats >
typedef players table < string, playerStats >
struct {
table < string, players > weaponsUsed
} file
void function matchstat_Init(){
WeaponFireCallbacks_AddCallbackOnOwnerClassFired("player", OnWeaponFired)
AddDamageCallback("player", OnDamage)
AddCallback_OnPlayerRespawned( TrackPlayer )
// AddCallback_GameStateEnter(eGameState.WinnerDetermined, StopTrackPlayer)
// FlagInit( "" )
AddCallback_GameStateEnter(eGameState.Postmatch, ToneAPI_CloseMatch)
}
var function incrementVar(var value){
return expect float(value) + 1
}
void function CreatePlayer(entity player){
string playerUID = player.GetUID()
if(!(playerUID in file.weaponsUsed)){
var playerName = player.GetPlayerName()
file.weaponsUsed[playerUID] <- {}
file.weaponsUsed[playerUID].weapons <- {}
file.weaponsUsed[playerUID].titans <- {}
file.weaponsUsed[playerUID].stats <- {}
file.weaponsUsed[playerUID].stats.distance <- {
ground = 0.0,
wall = 0.0,
air = 0.0
}
file.weaponsUsed[playerUID].stats.time <- {
ground = 0.0,
wall = 0.0,
air = 0.0
}
}
}
void function CreateWeaponStats(string weaponName, entity player){
CreatePlayer(player)
string playerUID = player.GetUID()
if(!(weaponName in file.weaponsUsed[playerUID].weapons)){
// Has to make ints floats because you can't mix types apparently
playerSpecificStats stats = {
shotsFired = 0.0,
shotsHit = 0.0,
shotsCrit = 0.0,
shotsHeadshot = 0.0,
shotsRichochet = 0.0,
playtime = 0.0
}
file.weaponsUsed[playerUID].weapons[weaponName] <- stats
}
}
void function CreateTitanStats(string titanName, entity player){
CreatePlayer(player)
string playerUID = player.GetUID()
if(!(titanName in file.weaponsUsed[playerUID].titans)){
// Has to make ints floats because you can't mix types apparently
playerSpecificStats stats = {
shotsFired = 0.0,
shotsHit = 0.0,
shotsCrit = 0.0,
shotsHeadshot = 0.0,
shotsRichochet = 0.0,
playtime = 0.0
}
file.weaponsUsed[playerUID].titans[titanName] <- stats
}
}
void function OnWeaponFired(entity weapon, WeaponPrimaryAttackParams attackParams, var ammoUsed){
entity player = weapon.GetOwner()
string weaponName = weapon.GetWeaponClassName()
if(!IsValid(player) || !player.IsPlayer()){
return
}
string playerUID = player.GetUID()
CreateWeaponStats(weaponName, player)
file.weaponsUsed[playerUID].weapons[weaponName].shotsFired = incrementVar(file.weaponsUsed[playerUID].weapons[weaponName].shotsFired)
if(player.IsTitan()){
string titanName = GetTitanCharacterName(player)
CreateTitanStats(titanName, player)
file.weaponsUsed[playerUID].titans[titanName].shotsFired = incrementVar(file.weaponsUsed[playerUID].titans[titanName].shotsFired)
}
}
void function OnDamage( entity victim, var damageInfo){
entity player = DamageInfo_GetAttacker( damageInfo )
if(!IsValid(player) || !player.IsPlayer()){
return
}
string playerUID = player.GetUID()
entity weapon = DamageInfo_GetWeapon( damageInfo )
entity inflictor = DamageInfo_GetInflictor( damageInfo )
string weaponName
if(weapon){
weaponName = weapon.GetWeaponClassName()
}
else{
if ( inflictor && inflictor instanceof CProjectile && inflictor.IsProjectile() ){
weaponName = inflictor.ProjectileGetWeaponClassName()
}else{
ToneAPI_Log("[ERRR] Couldn't get weapon information")
return
}
}
CreateWeaponStats(weaponName, player)
file.weaponsUsed[playerUID].weapons[weaponName].shotsHit = incrementVar(file.weaponsUsed[playerUID].weapons[weaponName].shotsHit)
if(player.IsTitan()){
string titanName = GetTitanCharacterName(player)
CreateTitanStats(titanName, player)
file.weaponsUsed[playerUID].titans[titanName].shotsHit = incrementVar(file.weaponsUsed[playerUID].titans[titanName].shotsHit)
}
int damageType = DamageInfo_GetCustomDamageType( damageInfo )
bool crit = bool( damageType & DF_CRITICAL )
bool headshot = bool( damageType & DF_HEADSHOT )
// if(crit){
// file.weaponsUsed[playerUID].weapons[weaponName].shotsCrit = incrementVar(file.weaponsUsed[playerUID].weapons[weaponName].shotsCrit)
// if(player.IsTitan()){
// file.weaponsUsed[playerUID].titans[titanName].shotsCrit = incrementVar(file.weaponsUsed[playerUID].titans[titanName].shotsCrit)
// }
// }
if(headshot || crit){
file.weaponsUsed[playerUID].weapons[weaponName].shotsHeadshot = incrementVar(file.weaponsUsed[playerUID].weapons[weaponName].shotsHeadshot)
if(player.IsTitan()){
string titanName = GetTitanCharacterName(player)
file.weaponsUsed[playerUID].titans[titanName].shotsHeadshot = incrementVar(file.weaponsUsed[playerUID].titans[titanName].shotsHeadshot)
}
}
if ( inflictor && inflictor.IsProjectile() ){
if(inflictor.proj.projectileBounceCount > 1){
file.weaponsUsed[playerUID].weapons[weaponName].shotsRichochet = incrementVar(file.weaponsUsed[playerUID].weapons[weaponName].shotsRichochet)
if(player.IsTitan()){
string titanName = GetTitanCharacterName(player)
file.weaponsUsed[playerUID].titans[titanName].shotsRichochet = incrementVar(file.weaponsUsed[playerUID].titans[titanName].shotsRichochet)
}
}
}
}
void function TrackPlayer(entity player) {
string playerUID = player.GetUID()
CreatePlayer(player)
thread TrackPlayer_Threaded(player)
}
// void function StopTrackPlayer() {
// }
void function TrackPlayer_Threaded(entity player){
player.EndSignal( "OnDestroy" )
player.EndSignal( "OnDeath" )
vector position = player.GetOrigin()
string playerUID = player.GetUID()
float interval = 0.2
while(true){
wait interval
// Hmm
Assert( IsValid( player ) )
if(!IsValid(player)) return
// Ugly, should probably use flags
if(GetGameState() == eGameState.WinnerDetermined) return
entity weapon = player.GetActiveWeapon()
if(weapon){
string weaponName = weapon.GetWeaponClassName()
CreateWeaponStats(weaponName, player)
file.weaponsUsed[playerUID].weapons[weaponName].playtime = expect float(file.weaponsUsed[playerUID].weapons[weaponName].playtime) + interval
}else{
CreatePlayer(player)
}
if(player.IsTitan()){
string titanName = GetTitanCharacterName(player)
CreateTitanStats(titanName, player)
file.weaponsUsed[playerUID].titans[titanName].playtime = expect float(file.weaponsUsed[playerUID].titans[titanName].playtime) + interval
}else if(player.IsPlayer()){
// Could be a little inaccurate but should work fine if interval is small enough
if(player.IsWallRunning()){
file.weaponsUsed[playerUID].stats.time.wall = expect float(file.weaponsUsed[playerUID].stats.time.wall) + interval
file.weaponsUsed[playerUID].stats.distance.wall = expect float(file.weaponsUsed[playerUID].stats.distance.wall) + Distance(position, player.GetOrigin())
}
else if(!player.IsOnGround()){
file.weaponsUsed[playerUID].stats.time.air = expect float(file.weaponsUsed[playerUID].stats.time.air) + interval
file.weaponsUsed[playerUID].stats.distance.air = expect float(file.weaponsUsed[playerUID].stats.distance.air) + Distance(position, player.GetOrigin())
}
else{
file.weaponsUsed[playerUID].stats.time.ground = expect float(file.weaponsUsed[playerUID].stats.time.ground) + interval
file.weaponsUsed[playerUID].stats.distance.ground = expect float(file.weaponsUsed[playerUID].stats.distance.ground) + Distance(position, player.GetOrigin())
}
}
position = player.GetOrigin()
}
}
void function ToneAPI_CloseMatch(){
if(!toneapi_data.matchId){
ToneAPI_Log("[ERRR] Match is not registered!")
return
}
HttpRequest request
request.method = HttpRequestMethod.POST
request.url = toneapi_data.Tone_URI + "/match/" + string(toneapi_data.matchId) + "/close"
request.body = EncodeJSON(file.weaponsUsed)
Tone_HTTP_Request(
request,
void
function(HttpRequestResponse response) {}
)
}