update
This commit is contained in:
parent
e41bb63fbd
commit
9533b13806
177
main.go
177
main.go
@ -43,6 +43,14 @@ type PlayerStats struct {
|
|||||||
RankNew int `json:"rankNew,omitempty"`
|
RankNew int `json:"rankNew,omitempty"`
|
||||||
RankChange int `json:"rankChange,omitempty"`
|
RankChange int `json:"rankChange,omitempty"`
|
||||||
WinCount int `json:"winCount,omitempty"`
|
WinCount int `json:"winCount,omitempty"`
|
||||||
|
OneK int `json:"oneK"`
|
||||||
|
TwoK int `json:"twoK"`
|
||||||
|
ThreeK int `json:"threeK"`
|
||||||
|
FourK int `json:"fourK"`
|
||||||
|
FiveK int `json:"fiveK"`
|
||||||
|
ShotsFired int `json:"shotsFired"`
|
||||||
|
ShotsHit int `json:"shotsHit"`
|
||||||
|
Aim float64 `json:"aim"` // Prozent
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoundResult struct {
|
type RoundResult struct {
|
||||||
@ -107,6 +115,22 @@ func parseSteamID(id string) (uint64, error) {
|
|||||||
return sid, err
|
return sid, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bullet-Waffen (Schusswaffen) erkennen – keine Nades/Knife/Zeus/Equipment
|
||||||
|
func isBulletWeapon(eq *common.Equipment) bool {
|
||||||
|
if eq == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch eq.Type {
|
||||||
|
case common.EqKnife, common.EqZeus, common.EqHE, common.EqMolotov, common.EqIncendiary, common.EqFlash, common.EqSmoke, common.EqDecoy:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
cls := eq.Class()
|
||||||
|
if cls == common.EqClassGrenade || cls == common.EqClassEquipment {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true // Pistols/SMG/Rifles/Heavy/Sniper
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
fmt.Println("❌ Demo-Datei fehlt")
|
fmt.Println("❌ Demo-Datei fehlt")
|
||||||
@ -129,18 +153,23 @@ func main() {
|
|||||||
var roundHistory []RoundResult
|
var roundHistory []RoundResult
|
||||||
var teamHistory = make(PlayerTeamHistory)
|
var teamHistory = make(PlayerTeamHistory)
|
||||||
|
|
||||||
|
// Per-Runde Kills, die bis zum *nächsten* RoundStart gehalten werden
|
||||||
|
var roundKills = make(map[uint64]int) // SteamID64 -> Kills in der aktuellen (zuletzt gestarteten) Runde
|
||||||
|
var haveOpenRound bool // true ab erstem RoundStart nach MatchStart
|
||||||
|
var lastNonSpecTeam = make(map[uint64]string) // "CT" oder "T"
|
||||||
|
|
||||||
if len(os.Args) >= 3 {
|
if len(os.Args) >= 3 {
|
||||||
inputId := os.Args[2]
|
inputId := os.Args[2]
|
||||||
_, err := fmt.Sscanf(inputId, "%d", &matchId)
|
_, err := fmt.Sscanf(inputId, "%d", &matchId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("⚠️ Ungültige matchId-Argument: %v\n", err)
|
fmt.Printf("⚠️ Ungültiges matchId-Argument: %v\n", err)
|
||||||
matchId = 0
|
matchId = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.RegisterNetMessageHandler(func(msg *msg.CSVCMsg_ServerInfo) {
|
p.RegisterNetMessageHandler(func(m *msg.CSVCMsg_ServerInfo) {
|
||||||
if msg != nil && msg.GetMapName() != "" {
|
if m != nil && m.GetMapName() != "" {
|
||||||
mapName = msg.GetMapName()
|
mapName = m.GetMapName()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -166,19 +195,81 @@ func main() {
|
|||||||
return stat
|
return stat
|
||||||
}
|
}
|
||||||
|
|
||||||
p.RegisterEventHandler(func(e events.RoundStart) {
|
// Hilfsfunktion: roundKills -> 1k/2k/3k/4k/5k übertragen
|
||||||
round := roundCount + 1 // nächste Runde
|
flushRoundKills := func() {
|
||||||
teamHistory[round] = map[uint64]string{}
|
for sid, k := range roundKills {
|
||||||
|
stat := playerStats[sid]
|
||||||
|
if stat == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case k == 1:
|
||||||
|
stat.OneK++
|
||||||
|
case k == 2:
|
||||||
|
stat.TwoK++
|
||||||
|
case k == 3:
|
||||||
|
stat.ThreeK++
|
||||||
|
case k == 4:
|
||||||
|
stat.FourK++
|
||||||
|
case k >= 5:
|
||||||
|
stat.FiveK++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roundKills = make(map[uint64]int)
|
||||||
|
}
|
||||||
|
|
||||||
for _, p := range p.GameState().Participants().Playing() {
|
p.RegisterEventHandler(func(e events.RoundStart) {
|
||||||
if p.Team == common.TeamCounterTerrorists {
|
if !p.GameState().IsMatchStarted() {
|
||||||
teamHistory[round][p.SteamID64] = "CT"
|
return
|
||||||
} else if p.Team == common.TeamTerrorists {
|
}
|
||||||
teamHistory[round][p.SteamID64] = "T"
|
|
||||||
|
if haveOpenRound {
|
||||||
|
flushRoundKills()
|
||||||
|
}
|
||||||
|
haveOpenRound = true
|
||||||
|
|
||||||
|
round := roundCount + 1
|
||||||
|
teamHistory[round] = map[uint64]string{}
|
||||||
|
for _, pl := range p.GameState().Participants().Playing() {
|
||||||
|
switch pl.Team {
|
||||||
|
case common.TeamCounterTerrorists:
|
||||||
|
teamHistory[round][pl.SteamID64] = "CT"
|
||||||
|
lastNonSpecTeam[pl.SteamID64] = "CT"
|
||||||
|
case common.TeamTerrorists:
|
||||||
|
teamHistory[round][pl.SteamID64] = "T"
|
||||||
|
lastNonSpecTeam[pl.SteamID64] = "T"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
p.RegisterEventHandler(func(e events.PlayerTeamChange) {
|
||||||
|
if e.Player == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sid := e.Player.SteamID64
|
||||||
|
// Nur Nicht-Spectator übernehmen; Spectator/Unassigned löscht NICHT den letzten Stand
|
||||||
|
switch e.NewTeam {
|
||||||
|
case common.TeamCounterTerrorists:
|
||||||
|
lastNonSpecTeam[sid] = "CT"
|
||||||
|
case common.TeamTerrorists:
|
||||||
|
lastNonSpecTeam[sid] = "T"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Schüsse zählen (nur Schusswaffen)
|
||||||
|
p.RegisterEventHandler(func(e events.WeaponFire) {
|
||||||
|
if !haveOpenRound {
|
||||||
|
return // Warmup ignorieren
|
||||||
|
}
|
||||||
|
if e.Shooter == nil || e.Weapon == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !isBulletWeapon(e.Weapon) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
getOrCreate(*e.Shooter).ShotsFired++
|
||||||
|
})
|
||||||
|
|
||||||
p.RegisterEventHandler(func(e events.Kill) {
|
p.RegisterEventHandler(func(e events.Kill) {
|
||||||
if e.Killer != nil && e.Victim != nil && e.Killer.SteamID64 != e.Victim.SteamID64 {
|
if e.Killer != nil && e.Victim != nil && e.Killer.SteamID64 != e.Victim.SteamID64 {
|
||||||
killerTeam := e.Killer.Team
|
killerTeam := e.Killer.Team
|
||||||
@ -187,6 +278,12 @@ func main() {
|
|||||||
if killerTeam != victimTeam && killerTeam != common.TeamSpectators {
|
if killerTeam != victimTeam && killerTeam != common.TeamSpectators {
|
||||||
stat := getOrCreate(*e.Killer)
|
stat := getOrCreate(*e.Killer)
|
||||||
stat.Kills++
|
stat.Kills++
|
||||||
|
|
||||||
|
// Nur zählen, wenn wir uns in/zwischen echten Runden befinden
|
||||||
|
if haveOpenRound {
|
||||||
|
roundKills[e.Killer.SteamID64]++
|
||||||
|
}
|
||||||
|
|
||||||
if e.IsHeadshot {
|
if e.IsHeadshot {
|
||||||
stat.Headshots++
|
stat.Headshots++
|
||||||
}
|
}
|
||||||
@ -214,32 +311,39 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if e.Victim != nil {
|
if e.Victim != nil {
|
||||||
stat := getOrCreate(*e.Victim)
|
getOrCreate(*e.Victim).Deaths++
|
||||||
stat.Deaths++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Assister != nil {
|
if e.Assister != nil {
|
||||||
stat := getOrCreate(*e.Assister)
|
getOrCreate(*e.Assister).Assists++
|
||||||
stat.Assists++
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
p.RegisterEventHandler(func(e events.PlayerFlashed) {
|
p.RegisterEventHandler(func(e events.PlayerFlashed) {
|
||||||
if e.Attacker != nil && e.Attacker.SteamID64 != e.Player.SteamID64 {
|
if e.Attacker != nil && e.Attacker.SteamID64 != e.Player.SteamID64 {
|
||||||
stat := getOrCreate(*e.Attacker)
|
getOrCreate(*e.Attacker).FlashAssists++
|
||||||
stat.FlashAssists++
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
p.RegisterEventHandler(func(e events.PlayerHurt) {
|
p.RegisterEventHandler(func(e events.PlayerHurt) {
|
||||||
if e.Attacker != nil && e.Attacker != e.Player {
|
if e.Attacker != nil && e.Attacker != e.Player {
|
||||||
stat := getOrCreate(*e.Attacker)
|
stat := getOrCreate(*e.Attacker)
|
||||||
|
|
||||||
|
// Utility-Damage separat zählen
|
||||||
if e.Weapon != nil {
|
if e.Weapon != nil {
|
||||||
switch e.Weapon.Type {
|
switch e.Weapon.Type {
|
||||||
case common.EqHE, common.EqMolotov, common.EqIncendiary:
|
case common.EqHE, common.EqMolotov, common.EqIncendiary:
|
||||||
stat.UtilityDamage += e.HealthDamage
|
stat.UtilityDamage += e.HealthDamage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Treffer (nur Schusswaffen, nur Gegner, nur echte Runden)
|
||||||
|
if haveOpenRound && e.HealthDamage > 0 && e.Weapon != nil && isBulletWeapon(e.Weapon) {
|
||||||
|
attTeam := e.Attacker.Team
|
||||||
|
vicTeam := e.Player.Team
|
||||||
|
if attTeam != vicTeam && attTeam != common.TeamSpectators {
|
||||||
|
stat.ShotsHit++
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -259,6 +363,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
p.RegisterEventHandler(func(e events.RoundEnd) {
|
p.RegisterEventHandler(func(e events.RoundEnd) {
|
||||||
|
// Scores & Round-History wie gehabt
|
||||||
scoreCT = p.GameState().TeamCounterTerrorists().Score()
|
scoreCT = p.GameState().TeamCounterTerrorists().Score()
|
||||||
scoreT = p.GameState().TeamTerrorists().Score()
|
scoreT = p.GameState().TeamTerrorists().Score()
|
||||||
roundCount++
|
roundCount++
|
||||||
@ -278,6 +383,7 @@ func main() {
|
|||||||
Winner: winner,
|
Winner: winner,
|
||||||
WinReason: reasonToString(e.Reason),
|
WinReason: reasonToString(e.Reason),
|
||||||
})
|
})
|
||||||
|
// KEIN flush hier! Nach-Runden-Kills sollen noch in diese Runde fallen.
|
||||||
})
|
})
|
||||||
|
|
||||||
p.RegisterEventHandler(func(e events.RankUpdate) {
|
p.RegisterEventHandler(func(e events.RankUpdate) {
|
||||||
@ -296,6 +402,11 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Letztes Flush falls Match endet ohne weiteren RoundStart
|
||||||
|
if haveOpenRound && len(roundKills) > 0 {
|
||||||
|
flushRoundKills()
|
||||||
|
}
|
||||||
|
|
||||||
teamAName := p.GameState().TeamCounterTerrorists().ClanName()
|
teamAName := p.GameState().TeamCounterTerrorists().ClanName()
|
||||||
if teamAName == "" {
|
if teamAName == "" {
|
||||||
teamAName = "CT"
|
teamAName = "CT"
|
||||||
@ -307,32 +418,44 @@ func main() {
|
|||||||
|
|
||||||
for _, stat := range playerStats {
|
for _, stat := range playerStats {
|
||||||
sid, _ := parseSteamID(stat.SteamID)
|
sid, _ := parseSteamID(stat.SteamID)
|
||||||
|
|
||||||
|
if t, ok := lastNonSpecTeam[sid]; ok && (t == "CT" || t == "T") {
|
||||||
|
stat.Team = t
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: letzter Runden-Eintrag aus teamHistory
|
||||||
lastTeam := ""
|
lastTeam := ""
|
||||||
lastRound := 0
|
lastRound := 0
|
||||||
|
|
||||||
for roundNum, roundTeams := range teamHistory {
|
for roundNum, roundTeams := range teamHistory {
|
||||||
if team, ok := roundTeams[sid]; ok && roundNum > lastRound {
|
if team, ok := roundTeams[sid]; ok && roundNum > lastRound {
|
||||||
lastTeam = team
|
lastTeam = team
|
||||||
lastRound = roundNum
|
lastRound = roundNum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stat.Team = lastTeam
|
stat.Team = lastTeam
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, player := range p.GameState().Participants().All() {
|
for _, pl := range p.GameState().Participants().All() {
|
||||||
sid := player.SteamID64
|
sid := pl.SteamID64
|
||||||
stat, ok := playerStats[sid]
|
stat, ok := playerStats[sid]
|
||||||
if !ok || player.Entity == nil {
|
if !ok || pl.Entity == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if val, ok := pl.Entity.PropertyValue("m_pActionTrackingServices.m_iDamage"); ok {
|
||||||
val, ok := player.Entity.PropertyValue("m_pActionTrackingServices.m_iDamage")
|
|
||||||
if ok {
|
|
||||||
stat.TotalDamage = val.Int()
|
stat.TotalDamage = val.Int()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Aim-Wert berechnen
|
||||||
|
for _, stat := range playerStats {
|
||||||
|
if stat.ShotsFired > 0 {
|
||||||
|
stat.Aim = sanitizeFloat(float64(stat.ShotsHit) * 100.0 / float64(stat.ShotsFired))
|
||||||
|
} else {
|
||||||
|
stat.Aim = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var ctPlayers, tPlayers []PlayerStats
|
var ctPlayers, tPlayers []PlayerStats
|
||||||
for _, stat := range playerStats {
|
for _, stat := range playerStats {
|
||||||
switch stat.Team {
|
switch stat.Team {
|
||||||
|
|||||||
BIN
parser_cs2-linux
BIN
parser_cs2-linux
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user