Problem with tRoundStartMoney and ctRoundStartMoney (first round of each side)
**Describe the bug**
Incorrect amounts for tRoundStartMoney and ctRoundStartMoney but **only** for the first round of each side (other rounds are OK).
Using parse function + clean_rounds (same problem using or not the argument remove_bad_scoring=True).

**To Reproduce**
Steps to reproduce the behavior:
1. Parse the following demos : [AST-MIBR](https://www.hltv.org/matches/2354338/astralis-vs-mibr-iem-katowice-2022-play-in), [BIG-GOD](https://www.hltv.org/matches/2354569/big-vs-godsent-esl-pro-league-season-15), [G2-VIT](https://www.hltv.org/matches/2353988/g2-vs-vitality-blast-premier-spring-groups-2022)
2. Check the following fields for the JSON : tRoundStartMoney and ctRoundStartMoney 
3. Problems detected: 

- AST-MIBR and BIG-GOD : wrong amounts for both team at round 1 and round 16
- G2-VIT : inferno : wrong amounts for both team at round 16, mirage : wrong amount at round 16 for Team Vitality, incorrect amounts for both team at round 16

**Expected behavior**
For round 1 and 16 the tRoundStartMoney and ctRoundStartMoney should be 4000$ (800$ per player)

**Screenshots**
N/A

**Desktop (please complete the following information):**
 - OS: [Windows]
 - Browser [N/A]
 - Version [N/A]

**Smartphone (please complete the following information):**
 - Device: [N/A]
 - OS: [N/A]
 - Browser [N/A]
 - Version [N/A]

**Additional context**
Other rounds work fine, no problem detected.

diff --git a/awpy/analytics/stats.py b/awpy/analytics/stats.py
index 6f48f0a..88e1f86 100644
--- a/awpy/analytics/stats.py
+++ b/awpy/analytics/stats.py
@@ -201,7 +201,9 @@ def player_stats(game_rounds, return_type="json"):
         )
     for player in player_statistics:
         player_statistics[player]["kdr"] = round(
-            player_statistics[player]["kills"] / player_statistics[player]["deaths"],
+            player_statistics[player]["kills"] / player_statistics[player]["deaths"]
+            if player_statistics[player]["deaths"] != 0
+            else player_statistics[player]["kills"],
             2,
         )
     for player in player_statistics:
@@ -218,7 +220,10 @@ def player_stats(game_rounds, return_type="json"):
         )
     for player in player_statistics:
         player_statistics[player]["hsPercent"] = round(
-            player_statistics[player]["hs"] / player_statistics[player]["kills"], 2
+            player_statistics[player]["hs"] / player_statistics[player]["kills"]
+            if player_statistics[player]["kills"] != 0
+            else 0,
+            2,
         )
     for player in player_statistics:
         impact = (
diff --git a/awpy/parser/demoparser.py b/awpy/parser/demoparser.py
index fde0df7..d97ec6e 100644
--- a/awpy/parser/demoparser.py
+++ b/awpy/parser/demoparser.py
@@ -16,6 +16,7 @@ class DemoParser:
         demo_id (string): A unique demo name/game id. Default is inferred from demofile name
         parse_rate (int): One of 128, 64, 32, 16, 8, 4, 2, or 1. The lower the value, the more frames are collected. Indicates spacing between parsed demo frames in ticks. Default is 128.
         parse_frames (bool): Flag if you want to parse frames (trajectory data) or not
+        parse_kill_frames (bool): Flag if you want to parse frames on kills
         trade_time (int): Length of the window for a trade (in seconds). Default is 5.
         dmg_rolled (bool): Boolean if you want damages rolled up (since multiple damages for a player can happen in 1 tick from the same weapon.)
         buy_style (string): Buy style string, one of "hltv" or "csgo"
@@ -32,6 +33,7 @@ class DemoParser:
         demo_id=None,
         parse_rate=128,
         parse_frames=True,
+        parse_kill_frames=False,
         trade_time=5,
         dmg_rolled=False,
         buy_style="hltv",
@@ -123,9 +125,11 @@ class DemoParser:
 
         self.dmg_rolled = dmg_rolled
         self.parse_frames = parse_frames
+        self.parse_kill_frames = parse_kill_frames
         self.json_indentation = json_indentation
         self.logger.info("Rollup damages set to " + str(self.dmg_rolled))
         self.logger.info("Parse frames set to " + str(self.parse_frames))
+        self.logger.info("Parse kill frames set to " + str(self.parse_kill_frames))
         self.logger.info("Output json indentation set to " + str(self.json_indentation))
 
         # Set parse error to False
@@ -182,6 +186,8 @@ class DemoParser:
             self.parser_cmd.append("--dmgrolled")
         if self.parse_frames:
             self.parser_cmd.append("--parseframes")
+        if self.parse_kill_frames:
+            self.parser_cmd.append("--parsekillframes")
         if self.json_indentation:
             self.parser_cmd.append("--jsonindentation")
         proc = subprocess.Popen(
@@ -455,12 +461,10 @@ class DemoParser:
                 "roundEndReason",
                 "tStartEqVal",
                 "tRoundStartEqVal",
-                "tRoundStartMoney",
                 "tBuyType",
                 "tSpend",
                 "ctStartEqVal",
                 "ctRoundStartEqVal",
-                "ctRoundStartMoney",
                 "ctBuyType",
                 "ctSpend",
             ]
@@ -657,7 +661,7 @@ class DemoParser:
         remove_excess_players=True,
         remove_excess_kills=True,
         remove_bad_endings=True,
-        remove_bad_scoring=False,
+        remove_bad_scoring=True,
         return_type="json",
         save_to_json=True,
     ):
diff --git a/awpy/parser/parse_demo.go b/awpy/parser/parse_demo.go
index a356e46..4243ad8 100644
--- a/awpy/parser/parse_demo.go
+++ b/awpy/parser/parse_demo.go
@@ -34,11 +34,12 @@ type Game struct {
 
 // ParserOpts holds the parameters passed to the parser
 type ParserOpts struct {
-	ParseRate     int          `json:"parseRate"`
-	ParseFrames   bool         `json:"parseFrames"`
-	TradeTime     int64        `json:"tradeTime"`
-	RoundBuyStyle string       `json:"roundBuyStyle"`
-	DamagesRolled bool         `json:"damagesRolledUp"`
+	ParseRate       int    `json:"parseRate"`
+	ParseFrames     bool   `json:"parseFrames"`
+	ParseKillFrames bool   `json:"parseKillFrames"`
+	TradeTime       int64  `json:"tradeTime"`
+	RoundBuyStyle   string `json:"roundBuyStyle"`
+	DamagesRolled   bool   `json:"damagesRolledUp"`
 }
 
 // MatchPhases holds lists of when match events occurred
@@ -116,12 +117,12 @@ type GameRound struct {
 	Reason            string             `json:"roundEndReason"`
 	CTStartEqVal      int64              `json:"ctStartEqVal"`
 	CTBeginEqVal      int64              `json:"ctRoundStartEqVal"`
-	CTBeginMoney      int64              `json:"ctRoundStartMoney"`
+	// CTBeginMoney      int64              `json:"ctRoundStartMoney"`
 	CTBuyType         string             `json:"ctBuyType"`
 	CTSpend           int64              `json:"ctSpend"`
 	TStartEqVal       int64              `json:"tStartEqVal"`
 	TBeginEqVal       int64              `json:"tRoundStartEqVal"`
-	TBeginMoney       int64              `json:"tRoundStartMoney"`
+	// TBeginMoney       int64              `json:"tRoundStartMoney"`
 	TBuyType          string             `json:"tBuyType"`
 	TSpend            int64              `json:"tSpend"`
 	CTSide            PlayerTeams        `json:"ctSide"`
@@ -320,6 +321,7 @@ type FlashAction struct {
 
 // GameFrame (game state at time t)
 type GameFrame struct {
+	IsKillFrame bool          `json:"isKillFrame"`
 	Tick        int64         `json:"tick"`
 	Second      float64       `json:"seconds"`
 	ClockTime   string        `json:"clockTime"`
@@ -858,6 +860,7 @@ func main() {
 	demoPathPtr := fl.String("demo", "", "Demo file `path`")
 	parseRatePtr := fl.Int("parserate", 128, "Parse rate, indicates spacing between ticks")
 	parseFramesPtr := fl.Bool("parseframes", false, "Parse frames")
+	parseKillFramesPtr := fl.Bool("parsekillframes", false, "Parse kill frames")
 	tradeTimePtr := fl.Int("tradetime", 5, "Trade time frame (in seconds)")
 	roundBuyPtr := fl.String("buystyle", "hltv", "Round buy style")
 	damagesRolledPtr := fl.Bool("dmgrolled", false, "Roll up damages")
@@ -871,6 +874,7 @@ func main() {
 	demPath := *demoPathPtr
 	parseRate := *parseRatePtr
 	parseFrames := *parseFramesPtr
+	parseKillFrames := *parseKillFramesPtr
 	tradeTime := int64(*tradeTimePtr)
 	roundBuyStyle := *roundBuyPtr
 	damagesRolled := *damagesRolledPtr
@@ -1077,21 +1081,21 @@ func main() {
 		} 
 		
 		// Parse round money
-		tPlayers := gs.TeamTerrorists().Members()
-		currentRound.TBeginMoney = 0
-		ctPlayers := gs.TeamCounterTerrorists().Members()
-		currentRound.CTBeginMoney = 0
-		for _, p := range tPlayers {
-			if p != nil {
-				currentRound.TBeginMoney += int64(p.Money())
-			}
-
-		}
-		for _, p := range ctPlayers {
-			if p != nil {
-				currentRound.CTBeginMoney += int64(p.Money())
-			}
-		}
+		// tPlayers := gs.TeamTerrorists().Members()
+		// currentRound.TBeginMoney = 0
+		// ctPlayers := gs.TeamCounterTerrorists().Members()
+		// currentRound.CTBeginMoney = 0
+		// for _, p := range tPlayers {
+		// 	if p != nil {
+		// 		currentRound.TBeginMoney += int64(p.Money())
+		// 	}
+
+		// }
+		// for _, p := range ctPlayers {
+		// 	if p != nil {
+		// 		currentRound.CTBeginMoney += int64(p.Money())
+		// 	}
+		// }
 
 		// Parse the players
 		teamCT := PlayerTeams{}
@@ -1204,22 +1208,22 @@ func main() {
 				}
 			}
 
-			// Parse round money
-			tPlayers := gs.TeamTerrorists().Members()
-			currentRound.TBeginMoney = 0
-			ctPlayers := gs.TeamCounterTerrorists().Members()
-			currentRound.CTBeginMoney = 0
-			for _, p := range tPlayers {
-				if p != nil {
-					currentRound.TBeginMoney += int64(p.Money())
-				}
-
-			}
-			for _, p := range ctPlayers {
-				if p != nil {
-					currentRound.CTBeginMoney += int64(p.Money())
-				}
-			}
+			// // Parse round money
+			// tPlayers := gs.TeamTerrorists().Members()
+			// currentRound.TBeginMoney = 0
+			// ctPlayers := gs.TeamCounterTerrorists().Members()
+			// currentRound.CTBeginMoney = 0
+			// for _, p := range tPlayers {
+			// 	if p != nil {
+			// 		currentRound.TBeginMoney += int64(p.Money())
+			// 	}
+
+			// }
+			// for _, p := range ctPlayers {
+			// 	if p != nil {
+			// 		currentRound.CTBeginMoney += int64(p.Money())
+			// 	}
+			// }
 		}
 
 		// Parse the players
@@ -1356,8 +1360,8 @@ func main() {
 			}
 
 			// Parse round spend
-			currentRound.TBeginMoney = 800 * 5
-			currentRound.CTBeginMoney = 800 * 5
+			//currentRound.TBeginMoney = 800 * 5
+			//currentRound.CTBeginMoney = 800 * 5
 		}
 
 		roundInEndTime = 1
@@ -1854,6 +1858,111 @@ func main() {
 	p.RegisterEventHandler(func(e events.Kill) {
 		gs := p.GameState()
 
+		if (roundInFreezetime == 0) && (parseKillFrames == true) {
+			currentFrame := GameFrame{}
+			currentFrame.IsKillFrame = true
+
+			// Create empty player lists
+			currentFrame.CT.Players = []PlayerInfo{}
+			currentFrame.T.Players = []PlayerInfo{}
+
+			currentFrame.Tick = int64(gs.IngameTick())
+			currentFrame.Second = determineSecond(currentFrame.Tick, currentRound, currentGame)
+			currentFrame.ClockTime = calculateClocktime(currentFrame.Tick, currentRound, currentGame)
+
+			// Parse T
+			currentFrame.T = TeamFrameInfo{}
+			currentFrame.T.Side = "T"
+			if (gs.TeamTerrorists() != nil) {
+				currentFrame.T.Team = gs.TeamTerrorists().ClanName()
+			}
+			currentFrame.T.CurrentEqVal = int64(gs.TeamTerrorists().CurrentEquipmentValue())
+			tPlayers := gs.TeamTerrorists().Members()
+
+			for _, p := range tPlayers {
+				if p != nil {
+					if playerInList(p, currentFrame.T.Players) == false {
+						currentFrame.T.Players = append(currentFrame.T.Players, parsePlayer(gs, p))
+					}
+				}
+			}
+			
+			currentFrame.T.AlivePlayers = countAlivePlayers(currentFrame.T.Players)
+			currentFrame.T.TotalUtility = countUtility(currentFrame.T.Players)
+
+			// Parse CT
+			currentFrame.CT = TeamFrameInfo{}
+			currentFrame.CT.Side = "CT"
+			if (gs.TeamCounterTerrorists() != nil) {
+				currentFrame.CT.Team = gs.TeamCounterTerrorists().ClanName()
+			}
+			currentFrame.CT.CurrentEqVal = int64(gs.TeamCounterTerrorists().CurrentEquipmentValue())
+			ctPlayers := gs.TeamCounterTerrorists().Members()
+
+			for _, p := range ctPlayers {
+				if p != nil {
+					if playerInList(p, currentFrame.CT.Players) == false {
+						currentFrame.CT.Players = append(currentFrame.CT.Players, parsePlayer(gs, p))
+					}
+				}
+			}
+			
+			currentFrame.CT.AlivePlayers = countAlivePlayers(currentFrame.CT.Players)
+			currentFrame.CT.TotalUtility = countUtility(currentFrame.CT.Players)
+			
+
+			// Parse world (grenade) objects
+			allGrenades := gs.GrenadeProjectiles()
+			for _, ele := range allGrenades {
+				currentWorldObj := WorldObject{}
+				currentWorldObj.ObjType = ele.WeaponInstance.String()
+				objPos := ele.Trajectory[len(ele.Trajectory)-1]
+
+				currentWorldObj.X = float64(objPos.X)
+				currentWorldObj.Y = float64(objPos.Y)
+				currentWorldObj.Z = float64(objPos.Z)
+				currentFrame.World = append(currentFrame.World, currentWorldObj)
+			}
+
+			// Parse bomb
+			bombObj := gs.Bomb()
+			currentWorldObj := WorldObject{}
+			currentWorldObj.ObjType = "bomb"
+			objPos := bombObj.Position()
+
+			currentWorldObj.X = float64(objPos.X)
+			currentWorldObj.Y = float64(objPos.Y)
+			currentWorldObj.Z = float64(objPos.Z)
+			currentFrame.World = append(currentFrame.World, currentWorldObj)
+			if len(currentRound.Bomb) > 0 {
+				for _, b := range currentRound.Bomb {
+					if b.BombAction == "plant" {
+						currentFrame.BombPlanted = true
+						currentFrame.BombSite = *b.BombSite
+					}
+				}	
+			} else {
+				currentFrame.BombPlanted = false
+			}
+
+			// Add frame
+			if (len(currentFrame.CT.Players) > 0) || (len(currentFrame.T.Players) > 0) {
+				if (len(currentRound.Frames) > 0) {
+					if currentRound.Frames[len(currentRound.Frames)-1].Tick < currentFrame.Tick {
+						currentRound.Frames = append(currentRound.Frames, currentFrame)
+					}
+				} else {
+					currentRound.Frames = append(currentRound.Frames, currentFrame)
+				}
+			}
+			
+			if currentFrameIdx == (currentGame.ParsingOpts.ParseRate - 1) {
+				currentFrameIdx = 0
+			} else {
+				currentFrameIdx = currentFrameIdx + 1
+			}	
+		}
+
 		currentKill := KillAction{}
 		currentKill.Tick = int64(gs.IngameTick())
 		currentKill.Second = determineSecond(currentKill.Tick, currentRound, currentGame)
@@ -2170,8 +2279,30 @@ func main() {
 	p.RegisterEventHandler(func(e events.FrameDone) {
 		gs := p.GameState()
 
+		// Parse the players
+		teamCT := PlayerTeams{}
+		teamCT.TeamName = gs.TeamCounterTerrorists().ClanName()
+		for _, player := range gs.TeamCounterTerrorists().Members() {
+			pl := Players{}
+			pl.PlayerName = player.Name
+			pl.SteamID = int64(player.SteamID64)
+			teamCT.Players = append(teamCT.Players, pl)
+		}
+		currentRound.CTSide = teamCT
+
+		teamT := PlayerTeams{}
+		teamT.TeamName = gs.TeamTerrorists().ClanName()
+		for _, player := range gs.TeamTerrorists().Members() {
+			pl := Players{}
+			pl.PlayerName = player.Name
+			pl.SteamID = int64(player.SteamID64)
+			teamT.Players = append(teamT.Players, pl)
+		}
+		currentRound.TSide = teamT
+		
 		if (roundInFreezetime == 0) && (currentFrameIdx == 0) && (parseFrames == true) {
 			currentFrame := GameFrame{}
+			currentFrame.IsKillFrame = false
 
 			// Create empty player lists
 			currentFrame.CT.Players = []PlayerInfo{}
diff --git a/docs/parser_output.rst b/docs/parser_output.rst
index 2deacbd..d847f46 100644
--- a/docs/parser_output.rst
+++ b/docs/parser_output.rst
@@ -32,7 +32,8 @@ Top level keys
         "parsedToFrameIdx": 80790,                      # Parsed until X frame
         "parserParameters": {                           # All the below parameters are set in DemoParser
             "parseRate": 256,                           # Parse rate set in DemoParser. Represents spacing between recorded frames.
-            "parseFrames": false,                        
+            "parseFrames": false,     
+            "parseKillFrames": true,                    # If set to true, a frame is recorded every kill. Doesn"t require parseFrames == true                   
             "tradeTime": 5,                             
             "roundBuyStyle": "hltv",                    # HLTV represents round buys (e.g., full eco, full buy, etc.) as they do in HLTV.
             "damagesRolledUp": false                    # Sometimes damages can happen in the same tick. This option means they are combined.
@@ -155,52 +156,52 @@ Kills
 .. code-block:: json
 
     {
-        'tick': 9582, 
-        'seconds': 25.71875, 
-        'clockTime': '01:30', 
-        'attackerSteamID': 76561198088580941, 
-        'attackerName': 'febix', 
-        'attackerTeam': '', 
-        'attackerSide': 'T', 
-        'attackerX': 509.1275939941406, 
-        'attackerY': 630.7955322265625, 
-        'attackerZ': 86.98412322998047, 
-        'attackerViewX': 327.601318359375, 
-        'attackerViewY': 1.9775390625, 
-        'victimSteamID': 76561198084596669, 
-        'victimName': 'Rullaan Spotil KANDALFWOZ ;)', 
-        'victimTeam': '', 
-        'victimSide': 'CT', 
-        'victimX': 781.4129638671875, 
-        'victimY': 491.81201171875, 
-        'victimZ': 87.30707550048828, 
-        'victimViewX': 153.6328125, 
-        'victimViewY': 1.0711669921875, 
-        'assisterSteamID': None,                       # If there is an assister, this data will not be None
-        'assisterName': None, 
-        'assisterTeam': None, 
-        'assisterSide': None, 
-        'isSuicide': False, 
-        'isTeamkill': False, 
-        'isWallbang': False, 
-        'penetratedObjects': 0, 
-        'isFirstKill': True, 
-        'isHeadshot': True, 
-        'victimBlinded': False, 
-        'attackerBlinded': False, 
-        'flashThrowerSteamID': None, 
-        'flashThrowerName': None, 
-        'flashThrowerTeam': None, 
-        'flashThrowerSide': None, 
-        'noScope': False, 
-        'thruSmoke': False, 
-        'distance': 305.7054888578491,                 # Distance between attacker and victim
-        'isTrade': False, 
-        'playerTradedName': None, 
-        'playerTradedTeam': None, 
-        'playerTradedSteamID': None, 
-        'weapon': 'Glock-18'
-        'weaponClass': 'Pistols'
+        "tick": 9582, 
+        "seconds": 25.71875, 
+        "clockTime": "01:30", 
+        "attackerSteamID": 76561198088580941, 
+        "attackerName": "febix", 
+        "attackerTeam": "", 
+        "attackerSide": "T", 
+        "attackerX": 509.1275939941406, 
+        "attackerY": 630.7955322265625, 
+        "attackerZ": 86.98412322998047, 
+        "attackerViewX": 327.601318359375, 
+        "attackerViewY": 1.9775390625, 
+        "victimSteamID": 76561198084596669, 
+        "victimName": "Rullaan Spotil KANDALFWOZ ;)", 
+        "victimTeam": "", 
+        "victimSide": "CT", 
+        "victimX": 781.4129638671875, 
+        "victimY": 491.81201171875, 
+        "victimZ": 87.30707550048828, 
+        "victimViewX": 153.6328125, 
+        "victimViewY": 1.0711669921875, 
+        "assisterSteamID": None,                       # If there is an assister, this data will not be None
+        "assisterName": None, 
+        "assisterTeam": None, 
+        "assisterSide": None, 
+        "isSuicide": False, 
+        "isTeamkill": False, 
+        "isWallbang": False, 
+        "penetratedObjects": 0, 
+        "isFirstKill": True, 
+        "isHeadshot": True, 
+        "victimBlinded": False, 
+        "attackerBlinded": False, 
+        "flashThrowerSteamID": None, 
+        "flashThrowerName": None, 
+        "flashThrowerTeam": None, 
+        "flashThrowerSide": None, 
+        "noScope": False, 
+        "thruSmoke": False, 
+        "distance": 305.7054888578491,                 # Distance between attacker and victim
+        "isTrade": False, 
+        "playerTradedName": None, 
+        "playerTradedTeam": None, 
+        "playerTradedSteamID": None, 
+        "weapon": "Glock-18"
+        "weaponClass": "Pistols"
     }
 
 Damages
@@ -211,38 +212,38 @@ The possible hit groups are `Generic`, `Head`, `Chest`, `Stomach`, `LeftArm`, `R
 .. code-block:: json
 
     {
-        'tick': 8172, 
-        'seconds': 3.6875, 
-        'clockTime': '01:52', 
-        'attackerSteamID': 76561198035759667, 
-        'attackerName': 'alo0o0o0o0', 
-        'attackerTeam': '', 
-        'attackerSide': 'T', 
-        'attackerX': -1184.6986083984375, 
-        'attackerY': 477.1373596191406, 
-        'attackerZ': -55.96875, 
-        'attackerViewX': 56.79931640625, 
-        'attackerViewY': 3.3837890625, 
-        'attackerStrafe': False,                 # Was the attacker moving when they shot
-        'victimSteamID': 76561197960742750, 
-        'victimName': 'howl', 
-        'victimTeam': '', 
-        'victimSide': 'T', 
-        'victimX': -1125.4398193359375, 
-        'victimY': 520.9878540039062, 
-        'victimZ': -51.978607177734375, 
-        'victimViewX': 9.2230224609375, 
-        'victimViewY': 0.6097412109375, 
-        'weapon': 'Knife', 
-        'weaponClass': 'Equipment',
-        'hpDamage': 61,                          # Can be over 100 (e.g., AWP headshots)
-        'hpDamageTaken': 61,                     # Damage actually taken by the victim
-        'armorDamage': 5, 
-        'armorDamageTaken': 5, 
-        'hitGroup': 'Generic', 
-        'isFriendlyFire': True, 
-        'distance': 73.82676464998524, 
-        'zoomLevel': 0                           # 0 for no zoom, 1 for half zoom, 2 for full zoom
+        "tick": 8172, 
+        "seconds": 3.6875, 
+        "clockTime": "01:52", 
+        "attackerSteamID": 76561198035759667, 
+        "attackerName": "alo0o0o0o0", 
+        "attackerTeam": "", 
+        "attackerSide": "T", 
+        "attackerX": -1184.6986083984375, 
+        "attackerY": 477.1373596191406, 
+        "attackerZ": -55.96875, 
+        "attackerViewX": 56.79931640625, 
+        "attackerViewY": 3.3837890625, 
+        "attackerStrafe": False,                 # Was the attacker moving when they shot
+        "victimSteamID": 76561197960742750, 
+        "victimName": "howl", 
+        "victimTeam": "", 
+        "victimSide": "T", 
+        "victimX": -1125.4398193359375, 
+        "victimY": 520.9878540039062, 
+        "victimZ": -51.978607177734375, 
+        "victimViewX": 9.2230224609375, 
+        "victimViewY": 0.6097412109375, 
+        "weapon": "Knife", 
+        "weaponClass": "Equipment",
+        "hpDamage": 61,                          # Can be over 100 (e.g., AWP headshots)
+        "hpDamageTaken": 61,                     # Damage actually taken by the victim
+        "armorDamage": 5, 
+        "armorDamageTaken": 5, 
+        "hitGroup": "Generic", 
+        "isFriendlyFire": True, 
+        "distance": 73.82676464998524, 
+        "zoomLevel": 0                           # 0 for no zoom, 1 for half zoom, 2 for full zoom
     }
 
 Grenades
@@ -251,24 +252,24 @@ Grenades
 .. code-block:: json
 
     {
-        'throwTick': 8500, 
-        'destroyTick': 8860,                  # When was the entity destroyed
-        'throwSeconds': 8.8125, 
-        'throwClockTime': '01:47', 
-        'destroySeconds': 14.4375, 
-        'destroyClockTime': '01:41', 
-        'throwerSteamID': 76561198098005932, 
-        'throwerName': 'aidan', 
-        'throwerTeam': '', 
-        'throwerSide': 'CT', 
-        'throwerX': 1330.09375, 
-        'throwerY': 570.0625, 
-        'throwerZ': 200.96875, 
-        'grenadeType': 'HE Grenade',
-        'grenadeX': 53.96875, 
-        'grenadeY': 671.5, 
-        'grenadeZ': 68.09375, 
-        'entityID': 5031578313293207366        # entity ID of the grenade
+        "throwTick": 8500, 
+        "destroyTick": 8860,                  # When was the entity destroyed
+        "throwSeconds": 8.8125, 
+        "throwClockTime": "01:47", 
+        "destroySeconds": 14.4375, 
+        "destroyClockTime": "01:41", 
+        "throwerSteamID": 76561198098005932, 
+        "throwerName": "aidan", 
+        "throwerTeam": "", 
+        "throwerSide": "CT", 
+        "throwerX": 1330.09375, 
+        "throwerY": 570.0625, 
+        "throwerZ": 200.96875, 
+        "grenadeType": "HE Grenade",
+        "grenadeX": 53.96875, 
+        "grenadeY": 671.5, 
+        "grenadeZ": 68.09375, 
+        "entityID": 5031578313293207366        # entity ID of the grenade
     }
 
 Bomb Events
@@ -279,17 +280,17 @@ The bomb action can be `defuse`, `defuse_start`, `defuse_aborted`, `plant`, `pla
 .. code-block:: json
 
     {
-        'tick': 12250, 
-        'seconds': 67.40625, 
-        'clockTime': '00:48', 
-        'playerSteamID': 76561198043315625, 
-        'playerName': 'Beach', 
-        'playerTeam': '', 
-        'playerX': 2160.965576171875, 
-        'playerY': 144.39041137695312, 
-        'playerZ': 160.03125, 
-        'bombAction': 'plant_begin',
-        'bombSite': 'A'
+        "tick": 12250, 
+        "seconds": 67.40625, 
+        "clockTime": "00:48", 
+        "playerSteamID": 76561198043315625, 
+        "playerName": "Beach", 
+        "playerTeam": "", 
+        "playerX": 2160.965576171875, 
+        "playerY": 144.39041137695312, 
+        "playerZ": 160.03125, 
+        "bombAction": "plant_begin",
+        "bombSite": "A"
     }
 
 Weapon Fires
@@ -298,22 +299,22 @@ Weapon Fires
 .. code-block:: json
 
     {
-        'tick': 8492, 
-        'seconds': 8.6875, 
-        'clockTime': '01:47', 
-        'playerSteamID': 76561198098005932, 
-        'playerName': 'aidan', 
-        'playerTeam': '', 
-        'playerSide': 'CT', 
-        'playerX': 1377.0318603515625, 
-        'playerY': 566.3394775390625, 
-        'playerZ': 131.50010681152344, 
-        'playerViewX': 175.49560546875, 
-        'playerViewY': 355.4901123046875, 
-        'playerStrafe': False, 
-        'weapon': 'HE Grenade',
-        'weaponClass': 'Grenades', 
-        'zoomLevel': 0
+        "tick": 8492, 
+        "seconds": 8.6875, 
+        "clockTime": "01:47", 
+        "playerSteamID": 76561198098005932, 
+        "playerName": "aidan", 
+        "playerTeam": "", 
+        "playerSide": "CT", 
+        "playerX": 1377.0318603515625, 
+        "playerY": 566.3394775390625, 
+        "playerZ": 131.50010681152344, 
+        "playerViewX": 175.49560546875, 
+        "playerViewY": 355.4901123046875, 
+        "playerStrafe": False, 
+        "weapon": "HE Grenade",
+        "weaponClass": "Grenades", 
+        "zoomLevel": 0
     }
 
 Flashes
@@ -322,28 +323,28 @@ Flashes
 .. code-block:: json
 
     {
-        'tick': 9518, 
-        'seconds': 24.71875, 
-        'clockTime': '01:31', 
-        'attackerSteamID': 76561198098005932, 
-        'attackerName': 'aidan', 
-        'attackerTeam': '', 
-        'attackerSide': 'CT', 
-        'attackerX': 1434.30224609375, 
-        'attackerY': 2835.972412109375, 
-        'attackerZ': 127.61480712890625, 
-        'attackerViewX': 154.5062255859375, 
-        'attackerViewY': 317.7081298828125, 
-        'playerSteamID': 76561198060045535, 
-        'playerName': 'Daniel', 
-        'playerTeam': '', 
-        'playerSide': 'CT', 
-        'playerX': 923.0872192382812, 
-        'playerY': 2777.9443359375, 
-        'playerZ': 128.74525451660156, 
-        'playerViewX': 239.095458984375, 
-        'playerViewY': 358.2037353515625, 
-        'flashDuration': 2.676444416
+        "tick": 9518, 
+        "seconds": 24.71875, 
+        "clockTime": "01:31", 
+        "attackerSteamID": 76561198098005932, 
+        "attackerName": "aidan", 
+        "attackerTeam": "", 
+        "attackerSide": "CT", 
+        "attackerX": 1434.30224609375, 
+        "attackerY": 2835.972412109375, 
+        "attackerZ": 127.61480712890625, 
+        "attackerViewX": 154.5062255859375, 
+        "attackerViewY": 317.7081298828125, 
+        "playerSteamID": 76561198060045535, 
+        "playerName": "Daniel", 
+        "playerTeam": "", 
+        "playerSide": "CT", 
+        "playerX": 923.0872192382812, 
+        "playerY": 2777.9443359375, 
+        "playerZ": 128.74525451660156, 
+        "playerViewX": 239.095458984375, 
+        "playerViewY": 358.2037353515625, 
+        "flashDuration": 2.676444416
     }
 
 Frames
@@ -352,74 +353,75 @@ Frames
 .. code-block:: json
 
     {
-        'tick': 8174, 
-        'seconds': 3.71875, 
-        'clockTime': '01:52', 
-        't': {
-            'side': 'T', 
-            'teamName': '', 
-            'teamEqVal': 3550, 
-            'alivePlayers': 5, 
-            'totalUtility': 1, 
-            'players': [{                            # List of player objects with the following structure
-                'steamID': 76561198035759667, 
-                'name': 'alo0o0o0o0', 
-                'team': '', 
-                'side': 'T', 
-                'x': -1179.1435546875, 
-                'y': 483.21026611328125, 
-                'z': -55.96875, 
-                'velocityX': 109.83319854736328, 
-                'velocityY': 91.87308502197266, 
-                'velocityZ': 0, 
-                'viewX': 56.84326171875, 
-                'viewY': 3.33984375, 
-                'hp': 100, 
-                'armor': 0, 
-                'activeWeapon': 'Knife',             # Weapon the player is currently holding
-                'totalUtility': 0, 
-                'isAlive': True, 
-                'isBlinded': False, 
-                'isAirborne': False, 
-                'isDucking': False, 
-                'isDuckingInProgress': False, 
-                'isUnDuckingInProgress': False, 
-                'isDefusing': False, 
-                'isPlanting': False, 
-                'isReloading': False, 
-                'isInBombZone': False, 
-                'isInBuyZone': False, 
-                'isStanding': True, 
-                'isScoped': False, 
-                'isWalking': False, 
-                'isUnknown': False, 
-                'inventory': [{                     # List of weapons
-                    'weaponName': 'Glock-18', 
-                    'weaponClass': 'Pistols', 
-                    'ammoInMagazine': 20, 
-                    'ammoInReserve': 120
+        "parseKillFrame": true                       # True if the frame was parsed due to a kill
+        "tick": 8174, 
+        "seconds": 3.71875, 
+        "clockTime": "01:52", 
+        "t": {
+            "side": "T", 
+            "teamName": "", 
+            "teamEqVal": 3550, 
+            "alivePlayers": 5, 
+            "totalUtility": 1, 
+            "players": [{                            # List of player objects with the following structure
+                "steamID": 76561198035759667, 
+                "name": "alo0o0o0o0", 
+                "team": "", 
+                "side": "T", 
+                "x": -1179.1435546875, 
+                "y": 483.21026611328125, 
+                "z": -55.96875, 
+                "velocityX": 109.83319854736328, 
+                "velocityY": 91.87308502197266, 
+                "velocityZ": 0, 
+                "viewX": 56.84326171875, 
+                "viewY": 3.33984375, 
+                "hp": 100, 
+                "armor": 0, 
+                "activeWeapon": "Knife",             # Weapon the player is currently holding
+                "totalUtility": 0, 
+                "isAlive": True, 
+                "isBlinded": False, 
+                "isAirborne": False, 
+                "isDucking": False, 
+                "isDuckingInProgress": False, 
+                "isUnDuckingInProgress": False, 
+                "isDefusing": False, 
+                "isPlanting": False, 
+                "isReloading": False, 
+                "isInBombZone": False, 
+                "isInBuyZone": False, 
+                "isStanding": True, 
+                "isScoped": False, 
+                "isWalking": False, 
+                "isUnknown": False, 
+                "inventory": [{                     # List of weapons
+                    "weaponName": "Glock-18", 
+                    "weaponClass": "Pistols", 
+                    "ammoInMagazine": 20, 
+                    "ammoInReserve": 120
                 }], 
-                'spotters': [...]                   # SteamIDs of players that the current player has spotted
-                'equipmentValue': 200, 
-                'equipmentValueFreezetimeEnd': 200, 
-                'equipmentValueRoundStart': 200, 
-                'cash': 800, 
-                'cashSpendThisRound': 0, 
-                'cashSpendTotal': 0,                # Cash spent the entire game
-                'hasHelmet': False, 
-                'hasDefuse': False, 
-                'hasBomb': False, 
-                'ping': 32, 
-                'zoomLevel': 0
+                "spotters": [...]                   # SteamIDs of players that the current player has spotted
+                "equipmentValue": 200, 
+                "equipmentValueFreezetimeEnd": 200, 
+                "equipmentValueRoundStart": 200, 
+                "cash": 800, 
+                "cashSpendThisRound": 0, 
+                "cashSpendTotal": 0,                # Cash spent the entire game
+                "hasHelmet": False, 
+                "hasDefuse": False, 
+                "hasBomb": False, 
+                "ping": 32, 
+                "zoomLevel": 0
                 }]
             }, 
-            'ct': {...},                            # Same structure as 't'               
-            'world': [{                             # List of world objects, like bombs, mollies or smokes
-                    'objectType': 'bomb', 
-                    'x': -1215.3546142578125, 
-                    'y': 470.23406982421875, 
-                    'z': -55.96875
+            "ct": {...},                            # Same structure as "t"               
+            "world": [{                             # List of world objects, like bombs, mollies or smokes
+                    "objectType": "bomb", 
+                    "x": -1215.3546142578125, 
+                    "y": 470.23406982421875, 
+                    "z": -55.96875
             }], 
-            'bombPlanted': False, 
-            'bombsite': ''
+            "bombPlanted": False, 
+            "bombsite": ""
     }
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 9c12863..b259e2e 100644
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@ long_description = (this_directory / "README.md").read_text()
 
 setup(
     name="awpy",
-    version="1.1.2",
+    version="1.1.3",
     packages=find_packages(),
     # Project uses reStructuredText, so ensure that the docutils get
     # installed or upgraded on the target machine
diff --git a/tests/test_demo_parse.py b/tests/test_demo_parse.py
index ffe6794..7757fab 100644
--- a/tests/test_demo_parse.py
+++ b/tests/test_demo_parse.py
@@ -142,6 +142,7 @@ class TestDemoParser:
         assert self.parser_opts.buy_style == "hltv"
         assert self.parser_opts.dmg_rolled == False
         assert self.parser_opts.parse_frames == True
+        assert self.parser_opts.parse_kill_frames == False
         self.bad_parser_opts = DemoParser(
             demofile="default.dem",
             log=False,
@@ -201,6 +202,15 @@ class TestDemoParser:
             assert type(r["weaponFires"]) == list
             assert type(r["frames"]) == list
 
+    def test_parse_kill_frames(self):
+        """Tests parse kill frames"""
+        self.parser_kill_frames = DemoParser(
+            demofile="default.dem", log=True, parse_frames=False, parse_kill_frames=True
+        )
+        self.default_data = self.parser_kill_frames.parse()
+        for r in self.default_data["gameRounds"]:
+            assert len(r["kills"]) == len(r["frames"])
+
     def test_default_parse_df(self):
         """Tests default parse to dataframe"""
         self.default_data_df = self.parser.parse(return_type="df")
['tests/test_demo_parse.py', 'docs/parser_output.rst', 'awpy/analytics/stats.py', 'setup.py', 'awpy/parser/parse_demo.go', 'awpy/parser/demoparser.py']