protected override void HandlePlayerKilled(object sender, PlayerKilledEventArgs e)
		{
			if (!IsMatchStarted) return;
			if (e.Killer == null || e.Victim == null) return;

			KillEvent killEvent = new KillEvent(Parser.IngameTick)
			{
				Weapon = new Weapon(e.Weapon)
			};

			killEvent.DeathPerson = Demo.Players.FirstOrDefault(player => player.SteamId == e.Victim.SteamID);
			if (killEvent.DeathPerson != null)
			{
				killEvent.DeathPerson.IsAlive = false;
			}

			if (e.Assister != null)
			{
				killEvent.Assister = Demo.Players.FirstOrDefault(player => player.SteamId == e.Assister.SteamID);
			}

			// If the killer isn't a bot we can add a kill to the match
			killEvent.Killer = Demo.Players.FirstOrDefault(player => player.SteamId == e.Killer.SteamID);

			if (killEvent.Killer != null)
			{
				if (!KillsThisRound.ContainsKey(e.Killer))
				{
					KillsThisRound[e.Killer] = 0;
				}
				KillsThisRound[e.Killer]++;

				ProcessOpenAndEntryKills(killEvent);
			}

			if (killEvent.DeathPerson != null)
			{
				killEvent.DeathPerson.DeathCount++;

				// TK
				if (e.Killer.Team == e.Victim.Team)
				{
					if (killEvent.Killer != null && killEvent.DeathPerson != null)
					{
						PlayerExtended player = Demo.Players.FirstOrDefault(p => p.SteamId == e.Killer.SteamID);
						if (player != null) player.TeamKillCount++;
					}
				}
				else
				{
					if (killEvent.Killer != null)
					{
						killEvent.Killer.KillsCount++;
						if (e.Headshot)
						{
							killEvent.Killer.HeadshotCount++;
						}
					}
				}
			}

			if (killEvent.Assister != null)
			{
				killEvent.Assister.AssistCount++;
			}

			ProcessClutches();

			if (AnalyzeHeatmapPoint)
			{
				killEvent.Point = new HeatmapPoint
				{
					X = e.Victim.Position.X,
					Y = e.Victim.Position.Y,
					Round = CurrentRound,
					Player = killEvent.Killer,
					Team = e.Killer.Team
				};
			}

			Demo.Kills.Add(killEvent);
			CurrentRound.Kills.Add(killEvent);

			if (AnalyzePlayersPosition && killEvent.Killer != null)
			{
				PositionPoint positionPoint = new PositionPoint
				{
					X = e.Victim.Position.X,
					Y = e.Victim.Position.Y,
					Player = Demo.Players.First(p => p.SteamId == e.Killer.SteamID),
					Team = e.Killer.Team,
					Event = killEvent,
					Round = CurrentRound
				};
				Demo.PositionsPoint.Add(positionPoint);
			}
		}
		protected void ProcessOpenAndEntryKills(KillEvent killEvent)
		{
			if (killEvent.DeathPerson == null || killEvent.Killer == null) return;

			if (IsEntryKillDone) return;

			if (IsOpeningKillDone) return;

			if (killEvent.Killer.Team == Team.Terrorist)
			{
				// This is an entry kill
				Application.Current.Dispatcher.Invoke(delegate
				{
					killEvent.Killer.HasEntryKill = true;
					killEvent.Killer.HasOpeningKill = true;

					CurrentRound.EntryKillEvent = new EntryKillEvent(Parser.IngameTick)
					{
						Killed = Demo.Players.First(p => Equals(p, killEvent.DeathPerson)),
						KilledTeam = killEvent.DeathPerson.Team,
						Killer = Demo.Players.First(p => Equals(p, killEvent.Killer)),
						KillerTeam = killEvent.Killer.Team,
						Weapon = killEvent.Weapon
					};
					CurrentRound.OpenKillEvent = new OpenKillEvent(Parser.IngameTick)
					{
						Killer = Demo.Players.First(p => Equals(p, killEvent.Killer)),
						KilledTeam = killEvent.DeathPerson.Team,
						Killed = Demo.Players.First(p => Equals(p, killEvent.DeathPerson)),
						KillerTeam = killEvent.Killer.Team,
						Weapon = killEvent.Weapon
					};
					IsEntryKillDone = true;
					IsOpeningKillDone = true;
				});
			}
			else
			{
				// CT done the kill , it's an open kill
				CurrentRound.OpenKillEvent = new OpenKillEvent(Parser.IngameTick)
				{
					Killer = Demo.Players.First(p => Equals(p, killEvent.Killer)),
					KilledTeam = killEvent.DeathPerson.Team,
					Killed = Demo.Players.First(p => Equals(p, killEvent.DeathPerson)),
					KillerTeam = killEvent.Killer.Team,
					Weapon = killEvent.Weapon
				};
				killEvent.Killer.HasOpeningKill = true;
				IsOpeningKillDone = true;
			}
		}
		/// <summary>
		/// killer == null => world
		/// killer.SteamID == 0 => BOT
		/// if a player is killed by bomb explosion, killer == planter
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void HandlePlayerKilled(object sender, PlayerKilledEventArgs e)
		{
			if (!IsMatchStarted || e.Victim == null) return;

			PlayerExtended killed = Demo.Players.FirstOrDefault(player => player.SteamId == e.Victim.SteamID);
			if (killed == null) return;
			Weapon weapon = Weapon.WeaponList.FirstOrDefault(w => w.Element == e.Weapon.Weapon);
			if (weapon == null) return;
			PlayerExtended killer = null;

			KillEvent killEvent = new KillEvent(Parser.IngameTick, Parser.CurrentTime)
			{
				Weapon = weapon,
				KillerSteamId = e.Killer?.SteamID ?? 0,
				KillerName = e.Killer?.Name ?? string.Empty,
				KillerSide = e.Killer?.Team ?? Team.Spectate,
				KilledSide = e.Victim.Team,
				KilledSteamId = e.Victim.SteamID,
				KilledName = e.Victim.Name,
				KillerVelocityX = e.Killer?.Velocity.X ?? 0,
				KillerVelocityY = e.Killer?.Velocity.Y ?? 0,
				KillerVelocityZ = e.Killer?.Velocity.Z ?? 0,
				RoundNumber = CurrentRound.Number,
				IsKillerCrouching = e.Killer?.IsDucking ?? false
			};

			killed.IsAlive = false;
			killed.DeathCount++;
			if (e.Killer != null) killer = Demo.Players.FirstOrDefault(player => player.SteamId == e.Killer.SteamID);
			if (killer != null)
			{
				if (e.Killer.IsDucking) killer.CrouchKillCount++;
				if (e.Killer.Velocity.Z > 0) killer.JumpKillCount++;
			}

			if (e.Assister != null)
			{
				PlayerExtended assister = Demo.Players.FirstOrDefault(player => player.SteamId == e.Assister.SteamID);
				if (assister != null)
				{
					assister.AssistCount++;
					killEvent.AssisterSteamId = assister.SteamId;
					killEvent.AssisterName = assister.Name;
				}
			}

			if (e.Killer != null)
			{
				if (!KillsThisRound.ContainsKey(e.Killer))
				{
					KillsThisRound[e.Killer] = 0;
				}
				KillsThisRound[e.Killer]++;

				if (killer != null)
				{
					// TK
					if (e.Killer.Team == e.Victim.Team)
					{
						killer.KillsCount--;
						killer.TeamKillCount++;
					}
					else
					{
						killer.KillsCount++;
						if (e.Headshot) killer.HeadshotCount++;
					}
				}
			}

			ProcessOpenAndEntryKills(killEvent);
			ProcessClutches();
			ProcessPlayersRating();

			if (AnalyzeHeatmapPoint)
			{
				killEvent.Point = new KillHeatmapPoint
				{
					KillerX = e.Killer?.Position.X ?? 0,
					KillerY = e.Killer?.Position.Y ?? 0,
					VictimX = e.Victim.Position.X,
					VictimY = e.Victim.Position.Y,
					Round = CurrentRound,
					KillerSteamId = e.Killer?.SteamID ?? 0,
					KillerName = e.Killer?.Name ?? string.Empty,
					KillerTeam = e.Killer?.Team ?? Team.Spectate,
					VictimSteamId = e.Victim.SteamID,
					VictimName = e.Victim.Name,
					VictimTeam = e.Victim.Team
				};
			}

			Demo.Kills.Add(killEvent);
			CurrentRound.Kills.Add(killEvent);

			if (AnalyzePlayersPosition)
			{
				PositionPoint positionPoint = new PositionPoint
				{
					X = e.Victim.Position.X,
					Y = e.Victim.Position.Y,
					PlayerName = e.Killer?.Name ?? string.Empty,
					PlayerSteamId = e.Killer?.SteamID ?? 0,
					Team = e.Killer?.Team ?? Team.Spectate,
					Event = killEvent,
					RoundNumber = CurrentRound.Number
				};
				Demo.PositionsPoint.Add(positionPoint);
			}
		}
		protected void ProcessOpenAndEntryKills(KillEvent killEvent)
		{
			if (killEvent.KillerSteamId == 0) return;

			if (IsEntryKillDone) return;

			if (IsOpeningKillDone) return;

			PlayerExtended killed = Demo.Players.FirstOrDefault(p => Equals(p.SteamId, killEvent.KilledSteamId));
			if (killed == null) return;
			PlayerExtended killer = Demo.Players.FirstOrDefault(p => Equals(p.SteamId, killEvent.KillerSteamId));
			if (killer == null) return;

			if (killEvent.KillerSide == Team.Terrorist)
			{
				// This is an entry kill
				Application.Current.Dispatcher.Invoke(delegate
				{
					killer.HasEntryKill = true;
					killer.HasOpeningKill = true;

					CurrentRound.EntryKillEvent = new EntryKillEvent(Parser.IngameTick, Parser.CurrentTime)
					{
						KilledSteamId = killed.SteamId,
						KilledName = killed.Name,
						KilledSide = killEvent.KilledSide,
						KillerSteamId = killer.SteamId,
						KillerName = killer.Name,
						KillerSide = killEvent.KillerSide,
						Weapon = killEvent.Weapon
					};
					CurrentRound.OpenKillEvent = new OpenKillEvent(Parser.IngameTick, Parser.CurrentTime)
					{
						KillerSteamId = killer.SteamId,
						KillerName = killer.Name,
						KilledSide = killEvent.KilledSide,
						KilledSteamId = killed.SteamId,
						KilledName = killed.Name,
						KillerSide = killEvent.KillerSide,
						Weapon = killEvent.Weapon
					};
					IsEntryKillDone = true;
					IsOpeningKillDone = true;
				});
			}
			else
			{
				// CT done the kill , it's an open kill
				CurrentRound.OpenKillEvent = new OpenKillEvent(Parser.IngameTick, Parser.CurrentTime)
				{
					KillerSteamId = killer.SteamId,
					KillerName = killer.Name,
					KilledSide = killEvent.KilledSide,
					KilledSteamId = killed.SteamId,
					KilledName = killed.Name,
					KillerSide = killEvent.KillerSide,
					Weapon = killEvent.Weapon
				};
				killer.HasOpeningKill = true;
				IsOpeningKillDone = true;
			}
		}
		protected override void HandlePlayerKilled(object sender, PlayerKilledEventArgs e)
		{
			if (!IsMatchStarted) return;
			if (e.Killer == null || e.Victim == null) return;

			KillEvent killEvent = new KillEvent(Parser.IngameTick)
			{
				Weapon = new Weapon(e.Weapon)
			};

			bool killerIsBot = false;
			bool victimIsBot = false;
			bool assisterIsBot = false;

			if (e.Killer.SteamID == 0) killerIsBot = true;
			if (e.Victim.SteamID == 0) victimIsBot = true;
			if (e.Assister != null && e.Assister.SteamID == 0) assisterIsBot = true;

			// Human killed human
			if (!killerIsBot && !victimIsBot)
			{
				killEvent.DeathPerson = Demo.Players.FirstOrDefault(player => player.SteamId == e.Victim.SteamID);
				if (killEvent.DeathPerson != null) killEvent.DeathPerson.IsAlive = false;
				killEvent.Killer = Demo.Players.FirstOrDefault(player => player.SteamId == e.Killer.SteamID);

				if (killEvent.DeathPerson != null && killEvent.Killer != null)
				{
					// TK
					if (killEvent.Killer.Team == killEvent.DeathPerson.Team)
					{
						killEvent.Killer.TeamKillCount++;
						killEvent.Killer.KillsCount--;
						if (killEvent.Killer.HeadshotCount > 0) killEvent.Killer.HeadshotCount--;
						killEvent.DeathPerson.DeathCount++;
					}
					else
					{
						// Regular kill
						if (!killEvent.Killer.IsControllingBot)
						{
							killEvent.Killer.KillsCount++;
							if(e.Headshot) killEvent.Killer.HeadshotCount++;
						}
						if (!killEvent.DeathPerson.IsControllingBot) killEvent.DeathPerson.DeathCount++;
					}
				}
			}

			// Human killed a bot
			if (!killerIsBot && victimIsBot)
			{
				killEvent.Killer = Demo.Players.FirstOrDefault(player => player.SteamId == e.Killer.SteamID);
				if (killEvent.Killer != null)
				{
					// TK
					if (killEvent.Killer.Team == e.Victim.Team)
					{
						killEvent.Killer.TeamKillCount++;
						killEvent.Killer.KillsCount--;
					}
					else
					{
						// Regular kill
						if (!killEvent.Killer.IsControllingBot)
						{
							killEvent.Killer.KillsCount++;
							if (e.Headshot) killEvent.Killer.HeadshotCount++;
						}
					}
				}
			}

			// A bot killed a human
			if (killerIsBot && !victimIsBot)
			{
				killEvent.DeathPerson = Demo.Players.FirstOrDefault(player => player.SteamId == e.Victim.SteamID);
				// TK or not we add a death to the human
				if (killEvent.DeathPerson != null) killEvent.DeathPerson.DeathCount++;
			}
		
			// Add assist if there was one
			if (e.Assister != null && !assisterIsBot && e.Assister.Team != e.Victim.Team)
			{
				killEvent.Assister = Demo.Players.FirstOrDefault(player => player.SteamId == e.Assister.SteamID);
				if (killEvent.Assister != null) killEvent.Assister.AssistCount++;
			}

			// If the killer isn't a bot we can update individual kill, open and entry kills
			if (killEvent.Killer != null && !killEvent.Killer.IsControllingBot)
			{
				if (!KillsThisRound.ContainsKey(e.Killer))
				{
					KillsThisRound[e.Killer] = 0;
				}
				KillsThisRound[e.Killer]++;

				ProcessOpenAndEntryKills(killEvent);
			}

			ProcessClutches();

			if (AnalyzeHeatmapPoint)
			{
				killEvent.Point = new HeatmapPoint
				{
					X = e.Victim.Position.X,
					Y = e.Victim.Position.Y,
					Round = CurrentRound,
					Player = killEvent.Killer,
					Team = e.Killer.Team
				};
			}

			Demo.Kills.Add(killEvent);
			CurrentRound.Kills.Add(killEvent);
			if (AnalyzePlayersPosition)
			{
				PositionPoint positionPoint = new PositionPoint
				{
					X = e.Victim.Position.X,
					Y = e.Victim.Position.Y,
					Player = Demo.Players.First(p => p.SteamId == e.Killer.SteamID),
					Team = e.Killer.Team,
					Event = killEvent,
					Round = CurrentRound
				};
				Demo.PositionsPoint.Add(positionPoint);
			}
		}
		protected new void HandlePlayerKilled(object sender, PlayerKilledEventArgs e)
		{
			if (!IsMatchStarted ||e.Victim == null) return;

			Weapon weapon = Weapon.WeaponList.FirstOrDefault(w => w.Element == e.Weapon.Weapon);
			if (weapon == null) return;
			PlayerExtended killed = Demo.Players.FirstOrDefault(player => player.SteamId == e.Victim.SteamID);
			if (killed == null) return;
			PlayerExtended killer = null;

			KillEvent killEvent = new KillEvent(Parser.IngameTick, Parser.CurrentTime)
			{
				KillerSteamId = e.Killer?.SteamID ?? 0,
				KillerName = e.Killer?.Name ?? "World",
				KillerSide = e.Killer?.Team ?? Team.Spectate,
				Weapon = weapon,
				KillerVelocityX = e.Killer?.Velocity.X ?? 0,
				KillerVelocityY = e.Killer?.Velocity.Y ?? 0,
				KillerVelocityZ = e.Killer?.Velocity.Z ?? 0,
				KilledSteamId = e.Victim.SteamID,
				KilledName = e.Victim.Name,
				KilledSide = e.Victim.Team,
				RoundNumber = CurrentRound.Number,
				IsKillerCrouching = e.Killer?.IsDucking ?? false
			};

			bool killerIsBot = false;
			bool victimIsBot = false;
			bool assisterIsBot = false;

			if (e.Killer != null && e.Killer.SteamID == 0) killerIsBot = true;
			if (e.Victim.SteamID == 0) victimIsBot = true;
			if (e.Assister != null && e.Assister.SteamID == 0) assisterIsBot = true;
			if (e.Killer != null) killer = Demo.Players.FirstOrDefault(player => player.SteamId == e.Killer.SteamID);
			if (killer != null)
			{
				if (e.Killer.IsDucking) killer.CrouchKillCount++;
				if (e.Killer.Velocity.Z > 0) killer.JumpKillCount++;
			}

			// Human killed human
			if (!killerIsBot && !victimIsBot)
			{
				killed.IsAlive = false;
				if (killer != null)
				{
					// TK
					if (killer.TeamName == killed.TeamName)
					{
						killer.TeamKillCount++;
						killer.KillsCount--;
						if (killer.HeadshotCount > 0) killer.HeadshotCount--;
						killed.DeathCount++;
					}
					else
					{
						// Regular kill
						if (!killer.IsControllingBot)
						{
							killer.KillsCount++;
							if(e.Headshot) killer.HeadshotCount++;
						}
						if (!killed.IsControllingBot) killed.DeathCount++;
					}
				}
			}

			// Human killed a bot
			if (!killerIsBot && victimIsBot)
			{
				if (killer != null)
				{
					// TK
					if (killer.Side == e.Victim.Team)
					{
						killer.TeamKillCount++;
						killer.KillsCount--;
					}
					else
					{
						// Regular kill
						if (!killer.IsControllingBot)
						{
							killer.KillsCount++;
							if (e.Headshot) killer.HeadshotCount++;
						}
					}
				}
			}

			// A bot killed a human
			if (killerIsBot && !victimIsBot)
			{
				// TK or not we add a death to the human
				killed.DeathCount++;
			}
		
			// Add assist if there was one
			if (e.Assister != null && !assisterIsBot && e.Assister.Team != e.Victim.Team)
			{
				PlayerExtended assister = Demo.Players.FirstOrDefault(player => player.SteamId == e.Assister.SteamID);
				if (assister != null)
				{
					killEvent.AssisterSteamId = e.Assister.SteamID;
					killEvent.AssisterName = e.Assister.Name;
					assister.AssistCount++;
				}
			}

			// If the killer isn't a bot we can update individual kill, open and entry kills
			if (e.Killer != null && killer != null && !killer.IsControllingBot)
			{
				if (!KillsThisRound.ContainsKey(e.Killer))
				{
					KillsThisRound[e.Killer] = 0;
				}
				KillsThisRound[e.Killer]++;

				ProcessOpenAndEntryKills(killEvent);
			}

			ProcessClutches();

			if (AnalyzeHeatmapPoint)
			{
				killEvent.Point = new KillHeatmapPoint
				{
					KillerX = e.Killer?.Position.X ?? 0,
					KillerY = e.Killer?.Position.Y ?? 0,
					VictimX = e.Victim.Position.X,
					VictimY = e.Victim.Position.Y,
					Round = CurrentRound,
					KillerSteamId = e.Killer?.SteamID ?? 0,
					KillerName = e.Killer?.Name ?? string.Empty,
					KillerTeam = e.Killer?.Team ?? Team.Spectate,
					VictimSteamId = e.Victim.SteamID,
					VictimName = e.Victim.Name,
					VictimTeam = e.Victim.Team
				};
			}

			Demo.Kills.Add(killEvent);
			CurrentRound.Kills.Add(killEvent);
			if (AnalyzePlayersPosition)
			{
				PositionPoint positionPoint = new PositionPoint
				{
					X = e.Victim.Position.X,
					Y = e.Victim.Position.Y,
					PlayerSteamId = e.Killer?.SteamID ?? 0,
					PlayerName = e.Killer?.Name ?? string.Empty,
					Team = e.Killer?.Team ?? Team.Spectate,
					Event = killEvent,
					RoundNumber = CurrentRound.Number
				};
				Demo.PositionsPoint.Add(positionPoint);
			}
		}