/// <summary> /// Apply the specified rawEvent to the parser. /// </summary> /// <param name="rawEvent">The raw event.</param> /// <param name="parser">The parser to mutate.</param> public static void Apply(GameEvent rawEvent, DemoParser parser) { var descriptors = parser.GEH_Descriptors; var blindPlayers = parser.GEH_BlindPlayers; if (descriptors == null) { return; } Dictionary <string, object> data; var eventDescriptor = descriptors[rawEvent.EventId]; if (parser.Players.Count == 0 && eventDescriptor.Name != "player_connect") { return; } if (eventDescriptor.Name == "round_start") { data = MapData(eventDescriptor, rawEvent); RoundStartedEventArgs rs = new RoundStartedEventArgs() { TimeLimit = (int)data["timelimit"], FragLimit = (int)data["fraglimit"], Objective = (string)data["objective"] }; parser.RaiseRoundStart(rs); } if (eventDescriptor.Name == "cs_win_panel_match") { parser.RaiseWinPanelMatch(); } if (eventDescriptor.Name == "round_announce_final") { parser.RaiseRoundFinal(); } if (eventDescriptor.Name == "round_announce_last_round_half") { parser.RaiseLastRoundHalf(); } if (eventDescriptor.Name == "round_end") { data = MapData(eventDescriptor, rawEvent); Team t = Team.Spectate; int winner = (int)data ["winner"]; if (winner == parser.tID) { t = Team.Terrorist; } else if (winner == parser.ctID) { t = Team.CounterTerrorist; } RoundEndedEventArgs roundEnd = new RoundEndedEventArgs() { Reason = (RoundEndReason)data["reason"], Winner = t, Message = (string)data["message"], }; parser.RaiseRoundEnd(roundEnd); } if (eventDescriptor.Name == "round_officially_ended") { parser.RaiseRoundOfficiallyEnd(); } if (eventDescriptor.Name == "round_mvp") { data = MapData(eventDescriptor, rawEvent); RoundMVPEventArgs roundMVPArgs = new RoundMVPEventArgs(); roundMVPArgs.Player = parser.Players.ContainsKey((int)data["userid"]) ? parser.Players[(int)data["userid"]] : null; roundMVPArgs.Reason = (RoundMVPReason)data["reason"]; parser.RaiseRoundMVP(roundMVPArgs); } if (eventDescriptor.Name == "bot_takeover") { data = MapData(eventDescriptor, rawEvent); BotTakeOverEventArgs botTakeOverArgs = new BotTakeOverEventArgs(); botTakeOverArgs.Taker = parser.Players.ContainsKey((int)data["userid"]) ? parser.Players[(int)data["userid"]] : null; parser.RaiseBotTakeOver(botTakeOverArgs); } if (eventDescriptor.Name == "begin_new_match") { parser.RaiseMatchStarted(); } if (eventDescriptor.Name == "round_announce_match_start") { parser.RaiseRoundAnnounceMatchStarted(); } if (eventDescriptor.Name == "round_freeze_end") { parser.RaiseFreezetimeEnded(); } //if (eventDescriptor.Name != "player_footstep" && eventDescriptor.Name != "weapon_fire" && eventDescriptor.Name != "player_jump") { // Console.WriteLine (eventDescriptor.Name); //} switch (eventDescriptor.Name) { case "weapon_fire": data = MapData(eventDescriptor, rawEvent); WeaponFiredEventArgs fire = new WeaponFiredEventArgs(); fire.Shooter = parser.Players.ContainsKey((int)data ["userid"]) ? parser.Players [(int)data ["userid"]] : null; if (fire.Shooter != null && fire.Shooter.ActiveWeapon != null) { fire.Weapon = fire.Shooter.ActiveWeapon; } else { // should not happen but we never know fire.Weapon = new Equipment((string)data["weapon"]); } // Workaround to detect who throw molo / inc if (fire.Weapon.Weapon == EquipmentElement.Molotov || fire.Weapon.Weapon == EquipmentElement.Incendiary) { parser.LastPlayerIdsThrownFire.Enqueue((int)data["userid"]); } parser.RaiseWeaponFired(fire); break; case "player_death": data = MapData(eventDescriptor, rawEvent); PlayerKilledEventArgs kill = new PlayerKilledEventArgs(); kill.Victim = parser.Players.ContainsKey((int)data["userid"]) ? parser.Players[(int)data["userid"]] : null; kill.Killer = parser.Players.ContainsKey((int)data["attacker"]) ? parser.Players[(int)data["attacker"]] : null; kill.Assister = parser.Players.ContainsKey((int)data["assister"]) ? parser.Players[(int)data["assister"]] : null; kill.Headshot = (bool)data["headshot"]; kill.Weapon = new Equipment((string)data["weapon"], (string)data["weapon_itemid"]); if (kill.Killer != null && kill.Killer.ActiveWeapon != null) { // in case of grenade kills, killer's active weapon is not his grenade at this state if (kill.Weapon == null || (kill.Weapon != null && kill.Weapon.Class != EquipmentClass.Grenade)) { kill.Weapon = kill.Killer.ActiveWeapon; kill.Weapon.SkinID = (string)data["weapon_itemid"]; } } kill.PenetratedObjects = (int)data["penetrated"]; parser.RaisePlayerKilled(kill); break; case "player_hurt": data = MapData(eventDescriptor, rawEvent); PlayerHurtEventArgs hurt = new PlayerHurtEventArgs(); hurt.Player = parser.Players.ContainsKey((int)data ["userid"]) ? parser.Players [(int)data ["userid"]] : null; hurt.Attacker = parser.Players.ContainsKey((int)data ["attacker"]) ? parser.Players [(int)data ["attacker"]] : null; hurt.Health = (int)data ["health"]; hurt.Armor = (int)data ["armor"]; hurt.HealthDamage = (int)data ["dmg_health"]; hurt.ArmorDamage = (int)data ["dmg_armor"]; hurt.Hitgroup = (Hitgroup)((int)data ["hitgroup"]); hurt.Weapon = new Equipment((string)data["weapon"]); if (hurt.Attacker != null && hurt.Attacker.ActiveWeapon != null) { // in case of grenade attacks, attacker's active weapon is not his grenade at this state if (hurt.Weapon == null || (hurt.Weapon != null && hurt.Weapon.Class != EquipmentClass.Grenade)) { hurt.Weapon = hurt.Attacker.ActiveWeapon; } } parser.RaisePlayerHurt(hurt); break; #region Nades case "player_blind": // BOT are ignored (thrower or not) data = MapData(eventDescriptor, rawEvent); if (parser.Players.ContainsKey((int)data["userid"])) { Player p = parser.Players[(int)data["userid"]]; if (data.ContainsKey("attacker") && parser.Players.ContainsKey((int)data["attacker"])) { Player attacker = parser.Players[(int)data["attacker"]]; PlayerBlindEventArgs ev = new PlayerBlindEventArgs { Player = p, Duration = (float)data["blind_duration"], Attacker = attacker, }; blindPlayers.Add(p); parser.RaisePlayerBlind(ev); } } break; case "flashbang_detonate": var args = FillNadeEvent <FlashEventArgs>(MapData(eventDescriptor, rawEvent), parser); args.FlashedPlayers = blindPlayers.ToArray(); parser.RaiseFlashExploded(args); blindPlayers.Clear(); break; case "hegrenade_detonate": parser.RaiseGrenadeExploded(FillNadeEvent <GrenadeEventArgs>(MapData(eventDescriptor, rawEvent), parser)); break; case "decoy_started": parser.RaiseDecoyStart(FillNadeEvent <DecoyEventArgs>(MapData(eventDescriptor, rawEvent), parser)); break; case "decoy_detonate": parser.RaiseDecoyEnd(FillNadeEvent <DecoyEventArgs>(MapData(eventDescriptor, rawEvent), parser)); break; case "smokegrenade_detonate": parser.RaiseSmokeStart(FillNadeEvent <SmokeEventArgs>(MapData(eventDescriptor, rawEvent), parser)); break; case "smokegrenade_expired": parser.RaiseSmokeEnd(FillNadeEvent <SmokeEventArgs>(MapData(eventDescriptor, rawEvent), parser)); break; case "inferno_startburn": var fireData = MapData(eventDescriptor, rawEvent); // molotov / inc events doesn't contains thrower, this is a hack to retrieve it // WARNING: This hack is not 100% accurated since if a molotov never burn, the ids will be incorrect // 1. when a molo / inc is thrown (weapon_fire events), we add the userid to the queue // 2. when this event (inferno_startburn) occurs we retrieve the last userid from this queue (LastPlayerIdsThrownFire) // 3. we add the userid to the queue LastPlayerIdsStartFire to retrieve the player at the next inferno_expire event if (!fireData.ContainsKey("userid") && parser.LastPlayerIdsThrownFire.Count > 0) { int throwerId = parser.LastPlayerIdsThrownFire.Dequeue(); fireData.Add("userid", throwerId); // add this id to the queue to be able to detect it when the inferno_expire event occurs parser.LastPlayerIdsStartFire.Enqueue(throwerId); } parser.RaiseFireStart(FillNadeEvent <FireEventArgs>(fireData, parser)); break; case "inferno_expire": var fireEndData = MapData(eventDescriptor, rawEvent); if (!fireEndData.ContainsKey("userid") && parser.LastPlayerIdsStartFire.Count > 0) { fireEndData.Add("userid", parser.LastPlayerIdsStartFire.Dequeue()); } parser.RaiseFireEnd(FillNadeEvent <FireEventArgs>(fireEndData, parser)); break; #endregion case "player_connect": data = MapData(eventDescriptor, rawEvent); PlayerInfo player = new PlayerInfo(); player.UserID = (int)data ["userid"]; player.Name = (string)data ["name"]; player.GUID = (string)data ["networkid"]; player.XUID = player.GUID == "BOT" ? 0 : GetCommunityID(player.GUID); //player.IsFakePlayer = (bool)data["bot"]; int index = (int)data["index"]; parser.RawPlayers[index] = player; break; case "player_disconnect": data = MapData(eventDescriptor, rawEvent); PlayerDisconnectEventArgs disconnect = new PlayerDisconnectEventArgs { Reason = (string)data["reason"], }; disconnect.Player = parser.Players.ContainsKey((int)data["userid"]) ? parser.Players[(int)data["userid"]] : null; parser.RaisePlayerDisconnect(disconnect); int toDelete = (int)data["userid"]; for (int i = 0; i < parser.RawPlayers.Length; i++) { if (parser.RawPlayers[i] != null && parser.RawPlayers[i].UserID == toDelete) { parser.RawPlayers[i] = null; break; } } if (parser.Players.ContainsKey(toDelete)) { parser.Players.Remove(toDelete); } break; case "player_team": data = MapData(eventDescriptor, rawEvent); PlayerTeamEventArgs playerTeamEvent = new PlayerTeamEventArgs(); Team t = Team.Spectate; int team = (int)data["team"]; if (team == parser.tID) { t = Team.Terrorist; } else if (team == parser.ctID) { t = Team.CounterTerrorist; } playerTeamEvent.NewTeam = t; t = Team.Spectate; team = (int)data["oldteam"]; if (team == parser.tID) { t = Team.Terrorist; } else if (team == parser.ctID) { t = Team.CounterTerrorist; } playerTeamEvent.OldTeam = t; playerTeamEvent.Swapped = parser.Players.ContainsKey((int)data["userid"]) ? parser.Players[(int)data["userid"]] : null; playerTeamEvent.IsBot = (bool)data["isbot"]; playerTeamEvent.Silent = (bool)data["silent"]; parser.RaisePlayerTeam(playerTeamEvent); break; case "bomb_beginplant": //When the bomb is starting to get planted case "bomb_abortplant": //When the bomb planter stops planting the bomb case "bomb_planted": //When the bomb has been planted case "bomb_defused": //When the bomb has been defused case "bomb_exploded": //When the bomb has exploded data = MapData(eventDescriptor, rawEvent); var bombEventArgs = new BombEventArgs(); bombEventArgs.Player = parser.Players.ContainsKey((int)data["userid"]) ? parser.Players[(int)data["userid"]] : null; int site = (int)data["site"]; if (site == parser.bombsiteAIndex) { bombEventArgs.Site = 'A'; } else if (site == parser.bombsiteBIndex) { bombEventArgs.Site = 'B'; } else { var relevantTrigger = parser.triggers.Single(a => a.Index == site); if (relevantTrigger.Contains(parser.bombsiteACenter)) { //planted at A. bombEventArgs.Site = 'A'; parser.bombsiteAIndex = site; } else { //planted at B. bombEventArgs.Site = 'B'; parser.bombsiteBIndex = site; } } switch (eventDescriptor.Name) { case "bomb_beginplant": parser.RaiseBombBeginPlant(bombEventArgs); break; case "bomb_abortplant": parser.RaiseBombAbortPlant(bombEventArgs); break; case "bomb_planted": parser.RaiseBombPlanted(bombEventArgs); break; case "bomb_defused": parser.RaiseBombDefused(bombEventArgs); break; case "bomb_exploded": parser.RaiseBombExploded(bombEventArgs); break; } break; case "bomb_begindefuse": data = MapData(eventDescriptor, rawEvent); var e = new BombDefuseEventArgs(); e.Player = parser.Players.ContainsKey((int)data["userid"]) ? parser.Players[(int)data["userid"]] : null; e.HasKit = (bool)data["haskit"]; parser.RaiseBombBeginDefuse(e); break; case "bomb_abortdefuse": data = MapData(eventDescriptor, rawEvent); var e2 = new BombDefuseEventArgs(); e2.Player = parser.Players.ContainsKey((int)data["userid"]) ? parser.Players[(int)data["userid"]] : null; e2.HasKit = e2.Player.HasDefuseKit; parser.RaiseBombAbortDefuse(e2); break; } }