diff --git a/jRandomSkills - SRC Files/src/jRandomSkills.cs b/jRandomSkills - SRC Files/src/jRandomSkills.cs index e935cec..42b10b3 100644 --- a/jRandomSkills - SRC Files/src/jRandomSkills.cs +++ b/jRandomSkills - SRC Files/src/jRandomSkills.cs @@ -31,7 +31,7 @@ namespace src public override string ModuleName => "[CS2] [ jRandomSkills ]"; public override string ModuleAuthor => "D3X (Original), Juzlus (Modifier), ByDexterTR (Contributor)"; public override string ModuleDescription => "Plugin adds random skills every round for CS2 by D3X. Modified by Juzlus."; - public override string ModuleVersion => "1.2.3.b3"; + public override string ModuleVersion => "1.2.3.b4"; public override void Load(bool hotReload) { @@ -125,7 +125,7 @@ namespace src SkillsUsedThisMap.TryAdd(skill, 0); } - if (SkillUtils.CurseLimitEnabled && SkillUtils.IsCurseSkill(skill)) + if (SkillUtils.IsCurseSkill(skill)) { if (methodName == "DisableSkill" && param?.Length > 0 && param[0] is CCSPlayerController curser && curser.IsValid) SkillUtils.ReleaseCurse(curser.Index); diff --git a/jRandomSkills - SRC Files/src/lang/de.json b/jRandomSkills - SRC Files/src/lang/de.json index c52c295..cf015ef 100644 --- a/jRandomSkills - SRC Files/src/lang/de.json +++ b/jRandomSkills - SRC Files/src/lang/de.json @@ -1,4 +1,4 @@ -{ +{ "none": "Keine", "none_desc": "Du hast keine Fertigkeit", @@ -276,6 +276,7 @@ "jetkick": "Jetkick", "jetkick_desc": "Wähle einen Spieler für einen Jetkick", + "jetkick_select_info": "Wähle einen Spieler für den Jetkick:", "jetkick_player_info": "Spieler '{0}' wurde wegge-kickt.", "jetkick_enemy_info": "Jeder Schuss stößt dich nach hinten", "jetkick_disable_info": "Dein Rückstoß ist wieder normal.", diff --git a/jRandomSkills - SRC Files/src/lang/en.json b/jRandomSkills - SRC Files/src/lang/en.json index c489c0f..2fc0948 100644 --- a/jRandomSkills - SRC Files/src/lang/en.json +++ b/jRandomSkills - SRC Files/src/lang/en.json @@ -1,4 +1,4 @@ -{ +{ "none": "None", "none_desc": "You have no skill", @@ -269,6 +269,7 @@ "jetkick": "Jetkick", "jetkick_desc": "Select a player to jetkick", + "jetkick_select_info": "Select a player to jetkick:", "jetkick_player_info": "Player '{0}' has been jetkicked.", "jetkick_enemy_info": "Every shot knocks you backwards", "jetkick_disable_info": "Your recoil is back to normal.", diff --git a/jRandomSkills - SRC Files/src/lang/fr.json b/jRandomSkills - SRC Files/src/lang/fr.json index 44b7f73..a5243e6 100644 --- a/jRandomSkills - SRC Files/src/lang/fr.json +++ b/jRandomSkills - SRC Files/src/lang/fr.json @@ -1,4 +1,4 @@ -{ +{ "none": "Aucune", "none_desc": "Vous n’avez aucune compétence", @@ -276,6 +276,7 @@ "jetkick": "Coup de pied propulsé", "jetkick_desc": "Sélectionnez un joueur pour lui donner un coup de pied propulsé", + "jetkick_select_info": "Sélectionnez un joueur à propulser :", "jetkick_player_info": "Le joueur '{0}' a reçu un coup de pied propulsé.", "jetkick_enemy_info": "Chaque tir vous repousse vers l'arrière", "jetkick_disable_info": "Votre recul est revenu à la normale.", diff --git a/jRandomSkills - SRC Files/src/lang/pl.json b/jRandomSkills - SRC Files/src/lang/pl.json index f544e6c..a71d592 100644 --- a/jRandomSkills - SRC Files/src/lang/pl.json +++ b/jRandomSkills - SRC Files/src/lang/pl.json @@ -1,4 +1,4 @@ -{ +{ "none": "Brak", "none_desc": "Nie posiadasz żadnej supermocy", @@ -276,6 +276,7 @@ "jetkick": "Odrzutowy Kop", "jetkick_desc": "Wybierz gracza, aby użyć na nim odrzutowego kopa", + "jetkick_select_info": "Wybierz gracza do odrzutowego kopa:", "jetkick_player_info": "Gracz '{0}' został odrzucony kopem.", "jetkick_enemy_info": "Każdy strzał mocno odrzuca Cię do tyłu", "jetkick_disable_info": "Twój odrzut wrócił do normy.", diff --git a/jRandomSkills - SRC Files/src/lang/pt-br.json b/jRandomSkills - SRC Files/src/lang/pt-br.json index 753b2d5..1c334a8 100644 --- a/jRandomSkills - SRC Files/src/lang/pt-br.json +++ b/jRandomSkills - SRC Files/src/lang/pt-br.json @@ -1,4 +1,4 @@ -{ +{ "none": "Nenhuma", "none_desc": "Você não tem nenhuma habilidade", @@ -276,6 +276,7 @@ "jetkick": "Chute a Jato", "jetkick_desc": "Selecione um jogador para aplicar um chute a jato", + "jetkick_select_info": "Selecione um jogador para o chute a jato:", "jetkick_player_info": "O jogador '{0}' recebeu um chute a jato.", "jetkick_enemy_info": "Cada tiro empurra você para trás", "jetkick_disable_info": "Seu recuo voltou ao normal.", diff --git a/jRandomSkills - SRC Files/src/lang/ru.json b/jRandomSkills - SRC Files/src/lang/ru.json index a4d6107..5fc6fe2 100644 --- a/jRandomSkills - SRC Files/src/lang/ru.json +++ b/jRandomSkills - SRC Files/src/lang/ru.json @@ -1,4 +1,4 @@ -{ +{ "none": "Нет навыка", "none_desc": "У вас нет навыка", @@ -276,6 +276,7 @@ "jetkick": "Реактивный удар", "jetkick_desc": "Выберите игрока для реактивного удара", + "jetkick_select_info": "Выберите игрока для реактивного удара:", "jetkick_player_info": "Игрок '{0}' получил реактивный удар.", "jetkick_enemy_info": "Каждый выстрел отбрасывает вас назад", "jetkick_disable_info": "Ваша отдача вернулась к норме.", diff --git a/jRandomSkills - SRC Files/src/lang/tr.json b/jRandomSkills - SRC Files/src/lang/tr.json index 4db8982..9361605 100644 --- a/jRandomSkills - SRC Files/src/lang/tr.json +++ b/jRandomSkills - SRC Files/src/lang/tr.json @@ -1,4 +1,4 @@ -{ +{ "none": "Yok", "none_desc": "Hiçbir yeteneğin yok", @@ -52,13 +52,13 @@ "behind_desc2": "Baş döndürme şansın: %{0}", "berserker": "Berserker", - "berserker_desc": "Canın azaldıkça daha fazla hasar verir ve daha hızlı hareket edersin", + "berserker_desc": "Canın azaldıkça hasarın artar ve daha hızlanırsın", "blademaster": "Kılıç Ustası", "blademaster_desc": "Bıçak tutarken mermileri sektirme şansın artar", "blastshot": "Patlama Atışı", - "blastshot_desc": "MP5 ile Attack2 tuşuna basarak bir HE bombası ateşle", + "blastshot_desc": "MP5 ile Sağ Tık'a basarak El bombası fırlat", "bunnyhop": "Tavşan", "bunnyhop_desc": "Otomatik \"BunnyHop\" yaparsın", @@ -156,14 +156,14 @@ "fastreload_desc": "[css_useSkill] tuşuna basarak şarjörünü hızlıca değiştir", "firerain": "Ateş Yağmuru", - "firerain_desc": "Molotof yağmuru çağırmak için bir yem at", + "firerain_desc": "Molotof yağdırmak için bir decoy at", "flash": "Flash", "flash_desc": "Raund başında rastgele oyuncu hızı", "flash_desc2": "Hızın: {0}x", "flashlight": "El Feneri", - "flashlight_desc": "El fenerini açıp kapatmak için [css_useSkill] tuşuna tıkla. Işığı düşmanları kör edebilir", + "flashlight_desc": "[css_useSkill] tuşuna basarak El fenerini açarsın/kaparsın (Işığı düşmanları kör edebilir)", "fortnite": "Fortnite", "fortnite_desc": "[css_useSkill] tuşuna basarak barikat kur", @@ -223,7 +223,7 @@ "healingsmoke_desc": "Sis bombaların iyileştirir", "hermit": "Münzevi", - "hermit_desc": "Öldürdüğünde mermi ve canın yenilenir", + "hermit_desc": "Birini öldürünce mermin ve canın yenilenir", "holyhandgrenade": "Kutsal El Bombası", "holyhandgrenade_desc": "El bomban iki kat hasara ve menzile sahip", @@ -267,9 +267,10 @@ "jester_on": "AÇIK", "jester_off": "KAPALI", - "jetkick": "Jet Tekmesi", - "jetkick_desc": "Jet tekmesi yapmak için bir oyuncu seç", - "jetkick_player_info": "'{0}' adlı oyuncuya jet tekmesi yapıldı.", + "jetkick": "Jetkick", + "jetkick_desc": "Seçtiğin bir rakibin her atışı onu geriye iter", + "jetkick_select_info": "Jetkick uygulanacak oyuncu:", + "jetkick_player_info": "'{0}' adlı oyuncuya jetkick uygulandı.", "jetkick_enemy_info": "Her atış seni geriye doğru iter", "jetkick_disable_info": "Geri tepmen normale döndü.", @@ -297,7 +298,7 @@ "knockback_desc": "Havadayken ateş etmek seni geriye savurur", "lastgasp": "Son Nefes", - "lastgasp_desc": "Öldükten sonra seni öldüren düşmana hasar verirsin", + "lastgasp_desc": "Öldükten sonra seni öldürene hasar verirsin", "lifeswap": "Can Takası", "lifeswap_desc": "Can değerlerini takas etmek için bir oyuncu seç", @@ -340,7 +341,7 @@ "deathbomb_desc": "Öldüğünde patlayarak etraftaki oyuncuları öldürürsün", "deathbomb_explosion": "BOOM!!!", - "demoneye": "Şeytan Gözü", + "demoneye": "Şeytani Göz", "demoneye_desc": "Baktığın tüm düşmanlara hasar verirsin", "nightmare": "Kabus", @@ -489,14 +490,14 @@ "swapposition": "Yer Değiştirme", "swapposition_desc": "[css_useSkill] tuşuna basarak vurduğun düşmanla yer değiştir", - "takeammo": "Mühimmat Al", - "takeammo_desc": "Rastgele bir düşmanın aktif silahının şarjörünü almak için [css_useSkill] tuşuna tıkla", - "takeammo_hud_info1": "Aktif şarjörü olan bir oyuncu bulunamadı.", - "takeammo_hud_info2": "Düşmanın şarjörü yok.", - "takeammo_enemy_info": "Bir miktar mühimmat kaybettin.", + "takeammo": "Cephane Hırsızı", + "takeammo_desc": "[css_useSkill] tuşuna basarak rastgele bir düşmanın silahının şarjörünü çalarsın", + "takeammo_hud_info1": "Cephanesi olan bir oyuncu bulunamadı.", + "takeammo_hud_info2": "Düşmanın cephanesi yok.", + "takeammo_enemy_info": "Birisi cephaneni çaldı.", "teamteleport": "Takıma Işınlanma", - "teamteleport_desc": "Baktığın takım arkadaşına ışınlanmak için [css_useSkill] tuşuna bas", + "teamteleport_desc": "[css_useSkill] tuşuna basarak baktığın takım arkadaşına ışınlanırsın", "teamteleport_noenemy": "Takım arkadaşı bulunamadı", "teamteleport_hud_info": "Bulundu: {0}", diff --git a/jRandomSkills - SRC Files/src/player/EntityEvents.cs b/jRandomSkills - SRC Files/src/player/EntityEvents.cs index 0a575e8..e83ba2b 100644 --- a/jRandomSkills - SRC Files/src/player/EntityEvents.cs +++ b/jRandomSkills - SRC Files/src/player/EntityEvents.cs @@ -206,7 +206,7 @@ namespace src.player Server.PrintToConsole($"[jRandomSkills] CheckTransmit dying-filter failed: {ex.Message}"); } - DispatchToActiveSkills("CheckTransmit", infoList); + DispatchCheckTransmit([infoList]); } PerfLog.Sample("CheckTransmit", perfStart); } diff --git a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs index 2830add..8570c21 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs @@ -136,6 +136,39 @@ namespace src.player } } + private static void ReleaseCursesTargeting(uint victimIndex) + { + foreach (uint curserIndex in SkillUtils.GetCursersOf(victimIndex)) + { + if (curserIndex == victimIndex) continue; + + var curser = Utilities.GetPlayerFromIndex((int)curserIndex); + if (curser == null || !curser.IsValid) continue; + + if (PlayerManager.GetPlayerByIndex(curserIndex)?.Skill is not Skills curserSkill || curserSkill == Skills.None) + continue; + + try + { + Instance.SkillAction(curserSkill.ToString(), "DisableSkill", [curser]); + } + catch (Exception ex) + { + Server.PrintToConsole($"[jRandomSkills] {curserSkill}.DisableSkill failed while releasing curse on leaving player: {(ex.InnerException ?? ex).Message}"); + } + } + } + + private static void DispatchCheckTransmit(object[] args) + { + var seen = new HashSet(); + foreach (var p in Instance.SkillPlayer) + { + if (!seen.Add(p.Skill)) continue; + InvokeSkill(p.Skill, "CheckTransmit", args); + } + } + private static void DispatchOnTakeDamage(DynamicHook h, bool post = false) { object[] args = [h]; @@ -517,6 +550,9 @@ namespace src.player Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [player]); uint leavingIndex = player.Index; + + ReleaseCursesTargeting(leavingIndex); + foreach (var skill in SkillData.Skills) Instance.SkillAction(skill.Skill.ToString(), "PlayerDisconnect", [leavingIndex]); diff --git a/jRandomSkills - SRC Files/src/player/RoundEvents.cs b/jRandomSkills - SRC Files/src/player/RoundEvents.cs index 71d2d4b..849a165 100644 --- a/jRandomSkills - SRC Files/src/player/RoundEvents.cs +++ b/jRandomSkills - SRC Files/src/player/RoundEvents.cs @@ -152,12 +152,24 @@ namespace src.player // nobody drew now would otherwise never clear state left over from an earlier round. // Skills that never ran cannot hold state, so they stay out of the sweep. foreach (var skillName in SkillsUsedThisMap.Keys) - Instance.SkillAction(skillName, "NewRound"); + SafeNewRound(skillName); ActiveSkillsThisRound.Clear(); tickFailuresLogged.Clear(); } } + private static void SafeNewRound(string skillName) + { + try + { + Instance.SkillAction(skillName, "NewRound"); + } + catch (Exception ex) + { + Server.PrintToConsole($"[jRandomSkills] {skillName}.NewRound failed, cleanup continues: {(ex.InnerException ?? ex).Message}"); + } + } + public static void OnMapChange() { lock (setLock) @@ -168,10 +180,16 @@ namespace src.player Fortnite.skillInThisRound = false; EntityManager.SuppressKills = true; - EntityManager.DestroyAllTracked(); - foreach (var skill in SkillData.Skills) - Instance.SkillAction(skill.Skill.ToString(), "NewRound"); - EntityManager.SuppressKills = false; + try + { + EntityManager.DestroyAllTracked(); + foreach (var skill in SkillData.Skills) + SafeNewRound(skill.Skill.ToString()); + } + finally + { + EntityManager.SuppressKills = false; + } ActiveSkillsThisRound.Clear(); SkillsUsedThisMap.Clear(); diff --git a/jRandomSkills - SRC Files/src/player/skills/BlastShot.cs b/jRandomSkills - SRC Files/src/player/skills/BlastShot.cs index 5aeeb8e..f85e70b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/BlastShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/BlastShot.cs @@ -135,7 +135,7 @@ namespace src.player.skills heProjectile.DmgRadius = SkillsInfo.GetValue(skillName, "explosionRadius"); if (nades.TryRemove(lastTick, out var source)) - heProjectile.Globalname = $"deathbomb_team_{source.Team}_{source.Owner}_{heProjectile.Index}"; + heProjectile.Globalname = $"blastshot_team_{source.Team}_{source.Owner}_{heProjectile.Index}"; }); } @@ -150,7 +150,7 @@ namespace src.player.skills if (nade == null || !nade.IsValid) return; if (nade.DesignerName != "hegrenade_projectile") return; - if (string.IsNullOrEmpty(nade.Globalname) || !nade.Globalname.StartsWith("deathbomb_team_")) return; + if (string.IsNullOrEmpty(nade.Globalname) || !nade.Globalname.StartsWith("blastshot_team_")) return; var parts = nade.Globalname.Split('_'); if (parts.Length < 4) return; @@ -169,33 +169,12 @@ namespace src.player.skills if (owner != null && !owner.IsValid) owner = null; if (victimPawn.TeamNum == nadeTeam) - { - float reduction = SkillsInfo.GetValue(skillName, "dmgReductionForTeamates"); - param2.Damage *= 1f - Math.Clamp(reduction, 0f, 1f); - - if (IsFriendlyFireOff()) - { - int teamDamage = (int)param2.Damage; - param2.Damage = 0; - - if (teamDamage > 0) - SkillUtils.TakeHealth(victimPawn, teamDamage, owner, KillfeedIcons.Explosion); - - return; - } - } + param2.Damage *= SkillUtils.GetTeamDamageMultiplier(skillName); if (owner != null && param2.Damage >= victimPawn.Health) SkillUtils.RegisterKillCredit(victim.Index, owner.Index, KillfeedIcons.Explosion); } - private static bool IsFriendlyFireOff() - { - bool ff = ConVar.Find("mp_friendlyfire")?.GetPrimitiveValue() ?? false; - bool tae = ConVar.Find("mp_teammates_are_enemies")?.GetPrimitiveValue() ?? false; - return !ff && !tae; - } - private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a - b) < epsilon; public class PlayerSkillInfo diff --git a/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs b/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs index de9c9d1..742cd65 100644 --- a/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs +++ b/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs @@ -234,6 +234,29 @@ namespace src.player.skills SkillUtils.CloseMenu(player); } + public static void PlayerDisconnect(uint playerIndex) + { + lock (setLock) + { + Forget(playerIndex); + + if (playersToTarget.TryRemove(playerIndex, out uint targetIndex)) + Forget(targetIndex); + + foreach (var kvp in playersToTarget) + if (kvp.Value == playerIndex) + playersToTarget.TryRemove(kvp.Key, out _); + } + } + + private static void Forget(uint index) + { + targetPlayers.TryRemove(index, out _); + lastShot.TryRemove(index, out _); + hitPlayer.TryRemove(index, out _); + targetToPlayer.TryRemove(index, out _); + } + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#db6c35", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common, int damageAfterMiss = 5) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity) { public int DamageAfterMiss { get; set; } = damageAfterMiss; diff --git a/jRandomSkills - SRC Files/src/player/skills/Chicken.cs b/jRandomSkills - SRC Files/src/player/skills/Chicken.cs index e999b17..3932272 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Chicken.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Chicken.cs @@ -13,12 +13,12 @@ namespace src.player.skills private static readonly HashSet disabledWeapons = [ "weapon_ak47", "weapon_m4a4", "weapon_m4a1", "weapon_m4a1_silencer", - "weapon_famas", "weapon_galilar", "weapon_aug", "weapon_sg553", + "weapon_famas", "weapon_galilar", "weapon_aug", "weapon_sg556", "weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90", "weapon_mp5sd", "weapon_ssg08", "weapon_awp", "weapon_scar20", "weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", - "weapon_negev", "weapon_sg556" + "weapon_negev" ]; private const string chickenModelPath = "models/chicken/chicken.vmdl"; private static readonly ConcurrentDictionary chickens = []; @@ -127,7 +127,7 @@ namespace src.player.skills var chickenModel = EntityManager.CreateTrackedDynamicProp(player.Index); if (chickenModel == null) return; - + chickenModel.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(chickenModel.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); chickenModel.SetModel(chickenModelPath); chickenModel.Render = Color.FromArgb(255, 255, 255, 255); @@ -138,8 +138,9 @@ namespace src.player.skills chickenModel.CBodyComponent.SceneNode.GetSkeletonInstance().Scale = 1; Utilities.SetStateChanged(chickenModel, "CBaseEntity", "m_CBodyComponent"); - - Server.NextFrame(() => { + + Server.NextFrame(() => + { if (chickenModel == null || !chickenModel.IsValid) return; chickenModel.AcceptInput("SetScale", chickenModel, chickenModel, "1"); }); diff --git a/jRandomSkills - SRC Files/src/player/skills/DeathBomb.cs b/jRandomSkills - SRC Files/src/player/skills/DeathBomb.cs index 43e262c..d25a364 100644 --- a/jRandomSkills - SRC Files/src/player/skills/DeathBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/DeathBomb.cs @@ -123,33 +123,12 @@ namespace src.player.skills if (owner != null && !owner.IsValid) owner = null; if (victimPawn.TeamNum == nadeTeam) - { - float reduction = SkillsInfo.GetValue(skillName, "dmgReductionForTeamates"); - param2.Damage *= 1f - Math.Clamp(reduction, 0f, 1f); - - if (IsFriendlyFireOff()) - { - int teamDamage = (int)param2.Damage; - param2.Damage = 0; - - if (teamDamage > 0) - SkillUtils.TakeHealth(victimPawn, teamDamage, owner, KillfeedIcons.Explosion); - - return; - } - } + param2.Damage *= SkillUtils.GetTeamDamageMultiplier(skillName); if (owner != null && param2.Damage >= victimPawn.Health) SkillUtils.RegisterKillCredit(victim.Index, owner.Index, KillfeedIcons.Explosion); } - private static bool IsFriendlyFireOff() - { - bool ff = ConVar.Find("mp_friendlyfire")?.GetPrimitiveValue() ?? false; - bool tae = ConVar.Find("mp_teammates_are_enemies")?.GetPrimitiveValue() ?? false; - return !ff && !tae; - } - private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a - b) < epsilon; private static bool IsDeadPlayerValid(CCSPlayerController? player) diff --git a/jRandomSkills - SRC Files/src/player/skills/ExplodingBarrel.cs b/jRandomSkills - SRC Files/src/player/skills/ExplodingBarrel.cs index f25828d..4dc5ff6 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ExplodingBarrel.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ExplodingBarrel.cs @@ -229,33 +229,12 @@ namespace src.player.skills if (owner != null && !owner.IsValid) owner = null; if (victimPawn.TeamNum == nadeTeam) - { - float reduction = SkillsInfo.GetValue(skillName, "dmgReductionForTeamates"); - param2.Damage *= 1f - Math.Clamp(reduction, 0f, 1f); - - if (IsFriendlyFireOff()) - { - int teamDamage = (int)param2.Damage; - param2.Damage = 0; - - if (teamDamage > 0) - SkillUtils.TakeHealth(victimPawn, teamDamage, owner, KillfeedIcons.Explosion); - - return; - } - } + param2.Damage *= SkillUtils.GetTeamDamageMultiplier(skillName); if (owner != null && param2.Damage >= victimPawn.Health) SkillUtils.RegisterKillCredit(victim.Index, owner.Index, KillfeedIcons.Explosion); } - private static bool IsFriendlyFireOff() - { - bool ff = ConVar.Find("mp_friendlyfire")?.GetPrimitiveValue() ?? false; - bool tae = ConVar.Find("mp_teammates_are_enemies")?.GetPrimitiveValue() ?? false; - return !ff && !tae; - } - private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a - b) < epsilon; public class PlayerSkillInfo diff --git a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs index f4eceb3..f778536 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs @@ -1,7 +1,10 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; +using jRandomSkills.src.utils; using src.utils; +using System.Collections.Concurrent; using static src.jRandomSkills; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; @@ -13,6 +16,13 @@ namespace src.player.skills private static readonly QAngle angle = new(5, 10, -4); private static int lastTick = 0; + private static byte pendingTeam = (byte)CsTeam.None; + private static readonly ConcurrentDictionary nades = []; + + public static void NewRound() + { + nades.Clear(); + } public static void LoadSkill() { @@ -31,10 +41,12 @@ namespace src.player.skills border: !PlayerManager.GetTickPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } - private static void SpawnExplosion(Vector vector) + private static void SpawnExplosion(Vector vector, CCSPlayerController player) { lastTick = Server.TickCount; - SkillUtils.CreateHEGrenadeProjectile(vector, angle, new Vector(0, 0, 0), 0); + pendingTeam = player.TeamNum; + nades.AddOrUpdate(Server.TickCount, (player.TeamNum, player.Index), (_, _) => (player.TeamNum, player.Index)); + SkillUtils.CreateHEGrenadeProjectile(vector, angle, new Vector(0, 0, 0), player.TeamNum); } public static void OnEntitySpawned(CEntityInstance entity) @@ -44,6 +56,8 @@ namespace src.player.skills var heProjectile = entity.As(); if (heProjectile == null || !heProjectile.IsValid || heProjectile.AbsRotation == null) return; + int spawnTick = Server.TickCount; + Server.NextFrame(() => { if (heProjectile == null || !heProjectile.IsValid) return; @@ -51,13 +65,52 @@ namespace src.player.skills return; heProjectile.TicksAtZeroVelocity = 100; - heProjectile.TeamNum = (byte)CsTeam.None; + heProjectile.TeamNum = pendingTeam; heProjectile.Damage = SkillsInfo.GetValue(skillName, "damage"); heProjectile.DmgRadius = SkillsInfo.GetValue(skillName, "damageRadius"); heProjectile.DetonateTime = 0; + + if (nades.TryRemove(spawnTick, out var source)) + heProjectile.Globalname = $"explosiveshot_team_{source.Team}_{source.Owner}_{heProjectile.Index}"; }); } + public static void OnTakeDamage(DynamicHook h) + { + CEntityInstance param = h.GetParam(0); + CTakeDamageInfo param2 = h.GetParam(1); + + if (param == null || param.Entity == null || param2 == null) return; + + var nade = param2.Attacker?.Value; + if (nade == null || !nade.IsValid) return; + + if (nade.DesignerName != "hegrenade_projectile") return; + if (string.IsNullOrEmpty(nade.Globalname) || !nade.Globalname.StartsWith("explosiveshot_team_")) return; + + var parts = nade.Globalname.Split('_'); + if (parts.Length < 4) return; + if (!int.TryParse(parts[2], out int nadeTeam)) return; + if (!uint.TryParse(parts[3], out uint ownerIndex)) return; + + CCSPlayerPawn victimPawn = new(param.Handle); + + if (victimPawn.DesignerName != "player") return; + if (victimPawn.Controller?.Value == null) return; + + var victim = victimPawn.Controller.Value.As(); + if (victim == null || !victim.IsValid || victim.Index == ownerIndex) return; + + if (victimPawn.TeamNum == nadeTeam) + param2.Damage *= SkillUtils.GetTeamDamageMultiplier(skillName); + + var owner = Utilities.GetPlayerFromIndex((int)ownerIndex); + if (owner != null && !owner.IsValid) owner = null; + + if (owner != null && param2.Damage >= victimPawn.Health) + SkillUtils.RegisterKillCredit(victim.Index, owner.Index, KillfeedIcons.Explosion); + } + private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a - b) < epsilon; public static void BulletImpact(EventBulletImpact @event) @@ -73,15 +126,16 @@ namespace src.player.skills if (playerInfo == null || playerInfo.Skill != skillName) return; if (Instance.Random.NextDouble() <= playerInfo.SkillChance) - SpawnExplosion(pos); + SpawnExplosion(pos, player); } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#9c0000", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common, float damage = 25f, float damageRadius = 210f, float chanceFrom = .15f, float chanceTo = .3f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity) + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#9c0000", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common, float damage = 25f, float damageRadius = 210f, float chanceFrom = .15f, float chanceTo = .3f, float dmgReductionForTeamates = 0.5f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity) { public float Damage { get; set; } = damage; public float DamageRadius { get; set; } = damageRadius; public float ChanceFrom { get; set; } = chanceFrom; public float ChanceTo { get; set; } = chanceTo; + public float DmgReductionForTeamates { get; set; } = dmgReductionForTeamates; } } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/FireRain.cs b/jRandomSkills - SRC Files/src/player/skills/FireRain.cs index b62f5a9..b43b2e4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FireRain.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FireRain.cs @@ -12,6 +12,10 @@ namespace src.player.skills private const Skills skillName = Skills.FireRain; private static readonly QAngle angle = new(10, -4, 13); private static readonly ConcurrentDictionary decoys = []; + private static int rainTick = -1; + private static CCSPlayerPawn? rainThrower; + private static byte rainTeam = (byte)CsTeam.None; + private static readonly ConcurrentDictionary rainMolotovs = []; public static void LoadSkill() { @@ -21,6 +25,7 @@ namespace src.player.skills public static void NewRound() { KillAllDecoys(); + rainMolotovs.Clear(); } private static void KillAllDecoys() @@ -43,58 +48,79 @@ namespace src.player.skills return; const int grenadeCount = 5; - const float spawnHeight = 800.0f; - const float approachDistance = 600.0f; - const float clusterRadius = 130.0f; - const float flightTime = 0.65f; - const float gravity = 800.0f; + const float maxSpawnHeight = 400.0f; + const float clusterRadius = 110.0f; + const float dropSpeed = 250.0f; - float approachAngle = Random.Shared.NextSingle() * MathF.Tau; - float dirX = MathF.Cos(approachAngle); - float dirY = MathF.Sin(approachAngle); + rainTick = Server.TickCount; + rainThrower = pawn; + rainTeam = player.TeamNum; - Vector skyCenter = new( - targetPos.X + dirX * approachDistance, - targetPos.Y + dirY * approachDistance, - targetPos.Z + spawnHeight - ); - - float dx = targetPos.X - skyCenter.X; - float dy = targetPos.Y - skyCenter.Y; - float dz = targetPos.Z - skyCenter.Z; - - float vx = dx / flightTime; - float vy = dy / flightTime; - float vz = (dz + 0.5f * gravity * flightTime * flightTime) / flightTime; - - Vector velocity = new(vx, vy, vz); - - float yaw = MathF.Atan2(vy, vx) * (180.0f / MathF.PI); - float horizontalSpeed = MathF.Sqrt(vx * vx + vy * vy); - float pitch = -MathF.Atan2(vz, horizontalSpeed) * (180.0f / MathF.PI); - QAngle launchAngle = new(pitch, yaw, 0.0f); + Vector decoyGround = new(targetPos.X, targetPos.Y, targetPos.Z + 8f); + Vector dropVelocity = new(0, 0, -dropSpeed); for (int i = 0; i < grenadeCount; i++) { float offsetAngle = Random.Shared.NextSingle() * MathF.Tau; float offsetDist = MathF.Sqrt(Random.Shared.NextSingle()) * clusterRadius; - float offsetX = MathF.Cos(offsetAngle) * offsetDist; - float offsetY = MathF.Sin(offsetAngle) * offsetDist; - - Vector spawnPos = new( - skyCenter.X + offsetX, - skyCenter.Y + offsetY, - skyCenter.Z + Vector ground = new( + decoyGround.X + MathF.Cos(offsetAngle) * offsetDist, + decoyGround.Y + MathF.Sin(offsetAngle) * offsetDist, + decoyGround.Z ); - SkillUtils.CreateMolotovProjectile(spawnPos, launchAngle, velocity, player.TeamNum); + var reach = RayTrace.TraceShape(player, decoyGround, ground, null, 0); + if (reach.HasValue && reach.Value.DidHit) + ground = decoyGround; + + float height = maxSpawnHeight; + var ceiling = RayTrace.TraceShape(player, ground, new Vector(ground.X, ground.Y, ground.Z + maxSpawnHeight), null, 0); + if (ceiling.HasValue && ceiling.Value.DidHit) + height = Math.Clamp(maxSpawnHeight * ceiling.Value.Fraction - 24f, 24f, maxSpawnHeight); + + Vector spawnPos = new(ground.X, ground.Y, ground.Z + height); + + SkillUtils.CreateMolotovProjectile(spawnPos, angle, dropVelocity, player.TeamNum); } } public static void OnEntitySpawned(CEntityInstance entity) { var name = entity.DesignerName; + + if (name == "molotov_projectile") + { + if (Server.TickCount != rainTick) return; + + var thrower = rainThrower; + if (thrower == null || !thrower.IsValid) return; + + var molotov = entity.As(); + if (molotov == null || !molotov.IsValid) return; + + molotov.TeamNum = rainTeam; + molotov.Thrower.Raw = thrower.EntityHandle.Raw; + molotov.OwnerEntity.Raw = thrower.EntityHandle.Raw; + rainMolotovs[molotov.Index] = (thrower.EntityHandle.Raw, rainTeam); + return; + } + + if (name == "inferno") + { + var inferno = entity.As(); + if (inferno == null || !inferno.IsValid) return; + + var ownerHandle = inferno.OwnerEntity; + var source = ownerHandle?.Value; + if (ownerHandle == null || source == null || !source.IsValid) return; + if (!rainMolotovs.TryGetValue(source.Index, out var origin)) return; + + inferno.TeamNum = origin.Team; + ownerHandle.Raw = origin.ThrowerRaw; + return; + } + if (name != "decoy_projectile") return; diff --git a/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs index c6e7987..f826a92 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs @@ -112,13 +112,31 @@ namespace src.player.skills box.Entity!.Name = box.Globalname = $"FortniteWall_{Server.TickCount}"; box.Collision.SolidType = SolidType_t.SOLID_VPHYSICS; box.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(box.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); - box.DispatchSpawn(); + box.Health = box.MaxHealth = 1_000_000; + + var keys = new CEntityKeyValues(); + try + { + keys.SetString("model", SkillsInfo.GetValue(skillName, "propModel")); + keys.SetVector("origin", pos); + keys.SetBool("solid", true); + box.DispatchSpawn(keys); + } + finally + { + keys.Dispose(); + } + + if (!box.IsValid) return; + box.Teleport(pos, angle, null); + barricades.TryAdd(box.Index, SkillsInfo.GetValue(skillName, "barricadeHealth")); + Server.NextFrame(() => { if (box == null || !box.IsValid) return; - box.SetModel(SkillsInfo.GetValue(skillName, "propModel")); box.Teleport(pos, angle, null); + Utilities.SetStateChanged(box, "CBaseEntity", "m_CBodyComponent"); }); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Giant.cs b/jRandomSkills - SRC Files/src/player/skills/Giant.cs index ac6eb3c..9c56055 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Giant.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Giant.cs @@ -72,6 +72,8 @@ namespace src.player.skills { if (Server.TickCount % 32 != 0) return; + ReapplyScales(); + foreach (var player in PlayerManager.GetTickPlayers()) { var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); @@ -155,6 +157,29 @@ namespace src.player.skills } } + private static void ReapplyScales() + { + lock (setLock) + { + foreach (var kvp in enlargedEnemies) + { + float expected = PlayerManager.GetPlayerByIndex(kvp.Key)?.SkillChance ?? 0f; + if (expected <= 0f) continue; + + var target = Utilities.GetPlayerFromIndex((int)kvp.Value); + if (target == null || !target.IsValid) continue; + + var pawn = target.PlayerPawn?.Value; + if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) continue; + + var skeleton = pawn.CBodyComponent?.SceneNode?.GetSkeletonInstance(); + if (skeleton == null || Math.Abs(skeleton.Scale - expected) < 0.01f) continue; + + SkillUtils.ChangePlayerScale(target, expected); + } + } + } + private static void ResetScale(uint targetIndex, bool notify = false) { var target = Utilities.GetPlayerFromIndex((int)targetIndex); diff --git a/jRandomSkills - SRC Files/src/player/skills/HealingChicken.cs b/jRandomSkills - SRC Files/src/player/skills/HealingChicken.cs index cd10384..e36c97c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HealingChicken.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HealingChicken.cs @@ -1,5 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; @@ -19,6 +20,7 @@ namespace src.player.skills } private static readonly ConcurrentDictionary> activeChickens = new(); + private static readonly ConcurrentDictionary chickenOwners = new(); public static void LoadSkill() { @@ -28,6 +30,29 @@ namespace src.player.skills public static void NewRound() { activeChickens.Clear(); + chickenOwners.Clear(); + } + + public static void OnTakeDamage(DynamicHook h) + { + CEntityInstance param = h.GetParam(0); + CTakeDamageInfo param2 = h.GetParam(1); + + if (param == null || param2 == null) return; + if (!chickenOwners.TryGetValue(param.Index, out uint ownerIndex)) return; + + var owner = Utilities.GetPlayerFromIndex((int)ownerIndex); + if (owner == null || !owner.IsValid) return; + + var attackerEnt = param2.Attacker?.Value; + if (attackerEnt == null || !attackerEnt.IsValid) return; + + var attackerPawn = new CCSPlayerPawn(attackerEnt.Handle); + if (!attackerPawn.IsValid || attackerPawn.DesignerName != "player") return; + + if (attackerPawn.TeamNum != owner.TeamNum) return; + + param2.Damage = 0; } public static void EnableSkill(CCSPlayerController player) @@ -40,7 +65,10 @@ namespace src.player.skills if (activeChickens.TryRemove(player.Index, out var chickens)) foreach (var state in chickens) if (state.Chicken != null && state.Chicken.IsValid) + { + chickenOwners.TryRemove(state.Chicken.Index, out _); state.Chicken.Remove(); + } } private static void SpawnChicken(CCSPlayerController player) @@ -59,6 +87,7 @@ namespace src.player.skills if (chicken == null || !chicken.IsValid) continue; chicken.Render = Color.LightGreen; + chickenOwners[chicken.Index] = player.Index; Vector offset = new( (float)(100 * Math.Cos(2 * Math.PI * i / amount)), diff --git a/jRandomSkills - SRC Files/src/player/skills/JetKick.cs b/jRandomSkills - SRC Files/src/player/skills/JetKick.cs index e8f351c..5dc4e38 100644 --- a/jRandomSkills - SRC Files/src/player/skills/JetKick.cs +++ b/jRandomSkills - SRC Files/src/player/skills/JetKick.cs @@ -33,6 +33,21 @@ namespace src.player.skills } } + public static void PlayerDisconnect(uint playerIndex) + { + lock (setLock) + { + targetedPlayers.TryRemove(playerIndex, out _); + + if (playersToTarget.TryRemove(playerIndex, out uint targetIndex)) + targetedPlayers.TryRemove(targetIndex, out _); + + foreach (var kvp in playersToTarget) + if (kvp.Value == playerIndex) + playersToTarget.TryRemove(kvp.Key, out _); + } + } + public static void OnTick() { if (Server.TickCount % 32 != 0) return; @@ -75,7 +90,7 @@ namespace src.player.skills var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); - if (enemy == null) + if (enemy == null || !enemy.IsValid || enemy.Team == player.Team) { playerEvent.PrintToChat($" {ChatColors.Red}" + playerEvent.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; diff --git a/jRandomSkills - SRC Files/src/player/skills/Nightmare.cs b/jRandomSkills - SRC Files/src/player/skills/Nightmare.cs index c650155..207d968 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Nightmare.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Nightmare.cs @@ -25,7 +25,9 @@ namespace src.player.skills lock (setLock) { RemoveVolume(playerIndex); - playersToTarget.TryRemove(playerIndex, out _); + + if (playersToTarget.TryRemove(playerIndex, out uint leavingTarget)) + RemoveVolume(leavingTarget); foreach (var kvp in playersToTarget) if (kvp.Value == playerIndex) @@ -104,7 +106,7 @@ namespace src.player.skills } var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); - if (enemy == null || !enemy.IsValid) + if (enemy == null || !enemy.IsValid || enemy.Team == player.Team) { playerEvent.PrintToChat($" {ChatColors.Red}" + playerEvent.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; diff --git a/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs b/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs index d123d4c..d2e6fdb 100644 --- a/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs +++ b/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs @@ -15,12 +15,12 @@ namespace src.player.skills private static readonly string[] disabledWeapons = [ "weapon_ak47", "weapon_m4a4", "weapon_m4a1", "weapon_m4a1_silencer", - "weapon_famas", "weapon_galilar", "weapon_aug", "weapon_sg553", + "weapon_famas", "weapon_galilar", "weapon_aug", "weapon_sg556", "weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90", "weapon_mp5sd", "weapon_ssg08", "weapon_awp", "weapon_scar20", "weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", - "weapon_negev", "weapon_sg556" + "weapon_negev" ]; public static void LoadSkill() diff --git a/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs b/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs index 92bce0e..29e921a 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs @@ -23,7 +23,7 @@ namespace src.player.skills { "weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90", "weapon_mp5sd", "weapon_famas", "weapon_galilar", "weapon_m4a1", "weapon_m4a1_silencer", "weapon_ak47", - "weapon_aug", "weapon_sg553", "weapon_ssg08", "weapon_awp", "weapon_scar20", "weapon_g3sg1", + "weapon_aug", "weapon_sg556", "weapon_ssg08", "weapon_awp", "weapon_scar20", "weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", "weapon_negev" }; diff --git a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs index e8cb71e..fd8b9eb 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs @@ -20,7 +20,7 @@ namespace src.player.skills [ "weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90", "weapon_mp5sd", "weapon_famas", "weapon_galilar", "weapon_m4a1", "weapon_m4a1_silencer", "weapon_ak47", - "weapon_aug", "weapon_sg553", "weapon_ssg08", "weapon_awp", "weapon_scar20", "weapon_g3sg1", + "weapon_aug", "weapon_sg556", "weapon_ssg08", "weapon_awp", "weapon_scar20", "weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", "weapon_negev" ]; diff --git a/jRandomSkills - SRC Files/src/player/skills/Spectator.cs b/jRandomSkills - SRC Files/src/player/skills/Spectator.cs index 3c90713..45966d3 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Spectator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Spectator.cs @@ -185,10 +185,12 @@ namespace src.player.skills camNode.Flags = (uint)(camNode.Flags & ~(1 << 2)); camera.SetModel(cameraViewModel); - camera.Render = Color.FromArgb(1, 255, 255, 255); camera.Teleport(pos, angle); camera.DispatchSpawn(); + camera.Render = Color.FromArgb(1, 255, 255, 255); + Utilities.SetStateChanged(camera, "CBaseModelEntity", "m_clrRender"); + CBaseEntity? target = pawn != null && pawn.IsValid ? pawn : null; var entities = EntityManager.GetPlayerEntities(enemy.Index, "empty_prop"); @@ -203,10 +205,11 @@ namespace src.player.skills camera.AcceptInput("SetParent", target, target, "!activator"); }); - if (cameras.TryGetValue(player.Index, out var cameraInfo)) - cameras.AddOrUpdate(player.Index, (cameraInfo.Item1, camera.Index, enemy.Index), (k, v) => (cameraInfo.Item1, camera.Index, enemy.Index)); - else - cameras.AddOrUpdate(player.Index, (pawn.CameraServices.ViewEntity.Raw, camera.Index, enemy.Index), (k, v) => (pawn.CameraServices.ViewEntity.Raw, camera.Index, enemy.Index)); + uint originalView = cameras.TryGetValue(player.Index, out var cameraInfo) + ? cameraInfo.Item1 + : player.PlayerPawn?.Value?.CameraServices?.ViewEntity.Raw ?? 0; + + cameras[player.Index] = (originalView, camera.Index, enemy.Index); return camera.EntityHandle.Raw; } diff --git a/jRandomSkills - SRC Files/src/player/skills/TakeAmmo.cs b/jRandomSkills - SRC Files/src/player/skills/TakeAmmo.cs index 3c84c0e..9a02f1f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/TakeAmmo.cs +++ b/jRandomSkills - SRC Files/src/player/skills/TakeAmmo.cs @@ -29,9 +29,16 @@ namespace src.player.skills foreach (var kvp in OriginalWeaponMaxAmmo) { - var vdata = VirtualFunctions.GetCSWeaponDataFromKey(-1, kvp.Value.Item2); - if (vdata != null) + try + { + var vdata = VirtualFunctions.GetCSWeaponDataFromKey(-1, kvp.Value.Item2); + if (vdata == null || vdata.Handle == nint.Zero) continue; vdata.PrimaryReserveAmmoMax = kvp.Value.Item1; + } + catch (Exception ex) + { + Server.PrintToConsole($"[jRandomSkills] TakeAmmo could not restore ammo for {kvp.Value.Item2}: {ex.Message}"); + } } OriginalWeaponMaxAmmo.Clear(); } diff --git a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs index bf360b0..57a2320 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs @@ -95,9 +95,17 @@ namespace src.player.skills var pawn = eventPlayer.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; - if (SkillUtils.GetDistance(smoke.Key, pawn.AbsOrigin) <= smokeRadius) - if (SkillUtils.TakeHealth(pawn, smokeDamage, thrower, KillfeedIcons.Smokegrenade)) - player.EmitSound("Player.DamageBody.Onlooker"); + if (SkillUtils.GetDistance(smoke.Key, pawn.AbsOrigin) > smokeRadius) continue; + + int damage = smokeDamage; + if (thrower != null && eventPlayer.Index != thrower.Index && pawn.TeamNum == thrower.TeamNum) + { + damage = (int)MathF.Round(smokeDamage * SkillUtils.GetTeamDamageMultiplier(skillName)); + if (damage <= 0) continue; + } + + if (SkillUtils.TakeHealth(pawn, damage, thrower, KillfeedIcons.Smokegrenade)) + player.EmitSound("Player.DamageBody.Onlooker"); } } } @@ -162,12 +170,13 @@ namespace src.player.skills SkillUtils.UpdateGrenadeCount(player, CsItem.SmokeGrenade, 1); } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#507529", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common, int smokeDamage = 2, float smokeRadius = 180, int tickCooldown = 17, int grenadeLimit = 1) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity) + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#507529", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common, int smokeDamage = 2, float smokeRadius = 180, int tickCooldown = 17, int grenadeLimit = 1, float dmgReductionForTeamates = 0.5f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity) { public int SmokeDamage { get; set; } = smokeDamage; public float SmokeRadius { get; set; } = smokeRadius; public int TickCooldown { get; set; } = tickCooldown; public int GrenadeLimit { get; set; } = grenadeLimit; + public float DmgReductionForTeamates { get; set; } = dmgReductionForTeamates; } } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs b/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs index 10633b2..872f8d1 100644 --- a/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs +++ b/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs @@ -17,7 +17,7 @@ namespace src.player.skills "weapon_cz75a", "weapon_fiveseven", "weapon_p250", "weapon_tec9", "weapon_elite", "weapon_hkp2000", "weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90", "weapon_sg556", "weapon_mp5sd", "weapon_famas", "weapon_galilar", "weapon_m4a4", "weapon_m4a1_silencer", "weapon_ak47", - "weapon_aug", "weapon_sg553", "weapon_ssg08", "weapon_awp", "weapon_scar20", "weapon_g3sg1", + "weapon_aug", "weapon_sg556", "weapon_ssg08", "weapon_awp", "weapon_scar20", "weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", "weapon_negev" ]; public static void LoadSkill() diff --git a/jRandomSkills - SRC Files/src/player/skills/WildThrow.cs b/jRandomSkills - SRC Files/src/player/skills/WildThrow.cs index a2aa998..913dd7e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/WildThrow.cs +++ b/jRandomSkills - SRC Files/src/player/skills/WildThrow.cs @@ -75,6 +75,21 @@ namespace src.player.skills SkillUtils.CloseMenu(player); } + public static void PlayerDisconnect(uint playerIndex) + { + lock (setLock) + { + infectedPlayers.TryRemove(playerIndex, out _); + + if (playersToTarget.TryRemove(playerIndex, out uint targetIndex)) + infectedPlayers.TryRemove(targetIndex, out _); + + foreach (var kvp in playersToTarget) + if (kvp.Value == playerIndex) + playersToTarget.TryRemove(kvp.Key, out _); + } + } + public static void OnTick() { if (Server.TickCount % 32 != 0) return; diff --git a/jRandomSkills - SRC Files/src/utils/KillfeedIcons.cs b/jRandomSkills - SRC Files/src/utils/KillfeedIcons.cs index 79e3c27..4292c0c 100644 --- a/jRandomSkills - SRC Files/src/utils/KillfeedIcons.cs +++ b/jRandomSkills - SRC Files/src/utils/KillfeedIcons.cs @@ -279,7 +279,6 @@ namespace jRandomSkills.src.utils "weapon_p90" => KillfeedIcons.P90, "weapon_mp5sd" => KillfeedIcons.Mp5, "weapon_sg556" => KillfeedIcons.Sg556, - "weapon_sg553" => KillfeedIcons.Sg556, "weapon_famas" => KillfeedIcons.Famas, "weapon_galilar" => KillfeedIcons.Galilar, "weapon_m4a4" => KillfeedIcons.M4A4, diff --git a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs index 0a6e7fd..ddac847 100644 --- a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs +++ b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs @@ -106,7 +106,7 @@ namespace src.utils var exists = player.PlayerPawn.Value.WeaponServices.MyWeapons .FirstOrDefault(w => w != null && w.IsValid && w.Value != null && w.Value.IsValid && w.Value.DesignerName == itemString); - + if (exists == null || !existValidator) for (int i = 0; i < count; i++) player.GiveNamedItem(item); @@ -210,7 +210,7 @@ namespace src.utils collision.CollisionAttribute.CollisionGroup = collisionGroup; Utilities.SetStateChanged(pawn, "CCollisionProperty", "m_collisionAttribute"); - // CollisionRulesChanged(pawn); + // CollisionRulesChanged(pawn); } //public static void CollisionRulesChanged(CBaseEntity? entity) @@ -248,8 +248,9 @@ namespace src.utils skeleton.Scale = scale; playerPawn.AcceptInput("SetScale", null, null, scale.ToString(CultureInfo.InvariantCulture)); - - Server.NextWorldUpdate(() => { + + Server.NextWorldUpdate(() => + { if (playerPawn == null || !playerPawn.IsValid) return; Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_CBodyComponent"); }); @@ -338,6 +339,12 @@ namespace src.utils return !ff && !tae; // same team + FF off -> engine will zero this damage } + public static float GetTeamDamageMultiplier(Skills skill) + { + float reduction = SkillsInfo.GetValue(skill, "dmgReductionForTeamates"); + return 1f - Math.Clamp(reduction, 0f, 1f); + } + private static readonly ConcurrentDictionary pendingKillCredits = []; public static void RegisterKillCredit(uint victimIndex, uint attackerIndex, KillfeedIcons? killfeedIcon = null) @@ -367,7 +374,7 @@ namespace src.utils "deagle", "revolver", "glock", "usp_silencer", "cz75a", "fiveseven", "p250", "tec9", "elite", "hkp2000", "mp9", "mac10", "bizon", "mp7", "ump45", "p90", "mp5sd", - "famas", "galilar", "m4a1", "m4a1_silencer", "ak47", "aug", "sg553", + "famas", "galilar", "m4a1", "m4a1_silencer", "ak47", "aug", "sg556", "ssg08", "awp", "scar20", "g3sg1", "nova", "xm1014", "mag7", "sawedoff", "m249", "negev" @@ -389,7 +396,7 @@ namespace src.utils Skills.Deaf, Skills.ExpensiveAmmo, Skills.Giant, Skills.Glitch, Skills.Jammer, Skills.JumpBan, Skills.JumpCurse, Skills.LifeSwap, Skills.Magnifier, Skills.MoneySwap, Skills.Nightmare, Skills.Poison, - Skills.PrimaryBan, Skills.Thief, Skills.WildThrow + Skills.JetKick, Skills.PrimaryBan, Skills.Thief, Skills.WildThrow ]; private static readonly HashSet curseSkillNames = new(curseSkills.Select(s => s.ToString()), StringComparer.Ordinal); @@ -436,15 +443,14 @@ namespace src.utils public static bool TryClaimCurse(uint curserIndex, uint victimIndex, bool force = false) { - if (!CurseLimitEnabled) return true; - int limit = Config.LoadedConfig.CurseSkillPerPlayer!.Value; - lock (curseLock) { ReleaseCurseLocked(curserIndex); curseCounts.TryGetValue(victimIndex, out int used); - if (!force && used >= limit) return false; + + if (CurseLimitEnabled && !force && used >= Config.LoadedConfig.CurseSkillPerPlayer!.Value) + return false; curseCounts[victimIndex] = used + 1; curserToVictim[curserIndex] = victimIndex; @@ -454,15 +460,17 @@ namespace src.utils public static void ReleaseCurse(uint curserIndex) { - if (!CurseLimitEnabled) return; - lock (curseLock) ReleaseCurseLocked(curserIndex); } + public static uint[] GetCursersOf(uint victimIndex) + { + lock (curseLock) + return [.. curserToVictim.Where(kvp => kvp.Value == victimIndex).Select(kvp => kvp.Key)]; + } + public static void ClearCursesFor(uint playerIndex) { - if (!CurseLimitEnabled) return; - lock (curseLock) { ReleaseCurseLocked(playerIndex); @@ -888,7 +896,7 @@ namespace src.utils var hudContent = infoLine + skillLine + remainingLine; - string controllsLine = + string controllsLine = $"{emptySymbol}{player.GetTranslation($"menu_controlls_scroll")}" + $"{player.GetTranslation($"menu_controlls_padding")}" + $"{player.GetTranslation($"menu_controlls_select")}{emptySymbol}"; @@ -1025,7 +1033,7 @@ namespace src.utils if (roundsInOvertime % overtimeMaxRounds == 0) { int currentOvertime = roundsInOvertime / overtimeMaxRounds; - if ( currentOvertime < overtimeLimit) + if (currentOvertime < overtimeLimit) { gameRulesProxy.SwapTeamsOnRestart = true; gameRulesProxy.SwitchingTeamsAtRoundReset = true; diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll index c805238..4678da7 100644 Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll differ diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/configs/skillsInfo.json b/jRandomSkills - Server Files/plugins/jRandomSkills/configs/skillsInfo.json index 3c17250..0a236d5 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/configs/skillsInfo.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/configs/skillsInfo.json @@ -1,4 +1,4 @@ -[ +[ { "NeedsTeammates": false, "DisableOnFreezeTime": false, @@ -105,6 +105,7 @@ "SmokeRadius": 180.0, "TickCooldown": 17, "GrenadeLimit": 1, + "DmgReductionForTeamates": 0.5, "NeedsTeammates": false, "DisableOnFreezeTime": false, "OnlyTeam": 0, @@ -1522,6 +1523,7 @@ "DamageRadius": 210.0, "ChanceFrom": 0.15, "ChanceTo": 0.3, + "DmgReductionForTeamates": 0.5, "NeedsTeammates": false, "DisableOnFreezeTime": false, "OnlyTeam": 0, @@ -1857,9 +1859,9 @@ { "ExplosionRadius": 400.0, "ExplosionDamage": 60, - "DmgReductionForTeamates": 0.5, "Cooldown": 10.0, "Force": 1000.0, + "DmgReductionForTeamates": 0.5, "NeedsTeammates": false, "DisableOnFreezeTime": false, "OnlyTeam": 0, diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll index 9a41e0f..3f749dc 100644 Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll differ diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/de.json b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/de.json index c52c295..cf015ef 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/de.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/de.json @@ -1,4 +1,4 @@ -{ +{ "none": "Keine", "none_desc": "Du hast keine Fertigkeit", @@ -276,6 +276,7 @@ "jetkick": "Jetkick", "jetkick_desc": "Wähle einen Spieler für einen Jetkick", + "jetkick_select_info": "Wähle einen Spieler für den Jetkick:", "jetkick_player_info": "Spieler '{0}' wurde wegge-kickt.", "jetkick_enemy_info": "Jeder Schuss stößt dich nach hinten", "jetkick_disable_info": "Dein Rückstoß ist wieder normal.", diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/en.json b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/en.json index c489c0f..2fc0948 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/en.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/en.json @@ -1,4 +1,4 @@ -{ +{ "none": "None", "none_desc": "You have no skill", @@ -269,6 +269,7 @@ "jetkick": "Jetkick", "jetkick_desc": "Select a player to jetkick", + "jetkick_select_info": "Select a player to jetkick:", "jetkick_player_info": "Player '{0}' has been jetkicked.", "jetkick_enemy_info": "Every shot knocks you backwards", "jetkick_disable_info": "Your recoil is back to normal.", diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/fr.json b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/fr.json index 44b7f73..a5243e6 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/fr.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/fr.json @@ -1,4 +1,4 @@ -{ +{ "none": "Aucune", "none_desc": "Vous n’avez aucune compétence", @@ -276,6 +276,7 @@ "jetkick": "Coup de pied propulsé", "jetkick_desc": "Sélectionnez un joueur pour lui donner un coup de pied propulsé", + "jetkick_select_info": "Sélectionnez un joueur à propulser :", "jetkick_player_info": "Le joueur '{0}' a reçu un coup de pied propulsé.", "jetkick_enemy_info": "Chaque tir vous repousse vers l'arrière", "jetkick_disable_info": "Votre recul est revenu à la normale.", diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pl.json b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pl.json index f544e6c..a71d592 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pl.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pl.json @@ -1,4 +1,4 @@ -{ +{ "none": "Brak", "none_desc": "Nie posiadasz żadnej supermocy", @@ -276,6 +276,7 @@ "jetkick": "Odrzutowy Kop", "jetkick_desc": "Wybierz gracza, aby użyć na nim odrzutowego kopa", + "jetkick_select_info": "Wybierz gracza do odrzutowego kopa:", "jetkick_player_info": "Gracz '{0}' został odrzucony kopem.", "jetkick_enemy_info": "Każdy strzał mocno odrzuca Cię do tyłu", "jetkick_disable_info": "Twój odrzut wrócił do normy.", diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pt-br.json b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pt-br.json index 753b2d5..1c334a8 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pt-br.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pt-br.json @@ -1,4 +1,4 @@ -{ +{ "none": "Nenhuma", "none_desc": "Você não tem nenhuma habilidade", @@ -276,6 +276,7 @@ "jetkick": "Chute a Jato", "jetkick_desc": "Selecione um jogador para aplicar um chute a jato", + "jetkick_select_info": "Selecione um jogador para o chute a jato:", "jetkick_player_info": "O jogador '{0}' recebeu um chute a jato.", "jetkick_enemy_info": "Cada tiro empurra você para trás", "jetkick_disable_info": "Seu recuo voltou ao normal.", diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/ru.json b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/ru.json index a4d6107..5fc6fe2 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/ru.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/ru.json @@ -1,4 +1,4 @@ -{ +{ "none": "Нет навыка", "none_desc": "У вас нет навыка", @@ -276,6 +276,7 @@ "jetkick": "Реактивный удар", "jetkick_desc": "Выберите игрока для реактивного удара", + "jetkick_select_info": "Выберите игрока для реактивного удара:", "jetkick_player_info": "Игрок '{0}' получил реактивный удар.", "jetkick_enemy_info": "Каждый выстрел отбрасывает вас назад", "jetkick_disable_info": "Ваша отдача вернулась к норме.", diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/tr.json b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/tr.json index 4db8982..9361605 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/tr.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/tr.json @@ -1,4 +1,4 @@ -{ +{ "none": "Yok", "none_desc": "Hiçbir yeteneğin yok", @@ -52,13 +52,13 @@ "behind_desc2": "Baş döndürme şansın: %{0}", "berserker": "Berserker", - "berserker_desc": "Canın azaldıkça daha fazla hasar verir ve daha hızlı hareket edersin", + "berserker_desc": "Canın azaldıkça hasarın artar ve daha hızlanırsın", "blademaster": "Kılıç Ustası", "blademaster_desc": "Bıçak tutarken mermileri sektirme şansın artar", "blastshot": "Patlama Atışı", - "blastshot_desc": "MP5 ile Attack2 tuşuna basarak bir HE bombası ateşle", + "blastshot_desc": "MP5 ile Sağ Tık'a basarak El bombası fırlat", "bunnyhop": "Tavşan", "bunnyhop_desc": "Otomatik \"BunnyHop\" yaparsın", @@ -156,14 +156,14 @@ "fastreload_desc": "[css_useSkill] tuşuna basarak şarjörünü hızlıca değiştir", "firerain": "Ateş Yağmuru", - "firerain_desc": "Molotof yağmuru çağırmak için bir yem at", + "firerain_desc": "Molotof yağdırmak için bir decoy at", "flash": "Flash", "flash_desc": "Raund başında rastgele oyuncu hızı", "flash_desc2": "Hızın: {0}x", "flashlight": "El Feneri", - "flashlight_desc": "El fenerini açıp kapatmak için [css_useSkill] tuşuna tıkla. Işığı düşmanları kör edebilir", + "flashlight_desc": "[css_useSkill] tuşuna basarak El fenerini açarsın/kaparsın (Işığı düşmanları kör edebilir)", "fortnite": "Fortnite", "fortnite_desc": "[css_useSkill] tuşuna basarak barikat kur", @@ -223,7 +223,7 @@ "healingsmoke_desc": "Sis bombaların iyileştirir", "hermit": "Münzevi", - "hermit_desc": "Öldürdüğünde mermi ve canın yenilenir", + "hermit_desc": "Birini öldürünce mermin ve canın yenilenir", "holyhandgrenade": "Kutsal El Bombası", "holyhandgrenade_desc": "El bomban iki kat hasara ve menzile sahip", @@ -267,9 +267,10 @@ "jester_on": "AÇIK", "jester_off": "KAPALI", - "jetkick": "Jet Tekmesi", - "jetkick_desc": "Jet tekmesi yapmak için bir oyuncu seç", - "jetkick_player_info": "'{0}' adlı oyuncuya jet tekmesi yapıldı.", + "jetkick": "Jetkick", + "jetkick_desc": "Seçtiğin bir rakibin her atışı onu geriye iter", + "jetkick_select_info": "Jetkick uygulanacak oyuncu:", + "jetkick_player_info": "'{0}' adlı oyuncuya jetkick uygulandı.", "jetkick_enemy_info": "Her atış seni geriye doğru iter", "jetkick_disable_info": "Geri tepmen normale döndü.", @@ -297,7 +298,7 @@ "knockback_desc": "Havadayken ateş etmek seni geriye savurur", "lastgasp": "Son Nefes", - "lastgasp_desc": "Öldükten sonra seni öldüren düşmana hasar verirsin", + "lastgasp_desc": "Öldükten sonra seni öldürene hasar verirsin", "lifeswap": "Can Takası", "lifeswap_desc": "Can değerlerini takas etmek için bir oyuncu seç", @@ -340,7 +341,7 @@ "deathbomb_desc": "Öldüğünde patlayarak etraftaki oyuncuları öldürürsün", "deathbomb_explosion": "BOOM!!!", - "demoneye": "Şeytan Gözü", + "demoneye": "Şeytani Göz", "demoneye_desc": "Baktığın tüm düşmanlara hasar verirsin", "nightmare": "Kabus", @@ -489,14 +490,14 @@ "swapposition": "Yer Değiştirme", "swapposition_desc": "[css_useSkill] tuşuna basarak vurduğun düşmanla yer değiştir", - "takeammo": "Mühimmat Al", - "takeammo_desc": "Rastgele bir düşmanın aktif silahının şarjörünü almak için [css_useSkill] tuşuna tıkla", - "takeammo_hud_info1": "Aktif şarjörü olan bir oyuncu bulunamadı.", - "takeammo_hud_info2": "Düşmanın şarjörü yok.", - "takeammo_enemy_info": "Bir miktar mühimmat kaybettin.", + "takeammo": "Cephane Hırsızı", + "takeammo_desc": "[css_useSkill] tuşuna basarak rastgele bir düşmanın silahının şarjörünü çalarsın", + "takeammo_hud_info1": "Cephanesi olan bir oyuncu bulunamadı.", + "takeammo_hud_info2": "Düşmanın cephanesi yok.", + "takeammo_enemy_info": "Birisi cephaneni çaldı.", "teamteleport": "Takıma Işınlanma", - "teamteleport_desc": "Baktığın takım arkadaşına ışınlanmak için [css_useSkill] tuşuna bas", + "teamteleport_desc": "[css_useSkill] tuşuna basarak baktığın takım arkadaşına ışınlanırsın", "teamteleport_noenemy": "Takım arkadaşı bulunamadı", "teamteleport_hud_info": "Bulundu: {0}",