Merge pull request #49 from ByDexterTR/main

v1.2.3.b5
This commit is contained in:
Juzlus 2026-08-06 13:50:06 +02:00 • committed by GitHub
commit ca5ea47e89
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
59 changed files with 2248 additions and 458 deletions

View file

@ -31,7 +31,7 @@ namespace src
public override string ModuleName => "[CS2] [ jRandomSkills ]"; public override string ModuleName => "[CS2] [ jRandomSkills ]";
public override string ModuleAuthor => "D3X (Original), Juzlus (Modifier), ByDexterTR (Contributor)"; 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 ModuleDescription => "Plugin adds random skills every round for CS2 by D3X. Modified by Juzlus.";
public override string ModuleVersion => "1.2.3.b4"; public override string ModuleVersion => "1.2.3.b5";
public override void Load(bool hotReload) public override void Load(bool hotReload)
{ {
@ -386,6 +386,10 @@ namespace src
{ {
public static ConcurrentBag<jSkill_SkillInfo> Skills { get; } = []; public static ConcurrentBag<jSkill_SkillInfo> Skills { get; } = [];
private static jSkill_SkillInfo[]? _snapshot;
public static jSkill_SkillInfo[] GetSnapshot() => _snapshot ??= [.. Skills];
private static Dictionary<Skills, jSkill_SkillInfo>? _bySkill; private static Dictionary<Skills, jSkill_SkillInfo>? _bySkill;
public static jSkill_SkillInfo? GetInfo(Skills skill) public static jSkill_SkillInfo? GetInfo(Skills skill)
@ -401,7 +405,11 @@ namespace src
return map.TryGetValue(skill, out var info) ? info : null; return map.TryGetValue(skill, out var info) ? info : null;
} }
public static void Invalidate() => _bySkill = null; public static void Invalidate()
{
_bySkill = null;
_snapshot = null;
}
} }
public enum CS2ConsoleColors public enum CS2ConsoleColors

View file

@ -1,4 +1,4 @@
{ {
"none": "Keine", "none": "Keine",
"none_desc": "Du hast keine Fertigkeit", "none_desc": "Du hast keine Fertigkeit",
@ -77,6 +77,11 @@
"catapult_desc": "Du hast eine zufällige Chance, einen Gegner nach oben zu schleudern", "catapult_desc": "Du hast eine zufällige Chance, einen Gegner nach oben zu schleudern",
"catapult_desc2": "Deine Chance, einen Gegner bei einem Treffer zu schleudern, beträgt: {0} %", "catapult_desc2": "Deine Chance, einen Gegner bei einem Treffer zu schleudern, beträgt: {0} %",
"chameleon": "Chamäleon",
"chameleon_desc": "Der erste Spieler, den du tötest, gibt dir seine Fähigkeit",
"chameleon_copied_info": "Fähigkeit kopiert: {0}",
"chameleon_wrong_team_info": "'{0}' hatte eine Fähigkeit, die dein Team nicht nutzen kann.",
"chicken": "Huhn", "chicken": "Huhn",
"chicken_desc": "Du erhältst ein Huhn-Modell + 10 % schnellere Bewegung – 50 HP", "chicken_desc": "Du erhältst ein Huhn-Modell + 10 % schnellere Bewegung – 50 HP",
@ -220,6 +225,11 @@
"godmode_off": "Unsterblichkeit deaktiviert", "godmode_off": "Unsterblichkeit deaktiviert",
"godmode_on": "Unsterblichkeit aktiviert", "godmode_on": "Unsterblichkeit aktiviert",
"grapple": "Enterhaken",
"grapple_desc": "Drücke [css_useSkill], um einen Haken auf den anvisierten Punkt zu schießen und dich dorthin zu ziehen",
"grapple_no_anchor_info": "Keine Oberfläche zum Einhaken.",
"grapple_pulling_info": "ZUG",
"grenadier": "Grenadier", "grenadier": "Grenadier",
"grenadier_desc": "Du hast unendlich viele Granaten", "grenadier_desc": "Du hast unendlich viele Granaten",
@ -259,6 +269,11 @@
"infiniteammo": "Unendliche Munition", "infiniteammo": "Unendliche Munition",
"infiniteammo_desc": "Du erhältst unendliche Munition für alle deine Waffen", "infiniteammo_desc": "Du erhältst unendliche Munition für alle deine Waffen",
"inheritance": "Erbe",
"inheritance_desc": "Wenn ein Teamkollege stirbt, kannst du seine Fähigkeit übernehmen",
"inheritance_select_info": "Wähle die Fähigkeit, die du erbst:",
"inheritance_player_info": "Du hast die Fähigkeit von '{0}' geerbt.",
"jackal": "Spürhund", "jackal": "Spürhund",
"jackal_desc": "Jeder Gegner hinterlässt eine Spur", "jackal_desc": "Jeder Gegner hinterlässt eine Spur",
@ -448,6 +463,9 @@
"richboy": "Rich Boy", "richboy": "Rich Boy",
"richboy_desc": "Du erhältst zu Beginn der Runde einen zufälligen Geldbetrag", "richboy_desc": "Du erhältst zu Beginn der Runde einen zufälligen Geldbetrag",
"ricochet": "Querschläger",
"ricochet_desc": "Deine Kugeln prallen von Wänden ab und können Gegner weiterhin treffen",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Wenn du einem Gegner Schaden zufügst, stiehlst du ihm sein Geld", "robinhood_desc": "Wenn du einem Gegner Schaden zufügst, stiehlst du ihm sein Geld",

View file

@ -1,4 +1,4 @@
{ {
"none": "None", "none": "None",
"none_desc": "You have no skill", "none_desc": "You have no skill",
@ -77,6 +77,11 @@
"catapult_desc": "You have a random chance to launch an enemy upwards", "catapult_desc": "You have a random chance to launch an enemy upwards",
"catapult_desc2": "Your chance to launch an enemy on hit is: {0}%", "catapult_desc2": "Your chance to launch an enemy on hit is: {0}%",
"chameleon": "Chameleon",
"chameleon_desc": "The first player you kill gives you their skill",
"chameleon_copied_info": "You copied the skill: {0}",
"chameleon_wrong_team_info": "'{0}' had a skill your team cannot use.",
"chicken": "Chicken", "chicken": "Chicken",
"chicken_desc": "You get a chicken model + 10% faster movement - 50 HP", "chicken_desc": "You get a chicken model + 10% faster movement - 50 HP",
@ -213,6 +218,11 @@
"godmode_off": "Immortality disabled", "godmode_off": "Immortality disabled",
"godmode_on": "Immortality enabled", "godmode_on": "Immortality enabled",
"grapple": "Grapple Hook",
"grapple_desc": "Press [css_useSkill] to fire a hook at the point you are aiming at and pull yourself there",
"grapple_no_anchor_info": "No surface to hook onto.",
"grapple_pulling_info": "PULLING",
"grenadier": "Grenadier", "grenadier": "Grenadier",
"grenadier_desc": "You have infinite hegrenade", "grenadier_desc": "You have infinite hegrenade",
@ -252,6 +262,11 @@
"infiniteammo": "Infinite Ammo", "infiniteammo": "Infinite Ammo",
"infiniteammo_desc": "You receive infinite ammo for all your weapons", "infiniteammo_desc": "You receive infinite ammo for all your weapons",
"inheritance": "Inheritance",
"inheritance_desc": "When a teammate dies you can take over their skill",
"inheritance_select_info": "Choose the skill you inherit:",
"inheritance_player_info": "You inherited the skill of '{0}'.",
"jackal": "Tracker", "jackal": "Tracker",
"jackal_desc": "Every opponent leaves a trail behind them", "jackal_desc": "Every opponent leaves a trail behind them",
@ -448,6 +463,9 @@
"richboy": "Rich Boy", "richboy": "Rich Boy",
"richboy_desc": "You receive a random amount of money at the start of the round", "richboy_desc": "You receive a random amount of money at the start of the round",
"ricochet": "Ricochet",
"ricochet_desc": "Your bullets bounce off walls and can still hit enemies",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Dealing damage to an enemy steals their money", "robinhood_desc": "Dealing damage to an enemy steals their money",

View file

@ -1,4 +1,4 @@
{ {
"none": "Aucune", "none": "Aucune",
"none_desc": "Vous n’avez aucune compétence", "none_desc": "Vous n’avez aucune compétence",
@ -77,6 +77,11 @@
"catapult_desc": "Vous avez une chance aléatoire de projeter un ennemi en l’air", "catapult_desc": "Vous avez une chance aléatoire de projeter un ennemi en l’air",
"catapult_desc2": "Votre chance de projeter un ennemi à l’impact est : {0}%", "catapult_desc2": "Votre chance de projeter un ennemi à l’impact est : {0}%",
"chameleon": "Caméléon",
"chameleon_desc": "Le premier joueur que vous tuez vous donne sa compétence",
"chameleon_copied_info": "Compétence copiée : {0}",
"chameleon_wrong_team_info": "'{0}' avait une compétence que votre équipe ne peut pas utiliser.",
"chicken": "Poulet", "chicken": "Poulet",
"chicken_desc": "Vous obtenez un modèle de poulet + 10% de vitesse de déplacement en plus - 50 PV", "chicken_desc": "Vous obtenez un modèle de poulet + 10% de vitesse de déplacement en plus - 50 PV",
@ -220,6 +225,11 @@
"godmode_off": "Immortalité désactivée", "godmode_off": "Immortalité désactivée",
"godmode_on": "Immortalité activée", "godmode_on": "Immortalité activée",
"grapple": "Grappin",
"grapple_desc": "Appuyez sur [css_useSkill] pour lancer un grappin sur le point visé et vous y propulser",
"grapple_no_anchor_info": "Aucune surface pour accrocher le grappin.",
"grapple_pulling_info": "TRACTION",
"grenadier": "Grenadier", "grenadier": "Grenadier",
"grenadier_desc": "Tu as des grenades HE infinies", "grenadier_desc": "Tu as des grenades HE infinies",
@ -259,6 +269,11 @@
"infiniteammo": "Munitions Infinies", "infiniteammo": "Munitions Infinies",
"infiniteammo_desc": "Vous recevez des munitions infinies pour toutes vos armes", "infiniteammo_desc": "Vous recevez des munitions infinies pour toutes vos armes",
"inheritance": "Héritage",
"inheritance_desc": "Quand un coéquipier meurt, vous pouvez reprendre sa compétence",
"inheritance_select_info": "Choisissez la compétence à hériter :",
"inheritance_player_info": "Vous avez hérité de la compétence de '{0}'.",
"jackal": "Traqueur", "jackal": "Traqueur",
"jackal_desc": "Chaque adversaire laisse une trace derrière lui", "jackal_desc": "Chaque adversaire laisse une trace derrière lui",
@ -448,6 +463,9 @@
"richboy": "Gosse de Riche", "richboy": "Gosse de Riche",
"richboy_desc": "Vous recevez une somme d’argent aléatoire au début du round", "richboy_desc": "Vous recevez une somme d’argent aléatoire au début du round",
"ricochet": "Ricochet",
"ricochet_desc": "Vos balles rebondissent sur les murs et peuvent encore toucher les ennemis",
"robinhood": "Robin des Bois", "robinhood": "Robin des Bois",
"robinhood_desc": "Infliger des dégâts à un ennemi lui vole de l’argent", "robinhood_desc": "Infliger des dégâts à un ennemi lui vole de l’argent",

View file

@ -1,4 +1,4 @@
{ {
"none": "Brak", "none": "Brak",
"none_desc": "Nie posiadasz żadnej supermocy", "none_desc": "Nie posiadasz żadnej supermocy",
@ -77,6 +77,11 @@
"catapult_desc": "Masz losową szanse na podrzucenie wroga", "catapult_desc": "Masz losową szanse na podrzucenie wroga",
"catapult_desc2": "Twoje szanse na podrzucenie wroga po trafieniu to: {0}%", "catapult_desc2": "Twoje szanse na podrzucenie wroga po trafieniu to: {0}%",
"chameleon": "Kameleon",
"chameleon_desc": "Pierwszy zabity gracz oddaje ci swoją umiejętność",
"chameleon_copied_info": "Skopiowano umiejętność: {0}",
"chameleon_wrong_team_info": "'{0}' miał umiejętność, której twoja drużyna nie może użyć.",
"chicken": "Kurczak", "chicken": "Kurczak",
"chicken_desc": "Otrzymujesz model kurczaka + jesteś o 10% szybszy - 50hp", "chicken_desc": "Otrzymujesz model kurczaka + jesteś o 10% szybszy - 50hp",
@ -220,6 +225,11 @@
"godmode_off": "Nieśmiertelność wyłączona", "godmode_off": "Nieśmiertelność wyłączona",
"godmode_on": "Nieśmiertelność włączona", "godmode_on": "Nieśmiertelność włączona",
"grapple": "Hak",
"grapple_desc": "Naciśnij [css_useSkill], aby wystrzelić hak w celowany punkt i przyciągnąć się do niego",
"grapple_no_anchor_info": "Brak powierzchni do zaczepienia haka.",
"grapple_pulling_info": "PRZYCIĄGANIE",
"grenadier": "Granatnik", "grenadier": "Granatnik",
"grenadier_desc": "Masz nieskończone granaty odłamkowe", "grenadier_desc": "Masz nieskończone granaty odłamkowe",
@ -259,6 +269,11 @@
"infiniteammo": "Nieskończone Ammo", "infiniteammo": "Nieskończone Ammo",
"infiniteammo_desc": "Otrzymujesz nieskończoną ilość amunicji do wszystkich broni", "infiniteammo_desc": "Otrzymujesz nieskończoną ilość amunicji do wszystkich broni",
"inheritance": "Spadek",
"inheritance_desc": "Gdy członek drużyny ginie, możesz przejąć jego umiejętność",
"inheritance_select_info": "Wybierz dziedziczoną umiejętność:",
"inheritance_player_info": "Odziedziczyłeś umiejętność gracza '{0}'.",
"jackal": "Stópkarz", "jackal": "Stópkarz",
"jackal_desc": "Każdy przeciwnik pozostawia za sobą ślad", "jackal_desc": "Każdy przeciwnik pozostawia za sobą ślad",
@ -448,6 +463,9 @@
"richboy": "Bogacz", "richboy": "Bogacz",
"richboy_desc": "Na początku rundy otrzymujesz losową kwotę gotówki", "richboy_desc": "Na początku rundy otrzymujesz losową kwotę gotówki",
"ricochet": "Rykoszet",
"ricochet_desc": "Twoje pociski odbijają się od ścian i nadal mogą trafić przeciwników",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Zadanie obrażeń przeciwnikowi powoduje kradzież jego pieniędzy", "robinhood_desc": "Zadanie obrażeń przeciwnikowi powoduje kradzież jego pieniędzy",

View file

@ -1,4 +1,4 @@
{ {
"none": "Nenhuma", "none": "Nenhuma",
"none_desc": "Você não tem nenhuma habilidade", "none_desc": "Você não tem nenhuma habilidade",
@ -77,6 +77,11 @@
"catapult_desc": "Você tem uma chance aleatória de lançar um inimigo para cima", "catapult_desc": "Você tem uma chance aleatória de lançar um inimigo para cima",
"catapult_desc2": "Sua chance de lançar um inimigo ao acertá-lo é: {0}%", "catapult_desc2": "Sua chance de lançar um inimigo ao acertá-lo é: {0}%",
"chameleon": "Camaleão",
"chameleon_desc": "O primeiro jogador que você matar lhe dá a habilidade dele",
"chameleon_copied_info": "Habilidade copiada: {0}",
"chameleon_wrong_team_info": "'{0}' tinha uma habilidade que sua equipe não pode usar.",
"chicken": "Galinha", "chicken": "Galinha",
"chicken_desc": "Você é uma galinha com +10% de movimento mais rápido e -50 HP", "chicken_desc": "Você é uma galinha com +10% de movimento mais rápido e -50 HP",
@ -220,6 +225,11 @@
"godmode_off": "Imortalidade desativada", "godmode_off": "Imortalidade desativada",
"godmode_on": "Imortalidade ativada", "godmode_on": "Imortalidade ativada",
"grapple": "Gancho",
"grapple_desc": "Pressione [css_useSkill] para lançar um gancho no ponto mirado e se puxar até lá",
"grapple_no_anchor_info": "Nenhuma superfície para prender o gancho.",
"grapple_pulling_info": "PUXANDO",
"grenadier": "Bomberman", "grenadier": "Bomberman",
"grenadier_desc": "Você tem HEs infinitas", "grenadier_desc": "Você tem HEs infinitas",
@ -259,6 +269,11 @@
"infiniteammo": "Munição Infinita", "infiniteammo": "Munição Infinita",
"infiniteammo_desc": "Você recebe munição infinita para todas as suas armas", "infiniteammo_desc": "Você recebe munição infinita para todas as suas armas",
"inheritance": "Herança",
"inheritance_desc": "Quando um companheiro de equipe morre, você pode assumir a habilidade dele",
"inheritance_select_info": "Escolha a habilidade que você herda:",
"inheritance_player_info": "Você herdou a habilidade de '{0}'.",
"jackal": "Lesma", "jackal": "Lesma",
"jackal_desc": "Cada adversário deixa um rastro atrás de si", "jackal_desc": "Cada adversário deixa um rastro atrás de si",
@ -448,6 +463,9 @@
"richboy": "Filhinho de Papai", "richboy": "Filhinho de Papai",
"richboy_desc": "Você recebe uma quantidade aleatória de dinheiro no início da rodada", "richboy_desc": "Você recebe uma quantidade aleatória de dinheiro no início da rodada",
"ricochet": "Ricochete",
"ricochet_desc": "Suas balas ricocheteiam nas paredes e ainda podem acertar inimigos",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Atirar em um inimigo rouba seu dinheiro", "robinhood_desc": "Atirar em um inimigo rouba seu dinheiro",

View file

@ -1,4 +1,4 @@
{ {
"none": "Нет навыка", "none": "Нет навыка",
"none_desc": "У вас нет навыка", "none_desc": "У вас нет навыка",
@ -77,6 +77,11 @@
"catapult_desc": "Есть шанс подбросить врага вверх при попадании", "catapult_desc": "Есть шанс подбросить врага вверх при попадании",
"catapult_desc2": "Ваш шанс подбросить врага при попадании: {0}%", "catapult_desc2": "Ваш шанс подбросить врага при попадании: {0}%",
"chameleon": "Хамелеон",
"chameleon_desc": "Первый убитый вами игрок отдаёт свой навык",
"chameleon_copied_info": "Навык скопирован: {0}",
"chameleon_wrong_team_info": "У '{0}' был навык, недоступный вашей команде.",
"chicken": "Курица", "chicken": "Курица",
"chicken_desc": "Вы получаете модель курицы + 10% к скорости передвижения - 50 HP", "chicken_desc": "Вы получаете модель курицы + 10% к скорости передвижения - 50 HP",
@ -220,6 +225,11 @@
"godmode_off": "Неуязвимость отключена", "godmode_off": "Неуязвимость отключена",
"godmode_on": "Неуязвимость включена", "godmode_on": "Неуязвимость включена",
"grapple": "Крюк",
"grapple_desc": "Нажмите [css_useSkill], чтобы выстрелить крюком в точку прицеливания и притянуться к ней",
"grapple_no_anchor_info": "Нет поверхности для зацепа.",
"grapple_pulling_info": "ПРИТЯГИВАНИЕ",
"grenadier": "Гренадёр", "grenadier": "Гренадёр",
"grenadier_desc": "У вас бесконечные осколочные гранаты", "grenadier_desc": "У вас бесконечные осколочные гранаты",
@ -259,6 +269,11 @@
"infiniteammo": "Бесконечные патроны", "infiniteammo": "Бесконечные патроны",
"infiniteammo_desc": "Вы получаете бесконечные патроны для всего оружия", "infiniteammo_desc": "Вы получаете бесконечные патроны для всего оружия",
"inheritance": "Наследие",
"inheritance_desc": "Когда союзник погибает, вы можете перенять его навык",
"inheritance_select_info": "Выберите наследуемый навык:",
"inheritance_player_info": "Вы унаследовали навык игрока '{0}'.",
"jackal": "Трекер", "jackal": "Трекер",
"jackal_desc": "Каждый противник оставляет за собой след", "jackal_desc": "Каждый противник оставляет за собой след",
@ -448,6 +463,9 @@
"richboy": "Богач", "richboy": "Богач",
"richboy_desc": "Вы получаете случайную сумму денег в начале раунда", "richboy_desc": "Вы получаете случайную сумму денег в начале раунда",
"ricochet": "Рикошет",
"ricochet_desc": "Ваши пули отскакивают от стен и могут поразить врагов",
"robinhood": "Робин Гуд", "robinhood": "Робин Гуд",
"robinhood_desc": "Нанесение урона врагу крадёт его деньги", "robinhood_desc": "Нанесение урона врагу крадёт его деньги",

View file

@ -1,4 +1,4 @@
{ {
"none": "Yok", "none": "Yok",
"none_desc": "Hiçbir yeteneğin yok", "none_desc": "Hiçbir yeteneğin yok",
@ -6,79 +6,84 @@
"aimbot_desc": "Vurduğunda kafadan (HS) sayılır", "aimbot_desc": "Vurduğunda kafadan (HS) sayılır",
"aimlock": "Kitlenme", "aimlock": "Kitlenme",
"aimlock_desc": "En yakın düşmana nişan almak için [css_useSkill] tuşuna basın", "aimlock_desc": "[css_useSkill] tuşuna basarak en yakın düşmana kitlen",
"anomaly": "Zaman Büken", "anomaly": "Zaman Büken",
"anomaly_desc": "[css_useSkill] tuşuna basarak zamanı birkaç saniye geriye alırsın", "anomaly_desc": "[css_useSkill] tuşuna basarak zamanı birkaç saniye geri al",
"antyflash": "Anti-Flash", "antyflash": "Anti-Flash",
"antyflash_desc": "Flaşa kör olmazsın ve flaşların 7 saniye sürer", "antyflash_desc": "Kör olmazsın ve flaşın 7 saniye sürer",
"antyhead": "Beton Kafa", "antyhead": "Beton Kafa",
"antyhead_desc": "Kafadan hasar almazsın", "antyhead_desc": "Kafadan hasar almazsın",
"areareaper": "Mekan Kapatan", "areareaper": "Mekan Kapatan",
"areareaper_desc": "Haritadaki bir bomba alanını tamamen devre dışı bırakabilirsin", "areareaper_desc": "Haritadaki bir bomba alanını devre dışı bırak",
"areareaper_incorrect_site": "Böyle bir bomba alanı yok uydurma", "areareaper_incorrect_site": "Böyle bir bomba alanı yok uydurma",
"areareaper_no_site": "Haritada bomba alanı bulunamadı", "areareaper_no_site": "Haritada bomba alanı bulunamadı",
"areareaper_select_info": "Kapatılacak bomba alanını seç:", "areareaper_select_info": "Alan seçin:",
"areareaper_site_disabled": "{0} Bölgesi kapandı - artık buraya bomba kurulamaz!", "areareaper_site_disabled": "{0} Bölgesi kapandı - artık buraya C4 kurulamaz!",
"areareaper_used_info": "Yeteneğini zaten kullandın, açgözlülük yapma", "areareaper_used_info": "Yeteneğini zaten kullandın!",
"areareaper_teammates_info": "{0} Bölgesi bomba kurmaya kapatıldı.", "areareaper_teammates_info": "{0} Bölgesi bomba kurmaya kapatıldı.",
"areareaper_bombsite_disabled": "Bu bomba alanı kullanıma kapatıldı!", "areareaper_bombsite_disabled": "Bu bomba alanı kullanıma kapatıldı.",
"armored": "Zırhlı", "armored": "Zırhlı",
"armored_desc": "Rastgele hasar alma çarpanına sahip olursun", "armored_desc": "Rastgele hasar alma çarpanın olur",
"armored_desc2": "Hasar alma: {0}x", "armored_desc2": "Hasar alma: {0}x",
"assassin": "Suikastçı", "assassin": "Suikastçı",
"assassin_desc": "Düşmanlara arkadan daha fazla hasar verirsin", "assassin_desc": "Düşmana arkadan daha fazla hasar verirsin",
"astronaut": "Astronot", "astronaut": "Astronot",
"astronaut_desc": "Rastgele bir yerçekimi değerine sahip olursun", "astronaut_desc": "Rastgele bir yerçekimine sahipsin",
"astronaut_desc2": "Yerçekimin: {0}x", "astronaut_desc2": "Yerçekimin: {0}x",
"moneyswap": "Vergi Memuru", "moneyswap": "Vergi Memuru",
"moneyswap_desc": "Bir düşmanla paranı takasla", "moneyswap_desc": "Bir düşmanla paranı takasla",
"moneyswap_enemy_info": "Maliye kapına dayandı", "moneyswap_enemy_info": "Maliye kapına dayandı.",
"moneyswap_player_info": "'{0}' isimli oyuncuyla paraları takas ettin", "moneyswap_player_info": "'{0}' ile paranı takasladın.",
"moneyswap_select_info": "Para takasla biriyle:", "moneyswap_select_info": "Birini seçin:",
"baseball": "Beyzbolcu", "baseball": "Beyzbolcu",
"baseball_desc": "Yanıltıcı bomban (decoy) duvarlardan seker ve çarptığı düşmanı öldürür", "baseball_desc": "Yanıltıcı bomban duvarlardan seker ve çarptığı düşmanı öldürür",
"behind": "Baş Döndüren", "behind": "Baş Döndüren",
"behind_desc": "Vurduğunda düşmanı 180 derece döndürme şansın olur", "behind_desc": "Vurduğunda düşmanı 180 derece döndürme şansın olur",
"behind_desc2": "Baş döndürme şansın: %{0}", "behind_desc2": "Baş döndürme şansın: %{0}",
"berserker": "Berserker", "berserker": "Berserker",
"berserker_desc": "Canın azaldıkça hasarın artar ve daha hızlanırsın", "berserker_desc": "Canın azaldıkça hasarın ve hızın artar",
"blademaster": "Kılıç Ustası", "blademaster": "Kılıç Ustası",
"blademaster_desc": "Bıçak tutarken mermileri sektirme şansın artar", "blademaster_desc": "Bıçak tutarken mermileri savuşturursun",
"blastshot": "Patlama Atışı", "blastshot": "Patlama Atışı",
"blastshot_desc": "MP5 ile Sağ Tık'a basarak El bombası fırlat", "blastshot_desc": "MP5 ile sağ tıklayarak el bombası fırlat",
"bunnyhop": "Tavşan", "bunnyhop": "Tavşan",
"bunnyhop_desc": "Otomatik \"BunnyHop\" yaparsın", "bunnyhop_desc": "Otomatik BunnyHop yaparsın",
"c4camouflage": "C4 Kamuflaj", "c4camouflage": "C4 Kamuflaj",
"c4camouflage_desc": "Elinde C4 varken tamamen görünmez olursun", "c4camouflage_desc": "Elinde C4 varken görünmezsin",
"carefulbullets": "Dikkatli Mermiler", "carefulbullets": "Dikkatli Mermiler",
"carefulbullets_desc": "Düşman mermi kaçırırsa hasar alır", "carefulbullets_desc": "Düşman mermi kaçırırsa hasar alır",
"carefulbullets_enemy_info": "Mermi kaçırmak canını yakacak", "carefulbullets_enemy_info": "Mermi kaçırman can yakar.",
"carefulbullets_disable_info": "Artık mermi kaçırmak can yakmayacak.", "carefulbullets_disable_info": "Artık mermi kaçırmak can yakmayacak.",
"carefulbullets_player_info": "'{0}' artık mermi sıkarken iki kere düşünecek", "carefulbullets_player_info": "'{0}' mermi sıkarken iki kere düşünecek.",
"carefulbullets_select_info": "İsabetsiz atışların hasar vereceği oyuncu:", "carefulbullets_select_info": "Birini seçin:",
"catapult": "Mancınık", "catapult": "Mancınık",
"catapult_desc": "Vurduğun rakibi uzaya (yukarı doğru) fırlatma şansın var", "catapult_desc": "Vurduğun rakibi uzaya (yukarı doğru) fırlatma şansın var",
"catapult_desc2": "Fırlatma şansın: %{0}", "catapult_desc2": "Fırlatma şansın: %{0}",
"chameleon": "Bukalemun",
"chameleon_desc": "Öldürdüğün ilk oyuncunun yeteneği sana geçer",
"chameleon_copied_info": "Yeteneği kopyaladın: {0}",
"chameleon_wrong_team_info": "'{0}' takımının kullanamayacağı bir yeteneğe sahipti.",
"chicken": "Tavuk", "chicken": "Tavuk",
"chicken_desc": "Tavuk modeli ve %10 daha hızlısın fakat 50 HP", "chicken_desc": "Tavuk modeli, %10 daha hızlı ama 50 HP",
"chillout": "Ağırdan Al", "chillout": "Ağırdan Al",
"chillout_desc": "Bombayı kurmak çok daha uzun sürer", "chillout_desc": "Bombayı kurmak çok daha uzun sürer",
@ -87,28 +92,28 @@
"cutter_desc": "Bıçakla tek atarsın", "cutter_desc": "Bıçakla tek atarsın",
"cypher": "Gözcü", "cypher": "Gözcü",
"cypher_desc": "Kamera oluşturmak/geçmek için [css_useSkill] tuşuna bas", "cypher_desc": "[css_useSkill] tuşuna basarak kamera kur ve kameraya geç",
"cypher_nospace": "Kamerayı duvara dik yerleştir", "cypher_nospace": "Kamerayı duvara dik yerleştir",
"darkness": "Karanlık", "darkness": "Karanlık",
"darkness_desc": "Bir düşmanın ekranını karart", "darkness_desc": "Düşmanın ekranını karart",
"darkness_enemy_info": "Işıklar sönsün", "darkness_enemy_info": "Işıklar sönsün.",
"darkness_disable_info": "Işıklar geldi.", "darkness_disable_info": "Işıklar geldi.",
"darkness_player_info": "'{0}' isimli oyuncunun dünyasını kararttın", "darkness_player_info": "'{0}' ışıkları söndü.",
"darkness_select_info": "Karanlık bir oyuncuyu seç:", "darkness_select_info": "Birini seçin:",
"deactivator": "Silgi", "deactivator": "Silgi",
"deactivator_desc": "Bir düşmanın yeteneğini sil", "deactivator_desc": "Bir düşmanın yeteneğini sil",
"deactivator_enemy_info": "Yeteneğin silindi", "deactivator_enemy_info": "Yeteneğin silindi.",
"deactivator_player_info": "'{0}' isimli oyuncunun yeteneği silindi", "deactivator_player_info": "'{0}' isimli oyuncunun yeteneği silindi.",
"deactivator_select_info": "Yetenek silmek için oyuncu seç:", "deactivator_select_info": "Birini seçin:",
"deaf": "Sağır", "deaf": "Sağır",
"deaf_desc": "Bir düşmanın kulağını kapat ve sesleri duymaz hale getir", "deaf_desc": "Bir düşmanı sağır et",
"deaf_enemy_info": "Kulaklıkların tıkandı", "deaf_enemy_info": "Kulaklıkların tıkandı.",
"deaf_disable_info": "Kulakların açıldı.", "deaf_disable_info": "Kulakların açıldı.",
"deaf_player_info": "'{0}' isimli oyuncu için sesler kapatıldı.", "deaf_player_info": "'{0}' sesleri kapatıldı.",
"deaf_select_info": "Sağır bir oyuncuyu seç:", "deaf_select_info": "Birini seçin:",
"disarmament": "Silahsızlandırma", "disarmament": "Silahsızlandırma",
"disarmament_desc": "Vurduğunda rakibin elindeki silahı yere düşürme şansın olur", "disarmament_desc": "Vurduğunda rakibin elindeki silahı yere düşürme şansın olur",
@ -121,15 +126,15 @@
"dash_desc": "Atılmak için ikinci kez zıpla", "dash_desc": "Atılmak için ikinci kez zıpla",
"dracula": "Drakula", "dracula": "Drakula",
"dracula_desc": "Rakiplere verdiğin hasarın belirli bir yüzdesi kadar can alırsın", "dracula_desc": "Rakibe verdiğin hasarın birazı kadar can alırsın",
"duplicator": "Kopyacı", "duplicator": "Kopyacı",
"duplicator_desc": "Yeteneğini kopyalamak için bir oyuncu seç", "duplicator_desc": "Bir düşmanın yeteneğini kopyala",
"duplicator_player_info": "'{0}' isimli oyuncunun yeteneği kopyalandı.", "duplicator_player_info": "'{0}' yeteneği kopyalandı.",
"duplicator_select_info": "Yeteneği kopyalanacak oyuncu:", "duplicator_select_info": "Birini seçin:",
"dwarf": "Cüce", "dwarf": "Cüce",
"dwarf_desc": "Raund başında rastgele karakter boyutu", "dwarf_desc": "Rastgele karakter boyutu",
"dwarf_desc2": "Boyutun: {0}x", "dwarf_desc2": "Boyutun: {0}x",
"enemyspawn": "Base Baskını", "enemyspawn": "Base Baskını",
@ -137,16 +142,16 @@
"expensiveammo": "Pahalı Mermi", "expensiveammo": "Pahalı Mermi",
"expensiveammo_desc": "Seçtiğin rakip her ateş ettiğinde para kaybeder", "expensiveammo_desc": "Seçtiğin rakip her ateş ettiğinde para kaybeder",
"expensiveammo_disable_info": "Mermilerin yeniden bedava.", "expensiveammo_disable_info": "Mermi yeniden bedava.",
"expensiveammo_enemy_info": "Artık her atışın sana {0}$ mal oluyor.", "expensiveammo_enemy_info": "Her atışın sana {0}$ mal oluyor.",
"expensiveammo_player_info": "'{0}' artık her mermisinin parasını ödüyor.", "expensiveammo_player_info": "'{0}' her mermisinin parasını ödüyor.",
"expensiveammo_select_info": "Mermisi pahalanacak oyuncu:", "expensiveammo_select_info": "Birini seçin:",
"explodingbarrel": "Patlayan Varil", "explodingbarrel": "Patlayan Varil",
"explodingbarrel_desc": "[css_useSkill] ile vurulunca patlayan bir varil koyarsın", "explodingbarrel_desc": "[css_useSkill] tuşuna basarak vurulunca patlayan varil koy",
"explosiveshot": "Patlayıcı Mermi", "explosiveshot": "Patlayıcı Mermi",
"explosiveshot_desc": "Ateş ederken rastgele mermilerin patlayabilir", "explosiveshot_desc": "Ateş ederken mermin patlayabilir",
"explosiveshot_desc2": "Patlayan mermi şansı: %{0}", "explosiveshot_desc2": "Patlayan mermi şansı: %{0}",
"falconeye": "Şahin Gözü", "falconeye": "Şahin Gözü",
@ -156,31 +161,31 @@
"fastreload_desc": "[css_useSkill] tuşuna basarak şarjörünü hızlıca değiştir", "fastreload_desc": "[css_useSkill] tuşuna basarak şarjörünü hızlıca değiştir",
"firerain": "Ateş Yağmuru", "firerain": "Ateş Yağmuru",
"firerain_desc": "Molotof yağdırmak için bir decoy at", "firerain_desc": "Molotof yağdırmak için yanıltıcı bomba at",
"flash": "Flash", "flash": "Flash",
"flash_desc": "Raund başında rastgele oyuncu hızı", "flash_desc": "Rastgele oyuncu hızı",
"flash_desc2": "Hızın: {0}x", "flash_desc2": "Hızın: {0}x",
"flashlight": "El Feneri", "flashlight": "El Feneri",
"flashlight_desc": "[css_useSkill] tuşuna basarak El fenerini açarsın/kaparsın (Işığı düşmanları kör edebilir)", "flashlight_desc": "[css_useSkill] tuşuna basarak el fenerini aç veya kapat, ışığı düşmanı kör eder",
"fortnite": "Fortnite", "fortnite": "Fortnite",
"fortnite_desc": "[css_useSkill] tuşuna basarak barikat kur", "fortnite_desc": "[css_useSkill] tuşuna basarak barikat kur",
"fragilebomb": "Hassas C4", "fragilebomb": "Hassas C4",
"fragilebomb_desc": "Kurulu C4'e ateş etmek C4'ün canını azaltır ve C4 imha edilir.", "fragilebomb_desc": "Kurulu C4'e ateş etmek canını azaltır ve C4'ü imha eder",
"fragilebomb_bomb_health": "Bombanın canı", "fragilebomb_bomb_health": "Bombanın canı",
"friendlyfire": "Dost Şifası", "friendlyfire": "Dost Şifası",
"friendlyfire_desc": "Takım arkadaşlarına ateş etmek onları iyileştirir", "friendlyfire_desc": "Takım arkadaşına ateş etmek onu iyileştirir",
"frozendecoy": "Buz Kıran", "frozendecoy": "Buz Kıran",
"frozendecoy_desc": "Yanıltıcı bomba (decoy) yakındaki tüm oyuncuları dondurur", "frozendecoy_desc": "Yanıltıcı bomban yakındaki herkesi yavaşlatır",
"gambler": "Kumarbaz", "gambler": "Kumarbaz",
"gambler_desc": "Sunulan listeden bir yetenek seç.", "gambler_desc": "Sunulan listeden bir yetenek seç.",
"gambler_select_info": "Yeteneğini seç:", "gambler_select_info": "Birini seçin:",
"gambler_more": "#00FF00|${0} yenile", "gambler_more": "#00FF00|${0} yenile",
"gambler_no_money": "Yeterli para yok.", "gambler_no_money": "Yeterli para yok.",
@ -188,106 +193,116 @@
"ghost_desc": "Tamamen görünmezsin", "ghost_desc": "Tamamen görünmezsin",
"giant": "Dev", "giant": "Dev",
"giant_desc": "Seçtiğin bir rakibi büyütür", "giant_desc": "Seçtiğin rakibi büyüt",
"giant_desc2": "Seçtiğin bir rakibi {0}x büyütür", "giant_desc2": "Rakibin boyutu: {0}x",
"giant_disable_info": "Normal boyutuna geri döndün.", "giant_disable_info": "Normal boyutuna döndün.",
"giant_enemy_info": "{0}x boyutuna büyütüldün.", "giant_enemy_info": "{0}x boyutuna büyüdün.",
"giant_player_info": "'{0}' oyuncusunu {1}x büyüttün.", "giant_player_info": "'{0}' boyutunu {1}x büyüttün.",
"giant_select_info": "Büyütülecek oyuncu:", "giant_select_info": "Birini seçin:",
"glaz": "Glaz", "glaz": "Glaz",
"glaz_desc": "Sis bombalarının içini görebilirsin", "glaz_desc": "Sis bombasının içini görürsün",
"glitch": "Glitç", "glitch": "Glitç",
"glitch_desc": "Seçilen bir düşmanın radarını kapatır", "glitch_desc": "Bir düşmanın radarını kapat",
"glitch_enemy_info": "Radarın kapandı", "glitch_enemy_info": "Radarın kapandı.",
"glitch_disable_info": "Radarın açıldı", "glitch_disable_info": "Radarın açıldı.",
"glitch_player_info": "'{0}' isimli oyuncunun radarı devre dışı bırakıldı.", "glitch_player_info": "'{0}' radarı kapandı.",
"glitch_select_info": "Radarı kapatılacak oyuncuyu seç:", "glitch_select_info": "Birini seçin:",
"glue": "Yapıştırıcı", "glue": "Yapıştırıcı",
"glue_desc": "Bombaların duvarlara yapışır", "glue_desc": "Bomban duvara yapışır",
"godmode": "Ölümsüz", "godmode": "Ölümsüz",
"godmode_desc": "[css_useSkill] tuşuna basarak kısa süreli ölümsüz ol", "godmode_desc": "[css_useSkill] tuşuna basarak kısa süreli ölümsüz ol",
"godmode_off": "Ölümsüzlük kapandı", "godmode_off": "Ölümsüzlük kapandı",
"godmode_on": "Ölümsüzlük açıldı", "godmode_on": "Ölümsüzlük açıldı",
"grapple": "Kanca",
"grapple_desc": "[css_useSkill] tuşuna basarak baktığın yere kanca at",
"grapple_no_anchor_info": "Kanca atılacak yüzey yok",
"grapple_pulling_info": "ÇEKİLİYOR",
"grenadier": "Bombacı", "grenadier": "Bombacı",
"grenadier_desc": "Sınırsız el bombasına sahipsin", "grenadier_desc": "El bomban sınırsız",
"healingchicken": "Şifacı Tavuk", "healingchicken": "Şifacı Tavuk",
"healingchicken_desc": "Yakınındayken tavukların seni iyileştirir", "healingchicken_desc": "Yakınındayken tavuğun seni iyileştirir",
"healingsmoke": "Şifalı Sis", "healingsmoke": "Şifalı Sis",
"healingsmoke_desc": "Sis bombaların iyileştirir", "healingsmoke_desc": "Sis bomban iyileştirir",
"hermit": "Münzevi", "hermit": "Münzevi",
"hermit_desc": "Birini öldürünce mermin ve canın yenilenir", "hermit_desc": "Birini öldürünce mermin ve canın yenilenir",
"holyhandgrenade": "Kutsal El Bombası", "holyhandgrenade": "Kutsal El Bombası",
"holyhandgrenade_desc": "El bomban iki kat hasara ve menzile sahip", "holyhandgrenade_desc": "El bombanın hasarı ve menzili iki kat",
"homingnades": "Güdümlü Bomba", "homingnades": "Güdümlü Bomba",
"homingnades_desc": "Bombalarınız (sis hariç) düşmanlara yönelir", "homingnades_desc": "Bomban (sis hariç) yakın düşmana yönelir",
"hotbomb": "Sıcak C4", "hotbomb": "Sıcak C4",
"hotbomb_desc": "Yaşadığın sürece bombacının canı azalıyor", "hotbomb_desc": "Yaşadığın sürece bombacının canı azalır",
"hotbomb_hint": "Bomba çok sıcak!", "hotbomb_hint": "C4 ÇOK SICAK!",
"hotbomb_disable_info": "Bomba artık yakmıyor.", "hotbomb_disable_info": "C4 soğudu.",
"iana": "Hologram", "iana": "Hologram",
"iana_desc": "[css_useSkill] tuşuna basarak bir hologram oluştur", "iana_desc": "[css_useSkill] tuşuna basarak bir hologram oluştur",
"illiterate": "Cahiliye", "illiterate": "Cahiliye",
"illiterate_desc": "Yaşadığın sürece rakibin sohbeti (chat) veya oyun yazılarını okuyamaz", "illiterate_desc": "Yaşadığın sürece rakip hiçbir yazıyı okuyamaz",
"illiterate_alert": "Cahiliye aktif! Bu yeteneğin sahibi ortadan kalkana kadar mesajları okuyamazsınız.", "illiterate_alert": "Cahiliye aktif! Bu yeteneğin sahibi ortadan kalkana kadar mesajları okuyamazsınız.",
"illusionist": "İllüzyonist", "illusionist": "İllüzyonist",
"illusionist_desc": "[css_useSkill] tuşuna basarak düz ilerleyen illüzyon oluştur", "illusionist_desc": "[css_useSkill] tuşuna basarak düz ilerleyen illüzyon oluştur",
"impostor": "Sahtekar", "impostor": "Sahtekar",
"impostor_desc": "Düşman oyuncu modeline dönüşürsün", "impostor_desc": "Düşman modeline dönüşürsün",
"infiniteammo": "Sınırsız Mermi", "infiniteammo": "Sınırsız Mermi",
"infiniteammo_desc": "Tüm silahların sınırsız mermisi olur", "infiniteammo_desc": "Silahlarının mermisi sınırsız",
"inheritance": "Miras",
"inheritance_desc": "Bir takım arkadaşın öldüğünde yeteneğini devralabilirsin",
"inheritance_select_info": "Birini seçin:",
"inheritance_player_info": "'{0}' yeteneğini devraldın.",
"jackal": "İzci", "jackal": "İzci",
"jackal_desc": "Her rakip yürüdüğünde ayak izi bırakır", "jackal_desc": "Her rakip yürüdüğünde ayak izi bırakır",
"jammer": "Sinyal Kesici", "jammer": "Sinyal Kesici",
"jammer_desc": "Bir oyuncunun nişangahını (crosshair) kapatmak için seç", "jammer_desc": "Bir düşmanın nişangahını kapat",
"jammer_enemy_info": "Nişangahın kapatıldı.", "jammer_enemy_info": "Nişangahın kapatıldı.",
"jammer_disable_info": "Nişangahın açıldı", "jammer_disable_info": "Nişangahın açıldı.",
"jammer_player_info": "'{0}' isimli oyuncunun nişangahı kapatıldı.", "jammer_player_info": "'{0}' isimli oyuncunun nişangahı kapatıldı.",
"jammer_select_info": "Nişangahı kapatılacak oyuncuyu seç:", "jammer_select_info": "Birini seçin:",
"jester": "Soytarı", "jester": "Soytarı",
"jester_desc": "Soytarı modunda hasar alamazsın ve veremezsin. Bu mod birkaç saniyede bir değişir.", "jester_desc": "Soytarı modunda hasar alamaz ve veremezsin, mod birkaç saniyede bir değişir",
"jester_mode": "Soytarı Modu", "jester_mode": "Soytarı Modu",
"jester_on": "AÇIK", "jester_on": "AÇIK",
"jester_off": "KAPALI", "jester_off": "KAPALI",
"jetkick": "Jetkick", "jetkick": "Jetkick",
"jetkick_desc": "Seçtiğin bir rakibin her atışı onu geriye iter", "jetkick_desc": "Seçtiğin rakibi her atışı geriye iter",
"jetkick_select_info": "Jetkick uygulanacak oyuncu:", "jetkick_select_info": "Birini seçin:",
"jetkick_player_info": "'{0}' adlı oyuncuya jetkick uygulandı.", "jetkick_player_info": "'{0}' adlı oyuncuya jetkick uygulandı.",
"jetkick_enemy_info": "Her atış seni geriye doğru iter", "jetkick_enemy_info": "Her atış seni geriye doğru iter",
"jetkick_disable_info": "Geri tepmen normale döndü.", "jetkick_disable_info": "Geri tepmen normale döndü.",
"jumpban": "Bacaksız", "jumpban": "Bacaksız",
"jumpban_desc": "Zıplayamayacak bir oyuncu seç", "jumpban_desc": "Zıplayamayacak bir düşman seç",
"jumpban_enemy_info": "Bacakların kesildi", "jumpban_enemy_info": "Bacakların kesildi.",
"jumpban_disable_info": "Bacaklarına kavuştun", "jumpban_disable_info": "Tekrar zıplayabilirsin.",
"jumpban_player_info": "'{0}' artık zıplayamaz.", "jumpban_player_info": "'{0}' artık zıplayamaz.",
"jumpban_select_info": "Zıplaması yasaklanacak oyuncu:", "jumpban_select_info": "Birini seçin:",
"jumpcurse": "Zıplama Laneti", "jumpcurse": "Zıplama Laneti",
"jumpcurse_desc": "Seçtiğin rakip, takım arkadaşları her zıpladığında zıplar", "jumpcurse_desc": "Seçtiğin rakip, takım arkadaşlarıyla zıpladıkça zıplar",
"jumpcurse_disable_info": "Bacakların yeniden senin.", "jumpcurse_disable_info": "Kendin için zıplayabilirsin.",
"jumpcurse_enemy_info": "Artık takım arkadaşların zıpladıkça sen de zıplıyorsun.", "jumpcurse_enemy_info": "Takım arkadaşların zıpladıkça sen de zıplıyorsun.",
"jumpcurse_player_info": "'{0}' artık takımıyla birlikte zıplıyor.", "jumpcurse_player_info": "'{0}' takımıyla birlikte zıplıyor.",
"jumpcurse_select_info": "Zıplama laneti verilecek oyuncu:", "jumpcurse_select_info": "Birini seçin:",
"jumpingjack": "Zıpzıp Jack", "jumpingjack": "Zıpzıp Jack",
"jumpingjack_desc": "Zıplamak canını yeniler", "jumpingjack_desc": "Zıplamak canını yeniler",
@ -302,10 +317,10 @@
"lastgasp_desc": "Öldükten sonra seni öldürene hasar verirsin", "lastgasp_desc": "Öldükten sonra seni öldürene hasar verirsin",
"lifeswap": "Can Takası", "lifeswap": "Can Takası",
"lifeswap_desc": "Can değerlerini takas etmek için bir oyuncu seç", "lifeswap_desc": "Bir düşmanla canını takasla",
"lifeswap_enemy_info": "Birisi canını çaldı", "lifeswap_enemy_info": "Birisi canını çaldı.",
"lifeswap_player_info": "'{0}' isimli oyuncuyla canlarını takas ettin.", "lifeswap_player_info": "'{0}' ile canını takasladın.",
"lifeswap_select_info": "Can takası yapılacak oyuncu:", "lifeswap_select_info": "Birini seçin:",
"longknife": "Uzun Bıçak", "longknife": "Uzun Bıçak",
"longknife_desc": "Bıçağın uzaktaki rakibe hasar verebilir", "longknife_desc": "Bıçağın uzaktaki rakibe hasar verebilir",
@ -314,46 +329,46 @@
"longzeus_desc": "Zeus uzaktaki rakibe hasar verebilir", "longzeus_desc": "Zeus uzaktaki rakibe hasar verebilir",
"magneticdecoy": "Manyetik Yanıltıcı", "magneticdecoy": "Manyetik Yanıltıcı",
"magneticdecoy_desc": "Yanıltıcı bombanız yakındaki oyuncuları kendine çeker", "magneticdecoy_desc": "Yanıltıcı bomban yakındaki herkesi kendine çeker",
"magneto": "Mıknatıs", "magneto": "Mıknatıs",
"magneto_desc": "Tüm düşman bombaları sizden uzaklaştırılır", "magneto_desc": "Tüm düşman bombası senden uzaklaşır",
"magnifier": "Büyüteç", "magnifier": "Büyüteç",
"magnifier_desc": "Düşmanın ekranını yakınlaştırarak görüş alanını daraltır", "magnifier_desc": "Bir düşmanın görüş alanını daralt",
"magnifier_enemy_info": "Görüşün bozuldu!", "magnifier_enemy_info": "Görüşün bozuldu!",
"magnifier_disable_info": "Görüşün düzeldi", "magnifier_disable_info": "Görüşün düzeldi",
"magnifier_player_info": "'{0}' isimli oyuncunun ekranı yakınlaştırıldı.", "magnifier_player_info": "'{0}' isimli oyuncunun ekranı yakınlaştırıldı.",
"magnifier_select_info": "Ekranı büyütülecek oyuncuyu seç:", "magnifier_select_info": "Birini seçin:",
"medic": "Sıhhiye", "medic": "Sıhhiye",
"medic_desc": "[css_useSkill] tuşuna basarak kendine anında 50 HP bas", "medic_desc": "[css_useSkill] tuşuna basarak kendine anında 50 HP bas",
"miner": "Mayın", "miner": "Mayın",
"miner_desc": "El bombanız (HE) sadece yakında bir düşman olduğunda patlar", "miner_desc": "El bomban sadece yakında düşman varken patlar",
"bankrupt": "İflas", "bankrupt": "İflas",
"bankrupt_desc": "Tüm parasını kaybedecek bir oyuncu seç", "bankrupt_desc": "Tüm parasını kaybedecek bir düşman seç",
"bankrupt_enemy_info": "İflas ettin!", "bankrupt_enemy_info": "İflas ettin!",
"bankrupt_player_info": "'{0}' isimli oyuncu iflas etti.", "bankrupt_player_info": "'{0}' iflas etti.",
"bankrupt_select_info": "İflas edecek oyuncuyu seç:", "bankrupt_select_info": "Birini seçin:",
"deathbomb": "Canlı Bomba", "deathbomb": "Canlı Bomba",
"deathbomb_desc": "Öldüğünde patlayarak etraftaki oyuncuları öldürürsün", "deathbomb_desc": "Öldüğünde patlayıp etrafındakilere hasar verirsin",
"deathbomb_explosion": "BOOM!!!", "deathbomb_explosion": "BOOM!!!",
"demoneye": "Şeytani Göz", "demoneye": "Şeytani Göz",
"demoneye_desc": "Baktığın tüm düşmanlara hasar verirsin", "demoneye_desc": "Baktığın tüm düşmana hasar verirsin",
"nightmare": "Kabus", "nightmare": "Kabus",
"nightmare_desc": "Seçtiğin bir rakibe kabus görüntüsü verir", "nightmare_desc": "Seçtiğin rakibe kabus gördür",
"nightmare_disable_info": "Kabus sona erdi.", "nightmare_disable_info": "Kabus sona erdi.",
"nightmare_enemy_info": "Gözlerini bir kabus bürüdü.", "nightmare_enemy_info": "Gözlerini bir kabus bürüdü.",
"nightmare_player_info": "'{0}' oyuncusuna kabus gördürdün.", "nightmare_player_info": "'{0}' oyuncusuna kabus gördürdün.",
"nightmare_select_info": "Kabus görecek oyuncu:", "nightmare_select_info": "Birini seçin:",
"ninja": "Ninja", "ninja": "Ninja",
"ninja_desc": "Görünmezliğini sabit durmak %33, eğilmek %33 ve bıçak tutmak %33 artırır", "ninja_desc": "Sabit durmak, eğilmek ve bıçak tutmak görünmezliğini %33 artırır",
"nonades": "Bomba Geçirmez", "nonades": "Bomba Geçirmez",
"nonades_desc": "Bombalar sana hasar vermez", "nonades_desc": "Bombalar sana hasar vermez",
@ -375,38 +390,38 @@
"paweljumper_desc2": "{0} kez ekstra zıplayabilirsin", "paweljumper_desc2": "{0} kez ekstra zıplayabilirsin",
"phoenix": "Anka Kuşu", "phoenix": "Anka Kuşu",
"phoenix_desc": "Öldükten sonra rastgele yeniden doğma şansın olur", "phoenix_desc": "Öldükten sonra yeniden doğma şansın olur",
"phoenix_desc2": "Yeniden doğma şansın: %{0}", "phoenix_desc2": "Yeniden doğma şansın: %{0}",
"phoenix_respawn": "Küllerinden yeniden doğdun!", "phoenix_respawn": "Küllerinden yeniden doğdun!",
"psychicdefusing": "Psişik İmha", "psychicdefusing": "Psişik İmha",
"psychicdefusing_desc": "Bombanın yanındayken onu otomatik imha etmeye başlarsın", "psychicdefusing_desc": "Bombanın yanındayken otomatik imhaya başlarsın",
"psychicdefusing_hud_info": "Bombanın çözülmesi için son {0} saniye", "psychicdefusing_hud_info": "Bombanın çözülmesi için son {0} saniye",
"pilot": "Pilot", "pilot": "Pilot",
"pilot_desc": "Sınırlı bir süre uçun. Uçmak için zıplama tuşuna iki kez basın", "pilot_desc": "Uçmak için zıplama tuşuna iki kez bas",
"pilot_hud_info": "Yakıt", "pilot_hud_info": "Yakıt",
"planter": "Serbest Kurucu", "planter": "Serbest Kurucu",
"planter_desc": "Bombayı her yere kurabilirsin, patlama süresi 60 saniyedir.", "planter_desc": "Bombayı her yere kurabilirsin, patlama süresi 60 saniye",
"planter_planting": "Kuruluyor ({0})...", "planter_planting": "Kuruluyor ({0})...",
"poison": "Zehir", "poison": "Zehir",
"poison_desc": "Birkaç saniyede bir hasar alacak bir oyuncu seç", "poison_desc": "Birkaç saniyede bir hasar alacak bir düşman seç",
"poison_enemy_info": "Zehirlendin.", "poison_enemy_info": "Zehirlendin.",
"poison_disable_info": "Zehire bağışıklık kazandın", "poison_disable_info": "Zehire bağışıklık kazandın",
"poison_player_info": "'{0}' isimli oyuncu zehirlendi.", "poison_player_info": "'{0}' isimli oyuncu zehirlendi.",
"poison_select_info": "Zehirlenecek oyuncuyu seç:", "poison_select_info": "Birini seçin:",
"primaryban": "Tüfek Yasak", "primaryban": "Tüfek Yasak",
"primaryban_desc": "Tüfek kullanamayacak bir oyuncu seç", "primaryban_desc": "Tüfek kullanamayacak bir düşman seç",
"primaryban_enemy_info": "Tüfek kullanmayı unuttun", "primaryban_enemy_info": "Tüfek kullanmayı unuttun",
"primaryban_disable_info": "Tüfek kullanabilirsin", "primaryban_disable_info": "Tüfek kullanabilirsin",
"primaryban_player_info": "'{0}' artık tüfek kullanamaz.", "primaryban_player_info": "'{0}' artık tüfek kullanamaz.",
"primaryban_select_info": "Tüfek kullanımı yasaklanacak oyuncu:", "primaryban_select_info": "Birini seçin:",
"prosthesis": "Protez", "prosthesis": "Protez",
"prosthesis_desc": "Kollar ve bacaklar kurşun geçirmezdir", "prosthesis_desc": "Kolların ve bacakların kurşun geçirmez",
"push": "İtici", "push": "İtici",
"push_desc": "Düşmana vurduğunda onu geri itme şansın olur", "push_desc": "Düşmana vurduğunda onu geri itme şansın olur",
@ -422,43 +437,46 @@
"radarhack_desc": "Düşmanlar radarda görünür", "radarhack_desc": "Düşmanlar radarda görünür",
"rambo": "Rambo", "rambo": "Rambo",
"rambo_desc": "Raund başında rastgele miktarda can alırsın", "rambo_desc": "Rastgele miktarda canın olur",
"randomweapon": "Silah Kumarı", "randomweapon": "Silah Kumarı",
"randomweapon_desc": "[css_useSkill] tuşuna basarak rastgele bir silah al", "randomweapon_desc": "[css_useSkill] tuşuna basarak rastgele bir silah al",
"rezombie": "Zombi", "rezombie": "Zombi",
"rezombie_desc": "Öldükten sonra daha fazla canla ve silahsız zombi olarak doğarsın", "rezombie_desc": "Öldüğünde silahsız zombi olarak daha çok canla dirilirsin",
"reactivearmor": "Reaktif Zırh", "reactivearmor": "Reaktif Zırh",
"reactivearmor_desc": "Zırhın alınan ilk hasarı emmer", "reactivearmor_desc": "Zırhın ilk hasarı emer",
"regeneration": "Yenilenme", "regeneration": "Yenilenme",
"regeneration_desc": "Birkaç saniyede bir canın yenilenir", "regeneration_desc": "Birkaç saniyede bir canın yenilenir",
"replicator": "Klon", "replicator": "Klon",
"replicator_desc": "[css_useSkill] tuşuna basarak klon oluştur ve öldürene hasar verir", "replicator_desc": "[css_useSkill] tuşuna basarak klon oluştur, klonu öldürene hasar verir",
"retreat": "Geri Çekil", "retreat": "Geri Çekil",
"retreat_desc": "[css_useSkill] tuşuna basarak başlangıç noktasına ışınlan", "retreat_desc": "[css_useSkill] tuşuna basarak başlangıcına ışınlan",
"returntosender": "İade", "returntosender": "İade",
"returntosender_desc": "Düşmana ilk vuruşun onu kendi başlangıç noktasına ışınlar", "returntosender_desc": "Düşmana ilk vuruşun onu kendi başlangıcına ışınlar",
"richboy": "Zengin Çocuk", "richboy": "Zengin Çocuk",
"richboy_desc": "Raund başında rastgele miktarda para alırsın", "richboy_desc": "Rastgele miktarda paran olur",
"ricochet": "Seken Mermi",
"ricochet_desc": "Mermin duvardan seker ve düşmana isabet edebilir",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Düşmana hasar vermek onun parasını çalar", "robinhood_desc": "Düşmana hasar vermek onun parasını çalar",
"rubber": "Lastik Mermi", "rubber": "Lastik Mermi",
"rubber_desc": "Mermilerin oyuncuları önemli ölçüde yavaşlatır", "rubber_desc": "Mermin isabet edeni yavaşlatır",
"saper": "İstihkamcı", "saper": "İstihkamcı",
"saper_desc": "Bombayı daha hızlı kurabilir ve imha edebilirsin", "saper_desc": "Bombayı daha hızlı kurar ve imha edersin",
"secondlife": "İkinci Şans", "secondlife": "İkinci Şans",
"secondlife_desc": "Öldükten sonra aynı miktarda canla yeniden doğarsın", "secondlife_desc": "Öldüğünde aynı canla yeniden doğarsın",
"shade": "Gölge", "shade": "Gölge",
"shade_desc": "Vurduğun düşmanın arkasına ışınlanma şansın olur", "shade_desc": "Vurduğun düşmanın arkasına ışınlanma şansın olur",
@ -466,24 +484,24 @@
"shade_nospace": "Uygun alan yok", "shade_nospace": "Uygun alan yok",
"shortbomb": "Kısa Fünye", "shortbomb": "Kısa Fünye",
"shortbomb_desc": "Bomba çok daha hızlı patlar", "shortbomb_desc": "C4 çok daha hızlı patlar",
"silent": "Sessiz", "silent": "Sessiz",
"silent_desc": "Ayak seslerini ve zıplamalarını DİĞER oyuncular duyamaz", "silent_desc": "Ayak ve zıplama sesini kimse duyamaz",
"smoker": "Tiryaki", "smoker": "Tiryaki",
"smoker_desc": "Attığın Sis asla bitmez", "smoker_desc": "Attığın sis asla bitmez",
"sniperelite": "Keskin Nişancı", "sniperelite": "Keskin Nişancı",
"sniperelite_customname": "Keskin Nişancı", "sniperelite_customname": "Keskin Nişancı",
"sniperelite_desc": "[css_useSkill] tuşuna basarak silahını AWP ile değiştir", "sniperelite_desc": "[css_useSkill] tuşuna basarak silahını AWP ile değiştir",
"soldier": "Teğmen", "soldier": "Teğmen",
"soldier_desc": "Rastgele bir oranda fazla hasar verirsin", "soldier_desc": "Rastgele hasar verme çarpanın olur",
"soldier_desc2": "Hasarın: {0}x", "soldier_desc2": "Hasarın: {0}x",
"soundmaker": "Çığlık", "soundmaker": "Çığlık",
"soundmaker_desc": "Rakiplerinin çığlıklarını duyarsın", "soundmaker_desc": "Rakibin çığlığını duyarsın",
"spectator": "Röntgen", "spectator": "Röntgen",
"spectator_desc": "[css_useSkill] tuşuna basarak rakibinin gözünden gör", "spectator_desc": "[css_useSkill] tuşuna basarak rakibinin gözünden gör",
@ -492,47 +510,47 @@
"swapposition_desc": "[css_useSkill] tuşuna basarak vurduğun düşmanla yer değiştir", "swapposition_desc": "[css_useSkill] tuşuna basarak vurduğun düşmanla yer değiştir",
"takeammo": "Cephane Hırsızı", "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_desc": "[css_useSkill] tuşuna basarak rastgele bir düşmanın şarjörünü çal",
"takeammo_hud_info1": "Cephanesi olan bir oyuncu bulunamadı.", "takeammo_hud_info1": "Şarjörü olan bir oyuncu bulunamadı.",
"takeammo_hud_info2": "Düşmanın cephanesi yok.", "takeammo_hud_info2": "Düşmanın şarjörü yok.",
"takeammo_enemy_info": "Birisi cephaneni çaldı.", "takeammo_enemy_info": "Birisi şarjörünü çaldı.",
"teamteleport": "Takıma Işınlanma", "teamteleport": "Takıma Işınlanma",
"teamteleport_desc": "[css_useSkill] tuşuna basarak baktığın takım arkadaşına ışınlanırsın", "teamteleport_desc": "[css_useSkill] tuşuna basarak baktığın takım arkadaşına ışınlan",
"teamteleport_noenemy": "Takım arkadaşı bulunamadı", "teamteleport_noenemy": "Takım arkadaşı bulunamadı",
"teamteleport_hud_info": "Bulundu: {0}", "teamteleport_hud_info": "Bulundu: {0}",
"teleporter": "Işınlayıcı", "teleporter": "Işınlayıcı",
"teleporter_desc": "Vurulan bir düşmanla yer değiştirme şansınız var", "teleporter_desc": "Vurduğun düşmanla yer değiştirme şansın olur",
"teleporter_desc2": "Yer değiştirme şansın: %{0}", "teleporter_desc2": "Yer değiştirme şansın: %{0}",
"thief": "Hırsız", "thief": "Hırsız",
"thief_desc": "Seçilen bir oyuncudan yeteneğini çalabilirsin", "thief_desc": "Bir düşmanın yeteneğini çal",
"thief_enemy_info": "Yeteneğin çalındı.", "thief_enemy_info": "Yeteneğin çalındı.",
"thief_player_info": "'{0}' isimli oyuncunun yeteneği çalındı.", "thief_player_info": "'{0}' isimli oyuncunun yeteneği çalındı.",
"thief_select_info": "Yetenek çalınacak oyuncu:", "thief_select_info": "Birini seçin:",
"thief_incorrect_skill": "Bu yetenek çalınamaz!", "thief_incorrect_skill": "Bu yetenek çalınamaz!",
"thirdeye": "Üçüncü Göz", "thirdeye": "Üçüncü Göz",
"thirdeye_desc": "[css_useSkill] tuşuna basarak üçüncü göze(thirdperson) geç", "thirdeye_desc": "[css_useSkill] tuşuna basarak üçüncü şahıs görünümüne geç",
"thorns": "Dikenler", "thorns": "Dikenler",
"thorns_desc": "Rakibin, sana verdiği hasarın bir kısmını geri alır", "thorns_desc": "Sana verilen hasarın bir kısmı rakibe döner",
"throwingknife": "Fırlatma Bıçağı", "throwingknife": "Fırlatma Bıçağı",
"throwingknife_desc": "Bıçak fırlatmak için [css_useSkill] tuşuna basın. Ama başkalarına dikkat edin", "throwingknife_desc": "[css_useSkill] tuşuna basarak bıçak fırlat",
"toxicsmoke": "Zehirli Sis", "toxicsmoke": "Zehirli Sis",
"toxicsmoke_desc": "Sis bombaların hasar verir", "toxicsmoke_desc": "Sis bomban hasar verir",
"tripwire": "Tel Tuzağı", "tripwire": "Tel Tuzağı",
"tripwire_desc": "[css_useSkill] ile iki duvar arasına tel ger. Tele değen düşman radarında görünür", "tripwire_desc": "[css_useSkill] tuşuna basarak iki duvar arasına tel ger, değen düşman radarda görünür",
"tripwire_no_wall_info": "İki yanında da yeterince yakın duvar yok.", "tripwire_no_wall_info": "İki yanında da yeterince yakın duvar yok.",
"tripwire_placed_info": "Tel gerildi.", "tripwire_placed_info": "Tel gerildi.",
"tripwire_triggered_info": "'{0}' teline takıldı.", "tripwire_triggered_info": "'{0}' teline takıldı.",
"wallhack": "Wallhack", "wallhack": "Wallhack",
"wallhack_desc": "Düşmanları duvarların arkasından görebilirsin", "wallhack_desc": "Düşmanları duvar arkasından görürsün",
"watchmaker": "Saat Ustası", "watchmaker": "Saat Ustası",
"watchmaker_desc": "Atılan her bomba raund süresini değiştirir", "watchmaker_desc": "Atılan her bomba raund süresini değiştirir",
@ -544,21 +562,21 @@
"weaponsswap_hud_info2": "Takas edilecek silahın yok", "weaponsswap_hud_info2": "Takas edilecek silahın yok",
"weightless": "Yerçekimsiz", "weightless": "Yerçekimsiz",
"weightless_desc": "El bombalarınız yerçekiminden etkilenmez ve dümdüz gider", "weightless_desc": "El bomban yerçekiminden etkilenmez ve dümdüz gider",
"wildthrow": "Unutkan Bombacı", "wildthrow": "Unutkan Bombacı",
"wildthrow_desc": "El bombası atmakta zorluk çekecek bir oyuncu seçin", "wildthrow_desc": "El bombası atmakta zorlanacak bir düşman seç",
"wildthrow_player_info": "'{0}' adlı oyuncu tüm taktiklerini unuttu", "wildthrow_player_info": "'{0}' tüm taktiklerini unuttu.",
"wildthrow_enemy_info": "Bomba atarken çok heyecanlanıyorsun.", "wildthrow_enemy_info": "Bomba atarken çok heyecanlanıyorsun.",
"wildthrow_disable_info": "Bombaların düzeldi.", "wildthrow_disable_info": "Bomban tekrardan düzgün.",
"wildthrow_select_info": "Bir oyuncu seçin:", "wildthrow_select_info": "Birini seçin:",
"zeus": "Zeus", "zeus": "Zeus",
"zeus_desc": "Zeus x27 anında şarj olur", "zeus_desc": "Zeus x27 anında şarj olur",
"your_skill": "Yeteneğin", "your_skill": "Yeteneğin",
"enemy_skill": "Düşmanın yeteneği", "enemy_skill": "Düşmanın yeteneği",
"observer_skill": "Oyuncunun yeteneği", "observer_skill": "Yeteneği",
"welcome_message": "{PLAYER}, {SERVER_NAME} sunucusuna hoş geldin!\nGüncel jRandomSkills versiyonu: {VERSION} ({SKILLS_COUNT} yetenek).\n\nOrijinal yapımcı:\n{AUTHOR1}\nGeliştiren:\n{AUTHOR2}\nResmi Discord: https://discord.gg/9H8EZYBpPF", "welcome_message": "{PLAYER}, {SERVER_NAME} sunucusuna hoş geldin!\nGüncel jRandomSkills versiyonu: {VERSION} ({SKILLS_COUNT} yetenek).\n\nOrijinal yapımcı:\n{AUTHOR1}\nGeliştiren:\n{AUTHOR2}\nResmi Discord: https://discord.gg/9H8EZYBpPF",
"drawing_skill": "Yetenek çarkı dönüyor...", "drawing_skill": "Yetenek çarkı dönüyor...",
"disabled_weapon": "Bu silahı kullanamazsın", "disabled_weapon": "Bu silahı kullanamazsın",

View file

@ -71,6 +71,11 @@
"catapult_desc": "你有随机几率将敌人向上弹射", "catapult_desc": "你有随机几率将敌人向上弹射",
"catapult_desc2": "你击中敌人将其弹射的几率是:{0}%", "catapult_desc2": "你击中敌人将其弹射的几率是:{0}%",
"chameleon": "变色龙",
"chameleon_desc": "你击杀的第一名玩家会把技能传给你",
"chameleon_copied_info": "已复制技能:{0}",
"chameleon_wrong_team_info": "'{0}' 的技能你的队伍无法使用。",
"chicken": "小鸡", "chicken": "小鸡",
"chicken_desc": "你获得小鸡模型 + 移动速度提高10% - 50生命值", "chicken_desc": "你获得小鸡模型 + 移动速度提高10% - 50生命值",
@ -201,6 +206,11 @@
"godmode_off": "无敌状态已禁用", "godmode_off": "无敌状态已禁用",
"godmode_on": "无敌状态已启用", "godmode_on": "无敌状态已启用",
"grapple": "钩爪",
"grapple_desc": "按 [css_useSkill] 向准星所指位置发射钩爪并将自己拉过去",
"grapple_no_anchor_info": "没有可以钩住的表面。",
"grapple_pulling_info": "拉动中",
"grenadier": "投弹手", "grenadier": "投弹手",
"grenadier_desc": "你拥有无限高爆手雷", "grenadier_desc": "你拥有无限高爆手雷",
@ -237,6 +247,11 @@
"infiniteammo": "无限弹药", "infiniteammo": "无限弹药",
"infiniteammo_desc": "你为所有武器获得无限弹药", "infiniteammo_desc": "你为所有武器获得无限弹药",
"inheritance": "继承",
"inheritance_desc": "当队友阵亡时,你可以接管他的技能",
"inheritance_select_info": "选择要继承的技能:",
"inheritance_player_info": "你继承了 '{0}' 的技能。",
"jackal": "追踪者", "jackal": "追踪者",
"jackal_desc": "每个对手都会留下痕迹", "jackal_desc": "每个对手都会留下痕迹",
@ -418,6 +433,9 @@
"richboy": "富少", "richboy": "富少",
"richboy_desc": "回合开始时你获得随机数量的钱", "richboy_desc": "回合开始时你获得随机数量的钱",
"ricochet": "跳弹",
"ricochet_desc": "你的子弹会从墙上弹开,并且仍能击中敌人",
"robinhood": "罗宾汉", "robinhood": "罗宾汉",
"robinhood_desc": "对敌人造成伤害会偷取他们的钱", "robinhood_desc": "对敌人造成伤害会偷取他们的钱",

View file

@ -4,7 +4,6 @@ using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using src.utils; using src.utils;
using System.Collections.Concurrent;
using static CounterStrikeSharp.API.Core.Listeners; using static CounterStrikeSharp.API.Core.Listeners;
using static src.jRandomSkills; using static src.jRandomSkills;
@ -96,33 +95,9 @@ namespace src.player
WriteToDebug($"Map changed: {mapName}."); WriteToDebug($"Map changed: {mapName}.");
}); });
Instance.RegisterEventHandler<EventPlayerShoot>((@event, info) =>
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return HookResult.Continue;
WriteToDebug($"{(player.IsBot ? "Bot" : "Player")} {player.PlayerName} fired a shot.");
return HookResult.Continue;
});
Instance.RegisterEventHandler<EventPlayerHurt>((@event, info) =>
{
var victim = PlayerManager.GetPlayerEvent(@event.Userid);
if (victim == null || !victim.IsValid) return HookResult.Continue;
if (!lastNativeHitGroup.TryRemove(victim.Index, out var native)) return HookResult.Continue;
if (native.HitGroup == @event.Hitgroup) return HookResult.Continue;
WriteToDebug($"[HITGROUP] mismatch on {victim.PlayerName}: native={(HitGroup_t)native.HitGroup} event={(HitGroup_t)@event.Hitgroup} " +
$"weapon={@event.Weapon} rawDmg={native.Damage:0.#} appliedDmg={@event.DmgHealth}");
return HookResult.Continue;
});
VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre);
} }
private static readonly ConcurrentDictionary<uint, (int HitGroup, float Damage)> lastNativeHitGroup = [];
public static void Unload() public static void Unload()
{ {
try { VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Unhook(OnTakeDamage, HookMode.Pre); } try { VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Unhook(OnTakeDamage, HookMode.Pre); }
@ -131,16 +106,6 @@ namespace src.player
lock (_writeLock) { _writer?.Dispose(); _writer = null; } lock (_writeLock) { _writer?.Dispose(); _writer = null; }
} }
private static string DescribeIdentitySplit(CCSPlayerController victim)
{
var routed = PlayerManager.GetPlayerEvent(victim);
uint routedIndex = routed?.Index ?? victim.Index;
if (routedIndex == victim.Index) return string.Empty;
return $" SPLIT(idx {victim.Index}->{routedIndex}, skill {PlayerManager.GetPlayerByIndex(victim.Index)?.Skill}" +
$"->{PlayerManager.GetPlayerByIndex(routedIndex)?.Skill}, controllingBot={victim.ControllingBot})";
}
private static HookResult OnTakeDamage(DynamicHook h) private static HookResult OnTakeDamage(DynamicHook h)
{ {
CEntityInstance param = h.GetParam<CEntityInstance>(0); CEntityInstance param = h.GetParam<CEntityInstance>(0);
@ -165,12 +130,10 @@ namespace src.player
if (playerInfo == null) return HookResult.Continue; if (playerInfo == null) return HookResult.Continue;
var nativeHitGroup = SkillUtils.GetHitGroup(param2); var nativeHitGroup = SkillUtils.GetHitGroup(param2);
lastNativeHitGroup[victim.Index] = ((int)nativeHitGroup, param2.Damage);
WriteToDebug($"{(victim.IsBot ? "Bot" : "Player")} {victim.PlayerName} took damage from {(attacker.IsBot ? "bot" : "player")} {attacker.PlayerName}. " + WriteToDebug($"{(victim.IsBot ? "Bot" : "Player")} {victim.PlayerName} took damage from {(attacker.IsBot ? "bot" : "player")} {attacker.PlayerName}. " +
$"[dmg={param2.Damage:0.#} hp={victimPawn.Health}/{victimPawn.MaxHealth} armor={victimPawn.ArmorValue} hitgroup={nativeHitGroup} " + $"[dmg={param2.Damage:0.#} hp={victimPawn.Health}/{victimPawn.MaxHealth} armor={victimPawn.ArmorValue} hitgroup={nativeHitGroup} " +
$"takes={victimPawn.TakesDamage} vskill={PlayerManager.GetPlayerByIndex(victim.Index)?.Skill} askill={playerInfo.Skill}" + $"takes={victimPawn.TakesDamage} vskill={PlayerManager.GetPlayerByIndex(victim.Index)?.Skill} askill={playerInfo.Skill}]");
$"{DescribeIdentitySplit(victim)}]");
return HookResult.Continue; return HookResult.Continue;
} }

View file

@ -79,6 +79,7 @@ public enum Skills
C4Camouflage, C4Camouflage,
CarefulBullets, CarefulBullets,
Catapult, Catapult,
Chameleon,
Chicken, Chicken,
ChillOut, ChillOut,
Cutter, Cutter,
@ -114,6 +115,7 @@ public enum Skills
Glitch, Glitch,
Glue, Glue,
GodMode, GodMode,
Grapple,
Grenadier, Grenadier,
HealingChicken, HealingChicken,
HealingSmoke, HealingSmoke,
@ -126,6 +128,7 @@ public enum Skills
Illusionist, Illusionist,
Impostor, Impostor,
InfiniteAmmo, InfiniteAmmo,
Inheritance,
Jackal, Jackal,
Jammer, Jammer,
Jester, Jester,
@ -173,6 +176,7 @@ public enum Skills
Retreat, Retreat,
ReturnToSender, ReturnToSender,
RichBoy, RichBoy,
Ricochet,
RobinHood, RobinHood,
Rubber, Rubber,
Saper, Saper,

View file

@ -226,8 +226,11 @@ namespace src.player
if (controller == null || !controller.IsValid) return string.Empty; if (controller == null || !controller.IsValid) return string.Empty;
uint routedIndex = PlayerManager.GetPlayerEvent(controller)?.Index ?? controller.Index; uint routedIndex = PlayerManager.GetPlayerEvent(controller)?.Index ?? controller.Index;
return $" on {controller.PlayerName} [idx={controller.Index} skill={PlayerManager.GetPlayerByIndex(controller.Index)?.Skill}" + string routing = routedIndex == controller.Index
$" routedIdx={routedIndex} routedSkill={PlayerManager.GetPlayerByIndex(routedIndex)?.Skill}]"; ? string.Empty
: $" routedIdx={routedIndex} routedSkill={PlayerManager.GetPlayerByIndex(routedIndex)?.Skill}";
return $" on {controller.PlayerName} [idx={controller.Index} skill={PlayerManager.GetPlayerByIndex(controller.Index)?.Skill}{routing}]";
} }
catch catch
{ {

View file

@ -15,7 +15,7 @@ namespace src.player
Instance.RegisterListener<OnTick>(() => Instance.RegisterListener<OnTick>(() =>
{ {
UpdateGameRules(); UpdateGameRules();
if (Server.TickCount % 2 != 0) return; if (!SkillUtils.IsHudFrame()) return;
if (PerfLog.Enabled && Server.TickCount % 1920 == 0) if (PerfLog.Enabled && Server.TickCount % 1920 == 0)
{ {
@ -99,26 +99,20 @@ namespace src.player
bool showDescriptionHUD = skillPlayer.SkillDescriptionHudExpired >= now || Config.LoadedConfig.DisplayAlwaysDescription; bool showDescriptionHUD = skillPlayer.SkillDescriptionHudExpired >= now || Config.LoadedConfig.DisplayAlwaysDescription;
bool isDescription = true; bool isDescription = true;
var skills = SkillData.Skills; var skills = SkillData.GetSnapshot();
if (skills == null || skills.IsEmpty) if (skills.Length == 0)
{ {
infoLine = player.GetTranslationWithoutIlliterate("your_skill"); infoLine = player.GetTranslationWithoutIlliterate("your_skill");
skillLine = player.GetTranslationWithoutIlliterate("none"); skillLine = player.GetTranslationWithoutIlliterate("none");
} }
else if (skillPlayer.IsDrawing && player.PawnIsAlive) else if (skillPlayer.IsDrawing && player.PawnIsAlive)
{ {
int skillCount = skills.Count; var randomSkill = skills[Instance.Random.Next(skills.Length)];
if (skillCount > 0)
{
var skillsArray = skills.ToArray();
var randomSkill = skillsArray[Instance.Random.Next(skillCount)];
infoLine = player.GetTranslationWithoutIlliterate("drawing_skill"); infoLine = player.GetTranslationWithoutIlliterate("drawing_skill");
skillLine = $"<font color='{randomSkill.Color}'>{player.GetSkillName(randomSkill.Skill)}</font>"; skillLine = $"<font color='{randomSkill.Color}'>{player.GetSkillName(randomSkill.Skill)}</font>";
} }
}
else else
{ {
if (player.PawnIsAlive) if (player.PawnIsAlive)

View file

@ -45,6 +45,7 @@ namespace src.player.skills
{ {
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
SkillPlayerInfo.TryRemove(player.Index, out _); SkillPlayerInfo.TryRemove(player.Index, out _);
SkillUtils.ResetPrintHTML(player);
} }
public static void OnTick() public static void OnTick()

View file

@ -0,0 +1,166 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Admin;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills
{
public class Chameleon : ISkill
{
private const Skills skillName = Skills.Chameleon;
private static readonly ConcurrentDictionary<uint, byte> holders = [];
private static jRandomSkills? registeredOn;
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
if (ReferenceEquals(registeredOn, Instance)) return;
registeredOn = Instance;
Instance.RegisterEventHandler<EventPlayerDeath>(OnAnyDeath);
}
public static void NewRound()
{
holders.Clear();
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
holders[player.Index] = 0;
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null) return;
holders.TryRemove(player.Index, out _);
}
public static void PlayerDisconnect(uint playerIndex)
{
holders.TryRemove(playerIndex, out _);
}
private static HookResult OnAnyDeath(EventPlayerDeath @event, GameEventInfo info)
{
try
{
if (holders.IsEmpty) return HookResult.Continue;
var attacker = PlayerManager.GetPlayerEvent(@event.Attacker);
if (attacker == null || !attacker.IsValid) return HookResult.Continue;
var victim = PlayerManager.GetPlayerEvent(@event.Userid);
if (victim == null || !victim.IsValid) return HookResult.Continue;
if (attacker.Index == victim.Index) return HookResult.Continue;
if (attacker.Team == victim.Team) return HookResult.Continue;
if (!holders.ContainsKey(attacker.Index)) return HookResult.Continue;
var victimInfo = PlayerManager.GetPlayerByIndex(victim.Index);
if (victimInfo == null || victimInfo.IsDrawing) return HookResult.Continue;
CopySkill(attacker, victim.PlayerName, victimInfo.Skill);
}
catch (Exception ex)
{
Server.PrintToConsole($"[jRandomSkills] Chameleon.OnAnyDeath failed: {ex.Message}");
}
return HookResult.Continue;
}
private static void CopySkill(CCSPlayerController player, string victimName, Skills victimSkill)
{
var playerInfo = PlayerManager.GetPlayerByIndex(player.Index);
if (playerInfo == null) return;
var playerEvent = PlayerManager.GetPlayerFromEvent(player);
if (!CanCopy(player, victimSkill, out string? blockReason))
{
if (blockReason != null && playerEvent != null && playerEvent.IsValid)
playerEvent.PrintToChat($" {ChatColors.Red}" + playerEvent.GetTranslation(blockReason, victimName));
return;
}
uint playerIndex = player.Index;
Skills previousSkill = playerInfo.Skill;
if (!holders.TryRemove(playerIndex, out _)) return;
Instance.AddTimer(.1f, () =>
{
var target = Utilities.GetPlayerFromIndex((int)playerIndex);
if (target == null || !target.IsValid) return;
var targetInfo = PlayerManager.GetPlayerByIndex(playerIndex);
if (targetInfo == null || targetInfo.Skill != previousSkill) return;
Instance.SkillAction(previousSkill.ToString(), "DisableSkill", [target]);
targetInfo.Skill = victimSkill;
targetInfo.SpecialSkill = skillName;
targetInfo.SkillChance = null;
if (target.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
if (SkillsInfo.GetValue<bool>(victimSkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime())
Instance.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () =>
{
var heir = Utilities.GetPlayerFromIndex((int)playerIndex);
if (heir == null || !heir.IsValid) return;
if (PlayerManager.GetPlayerByIndex(playerIndex)?.Skill != victimSkill) return;
Instance.SkillAction(victimSkill.ToString(), "EnableSkill", [heir]);
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
else
Instance.SkillAction(victimSkill.ToString(), "EnableSkill", [target]);
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
if (playerEvent != null && playerEvent.IsValid)
playerEvent.PrintToChat($" {ChatColors.Green}" + playerEvent.GetTranslation("chameleon_copied_info", player.GetSkillName(victimSkill)));
}
private static bool CanCopy(CCSPlayerController player, Skills victimSkill, out string? blockReason)
{
blockReason = null;
if (victimSkill == Skills.None || victimSkill == skillName) return false;
if (SkillData.GetInfo(victimSkill) == null) return false;
bool ctOnly = Event.counterterroristSkills.Any(s => s.Name == victimSkill.ToString());
bool ttOnly = Event.terroristSkills.Any(s => s.Name == victimSkill.ToString());
if ((player.Team == CsTeam.Terrorist && ctOnly) || (player.Team == CsTeam.CounterTerrorist && ttOnly))
{
blockReason = "chameleon_wrong_team_info";
return false;
}
if (!player.IsBot)
{
string permission = SkillsInfo.GetValue<string>(victimSkill, "requiredPermission");
if (!string.IsNullOrEmpty(permission) && !AdminManager.PlayerHasPermissions(player, permission))
return false;
}
if (!SkillsInfo.GetValue<bool>(victimSkill, "needsTeammates")) return true;
return PlayerManager.GetTickPlayers().Any(p =>
p != null && p.IsValid && p.Index != player.Index && p.Team == player.Team
&& p.PlayerPawn?.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0);
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#5fd98a", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = 2, Rarity rarity = Rarity.Rare) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
{
}
}
}

View file

@ -78,6 +78,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
if (plantingPlayers.IsEmpty) return; if (plantingPlayers.IsEmpty) return;
float currentTime = Server.CurrentTime; float currentTime = Server.CurrentTime;

View file

@ -71,6 +71,7 @@ namespace src.player.skills
KillCamera(playerSkill); KillCamera(playerSkill);
} }
playersInfo.TryRemove(player.Index, out _); playersInfo.TryRemove(player.Index, out _);
SkillUtils.ResetPrintHTML(player);
} }
private static void KillCamera(PlayerSkill playerSkill) private static void KillCamera(PlayerSkill playerSkill)

View file

@ -77,7 +77,7 @@ namespace src.player.skills
if (playerInfo?.Skill == skillName) if (playerInfo?.Skill == skillName)
if (SkillPlayerInfo.TryGetValue(eventPlayer!.Index, out var skillInfo)) if (SkillPlayerInfo.TryGetValue(eventPlayer!.Index, out var skillInfo))
{ {
UpdateHUD(player, skillInfo); if (SkillUtils.IsHudFrame()) UpdateHUD(player, skillInfo);
HandleDash(player, skillInfo); HandleDash(player, skillInfo);
} }
} }

View file

@ -25,6 +25,10 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (distancerPlayers.IsEmpty) return;
if (!SkillUtils.IsHudFrame()) return;
if (SkillUtils.IsFreezeTime()) return; if (SkillUtils.IsFreezeTime()) return;
foreach (var playerIndex in distancerPlayers.Keys) foreach (var playerIndex in distancerPlayers.Keys)
{ {
@ -41,8 +45,10 @@ namespace src.player.skills
string closetEnemy = "Bot"; string closetEnemy = "Bot";
double closetDistance = double.MaxValue; double closetDistance = double.MaxValue;
foreach (var enemy in PlayerManager.GetTickPlayers().Where(p => p.Team != player.Team)) foreach (var enemy in PlayerManager.GetTickPlayers())
{ {
if (enemy == null || enemy.Team == player.Team) continue;
var enemyPawn = enemy.PlayerPawn.Value; var enemyPawn = enemy.PlayerPawn.Value;
if (enemyPawn == null || !enemyPawn.IsValid) continue; if (enemyPawn == null || !enemyPawn.IsValid) continue;
if (enemyPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE || playerPawn.AbsOrigin == null || enemyPawn.AbsOrigin == null) continue; if (enemyPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE || playerPawn.AbsOrigin == null || enemyPawn.AbsOrigin == null) continue;

View file

@ -25,6 +25,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
if (SkillUtils.IsFreezeTime()) return; if (SkillUtils.IsFreezeTime()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {

View file

@ -39,7 +39,7 @@ namespace src.player.skills
var pawn = player!.PlayerPawn.Value; var pawn = player!.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return;
if (cameras.TryGetValue(player!.Index, out var cameraInfo) && cameraInfo.Item1 == pawn.CameraServices.ViewEntity.Raw) if (cameras.TryGetValue(player!.Index, out var cameraInfo) && cameraInfo.Item1 != pawn.CameraServices.ViewEntity.Raw)
BlockWeapon(player, true); BlockWeapon(player, true);
} }

View file

@ -54,7 +54,7 @@ namespace src.player.skills
if (!SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) if (!SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo))
continue; continue;
UpdateHUD(player, skillInfo); if (SkillUtils.IsHudFrame()) UpdateHUD(player, skillInfo);
if (!skillInfo.IsActive || skillInfo.LightEntityIndex == 0) if (!skillInfo.IsActive || skillInfo.LightEntityIndex == 0)
continue; continue;

View file

@ -34,6 +34,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);

View file

@ -46,10 +46,17 @@ namespace src.player.skills
if (player == null || !player.IsValid) continue; if (player == null || !player.IsValid) continue;
var playerInfo = PlayerManager.GetPlayerByIndex((PlayerManager.GetPlayerEvent(player)?.Index ?? player.Index)); var playerInfo = PlayerManager.GetPlayerByIndex((PlayerManager.GetPlayerEvent(player)?.Index ?? player.Index));
var observedPlayer = PlayerManager.GetTickPlayers().FirstOrDefault(p => p?.Pawn?.Value?.Handle == player?.Pawn?.Value?.ObserverServices?.ObserverTarget?.Value?.Handle); if (playerInfo?.Skill != skillName)
var observerInfo = observedPlayer != null ? PlayerManager.GetPlayerByIndex(observedPlayer.Index) : null; {
var observerTarget = player.Pawn?.Value?.ObserverServices?.ObserverTarget?.Value?.Handle ?? nint.Zero;
if (observerTarget == nint.Zero) continue;
var observedPlayer = PlayerManager.GetTickPlayers().FirstOrDefault(p => p?.Pawn?.Value?.Handle == observerTarget);
if (observedPlayer == null) continue;
if (PlayerManager.GetPlayerByIndex(observedPlayer.Index)?.Skill != skillName) continue;
}
if (playerInfo?.Skill != skillName && observerInfo?.Skill != skillName) continue;
foreach (var entityIndex in smokes.Keys) foreach (var entityIndex in smokes.Keys)
{ {
var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)entityIndex); var entity = Utilities.GetEntityFromIndex<CBaseEntity>((int)entityIndex);

View file

@ -43,6 +43,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);

View file

@ -0,0 +1,316 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using System.Drawing;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace src.player.skills
{
public class Grapple : ISkill
{
private const Skills skillName = Skills.Grapple;
private static readonly ConcurrentDictionary<uint, PlayerSkillInfo> SkillPlayerInfo = [];
private static readonly ConcurrentDictionary<uint, byte> liveRopes = [];
private static readonly object setLock = new();
private static readonly Color terroristRope = Color.FromArgb(255, 138, 84, 34);
private static readonly Color counterTerroristRope = Color.FromArgb(255, 52, 92, 138);
private const double attemptCooldown = .3;
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
}
public static void NewRound()
{
lock (setLock)
{
foreach (var skillInfo in SkillPlayerInfo.Values)
DestroyRope(skillInfo);
SkillPlayerInfo.Clear();
SweepOrphanRopes();
}
}
public static void RoundEnd()
{
foreach (var skillInfo in SkillPlayerInfo.Values)
DestroyRope(skillInfo);
SweepOrphanRopes();
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
SkillPlayerInfo[player.Index] = new PlayerSkillInfo
{
CanUse = true,
Cooldown = DateTime.MinValue,
};
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null) return;
if (SkillPlayerInfo.TryRemove(player.Index, out var skillInfo))
DestroyRope(skillInfo);
SkillUtils.ResetPrintHTML(player);
}
public static void PlayerDisconnect(uint playerIndex)
{
if (SkillPlayerInfo.TryRemove(playerIndex, out var skillInfo))
DestroyRope(skillInfo);
}
public static void PlayerDeath(EventPlayerDeath @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo))
DestroyRope(skillInfo);
}
public static void UseSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
if (!SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) return;
if (skillInfo.Anchor != null)
{
DestroyRope(skillInfo);
return;
}
if (!skillInfo.CanUse) return;
if ((DateTime.Now - skillInfo.LastAttempt).TotalSeconds < attemptCooldown) return;
skillInfo.LastAttempt = DateTime.Now;
var playerEvent = PlayerManager.GetPlayerFromEvent(player);
if (!TryAttach(player, skillInfo))
{
if (playerEvent != null && playerEvent.IsValid)
playerEvent.PrintToChat($" {ChatColors.Red}" + playerEvent.GetTranslation("grapple_no_anchor_info"));
return;
}
skillInfo.CanUse = false;
skillInfo.Cooldown = DateTime.Now;
}
private static bool TryAttach(CCSPlayerController player, PlayerSkillInfo skillInfo)
{
if (!RayTrace.IsAvailable) return false;
var pawn = player.PlayerPawn?.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return false;
var result = RayTrace.EyeTrace(player);
if (result == null || !result.Value.DidHit) return false;
if (result.Value.HitPlayer(out _)) return false;
Vector anchor = new(result.Value.EndPosX, result.Value.EndPosY, result.Value.EndPosZ);
Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z);
if (SkillUtils.GetDistance(eyePos, anchor) < SkillsInfo.GetValue<float>(skillName, "minDistance")) return false;
skillInfo.Anchor = anchor;
skillInfo.EndTick = Server.TickCount + (int)(SkillsInfo.GetValue<float>(skillName, "maxPullSeconds") * 64);
if (!EntityManager.OverBudget())
{
Color ropeColor = player.Team == CsTeam.Terrorist ? terroristRope : counterTerroristRope;
var rope = EntityManager.CreateTrackedBeam(player.Index, eyePos, anchor, ropeColor);
if (rope != null && rope.IsValid)
{
float width = SkillsInfo.GetValue<float>(skillName, "ropeWidth");
rope.Width = width;
rope.EndWidth = width;
Utilities.SetStateChanged(rope, "CBeam", "m_fWidth");
Utilities.SetStateChanged(rope, "CBeam", "m_fEndWidth");
uint ropeIndex = rope.Index;
skillInfo.RopeIndex = ropeIndex;
liveRopes[ropeIndex] = 0;
jRandomSkills.Instance.AddTimer(SkillsInfo.GetValue<float>(skillName, "maxPullSeconds") + 1f,
() => KillRope(ropeIndex),
CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
}
}
player.EmitSound("SolidMetal.BulletImpact");
return true;
}
private static void DestroyRope(PlayerSkillInfo skillInfo)
{
skillInfo.Anchor = null;
skillInfo.EndTick = 0;
if (skillInfo.RopeIndex == null) return;
uint ropeIndex = skillInfo.RopeIndex.Value;
skillInfo.RopeIndex = null;
KillRope(ropeIndex);
}
private static void KillRope(uint ropeIndex)
{
if (!liveRopes.TryRemove(ropeIndex, out _)) return;
var rope = Utilities.GetEntityFromIndex<CBeam>((int)ropeIndex);
if (rope != null && rope.IsValid)
{
rope.Width = 0;
rope.EndWidth = 0;
rope.Render = Color.FromArgb(0, 0, 0, 0);
Utilities.SetStateChanged(rope, "CBeam", "m_fWidth");
Utilities.SetStateChanged(rope, "CBeam", "m_fEndWidth");
Utilities.SetStateChanged(rope, "CBaseModelEntity", "m_clrRender");
}
EntityManager.DestroyEntity(ropeIndex);
Server.NextFrame(() =>
{
var leftover = Utilities.GetEntityFromIndex<CBeam>((int)ropeIndex);
if (leftover != null && leftover.IsValid)
leftover.Remove();
});
}
private static void SweepOrphanRopes()
{
foreach (uint ropeIndex in liveRopes.Keys)
KillRope(ropeIndex);
}
public static void OnTick()
{
if (SkillPlayerInfo.IsEmpty) return;
bool hudFrame = SkillUtils.IsHudFrame();
foreach (var player in PlayerManager.GetTickPlayers())
{
if (player == null || !player.IsValid) continue;
if (!SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) continue;
if (PlayerManager.GetPlayerByIndex(player.Index)?.Skill != skillName) continue;
if (skillInfo.Anchor != null)
HandlePull(player, skillInfo);
if (hudFrame)
UpdateHUD(player, skillInfo);
}
}
private static void HandlePull(CCSPlayerController player, PlayerSkillInfo skillInfo)
{
var pawn = player.PlayerPawn?.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
{
DestroyRope(skillInfo);
return;
}
if (Server.TickCount >= skillInfo.EndTick)
{
DestroyRope(skillInfo);
return;
}
Vector anchor = skillInfo.Anchor!;
Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z);
float dx = anchor.X - eyePos.X;
float dy = anchor.Y - eyePos.Y;
float dz = anchor.Z - eyePos.Z;
float distance = MathF.Sqrt(dx * dx + dy * dy + dz * dz);
if (distance <= SkillsInfo.GetValue<float>(skillName, "stopDistance"))
{
DestroyRope(skillInfo);
return;
}
float pullSpeed = SkillsInfo.GetValue<float>(skillName, "pullSpeed");
float invLength = pullSpeed / distance;
pawn.AbsVelocity.X = dx * invLength;
pawn.AbsVelocity.Y = dy * invLength;
pawn.AbsVelocity.Z = dz * invLength;
if (skillInfo.RopeIndex == null) return;
var rope = Utilities.GetEntityFromIndex<CBeam>((int)skillInfo.RopeIndex.Value);
if (rope == null || !rope.IsValid)
{
liveRopes.TryRemove(skillInfo.RopeIndex.Value, out _);
skillInfo.RopeIndex = null;
return;
}
rope.Teleport(eyePos);
}
private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo)
{
float time = (int)Math.Ceiling((skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue<float>(skillName, "cooldown")) - DateTime.Now).TotalSeconds);
float cooldown = Math.Max(time, 0);
if (cooldown == 0 && !skillInfo.CanUse)
skillInfo.CanUse = true;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo == null) return;
if (skillInfo.Anchor != null)
playerInfo.PrintHTML = $"<font color='#00FF00'>{player.GetTranslation("grapple_pulling_info")}</font>";
else if (cooldown == 0)
playerInfo.PrintHTML = null;
else
playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}";
}
public class PlayerSkillInfo
{
public bool CanUse { get; set; }
public DateTime Cooldown { get; set; }
public DateTime LastAttempt { get; set; }
public Vector? Anchor { get; set; }
public uint? RopeIndex { get; set; }
public int EndTick { get; set; }
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#38e0c4", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Rare, float cooldown = 10f, float maxDistance = 1500f, float minDistance = 150f, float stopDistance = 90f, float pullSpeed = 850f, float maxPullSeconds = 3f, float ropeWidth = 0.8f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
{
public float Cooldown { get; set; } = cooldown;
public float MaxDistance { get; set; } = maxDistance;
public float MinDistance { get; set; } = minDistance;
public float StopDistance { get; set; } = stopDistance;
public float PullSpeed { get; set; } = pullSpeed;
public float MaxPullSeconds { get; set; } = maxPullSeconds;
public float RopeWidth { get; set; } = ropeWidth;
}
}
}

View file

@ -139,12 +139,14 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (activeChickens.IsEmpty) return;
int tickCooldown = SkillsInfo.GetValue<int>(skillName, "tickCooldown"); int tickCooldown = SkillsInfo.GetValue<int>(skillName, "tickCooldown");
if (Server.TickCount % tickCooldown == 0) return; if (Server.TickCount % tickCooldown == 0) return;
float boostFactor = SkillsInfo.GetValue<float>(skillName, "boostFactor"); float boostFactor = SkillsInfo.GetValue<float>(skillName, "boostFactor");
var players = PlayerManager.GetTickPlayers().ToArray(); var players = PlayerManager.GetTickPlayers();
int healAmount = SkillsInfo.GetValue<int>(skillName, "heal"); int healAmount = SkillsInfo.GetValue<int>(skillName, "heal");
float healRadius = SkillsInfo.GetValue<float>(skillName, "healRadius"); float healRadius = SkillsInfo.GetValue<float>(skillName, "healRadius");

View file

@ -90,6 +90,7 @@ namespace src.player.skills
KillClone(playerSkill); KillClone(playerSkill);
playersInfo.TryRemove(player.Index, out _); playersInfo.TryRemove(player.Index, out _);
EntityManager.DestroyPlayerEntities(player.Index); EntityManager.DestroyPlayerEntities(player.Index);
SkillUtils.ResetPrintHTML(player);
} }
private static void UpdateWeapons(CCSPlayerController player, PlayerSkill playerSkill) private static void UpdateWeapons(CCSPlayerController player, PlayerSkill playerSkill)
@ -146,6 +147,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
foreach (var playerSkill in playersInfo.Values) foreach (var playerSkill in playersInfo.Values)
UpdateHUD(playerSkill); UpdateHUD(playerSkill);
} }

View file

@ -47,6 +47,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {
if (player == null || !player.IsValid) continue; if (player == null || !player.IsValid) continue;

View file

@ -0,0 +1,201 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Admin;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
using System.Collections.Concurrent;
using static src.jRandomSkills;
namespace src.player.skills
{
public class Inheritance : ISkill
{
private const Skills skillName = Skills.Inheritance;
private static readonly ConcurrentDictionary<uint, byte> holders = [];
private static readonly ConcurrentDictionary<uint, FallenInfo> fallen = [];
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
}
public static void NewRound()
{
holders.Clear();
fallen.Clear();
foreach (var player in PlayerManager.GetTickPlayers())
SkillUtils.CloseMenu(player);
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
holders[player.Index] = 0;
RefreshMenu(player);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null) return;
holders.TryRemove(player.Index, out _);
SkillUtils.CloseMenu(player);
}
public static void PlayerDisconnect(uint playerIndex)
{
holders.TryRemove(playerIndex, out _);
fallen.TryRemove(playerIndex, out _);
}
public static void PlayerDeath(EventPlayerDeath @event)
{
var victim = PlayerManager.GetPlayerEvent(@event.Userid);
if (victim == null || !victim.IsValid) return;
holders.TryRemove(victim.Index, out _);
var victimInfo = PlayerManager.GetPlayerByIndex(victim.Index);
if (victimInfo == null || victimInfo.IsDrawing) return;
if (victimInfo.Skill == Skills.None || victimInfo.Skill == skillName) return;
if (SkillData.GetInfo(victimInfo.Skill) == null) return;
fallen[victim.Index] = new FallenInfo
{
PlayerName = victim.PlayerName,
Skill = victimInfo.Skill,
Team = victim.Team,
};
foreach (uint holderIndex in holders.Keys)
{
var holder = Utilities.GetPlayerFromIndex((int)holderIndex);
if (holder == null || !holder.IsValid || holder.Team != victim.Team) continue;
RefreshMenu(holder);
}
}
public static void TypeSkill(CCSPlayerController player, string[] commands)
{
if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
var playerInfo = PlayerManager.GetPlayerByIndex(player.Index);
if (playerInfo?.Skill != skillName) return;
var playerEvent = PlayerManager.GetPlayerFromEvent(player);
if (playerEvent == null || !playerEvent.IsValid) return;
if (commands == null || commands.Length == 0 || !uint.TryParse(commands[0], out uint fallenIndex))
{
playerEvent.PrintToChat($" {ChatColors.Red}" + playerEvent.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return;
}
if (!fallen.TryGetValue(fallenIndex, out var fallenInfo) || !CanInherit(player, fallenInfo))
{
playerEvent.PrintToChat($" {ChatColors.Red}" + playerEvent.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return;
}
InheritSkill(player, fallenInfo);
}
private static void InheritSkill(CCSPlayerController player, FallenInfo fallenInfo)
{
var playerInfo = PlayerManager.GetPlayerByIndex(player.Index);
if (playerInfo == null) return;
var playerEvent = PlayerManager.GetPlayerFromEvent(player);
if (playerEvent == null || !playerEvent.IsValid) return;
uint playerIndex = player.Index;
Skills inheritedSkill = fallenInfo.Skill;
holders.TryRemove(playerIndex, out _);
SkillUtils.CloseMenu(player);
Instance.AddTimer(.1f, () =>
{
var target = Utilities.GetPlayerFromIndex((int)playerIndex);
if (target == null || !target.IsValid) return;
var targetInfo = PlayerManager.GetPlayerByIndex(playerIndex);
if (targetInfo == null || targetInfo.Skill != skillName) return;
targetInfo.Skill = inheritedSkill;
targetInfo.SpecialSkill = skillName;
SkillUtils.CloseMenu(target);
if (SkillsInfo.GetValue<bool>(inheritedSkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime())
Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () =>
{
var heir = Utilities.GetPlayerFromIndex((int)playerIndex);
if (heir == null || !heir.IsValid) return;
if (PlayerManager.GetPlayerByIndex(playerIndex)?.Skill != inheritedSkill) return;
Instance?.SkillAction(inheritedSkill.ToString(), "EnableSkill", [heir]);
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
else
Instance?.SkillAction(inheritedSkill.ToString(), "EnableSkill", [target]);
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
playerEvent.PrintToChat($" {ChatColors.Green}" + playerEvent.GetTranslation("inheritance_player_info", fallenInfo.PlayerName));
}
private static void RefreshMenu(CCSPlayerController player)
{
if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
if (PlayerManager.GetPlayerByIndex(player.Index)?.Skill != skillName) return;
ConcurrentBag<(string, string)> menuItems = [];
foreach (var (fallenIndex, fallenInfo) in fallen)
{
if (fallenIndex == player.Index) continue;
if (!CanInherit(player, fallenInfo)) continue;
menuItems.Add(($"\u202A{fallenInfo.PlayerName}\u202C : {player.GetSkillName(fallenInfo.Skill)}", fallenIndex.ToString()));
}
if (menuItems.IsEmpty) return;
if (SkillUtils.HasMenu(player))
SkillUtils.UpdateMenu(player, menuItems);
else
SkillUtils.CreateMenu(player, menuItems);
}
private static bool CanInherit(CCSPlayerController player, FallenInfo fallenInfo)
{
if (fallenInfo.Team != player.Team) return false;
if (!player.IsBot)
{
string permission = SkillsInfo.GetValue<string>(fallenInfo.Skill, "requiredPermission");
if (!string.IsNullOrEmpty(permission) && !AdminManager.PlayerHasPermissions(player, permission))
return false;
}
if (!SkillsInfo.GetValue<bool>(fallenInfo.Skill, "needsTeammates")) return true;
return PlayerManager.GetTickPlayers().Any(p =>
p != null && p.IsValid && p.Index != player.Index && p.Team == player.Team
&& p.PlayerPawn?.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0);
}
private class FallenInfo
{
public required string PlayerName { get; set; }
public required Skills Skill { get; set; }
public required CsTeam Team { get; set; }
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#c9a227", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = true, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = 2, Rarity rarity = Rarity.Rare) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
{
}
}
}

View file

@ -38,9 +38,27 @@ namespace src.player.skills
playersInAction.Clear(); playersInAction.Clear();
} }
private static readonly List<(CsTeam OwnerTeam, uint RelayEntityIndex)> transmitTrails = [];
public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList)
{ {
var snapshot = activeTrails.ToArray(); if (activeTrails.IsEmpty) return;
transmitTrails.Clear();
foreach (var (trackedPlayerIndex, relayIndex) in activeTrails)
{
if (relayIndex == null) continue;
var trailOwner = Utilities.GetPlayerFromIndex((int)trackedPlayerIndex);
if (trailOwner == null || !trailOwner.IsValid) continue;
var relayEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)relayIndex);
if (relayEntity == null || !relayEntity.IsValid) continue;
transmitTrails.Add((trailOwner.Team, relayEntity.Index));
}
if (transmitTrails.Count == 0) return;
foreach (var (info, player) in infoList) foreach (var (info, player) in infoList)
{ {
@ -65,19 +83,12 @@ namespace src.player.skills
} }
} }
foreach (var (trackedPlayerIndex, relayIndex) in snapshot) var playerTeam = player.Team;
foreach (var (ownerTeam, relayEntityIndex) in transmitTrails)
{ {
if (relayIndex == null) continue; if (playerTeam == ownerTeam || !isJackalOwner)
if (info.TransmitEntities.Contains(relayEntityIndex))
var trailOwner = Utilities.GetPlayerFromIndex((int)trackedPlayerIndex); info.TransmitEntities.Remove(relayEntityIndex);
if (trailOwner == null || !trailOwner.IsValid) continue;
var relayEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)relayIndex);
if (relayEntity == null || !relayEntity.IsValid) continue;
if (player.Team == trailOwner.Team || !isJackalOwner)
if (info.TransmitEntities.Contains(relayEntity.Index))
info.TransmitEntities.Remove(relayEntity.Index);
} }
} }
} }
@ -135,14 +146,6 @@ namespace src.player.skills
Event.EnableTransmit(); Event.EnableTransmit();
playersInAction.TryAdd(player.Index, 0); playersInAction.TryAdd(player.Index, 0);
var opponents = PlayerManager.GetTickPlayers()
.Where(p => p != null
&& p.IsValid
&& p.Team != player.Team
&& p.PawnIsAlive
&& (p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist))
.ToArray();
mainSkillTimer ??= Instance.AddTimer(2.5f, () => UpdateAllTrails(), mainSkillTimer ??= Instance.AddTimer(2.5f, () => UpdateAllTrails(),
CounterStrikeSharp.API.Modules.Timers.TimerFlags.REPEAT | CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); CounterStrikeSharp.API.Modules.Timers.TimerFlags.REPEAT | CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);

View file

@ -235,6 +235,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
if (SkillUtils.IsFreezeTime()) return; if (SkillUtils.IsFreezeTime()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {

View file

@ -26,6 +26,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
if (SkillUtils.IsFreezeTime()) return; if (SkillUtils.IsFreezeTime()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {

View file

@ -29,6 +29,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);

View file

@ -19,11 +19,11 @@ namespace src.player.skills
{ {
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {
if (!Instance.IsPlayerValid(player)) continue; if (player == null) continue;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (PlayerManager.GetPlayerByIndex(player.Index)?.Skill != skillName) continue;
if (!Instance.IsPlayerValid(player)) continue;
if (playerInfo?.Skill == skillName)
{
var pawn = player.PlayerPawn.Value!; var pawn = player.PlayerPawn.Value!;
var weaponServices = pawn.WeaponServices; var weaponServices = pawn.WeaponServices;
if (weaponServices == null || weaponServices.ActiveWeapon == null || !weaponServices.ActiveWeapon.IsValid) continue; if (weaponServices == null || weaponServices.ActiveWeapon == null || !weaponServices.ActiveWeapon.IsValid) continue;
@ -45,7 +45,6 @@ namespace src.player.skills
Schema.SetSchemaValue<Int32>(weapon.Handle, "CBasePlayerWeapon", "m_nNextSecondaryAttackTick", Server.TickCount); Schema.SetSchemaValue<Int32>(weapon.Handle, "CBasePlayerWeapon", "m_nNextSecondaryAttackTick", Server.TickCount);
} }
} }
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8a42f5", 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) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8a42f5", 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) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
{ {

View file

@ -21,10 +21,11 @@ namespace src.player.skills
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {
var playerEvent = PlayerManager.GetPlayerEvent(player); var playerEvent = PlayerManager.GetPlayerEvent(player);
if (playerEvent == null) continue;
if (PlayerManager.GetPlayerByIndex(playerEvent.Index)?.Skill != skillName) continue;
if (!Instance.IsPlayerValid(playerEvent)) continue; if (!Instance.IsPlayerValid(playerEvent)) continue;
var playerInfo = PlayerManager.GetPlayerByIndex(playerEvent!.Index);
if (playerInfo?.Skill == skillName)
SetEnemiesVisibleOnRadar(player); SetEnemiesVisibleOnRadar(player);
} }
} }
@ -36,8 +37,10 @@ namespace src.player.skills
// SpottedByMask is indexed by player slot (0-63), not entity index. // SpottedByMask is indexed by player slot (0-63), not entity index.
int slot = player.Slot; int slot = player.Slot;
foreach (var enemy in PlayerManager.GetTickPlayers().FindAll(p => p.Team != player.Team)) foreach (var enemy in PlayerManager.GetTickPlayers())
{ {
if (enemy == null || enemy.Team == player.Team) continue;
var enemyEvent = PlayerManager.GetPlayerEvent(enemy); var enemyEvent = PlayerManager.GetPlayerEvent(enemy);
if (enemyEvent == null || !enemyEvent.IsValid) continue; if (enemyEvent == null || !enemyEvent.IsValid) continue;
@ -59,7 +62,7 @@ namespace src.player.skills
public class SkillConfig : SkillsInfo.DefaultSkillInfo public class SkillConfig : SkillsInfo.DefaultSkillInfo
{ {
public SkillConfig(Skills skill = skillName, bool active = true, string color = "#2effcb", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = utils.Rarity.Common) : base(skill, active, color, onlyTeam, needsTeammates) public SkillConfig(Skills skill = skillName, bool active = true, string color = "#2effcb", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = utils.Rarity.Common) : base(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
{ {
} }
} }

View file

@ -40,6 +40,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
var players = PlayerManager.GetTickPlayers().ToArray(); var players = PlayerManager.GetTickPlayers().ToArray();
foreach (var player in players) foreach (var player in players)
{ {

View file

@ -25,6 +25,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);

View file

@ -33,7 +33,7 @@ namespace src.player.skills
{ {
public int HealthToAdd { get; set; } public int HealthToAdd { get; set; }
public float Cooldown { get; set; } public float Cooldown { get; set; }
public SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff462e", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = utils.Rarity.Common, int healthToAdd = 1, float cooldown = .25f) : base(skill, active, color, onlyTeam, needsTeammates) public SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff462e", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = utils.Rarity.Common, int healthToAdd = 1, float cooldown = .25f) : base(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
{ {
HealthToAdd = healthToAdd; HealthToAdd = healthToAdd;
Cooldown = cooldown; Cooldown = cooldown;

View file

@ -40,6 +40,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);

View file

@ -26,6 +26,7 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (!SkillUtils.IsHudFrame()) return;
foreach (var player in PlayerManager.GetTickPlayers()) foreach (var player in PlayerManager.GetTickPlayers())
{ {
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);

View file

@ -0,0 +1,661 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.utils;
using RayTraceAPI;
using src.utils;
using System.Collections.Concurrent;
using System.Drawing;
using System.Numerics;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
namespace src.player.skills
{
public class Ricochet : ISkill
{
private const Skills skillName = Skills.Ricochet;
private static readonly ConcurrentDictionary<uint, ImpactBudget> impactBudgets = [];
private static readonly HashSet<uint> ownedTracers = [];
private static readonly List<uint> tracerPool = [];
private static readonly List<Flight> flights = [];
private static readonly object flightLock = new();
private static readonly Color tracerColor = Color.FromArgb(170, 255, 226, 140);
private static readonly ulong worldOnlyMask = (ulong)InteractionLayers.MASK_WORLD_ONLY;
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
}
public static void NewRound()
{
impactBudgets.Clear();
ResetPool(false);
}
public static void RoundEnd()
{
ResetPool(true);
}
public static void PlayerDisconnect(uint playerIndex)
{
impactBudgets.TryRemove(playerIndex, out _);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null) return;
impactBudgets.TryRemove(player.Index, out _);
}
public static void BulletImpact(EventBulletImpact @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
if (PlayerManager.GetPlayerByIndex(player.Index)?.Skill != skillName) return;
if (!RayTrace.IsAvailable)
{
Trace("RayTrace module unavailable");
return;
}
var pawn = player.PlayerPawn?.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE)
{
Trace("shooter pawn invalid or dead");
return;
}
if (!TryConsumeBudget(player.Index)) return;
Vector3 eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z);
Vector3 impact = new(@event.X, @event.Y, @event.Z);
Vector3 toImpact = impact - eyePos;
if (toImpact.LengthSquared() < 1f)
{
Trace("impact too close to eye");
return;
}
Vector3 direction = Vector3.Normalize(toImpact);
var surface = RayTrace.TraceShape(player, ToVector(eyePos), ToVector(impact + direction * 8f), worldOnlyMask, 0);
if (surface == null)
{
Trace("surface trace returned null");
return;
}
if (!surface.Value.DidHit)
{
Trace($"surface trace missed (fraction={surface.Value.Fraction:0.###})");
return;
}
if (!TryResolveNormal(player, surface.Value, direction, out Vector3 normal))
{
Trace("could not resolve surface normal");
return;
}
Bounce(player, pawn, surface.Value.EndPos, direction, normal);
}
private static void Bounce(CCSPlayerController player, CCSPlayerPawn pawn, Vector3 point, Vector3 direction, Vector3 normal)
{
int bounces = Math.Max(SkillsInfo.GetValue<int>(skillName, "bounces"), 1);
float segmentDistance = SkillsInfo.GetValue<float>(skillName, "segmentDistance");
float damageFalloff = SkillsInfo.GetValue<float>(skillName, "damageFalloff");
var vdata = GetWeaponVData(pawn);
float damage = GetBaseDamage(vdata);
KillfeedIcons? killfeedIcon = KillfeedIconsExtensions.FromWeaponName(SkillUtils.GetDesignerName(pawn.WeaponServices?.ActiveWeapon?.Value));
List<Vector3> path = [];
for (int i = 0; i < bounces; i++)
{
direction = Vector3.Reflect(direction, normal);
Vector3 start = point + normal * 2f;
if (path.Count == 0) path.Add(start);
Vector3 end = start + direction * segmentDistance;
var hit = RayTrace.TraceShape(player, ToVector(start), ToVector(end));
if (hit == null)
{
Trace($"bounce {i + 1}: segment trace returned null");
break;
}
Vector3 stop = hit.Value.DidHit ? hit.Value.EndPos : end;
path.Add(stop);
if (!hit.Value.DidHit)
{
Trace($"bounce {i + 1}: no surface, len={Vector3.Distance(start, stop):0.#}");
break;
}
if (hit.Value.HitPlayer(out var victim))
{
DealDamage(player, victim, damage, vdata, killfeedIcon);
break;
}
if (!TryResolveNormal(player, hit.Value, direction, out normal))
{
Trace($"bounce {i + 1}: could not resolve normal");
break;
}
point = hit.Value.EndPos;
damage *= damageFalloff;
}
StartFlight(player, path);
}
public static void OnTick()
{
lock (flightLock)
{
if (flights.Count == 0) return;
float speed = MathF.Max(SkillsInfo.GetValue<float>(skillName, "tracerSpeed"), 100f);
float trail = MathF.Max(SkillsInfo.GetValue<float>(skillName, "tracerLength"), 16f);
float step = speed / 64f;
int tick = Server.TickCount;
for (int i = flights.Count - 1; i >= 0; i--)
{
var flight = flights[i];
flight.Travelled += step;
if (flight.Travelled - trail >= flight.TotalLength || tick >= flight.DeadlineTick)
{
ReleaseTracer(flight);
flights.RemoveAt(i);
continue;
}
float head = MathF.Min(flight.Travelled, flight.TotalLength);
int segment = SegmentAt(flight, head);
float tail = MathF.Max(head - trail, flight.Cumulative[segment]);
UpdateTracer(flight, PointAt(flight, tail), PointAt(flight, head));
}
}
}
private static void StartFlight(CCSPlayerController player, List<Vector3> path)
{
if (path.Count < 2) return;
if (!SkillsInfo.GetValue<bool>(skillName, "showTracer")) return;
if (EntityManager.OverBudget()) return;
var points = path.ToArray();
var cumulative = new float[points.Length];
for (int i = 1; i < points.Length; i++)
cumulative[i] = cumulative[i - 1] + Vector3.Distance(points[i - 1], points[i]);
float total = cumulative[^1];
if (total < 1f) return;
float speed = MathF.Max(SkillsInfo.GetValue<float>(skillName, "tracerSpeed"), 100f);
lock (flightLock)
{
if (flights.Count >= Math.Max(SkillsInfo.GetValue<int>(skillName, "maxActiveTracers"), 1)) return;
flights.Add(new Flight
{
OwnerIndex = player.Index,
Points = points,
Cumulative = cumulative,
TotalLength = total,
DeadlineTick = Server.TickCount + (int)(total / speed * 64f) + 128,
});
}
}
private static int SegmentAt(Flight flight, float distance)
{
for (int i = flight.Points.Length - 2; i >= 0; i--)
if (distance >= flight.Cumulative[i]) return i;
return 0;
}
private static Vector3 PointAt(Flight flight, float distance)
{
int i = SegmentAt(flight, distance);
float segmentStart = flight.Cumulative[i];
float segmentLength = flight.Cumulative[i + 1] - segmentStart;
if (segmentLength <= .0001f) return flight.Points[i];
float t = Math.Clamp((distance - segmentStart) / segmentLength, 0f, 1f);
return Vector3.Lerp(flight.Points[i], flight.Points[i + 1], t);
}
private static void UpdateTracer(Flight flight, Vector3 tail, Vector3 head)
{
CBeam? beam = null;
if (flight.BeamIndex != null)
{
beam = ResolveTracer(flight.BeamIndex.Value);
if (beam == null)
{
ownedTracers.Remove(flight.BeamIndex.Value);
flight.BeamIndex = null;
}
}
beam ??= AcquireTracer(flight);
if (beam == null) return;
beam.Teleport(ToVector(tail));
beam.EndPos.X = head.X;
beam.EndPos.Y = head.Y;
beam.EndPos.Z = head.Z;
Utilities.SetStateChanged(beam, "CBeam", "m_vecEndPos");
}
private static CBeam? AcquireTracer(Flight flight)
{
float width = SkillsInfo.GetValue<float>(skillName, "tracerWidth");
while (tracerPool.Count > 0)
{
uint pooledIndex = tracerPool[^1];
tracerPool.RemoveAt(tracerPool.Count - 1);
var pooled = ResolveTracer(pooledIndex);
if (pooled == null)
{
ownedTracers.Remove(pooledIndex);
continue;
}
pooled.Width = width;
pooled.EndWidth = width;
pooled.Render = tracerColor;
Utilities.SetStateChanged(pooled, "CBeam", "m_fWidth");
Utilities.SetStateChanged(pooled, "CBeam", "m_fEndWidth");
Utilities.SetStateChanged(pooled, "CBaseModelEntity", "m_clrRender");
flight.BeamIndex = pooledIndex;
return pooled;
}
if (ownedTracers.Count >= Math.Max(SkillsInfo.GetValue<int>(skillName, "maxActiveTracers"), 1)) return null;
if (EntityManager.OverBudget()) return null;
var beam = CreateTracerBeam(flight.Points[0], width);
if (beam == null) return null;
ownedTracers.Add(beam.Index);
flight.BeamIndex = beam.Index;
return beam;
}
private static CBeam? CreateTracerBeam(Vector3 at, float width)
{
try
{
var beam = Utilities.CreateEntityByName<CBeam>("beam");
if (beam == null || !beam.IsValid) return null;
beam.Render = tracerColor;
beam.Width = width;
beam.EndWidth = width;
beam.Teleport(ToVector(at));
beam.EndPos.X = at.X;
beam.EndPos.Y = at.Y;
beam.EndPos.Z = at.Z;
beam.DispatchSpawn();
return beam;
}
catch (Exception ex)
{
Trace($"beam create failed: {ex.Message}");
return null;
}
}
private static void ReleaseTracer(Flight flight)
{
if (flight.BeamIndex == null) return;
uint beamIndex = flight.BeamIndex.Value;
flight.BeamIndex = null;
if (!ownedTracers.Contains(beamIndex)) return;
var beam = ResolveTracer(beamIndex);
if (beam == null)
{
ownedTracers.Remove(beamIndex);
Trace($"tracer {beamIndex} vanished before release");
return;
}
HideTracer(beam);
tracerPool.Add(beamIndex);
}
private static void HideTracer(CBeam beam)
{
beam.Width = 0;
beam.EndWidth = 0;
beam.Render = Color.FromArgb(0, 0, 0, 0);
Utilities.SetStateChanged(beam, "CBeam", "m_fWidth");
Utilities.SetStateChanged(beam, "CBeam", "m_fEndWidth");
Utilities.SetStateChanged(beam, "CBaseModelEntity", "m_clrRender");
if (beam.AbsOrigin == null) return;
beam.EndPos.X = beam.AbsOrigin.X;
beam.EndPos.Y = beam.AbsOrigin.Y;
beam.EndPos.Z = beam.AbsOrigin.Z;
Utilities.SetStateChanged(beam, "CBeam", "m_vecEndPos");
}
private static void ResetPool(bool hideEntities)
{
lock (flightLock)
{
foreach (var flight in flights)
flight.BeamIndex = null;
flights.Clear();
if (hideEntities)
foreach (uint beamIndex in ownedTracers)
{
var beam = ResolveTracer(beamIndex);
if (beam != null) HideTracer(beam);
}
if (ownedTracers.Count > 0)
Trace($"pool reset: {ownedTracers.Count} tracer(s) released");
tracerPool.Clear();
ownedTracers.Clear();
}
}
private static CBeam? ResolveTracer(uint beamIndex)
{
var beam = Utilities.GetEntityFromIndex<CBeam>((int)beamIndex);
if (beam == null || !beam.IsValid) return null;
return beam.DesignerName == "beam" ? beam : null;
}
private static CCSWeaponBaseVData? GetWeaponVData(CCSPlayerPawn pawn)
{
var activeWeapon = pawn.WeaponServices?.ActiveWeapon?.Value;
if (activeWeapon == null || !activeWeapon.IsValid) return null;
try
{
return activeWeapon.As<CCSWeaponBase>().GetVData<CCSWeaponBaseVData>();
}
catch
{
return null;
}
}
private static float GetBaseDamage(CCSWeaponBaseVData? vdata)
{
float fallback = SkillsInfo.GetValue<float>(skillName, "fallbackDamage");
if (vdata == null) return fallback;
float weaponDamage = vdata.Damage;
if (weaponDamage <= 0) return fallback;
return weaponDamage * SkillsInfo.GetValue<float>(skillName, "damageMultiplier");
}
private static void DealDamage(CCSPlayerController attacker, CCSPlayerController? victim, float damage, CCSWeaponBaseVData? vdata, KillfeedIcons? killfeedIcon)
{
if (victim == null || !victim.IsValid) return;
var victimEvent = PlayerManager.GetPlayerEvent(victim);
if (victimEvent == null || !victimEvent.IsValid) return;
if (victimEvent.Index == attacker.Index || victimEvent.Team == attacker.Team) return;
var victimPawn = victimEvent.PlayerPawn?.Value;
if (victimPawn == null || !victimPawn.IsValid || victimPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
if (vdata != null && victimEvent.PawnArmor > 0 && SkillsInfo.GetValue<bool>(skillName, "respectArmor"))
damage *= vdata.ArmorRatio * .5f;
int finalDamage = (int)MathF.Round(damage);
if (finalDamage <= 0) return;
Trace($"hit {victimEvent.PlayerName} for {finalDamage}");
SkillUtils.TakeHealth(victimPawn, finalDamage, attacker, killfeedIcon ?? KillfeedIcons.Leg);
}
private static bool TryResolveNormal(CCSPlayerController player, CustomTraceResult result, Vector3 direction, out Vector3 normal)
{
normal = Vector3.Zero;
if (!TryRoughNormal(player, result, direction, out Vector3 rough)) return false;
if (TryRefineNormal(player, result.EndPos, direction, rough, out normal)) return true;
Trace("surface refine failed, using rough normal");
normal = rough;
return true;
}
private static bool TryRoughNormal(CCSPlayerController player, CustomTraceResult result, Vector3 direction, out Vector3 rough)
{
rough = result.Normal;
if (rough.LengthSquared() > .0001f)
{
rough = Vector3.Normalize(rough);
if (Vector3.Dot(direction, rough) < -.05f) return true;
}
return TryPlaneFitNormal(player, result.EndPos, direction, out rough);
}
private static bool TryRefineNormal(CCSPlayerController player, Vector3 baseHit, Vector3 direction, Vector3 rough, out Vector3 normal)
{
normal = Vector3.Zero;
Vector3 axis = MathF.Abs(rough.Z) > .9f ? Vector3.UnitX : Vector3.UnitZ;
Vector3 first = Vector3.Cross(rough, axis);
if (first.LengthSquared() < .0001f) return false;
first = Vector3.Normalize(first);
Vector3 second = Vector3.Normalize(Vector3.Cross(rough, first));
float offset = MathF.Max(SkillsInfo.GetValue<float>(skillName, "normalProbeOffset"), 1f);
float tolerance = offset * 2.5f;
Span<Vector3> ring = stackalloc Vector3[4];
int count = 0;
if (SampleSurface(player, baseHit, rough, first * offset, tolerance, out Vector3 firstPlus)) ring[count++] = firstPlus;
if (SampleSurface(player, baseHit, rough, second * offset, tolerance, out Vector3 secondPlus)) ring[count++] = secondPlus;
if (SampleSurface(player, baseHit, rough, first * -offset, tolerance, out Vector3 firstMinus)) ring[count++] = firstMinus;
if (SampleSurface(player, baseHit, rough, second * -offset, tolerance, out Vector3 secondMinus)) ring[count++] = secondMinus;
if (count == 2 && SampleSurface(player, baseHit, rough, Vector3.Zero, tolerance, out Vector3 center))
ring[count++] = center;
if (count < 3) return false;
normal = NewellNormal(ring[..count]);
if (normal.LengthSquared() < .0001f) return false;
normal = Vector3.Normalize(normal);
float dot = Vector3.Dot(direction, normal);
if (MathF.Abs(dot) < .05f) return false;
if (dot > 0f) normal = -normal;
return true;
}
private static bool SampleSurface(CCSPlayerController player, Vector3 baseHit, Vector3 rough, Vector3 tangentOffset, float tolerance, out Vector3 point)
{
point = Vector3.Zero;
Vector3 anchor = baseHit + tangentOffset;
Vector3 start = anchor + rough * 16f;
Vector3 end = anchor - rough * 48f;
var sample = RayTrace.TraceShape(player, ToVector(start), ToVector(end), worldOnlyMask, 0);
if (sample == null || !sample.Value.DidHit) return false;
point = sample.Value.EndPos;
return MathF.Abs(Vector3.Dot(point - baseHit, rough)) <= tolerance;
}
private static Vector3 NewellNormal(ReadOnlySpan<Vector3> points)
{
Vector3 normal = Vector3.Zero;
for (int i = 0; i < points.Length; i++)
{
Vector3 current = points[i];
Vector3 next = points[(i + 1) % points.Length];
normal.X += (current.Y - next.Y) * (current.Z + next.Z);
normal.Y += (current.Z - next.Z) * (current.X + next.X);
normal.Z += (current.X - next.X) * (current.Y + next.Y);
}
return normal;
}
private static bool TryPlaneFitNormal(CCSPlayerController player, Vector3 baseHit, Vector3 direction, out Vector3 normal)
{
normal = Vector3.Zero;
Vector3 axis = MathF.Abs(direction.Z) > .9f ? Vector3.UnitX : Vector3.UnitZ;
Vector3 right = Vector3.Cross(direction, axis);
if (right.LengthSquared() < .0001f) return false;
right = Vector3.Normalize(right);
Vector3 up = Vector3.Normalize(Vector3.Cross(right, direction));
float offset = MathF.Max(SkillsInfo.GetValue<float>(skillName, "normalProbeOffset"), 1f);
float tolerance = offset * 6f;
Vector3 origin = baseHit - direction * 24f;
if (!Probe(player, origin, direction, right * offset, baseHit, tolerance, out Vector3 rightHit)) return false;
if (!Probe(player, origin, direction, right * -offset, baseHit, tolerance, out Vector3 leftHit)) return false;
if (!Probe(player, origin, direction, up * offset, baseHit, tolerance, out Vector3 upHit)) return false;
if (!Probe(player, origin, direction, up * -offset, baseHit, tolerance, out Vector3 downHit)) return false;
normal = Vector3.Cross(rightHit - leftHit, upHit - downHit);
if (normal.LengthSquared() < .0001f) return false;
normal = Vector3.Normalize(normal);
float dot = Vector3.Dot(direction, normal);
if (MathF.Abs(dot) < .05f) return false;
if (dot > 0f) normal = -normal;
return true;
}
private static bool Probe(CCSPlayerController player, Vector3 origin, Vector3 direction, Vector3 offset, Vector3 baseHit, float tolerance, out Vector3 point)
{
point = Vector3.Zero;
Vector3 start = origin + offset;
Vector3 end = start + direction * 96f;
var probe = RayTrace.TraceShape(player, ToVector(start), ToVector(end), worldOnlyMask, 0);
if (probe == null || !probe.Value.DidHit) return false;
point = probe.Value.EndPos;
return Vector3.Distance(point, baseHit) <= tolerance;
}
private static void Trace(string message)
{
Debug.WriteToDebug($"[Ricochet] {message}");
}
private static bool TryConsumeBudget(uint playerIndex)
{
int tick = Server.TickCount;
var budget = impactBudgets.GetOrAdd(playerIndex, _ => new ImpactBudget());
if (budget.Tick != tick)
{
budget.Tick = tick;
budget.Count = 0;
}
if (budget.Count >= Math.Max(SkillsInfo.GetValue<int>(skillName, "maxImpactsPerTick"), 1)) return false;
budget.Count++;
return true;
}
private static Vector ToVector(Vector3 vector) => new(vector.X, vector.Y, vector.Z);
private class ImpactBudget
{
public int Tick { get; set; } = int.MinValue;
public int Count { get; set; }
}
private class Flight
{
public required uint OwnerIndex { get; set; }
public required Vector3[] Points { get; set; }
public required float[] Cumulative { get; set; }
public required float TotalLength { get; set; }
public required int DeadlineTick { get; set; }
public float Travelled { get; set; }
public uint? BeamIndex { get; set; }
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ffd75e", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = 2, Rarity rarity = Rarity.Rare, int bounces = 3, float segmentDistance = 1200f, float damageMultiplier = .5f, float fallbackDamage = 25f, bool respectArmor = true, float damageFalloff = .75f, int maxImpactsPerTick = 2, bool showTracer = true, float tracerWidth = 0.5f, float tracerSpeed = 2600f, float tracerLength = 220f, int maxActiveTracers = 12, float normalProbeOffset = 6f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
{
public int Bounces { get; set; } = bounces;
public float SegmentDistance { get; set; } = segmentDistance;
public float DamageMultiplier { get; set; } = damageMultiplier;
public float FallbackDamage { get; set; } = fallbackDamage;
public bool RespectArmor { get; set; } = respectArmor;
public float DamageFalloff { get; set; } = damageFalloff;
public int MaxImpactsPerTick { get; set; } = maxImpactsPerTick;
public bool ShowTracer { get; set; } = showTracer;
public float TracerWidth { get; set; } = tracerWidth;
public float TracerSpeed { get; set; } = tracerSpeed;
public float TracerLength { get; set; } = tracerLength;
public int MaxActiveTracers { get; set; } = maxActiveTracers;
public float NormalProbeOffset { get; set; } = normalProbeOffset;
}
}
}

View file

@ -50,6 +50,8 @@ namespace src.player.skills
public static void PlayerMakeSound(UserMessage um) public static void PlayerMakeSound(UserMessage um)
{ {
if (SkillPlayerInfo.IsEmpty) return;
var soundevent = um.ReadUInt("soundevent_hash"); var soundevent = um.ReadUInt("soundevent_hash");
if (soundevent != soundEventHash) return; if (soundevent != soundEventHash) return;
@ -96,7 +98,11 @@ namespace src.player.skills
public static void OnTick() public static void OnTick()
{ {
if (Server.TickCount % (60 * SkillsInfo.GetValue<int>(skillName, "cooldown")) != 0) return; if (SkillPlayerInfo.IsEmpty) return;
int cooldown = SkillsInfo.GetValue<int>(skillName, "cooldown");
if (cooldown < 1) cooldown = 1;
if (Server.TickCount % (60 * cooldown) != 0) return;
foreach (var player in PlayerManager.GetTickPlayers() foreach (var player in PlayerManager.GetTickPlayers()
.Where(p => p != null && p.IsValid && p.PlayerPawn.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0)) .Where(p => p != null && p.IsValid && p.PlayerPawn.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0))

View file

@ -133,7 +133,10 @@ namespace src.player.skills
pawn.CameraServices.ViewEntity.Raw = defaultCam ? orginalCameraRaw : newCameraRaw; pawn.CameraServices.ViewEntity.Raw = defaultCam ? orginalCameraRaw : newCameraRaw;
} }
else else
{
defaultCam = true;
pawn.CameraServices.ViewEntity.Raw = orginalCameraRaw; pawn.CameraServices.ViewEntity.Raw = orginalCameraRaw;
}
Utilities.SetStateChanged(pawn, "CBasePlayerPawn", "m_pCameraServices"); Utilities.SetStateChanged(pawn, "CBasePlayerPawn", "m_pCameraServices");

View file

@ -45,7 +45,7 @@ namespace src.player.skills
if (!SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) continue; if (!SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) continue;
GetTeamate(player, skillInfo); GetTeamate(player, skillInfo);
UpdateHUD(player, skillInfo); if (SkillUtils.IsHudFrame()) UpdateHUD(player, skillInfo);
} }
} }

View file

@ -400,14 +400,35 @@ namespace src.player.skills
return (closet, minKnifeInfo); return (closet, minKnifeInfo);
} }
private static readonly List<(uint OwnerIndex, uint GlowEntityIndex)> transmitGlows = [];
public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList)
{ {
var snapshot = knivesInfo.ToArray(); if (knivesInfo.IsEmpty) return;
transmitGlows.Clear();
foreach (var (knifeOwnerIndex, knifeInfo) in knivesInfo)
{
if (knifeInfo.GlowIndex == null) continue;
var glowEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)knifeInfo.GlowIndex);
if (glowEntity == null || !glowEntity.IsValid)
{
knifeInfo.GlowIndex = null;
continue;
}
transmitGlows.Add((knifeOwnerIndex, glowEntity.Index));
}
if (transmitGlows.Count == 0) return;
foreach (var (info, player) in infoList) foreach (var (info, player) in infoList)
{ {
if (player == null || !player.IsValid) continue; if (player == null || !player.IsValid) continue;
uint viewerIndex = PlayerManager.GetPlayerEvent(player)?.Index ?? player.Index;
uint? observedPlayerIndex = null; uint? observedPlayerIndex = null;
var playerPawn = player.Pawn?.Value; var playerPawn = player.Pawn?.Value;
if (playerPawn != null && playerPawn.IsValid) if (playerPawn != null && playerPawn.IsValid)
@ -423,23 +444,13 @@ namespace src.player.skills
} }
} }
foreach ((uint knifeOwnerIndex, KnifeInfo knifeInfo) in snapshot) foreach (var (knifeOwnerIndex, glowEntityIndex) in transmitGlows)
{ {
if (knifeInfo.GlowIndex == null) continue; if (knifeOwnerIndex == viewerIndex) continue;
if (observedPlayerIndex.HasValue && observedPlayerIndex.Value == knifeOwnerIndex) continue;
var glowEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)knifeInfo.GlowIndex); if (info.TransmitEntities.Contains(glowEntityIndex))
if (glowEntity == null || !glowEntity.IsValid) info.TransmitEntities.Remove(glowEntityIndex);
{
knifeInfo.GlowIndex = null;
continue;
}
bool isOwner = knifeOwnerIndex == (PlayerManager.GetPlayerEvent(player)?.Index ?? player.Index);
bool isObservingOwner = observedPlayerIndex.HasValue && observedPlayerIndex.Value == knifeOwnerIndex;
if (!isOwner && !isObservingOwner)
if (info.TransmitEntities.Contains(glowEntity.Index))
info.TransmitEntities.Remove(glowEntity.Index);
} }
} }
} }

View file

@ -93,6 +93,7 @@ namespace src.player.skills
public static void NewRound() public static void NewRound()
{ {
buildInProgress = false; buildInProgress = false;
buildScheduled = false;
foreach (var kvp in glows) foreach (var kvp in glows)
{ {
@ -139,10 +140,21 @@ namespace src.player.skills
Event.EnableTransmit(); Event.EnableTransmit();
playersInAction.TryAdd(player.Index, 0); playersInAction.TryAdd(player.Index, 0);
if (glows.IsEmpty && !buildInProgress) if (buildScheduled || buildInProgress || !glows.IsEmpty) return;
SetGlowEffectForAll();
SkillUtils.ForceFullUpdateToAll(); buildScheduled = true;
float delay = SkillUtils.IsFreezeTime()
? Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0f)
: 0f;
jRandomSkills.Instance.AddTimer(delay, () =>
{
buildScheduled = false;
if (playersInAction.IsEmpty || buildInProgress || !glows.IsEmpty) return;
SetGlowEffectForAll();
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
@ -158,6 +170,7 @@ namespace src.player.skills
private const int GlowsPerFrame = 4; private const int GlowsPerFrame = 4;
private static bool buildInProgress; private static bool buildInProgress;
private static bool buildScheduled;
private static void SetGlowEffectForAll() private static void SetGlowEffectForAll()
{ {
@ -180,6 +193,7 @@ namespace src.player.skills
if (start >= enemies.Count) if (start >= enemies.Count)
{ {
buildInProgress = false; buildInProgress = false;
SkillUtils.ForceFullUpdateToAllChunked();
return; return;
} }

View file

@ -65,10 +65,15 @@ namespace src.utils
return jRandomSkills.Instance?.GameRules?.FreezePeriod == true; return jRandomSkills.Instance?.GameRules?.FreezePeriod == true;
} }
public static bool IsHudFrame() => Server.TickCount % 4 == 0;
public static void RegisterSkill(Skills skill, string color, bool display = true) public static void RegisterSkill(Skills skill, string color, bool display = true)
{ {
if (!SkillData.Skills.Any(s => s.Skill == skill)) if (!SkillData.Skills.Any(s => s.Skill == skill))
{
SkillData.Skills.Add(new jSkill_SkillInfo(skill, color, display)); SkillData.Skills.Add(new jSkill_SkillInfo(skill, color, display));
SkillData.Invalidate();
}
} }
public static void UpdateGrenadeCount(CCSPlayerController player, CsItem item, int ammo) public static void UpdateGrenadeCount(CCSPlayerController player, CsItem item, int ammo)
@ -187,11 +192,6 @@ namespace src.utils
SnapViewAngles.Value?.Invoke(pawn, angle); SnapViewAngles.Value?.Invoke(pawn, angle);
} }
public static CBeam? CreateLine(Vector start, Vector end, Color color, uint ownerPlayerIndex = EntityManager.SystemOwnerIndex)
{
return EntityManager.CreateTrackedBeam(ownerPlayerIndex, start, end, color);
}
public static void SetPlayerCollisions(CCSPlayerController? player, bool enable) public static void SetPlayerCollisions(CCSPlayerController? player, bool enable)
{ {
return; return;
@ -684,6 +684,50 @@ namespace src.utils
}); });
} }
public static void ForceFullUpdateToAllChunked(int clientsPerFrame = 2)
{
if (!Config.LoadedConfig.EnableFullForceUpdate) return;
var pending = Utilities.GetPlayers().Where(p => p != null && p.IsValid && !p.IsBot).Select(p => p.Index).ToList();
if (pending.Count == 0) return;
ForceFullUpdateChunk(pending, 0, Math.Max(clientsPerFrame, 1));
}
private static void ForceFullUpdateChunk(List<uint> pending, int start, int clientsPerFrame)
{
if (start >= pending.Count) return;
int end = Math.Min(start + clientsPerFrame, pending.Count);
var toRestore = new List<(uint PlayerIndex, QAngle LastAngle)>();
INetworkGameServer networkGameServer = new INetworkServerService().GetIGameServer();
for (int i = start; i < end; i++)
{
var player = Utilities.GetPlayerFromIndex((int)pending[i]);
if (player == null || !player.IsValid) continue;
ForceFullUpdate(player, toRestore, networkGameServer);
}
if (toRestore.Count > 0)
jRandomSkills.Instance.AddTickTimer(3, () =>
{
foreach (var item in toRestore)
{
var target = Utilities.GetPlayerFromIndex((int)item.PlayerIndex);
if (target == null || !target.IsValid) continue;
var targetPawn = target.PlayerPawn?.Value;
if (targetPawn == null || !targetPawn.IsValid || targetPawn.AbsOrigin == null) continue;
targetPawn.Look(item.LastAngle);
}
});
Server.NextFrame(() => ForceFullUpdateChunk(pending, end, clientsPerFrame));
}
public static bool SetHealth(CCSPlayerPawn? pawn, int newHealth, int? maxHealth = null) public static bool SetHealth(CCSPlayerPawn? pawn, int newHealth, int? maxHealth = null)
{ {
if (pawn == null || !pawn.IsValid) if (pawn == null || !pawn.IsValid)

View file

@ -405,6 +405,32 @@
"MaxPerServer": -1, "MaxPerServer": -1,
"Rarity": "Common" "Rarity": "Common"
}, },
{
"Bounces": 3,
"SegmentDistance": 1200.0,
"DamageMultiplier": 0.5,
"FallbackDamage": 25.0,
"RespectArmor": true,
"DamageFalloff": 0.75,
"MaxImpactsPerTick": 2,
"ShowTracer": true,
"TracerWidth": 0.5,
"TracerSpeed": 2600.0,
"TracerLength": 220.0,
"MaxActiveTracers": 12,
"NormalProbeOffset": 6.0,
"NeedsTeammates": false,
"DisableOnFreezeTime": false,
"OnlyTeam": 0,
"Color": "#ffd75e",
"Active": true,
"Name": "Ricochet",
"HudDuration": null,
"DescriptionHudDuration": null,
"RequiredPermission": "",
"MaxPerServer": 2,
"Rarity": "Rare"
},
{ {
"MinMoney": 5000, "MinMoney": 5000,
"MaxMoney": 15000, "MaxMoney": 15000,
@ -1102,6 +1128,19 @@
"MaxPerServer": 1, "MaxPerServer": 1,
"Rarity": "Common" "Rarity": "Common"
}, },
{
"NeedsTeammates": true,
"DisableOnFreezeTime": false,
"OnlyTeam": 0,
"Color": "#c9a227",
"Active": true,
"Name": "Inheritance",
"HudDuration": null,
"DescriptionHudDuration": null,
"RequiredPermission": "",
"MaxPerServer": 2,
"Rarity": "Rare"
},
{ {
"NeedsTeammates": false, "NeedsTeammates": false,
"DisableOnFreezeTime": false, "DisableOnFreezeTime": false,
@ -1286,6 +1325,26 @@
"MaxPerServer": -1, "MaxPerServer": -1,
"Rarity": "Common" "Rarity": "Common"
}, },
{
"Cooldown": 10.0,
"MaxDistance": 1500.0,
"MinDistance": 150.0,
"StopDistance": 90.0,
"PullSpeed": 850.0,
"MaxPullSeconds": 3.0,
"RopeWidth": 0.8,
"NeedsTeammates": false,
"DisableOnFreezeTime": true,
"OnlyTeam": 0,
"Color": "#38e0c4",
"Active": true,
"Name": "Grapple",
"HudDuration": null,
"DescriptionHudDuration": null,
"RequiredPermission": "",
"MaxPerServer": -1,
"Rarity": "Rare"
},
{ {
"Cooldown": 30.0, "Cooldown": 30.0,
"Duration": 2.0, "Duration": 2.0,
@ -1800,6 +1859,19 @@
"MaxPerServer": -1, "MaxPerServer": -1,
"Rarity": "Common" "Rarity": "Common"
}, },
{
"NeedsTeammates": false,
"DisableOnFreezeTime": false,
"OnlyTeam": 0,
"Color": "#5fd98a",
"Active": true,
"Name": "Chameleon",
"HudDuration": null,
"DescriptionHudDuration": null,
"RequiredPermission": "",
"MaxPerServer": 2,
"Rarity": "Rare"
},
{ {
"ChanceFrom": 0.2, "ChanceFrom": 0.2,
"ChanceTo": 0.4, "ChanceTo": 0.4,

View file

@ -1,4 +1,4 @@
{ {
"none": "Keine", "none": "Keine",
"none_desc": "Du hast keine Fertigkeit", "none_desc": "Du hast keine Fertigkeit",
@ -77,6 +77,11 @@
"catapult_desc": "Du hast eine zufällige Chance, einen Gegner nach oben zu schleudern", "catapult_desc": "Du hast eine zufällige Chance, einen Gegner nach oben zu schleudern",
"catapult_desc2": "Deine Chance, einen Gegner bei einem Treffer zu schleudern, beträgt: {0} %", "catapult_desc2": "Deine Chance, einen Gegner bei einem Treffer zu schleudern, beträgt: {0} %",
"chameleon": "Chamäleon",
"chameleon_desc": "Der erste Spieler, den du tötest, gibt dir seine Fähigkeit",
"chameleon_copied_info": "Fähigkeit kopiert: {0}",
"chameleon_wrong_team_info": "'{0}' hatte eine Fähigkeit, die dein Team nicht nutzen kann.",
"chicken": "Huhn", "chicken": "Huhn",
"chicken_desc": "Du erhältst ein Huhn-Modell + 10 % schnellere Bewegung – 50 HP", "chicken_desc": "Du erhältst ein Huhn-Modell + 10 % schnellere Bewegung – 50 HP",
@ -220,6 +225,11 @@
"godmode_off": "Unsterblichkeit deaktiviert", "godmode_off": "Unsterblichkeit deaktiviert",
"godmode_on": "Unsterblichkeit aktiviert", "godmode_on": "Unsterblichkeit aktiviert",
"grapple": "Enterhaken",
"grapple_desc": "Drücke [css_useSkill], um einen Haken auf den anvisierten Punkt zu schießen und dich dorthin zu ziehen",
"grapple_no_anchor_info": "Keine Oberfläche zum Einhaken.",
"grapple_pulling_info": "ZUG",
"grenadier": "Grenadier", "grenadier": "Grenadier",
"grenadier_desc": "Du hast unendlich viele Granaten", "grenadier_desc": "Du hast unendlich viele Granaten",
@ -259,6 +269,11 @@
"infiniteammo": "Unendliche Munition", "infiniteammo": "Unendliche Munition",
"infiniteammo_desc": "Du erhältst unendliche Munition für alle deine Waffen", "infiniteammo_desc": "Du erhältst unendliche Munition für alle deine Waffen",
"inheritance": "Erbe",
"inheritance_desc": "Wenn ein Teamkollege stirbt, kannst du seine Fähigkeit übernehmen",
"inheritance_select_info": "Wähle die Fähigkeit, die du erbst:",
"inheritance_player_info": "Du hast die Fähigkeit von '{0}' geerbt.",
"jackal": "Spürhund", "jackal": "Spürhund",
"jackal_desc": "Jeder Gegner hinterlässt eine Spur", "jackal_desc": "Jeder Gegner hinterlässt eine Spur",
@ -448,6 +463,9 @@
"richboy": "Rich Boy", "richboy": "Rich Boy",
"richboy_desc": "Du erhältst zu Beginn der Runde einen zufälligen Geldbetrag", "richboy_desc": "Du erhältst zu Beginn der Runde einen zufälligen Geldbetrag",
"ricochet": "Querschläger",
"ricochet_desc": "Deine Kugeln prallen von Wänden ab und können Gegner weiterhin treffen",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Wenn du einem Gegner Schaden zufügst, stiehlst du ihm sein Geld", "robinhood_desc": "Wenn du einem Gegner Schaden zufügst, stiehlst du ihm sein Geld",

View file

@ -1,4 +1,4 @@
{ {
"none": "None", "none": "None",
"none_desc": "You have no skill", "none_desc": "You have no skill",
@ -77,6 +77,11 @@
"catapult_desc": "You have a random chance to launch an enemy upwards", "catapult_desc": "You have a random chance to launch an enemy upwards",
"catapult_desc2": "Your chance to launch an enemy on hit is: {0}%", "catapult_desc2": "Your chance to launch an enemy on hit is: {0}%",
"chameleon": "Chameleon",
"chameleon_desc": "The first player you kill gives you their skill",
"chameleon_copied_info": "You copied the skill: {0}",
"chameleon_wrong_team_info": "'{0}' had a skill your team cannot use.",
"chicken": "Chicken", "chicken": "Chicken",
"chicken_desc": "You get a chicken model + 10% faster movement - 50 HP", "chicken_desc": "You get a chicken model + 10% faster movement - 50 HP",
@ -213,6 +218,11 @@
"godmode_off": "Immortality disabled", "godmode_off": "Immortality disabled",
"godmode_on": "Immortality enabled", "godmode_on": "Immortality enabled",
"grapple": "Grapple Hook",
"grapple_desc": "Press [css_useSkill] to fire a hook at the point you are aiming at and pull yourself there",
"grapple_no_anchor_info": "No surface to hook onto.",
"grapple_pulling_info": "PULLING",
"grenadier": "Grenadier", "grenadier": "Grenadier",
"grenadier_desc": "You have infinite hegrenade", "grenadier_desc": "You have infinite hegrenade",
@ -252,6 +262,11 @@
"infiniteammo": "Infinite Ammo", "infiniteammo": "Infinite Ammo",
"infiniteammo_desc": "You receive infinite ammo for all your weapons", "infiniteammo_desc": "You receive infinite ammo for all your weapons",
"inheritance": "Inheritance",
"inheritance_desc": "When a teammate dies you can take over their skill",
"inheritance_select_info": "Choose the skill you inherit:",
"inheritance_player_info": "You inherited the skill of '{0}'.",
"jackal": "Tracker", "jackal": "Tracker",
"jackal_desc": "Every opponent leaves a trail behind them", "jackal_desc": "Every opponent leaves a trail behind them",
@ -448,6 +463,9 @@
"richboy": "Rich Boy", "richboy": "Rich Boy",
"richboy_desc": "You receive a random amount of money at the start of the round", "richboy_desc": "You receive a random amount of money at the start of the round",
"ricochet": "Ricochet",
"ricochet_desc": "Your bullets bounce off walls and can still hit enemies",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Dealing damage to an enemy steals their money", "robinhood_desc": "Dealing damage to an enemy steals their money",

View file

@ -1,4 +1,4 @@
{ {
"none": "Aucune", "none": "Aucune",
"none_desc": "Vous n’avez aucune compétence", "none_desc": "Vous n’avez aucune compétence",
@ -77,6 +77,11 @@
"catapult_desc": "Vous avez une chance aléatoire de projeter un ennemi en l’air", "catapult_desc": "Vous avez une chance aléatoire de projeter un ennemi en l’air",
"catapult_desc2": "Votre chance de projeter un ennemi à l’impact est : {0}%", "catapult_desc2": "Votre chance de projeter un ennemi à l’impact est : {0}%",
"chameleon": "Caméléon",
"chameleon_desc": "Le premier joueur que vous tuez vous donne sa compétence",
"chameleon_copied_info": "Compétence copiée : {0}",
"chameleon_wrong_team_info": "'{0}' avait une compétence que votre équipe ne peut pas utiliser.",
"chicken": "Poulet", "chicken": "Poulet",
"chicken_desc": "Vous obtenez un modèle de poulet + 10% de vitesse de déplacement en plus - 50 PV", "chicken_desc": "Vous obtenez un modèle de poulet + 10% de vitesse de déplacement en plus - 50 PV",
@ -220,6 +225,11 @@
"godmode_off": "Immortalité désactivée", "godmode_off": "Immortalité désactivée",
"godmode_on": "Immortalité activée", "godmode_on": "Immortalité activée",
"grapple": "Grappin",
"grapple_desc": "Appuyez sur [css_useSkill] pour lancer un grappin sur le point visé et vous y propulser",
"grapple_no_anchor_info": "Aucune surface pour accrocher le grappin.",
"grapple_pulling_info": "TRACTION",
"grenadier": "Grenadier", "grenadier": "Grenadier",
"grenadier_desc": "Tu as des grenades HE infinies", "grenadier_desc": "Tu as des grenades HE infinies",
@ -259,6 +269,11 @@
"infiniteammo": "Munitions Infinies", "infiniteammo": "Munitions Infinies",
"infiniteammo_desc": "Vous recevez des munitions infinies pour toutes vos armes", "infiniteammo_desc": "Vous recevez des munitions infinies pour toutes vos armes",
"inheritance": "Héritage",
"inheritance_desc": "Quand un coéquipier meurt, vous pouvez reprendre sa compétence",
"inheritance_select_info": "Choisissez la compétence à hériter :",
"inheritance_player_info": "Vous avez hérité de la compétence de '{0}'.",
"jackal": "Traqueur", "jackal": "Traqueur",
"jackal_desc": "Chaque adversaire laisse une trace derrière lui", "jackal_desc": "Chaque adversaire laisse une trace derrière lui",
@ -448,6 +463,9 @@
"richboy": "Gosse de Riche", "richboy": "Gosse de Riche",
"richboy_desc": "Vous recevez une somme d’argent aléatoire au début du round", "richboy_desc": "Vous recevez une somme d’argent aléatoire au début du round",
"ricochet": "Ricochet",
"ricochet_desc": "Vos balles rebondissent sur les murs et peuvent encore toucher les ennemis",
"robinhood": "Robin des Bois", "robinhood": "Robin des Bois",
"robinhood_desc": "Infliger des dégâts à un ennemi lui vole de l’argent", "robinhood_desc": "Infliger des dégâts à un ennemi lui vole de l’argent",

View file

@ -1,4 +1,4 @@
{ {
"none": "Brak", "none": "Brak",
"none_desc": "Nie posiadasz żadnej supermocy", "none_desc": "Nie posiadasz żadnej supermocy",
@ -77,6 +77,11 @@
"catapult_desc": "Masz losową szanse na podrzucenie wroga", "catapult_desc": "Masz losową szanse na podrzucenie wroga",
"catapult_desc2": "Twoje szanse na podrzucenie wroga po trafieniu to: {0}%", "catapult_desc2": "Twoje szanse na podrzucenie wroga po trafieniu to: {0}%",
"chameleon": "Kameleon",
"chameleon_desc": "Pierwszy zabity gracz oddaje ci swoją umiejętność",
"chameleon_copied_info": "Skopiowano umiejętność: {0}",
"chameleon_wrong_team_info": "'{0}' miał umiejętność, której twoja drużyna nie może użyć.",
"chicken": "Kurczak", "chicken": "Kurczak",
"chicken_desc": "Otrzymujesz model kurczaka + jesteś o 10% szybszy - 50hp", "chicken_desc": "Otrzymujesz model kurczaka + jesteś o 10% szybszy - 50hp",
@ -220,6 +225,11 @@
"godmode_off": "Nieśmiertelność wyłączona", "godmode_off": "Nieśmiertelność wyłączona",
"godmode_on": "Nieśmiertelność włączona", "godmode_on": "Nieśmiertelność włączona",
"grapple": "Hak",
"grapple_desc": "Naciśnij [css_useSkill], aby wystrzelić hak w celowany punkt i przyciągnąć się do niego",
"grapple_no_anchor_info": "Brak powierzchni do zaczepienia haka.",
"grapple_pulling_info": "PRZYCIĄGANIE",
"grenadier": "Granatnik", "grenadier": "Granatnik",
"grenadier_desc": "Masz nieskończone granaty odłamkowe", "grenadier_desc": "Masz nieskończone granaty odłamkowe",
@ -259,6 +269,11 @@
"infiniteammo": "Nieskończone Ammo", "infiniteammo": "Nieskończone Ammo",
"infiniteammo_desc": "Otrzymujesz nieskończoną ilość amunicji do wszystkich broni", "infiniteammo_desc": "Otrzymujesz nieskończoną ilość amunicji do wszystkich broni",
"inheritance": "Spadek",
"inheritance_desc": "Gdy członek drużyny ginie, możesz przejąć jego umiejętność",
"inheritance_select_info": "Wybierz dziedziczoną umiejętność:",
"inheritance_player_info": "Odziedziczyłeś umiejętność gracza '{0}'.",
"jackal": "Stópkarz", "jackal": "Stópkarz",
"jackal_desc": "Każdy przeciwnik pozostawia za sobą ślad", "jackal_desc": "Każdy przeciwnik pozostawia za sobą ślad",
@ -448,6 +463,9 @@
"richboy": "Bogacz", "richboy": "Bogacz",
"richboy_desc": "Na początku rundy otrzymujesz losową kwotę gotówki", "richboy_desc": "Na początku rundy otrzymujesz losową kwotę gotówki",
"ricochet": "Rykoszet",
"ricochet_desc": "Twoje pociski odbijają się od ścian i nadal mogą trafić przeciwników",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Zadanie obrażeń przeciwnikowi powoduje kradzież jego pieniędzy", "robinhood_desc": "Zadanie obrażeń przeciwnikowi powoduje kradzież jego pieniędzy",

View file

@ -1,4 +1,4 @@
{ {
"none": "Nenhuma", "none": "Nenhuma",
"none_desc": "Você não tem nenhuma habilidade", "none_desc": "Você não tem nenhuma habilidade",
@ -77,6 +77,11 @@
"catapult_desc": "Você tem uma chance aleatória de lançar um inimigo para cima", "catapult_desc": "Você tem uma chance aleatória de lançar um inimigo para cima",
"catapult_desc2": "Sua chance de lançar um inimigo ao acertá-lo é: {0}%", "catapult_desc2": "Sua chance de lançar um inimigo ao acertá-lo é: {0}%",
"chameleon": "Camaleão",
"chameleon_desc": "O primeiro jogador que você matar lhe dá a habilidade dele",
"chameleon_copied_info": "Habilidade copiada: {0}",
"chameleon_wrong_team_info": "'{0}' tinha uma habilidade que sua equipe não pode usar.",
"chicken": "Galinha", "chicken": "Galinha",
"chicken_desc": "Você é uma galinha com +10% de movimento mais rápido e -50 HP", "chicken_desc": "Você é uma galinha com +10% de movimento mais rápido e -50 HP",
@ -220,6 +225,11 @@
"godmode_off": "Imortalidade desativada", "godmode_off": "Imortalidade desativada",
"godmode_on": "Imortalidade ativada", "godmode_on": "Imortalidade ativada",
"grapple": "Gancho",
"grapple_desc": "Pressione [css_useSkill] para lançar um gancho no ponto mirado e se puxar até lá",
"grapple_no_anchor_info": "Nenhuma superfície para prender o gancho.",
"grapple_pulling_info": "PUXANDO",
"grenadier": "Bomberman", "grenadier": "Bomberman",
"grenadier_desc": "Você tem HEs infinitas", "grenadier_desc": "Você tem HEs infinitas",
@ -259,6 +269,11 @@
"infiniteammo": "Munição Infinita", "infiniteammo": "Munição Infinita",
"infiniteammo_desc": "Você recebe munição infinita para todas as suas armas", "infiniteammo_desc": "Você recebe munição infinita para todas as suas armas",
"inheritance": "Herança",
"inheritance_desc": "Quando um companheiro de equipe morre, você pode assumir a habilidade dele",
"inheritance_select_info": "Escolha a habilidade que você herda:",
"inheritance_player_info": "Você herdou a habilidade de '{0}'.",
"jackal": "Lesma", "jackal": "Lesma",
"jackal_desc": "Cada adversário deixa um rastro atrás de si", "jackal_desc": "Cada adversário deixa um rastro atrás de si",
@ -448,6 +463,9 @@
"richboy": "Filhinho de Papai", "richboy": "Filhinho de Papai",
"richboy_desc": "Você recebe uma quantidade aleatória de dinheiro no início da rodada", "richboy_desc": "Você recebe uma quantidade aleatória de dinheiro no início da rodada",
"ricochet": "Ricochete",
"ricochet_desc": "Suas balas ricocheteiam nas paredes e ainda podem acertar inimigos",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Atirar em um inimigo rouba seu dinheiro", "robinhood_desc": "Atirar em um inimigo rouba seu dinheiro",

View file

@ -1,4 +1,4 @@
{ {
"none": "Нет навыка", "none": "Нет навыка",
"none_desc": "У вас нет навыка", "none_desc": "У вас нет навыка",
@ -77,6 +77,11 @@
"catapult_desc": "Есть шанс подбросить врага вверх при попадании", "catapult_desc": "Есть шанс подбросить врага вверх при попадании",
"catapult_desc2": "Ваш шанс подбросить врага при попадании: {0}%", "catapult_desc2": "Ваш шанс подбросить врага при попадании: {0}%",
"chameleon": "Хамелеон",
"chameleon_desc": "Первый убитый вами игрок отдаёт свой навык",
"chameleon_copied_info": "Навык скопирован: {0}",
"chameleon_wrong_team_info": "У '{0}' был навык, недоступный вашей команде.",
"chicken": "Курица", "chicken": "Курица",
"chicken_desc": "Вы получаете модель курицы + 10% к скорости передвижения - 50 HP", "chicken_desc": "Вы получаете модель курицы + 10% к скорости передвижения - 50 HP",
@ -220,6 +225,11 @@
"godmode_off": "Неуязвимость отключена", "godmode_off": "Неуязвимость отключена",
"godmode_on": "Неуязвимость включена", "godmode_on": "Неуязвимость включена",
"grapple": "Крюк",
"grapple_desc": "Нажмите [css_useSkill], чтобы выстрелить крюком в точку прицеливания и притянуться к ней",
"grapple_no_anchor_info": "Нет поверхности для зацепа.",
"grapple_pulling_info": "ПРИТЯГИВАНИЕ",
"grenadier": "Гренадёр", "grenadier": "Гренадёр",
"grenadier_desc": "У вас бесконечные осколочные гранаты", "grenadier_desc": "У вас бесконечные осколочные гранаты",
@ -259,6 +269,11 @@
"infiniteammo": "Бесконечные патроны", "infiniteammo": "Бесконечные патроны",
"infiniteammo_desc": "Вы получаете бесконечные патроны для всего оружия", "infiniteammo_desc": "Вы получаете бесконечные патроны для всего оружия",
"inheritance": "Наследие",
"inheritance_desc": "Когда союзник погибает, вы можете перенять его навык",
"inheritance_select_info": "Выберите наследуемый навык:",
"inheritance_player_info": "Вы унаследовали навык игрока '{0}'.",
"jackal": "Трекер", "jackal": "Трекер",
"jackal_desc": "Каждый противник оставляет за собой след", "jackal_desc": "Каждый противник оставляет за собой след",
@ -448,6 +463,9 @@
"richboy": "Богач", "richboy": "Богач",
"richboy_desc": "Вы получаете случайную сумму денег в начале раунда", "richboy_desc": "Вы получаете случайную сумму денег в начале раунда",
"ricochet": "Рикошет",
"ricochet_desc": "Ваши пули отскакивают от стен и могут поразить врагов",
"robinhood": "Робин Гуд", "robinhood": "Робин Гуд",
"robinhood_desc": "Нанесение урона врагу крадёт его деньги", "robinhood_desc": "Нанесение урона врагу крадёт его деньги",

View file

@ -1,4 +1,4 @@
{ {
"none": "Yok", "none": "Yok",
"none_desc": "Hiçbir yeteneğin yok", "none_desc": "Hiçbir yeteneğin yok",
@ -6,79 +6,84 @@
"aimbot_desc": "Vurduğunda kafadan (HS) sayılır", "aimbot_desc": "Vurduğunda kafadan (HS) sayılır",
"aimlock": "Kitlenme", "aimlock": "Kitlenme",
"aimlock_desc": "En yakın düşmana nişan almak için [css_useSkill] tuşuna basın", "aimlock_desc": "[css_useSkill] tuşuna basarak en yakın düşmana kitlen",
"anomaly": "Zaman Büken", "anomaly": "Zaman Büken",
"anomaly_desc": "[css_useSkill] tuşuna basarak zamanı birkaç saniye geriye alırsın", "anomaly_desc": "[css_useSkill] tuşuna basarak zamanı birkaç saniye geri al",
"antyflash": "Anti-Flash", "antyflash": "Anti-Flash",
"antyflash_desc": "Flaşa kör olmazsın ve flaşların 7 saniye sürer", "antyflash_desc": "Kör olmazsın ve flaşın 7 saniye sürer",
"antyhead": "Beton Kafa", "antyhead": "Beton Kafa",
"antyhead_desc": "Kafadan hasar almazsın", "antyhead_desc": "Kafadan hasar almazsın",
"areareaper": "Mekan Kapatan", "areareaper": "Mekan Kapatan",
"areareaper_desc": "Haritadaki bir bomba alanını tamamen devre dışı bırakabilirsin", "areareaper_desc": "Haritadaki bir bomba alanını devre dışı bırak",
"areareaper_incorrect_site": "Böyle bir bomba alanı yok uydurma", "areareaper_incorrect_site": "Böyle bir bomba alanı yok uydurma",
"areareaper_no_site": "Haritada bomba alanı bulunamadı", "areareaper_no_site": "Haritada bomba alanı bulunamadı",
"areareaper_select_info": "Kapatılacak bomba alanını seç:", "areareaper_select_info": "Alan seçin:",
"areareaper_site_disabled": "{0} Bölgesi kapandı - artık buraya bomba kurulamaz!", "areareaper_site_disabled": "{0} Bölgesi kapandı - artık buraya C4 kurulamaz!",
"areareaper_used_info": "Yeteneğini zaten kullandın, açgözlülük yapma", "areareaper_used_info": "Yeteneğini zaten kullandın!",
"areareaper_teammates_info": "{0} Bölgesi bomba kurmaya kapatıldı.", "areareaper_teammates_info": "{0} Bölgesi bomba kurmaya kapatıldı.",
"areareaper_bombsite_disabled": "Bu bomba alanı kullanıma kapatıldı!", "areareaper_bombsite_disabled": "Bu bomba alanı kullanıma kapatıldı.",
"armored": "Zırhlı", "armored": "Zırhlı",
"armored_desc": "Rastgele hasar alma çarpanına sahip olursun", "armored_desc": "Rastgele hasar alma çarpanın olur",
"armored_desc2": "Hasar alma: {0}x", "armored_desc2": "Hasar alma: {0}x",
"assassin": "Suikastçı", "assassin": "Suikastçı",
"assassin_desc": "Düşmanlara arkadan daha fazla hasar verirsin", "assassin_desc": "Düşmana arkadan daha fazla hasar verirsin",
"astronaut": "Astronot", "astronaut": "Astronot",
"astronaut_desc": "Rastgele bir yerçekimi değerine sahip olursun", "astronaut_desc": "Rastgele bir yerçekimine sahipsin",
"astronaut_desc2": "Yerçekimin: {0}x", "astronaut_desc2": "Yerçekimin: {0}x",
"moneyswap": "Vergi Memuru", "moneyswap": "Vergi Memuru",
"moneyswap_desc": "Bir düşmanla paranı takasla", "moneyswap_desc": "Bir düşmanla paranı takasla",
"moneyswap_enemy_info": "Maliye kapına dayandı", "moneyswap_enemy_info": "Maliye kapına dayandı.",
"moneyswap_player_info": "'{0}' isimli oyuncuyla paraları takas ettin", "moneyswap_player_info": "'{0}' ile paranı takasladın.",
"moneyswap_select_info": "Para takasla biriyle:", "moneyswap_select_info": "Birini seçin:",
"baseball": "Beyzbolcu", "baseball": "Beyzbolcu",
"baseball_desc": "Yanıltıcı bomban (decoy) duvarlardan seker ve çarptığı düşmanı öldürür", "baseball_desc": "Yanıltıcı bomban duvarlardan seker ve çarptığı düşmanı öldürür",
"behind": "Baş Döndüren", "behind": "Baş Döndüren",
"behind_desc": "Vurduğunda düşmanı 180 derece döndürme şansın olur", "behind_desc": "Vurduğunda düşmanı 180 derece döndürme şansın olur",
"behind_desc2": "Baş döndürme şansın: %{0}", "behind_desc2": "Baş döndürme şansın: %{0}",
"berserker": "Berserker", "berserker": "Berserker",
"berserker_desc": "Canın azaldıkça hasarın artar ve daha hızlanırsın", "berserker_desc": "Canın azaldıkça hasarın ve hızın artar",
"blademaster": "Kılıç Ustası", "blademaster": "Kılıç Ustası",
"blademaster_desc": "Bıçak tutarken mermileri sektirme şansın artar", "blademaster_desc": "Bıçak tutarken mermileri savuşturursun",
"blastshot": "Patlama Atışı", "blastshot": "Patlama Atışı",
"blastshot_desc": "MP5 ile Sağ Tık'a basarak El bombası fırlat", "blastshot_desc": "MP5 ile sağ tıklayarak el bombası fırlat",
"bunnyhop": "Tavşan", "bunnyhop": "Tavşan",
"bunnyhop_desc": "Otomatik \"BunnyHop\" yaparsın", "bunnyhop_desc": "Otomatik BunnyHop yaparsın",
"c4camouflage": "C4 Kamuflaj", "c4camouflage": "C4 Kamuflaj",
"c4camouflage_desc": "Elinde C4 varken tamamen görünmez olursun", "c4camouflage_desc": "Elinde C4 varken görünmezsin",
"carefulbullets": "Dikkatli Mermiler", "carefulbullets": "Dikkatli Mermiler",
"carefulbullets_desc": "Düşman mermi kaçırırsa hasar alır", "carefulbullets_desc": "Düşman mermi kaçırırsa hasar alır",
"carefulbullets_enemy_info": "Mermi kaçırmak canını yakacak", "carefulbullets_enemy_info": "Mermi kaçırman can yakar.",
"carefulbullets_disable_info": "Artık mermi kaçırmak can yakmayacak.", "carefulbullets_disable_info": "Artık mermi kaçırmak can yakmayacak.",
"carefulbullets_player_info": "'{0}' artık mermi sıkarken iki kere düşünecek", "carefulbullets_player_info": "'{0}' mermi sıkarken iki kere düşünecek.",
"carefulbullets_select_info": "İsabetsiz atışların hasar vereceği oyuncu:", "carefulbullets_select_info": "Birini seçin:",
"catapult": "Mancınık", "catapult": "Mancınık",
"catapult_desc": "Vurduğun rakibi uzaya (yukarı doğru) fırlatma şansın var", "catapult_desc": "Vurduğun rakibi uzaya (yukarı doğru) fırlatma şansın var",
"catapult_desc2": "Fırlatma şansın: %{0}", "catapult_desc2": "Fırlatma şansın: %{0}",
"chameleon": "Bukalemun",
"chameleon_desc": "Öldürdüğün ilk oyuncunun yeteneği sana geçer",
"chameleon_copied_info": "Yeteneği kopyaladın: {0}",
"chameleon_wrong_team_info": "'{0}' takımının kullanamayacağı bir yeteneğe sahipti.",
"chicken": "Tavuk", "chicken": "Tavuk",
"chicken_desc": "Tavuk modeli ve %10 daha hızlısın fakat 50 HP", "chicken_desc": "Tavuk modeli, %10 daha hızlı ama 50 HP",
"chillout": "Ağırdan Al", "chillout": "Ağırdan Al",
"chillout_desc": "Bombayı kurmak çok daha uzun sürer", "chillout_desc": "Bombayı kurmak çok daha uzun sürer",
@ -87,28 +92,28 @@
"cutter_desc": "Bıçakla tek atarsın", "cutter_desc": "Bıçakla tek atarsın",
"cypher": "Gözcü", "cypher": "Gözcü",
"cypher_desc": "Kamera oluşturmak/geçmek için [css_useSkill] tuşuna bas", "cypher_desc": "[css_useSkill] tuşuna basarak kamera kur ve kameraya geç",
"cypher_nospace": "Kamerayı duvara dik yerleştir", "cypher_nospace": "Kamerayı duvara dik yerleştir",
"darkness": "Karanlık", "darkness": "Karanlık",
"darkness_desc": "Bir düşmanın ekranını karart", "darkness_desc": "Düşmanın ekranını karart",
"darkness_enemy_info": "Işıklar sönsün", "darkness_enemy_info": "Işıklar sönsün.",
"darkness_disable_info": "Işıklar geldi.", "darkness_disable_info": "Işıklar geldi.",
"darkness_player_info": "'{0}' isimli oyuncunun dünyasını kararttın", "darkness_player_info": "'{0}' ışıkları söndü.",
"darkness_select_info": "Karanlık bir oyuncuyu seç:", "darkness_select_info": "Birini seçin:",
"deactivator": "Silgi", "deactivator": "Silgi",
"deactivator_desc": "Bir düşmanın yeteneğini sil", "deactivator_desc": "Bir düşmanın yeteneğini sil",
"deactivator_enemy_info": "Yeteneğin silindi", "deactivator_enemy_info": "Yeteneğin silindi.",
"deactivator_player_info": "'{0}' isimli oyuncunun yeteneği silindi", "deactivator_player_info": "'{0}' isimli oyuncunun yeteneği silindi.",
"deactivator_select_info": "Yetenek silmek için oyuncu seç:", "deactivator_select_info": "Birini seçin:",
"deaf": "Sağır", "deaf": "Sağır",
"deaf_desc": "Bir düşmanın kulağını kapat ve sesleri duymaz hale getir", "deaf_desc": "Bir düşmanı sağır et",
"deaf_enemy_info": "Kulaklıkların tıkandı", "deaf_enemy_info": "Kulaklıkların tıkandı.",
"deaf_disable_info": "Kulakların açıldı.", "deaf_disable_info": "Kulakların açıldı.",
"deaf_player_info": "'{0}' isimli oyuncu için sesler kapatıldı.", "deaf_player_info": "'{0}' sesleri kapatıldı.",
"deaf_select_info": "Sağır bir oyuncuyu seç:", "deaf_select_info": "Birini seçin:",
"disarmament": "Silahsızlandırma", "disarmament": "Silahsızlandırma",
"disarmament_desc": "Vurduğunda rakibin elindeki silahı yere düşürme şansın olur", "disarmament_desc": "Vurduğunda rakibin elindeki silahı yere düşürme şansın olur",
@ -121,15 +126,15 @@
"dash_desc": "Atılmak için ikinci kez zıpla", "dash_desc": "Atılmak için ikinci kez zıpla",
"dracula": "Drakula", "dracula": "Drakula",
"dracula_desc": "Rakiplere verdiğin hasarın belirli bir yüzdesi kadar can alırsın", "dracula_desc": "Rakibe verdiğin hasarın birazı kadar can alırsın",
"duplicator": "Kopyacı", "duplicator": "Kopyacı",
"duplicator_desc": "Yeteneğini kopyalamak için bir oyuncu seç", "duplicator_desc": "Bir düşmanın yeteneğini kopyala",
"duplicator_player_info": "'{0}' isimli oyuncunun yeteneği kopyalandı.", "duplicator_player_info": "'{0}' yeteneği kopyalandı.",
"duplicator_select_info": "Yeteneği kopyalanacak oyuncu:", "duplicator_select_info": "Birini seçin:",
"dwarf": "Cüce", "dwarf": "Cüce",
"dwarf_desc": "Raund başında rastgele karakter boyutu", "dwarf_desc": "Rastgele karakter boyutu",
"dwarf_desc2": "Boyutun: {0}x", "dwarf_desc2": "Boyutun: {0}x",
"enemyspawn": "Base Baskını", "enemyspawn": "Base Baskını",
@ -137,16 +142,16 @@
"expensiveammo": "Pahalı Mermi", "expensiveammo": "Pahalı Mermi",
"expensiveammo_desc": "Seçtiğin rakip her ateş ettiğinde para kaybeder", "expensiveammo_desc": "Seçtiğin rakip her ateş ettiğinde para kaybeder",
"expensiveammo_disable_info": "Mermilerin yeniden bedava.", "expensiveammo_disable_info": "Mermi yeniden bedava.",
"expensiveammo_enemy_info": "Artık her atışın sana {0}$ mal oluyor.", "expensiveammo_enemy_info": "Her atışın sana {0}$ mal oluyor.",
"expensiveammo_player_info": "'{0}' artık her mermisinin parasını ödüyor.", "expensiveammo_player_info": "'{0}' her mermisinin parasını ödüyor.",
"expensiveammo_select_info": "Mermisi pahalanacak oyuncu:", "expensiveammo_select_info": "Birini seçin:",
"explodingbarrel": "Patlayan Varil", "explodingbarrel": "Patlayan Varil",
"explodingbarrel_desc": "[css_useSkill] ile vurulunca patlayan bir varil koyarsın", "explodingbarrel_desc": "[css_useSkill] tuşuna basarak vurulunca patlayan varil koy",
"explosiveshot": "Patlayıcı Mermi", "explosiveshot": "Patlayıcı Mermi",
"explosiveshot_desc": "Ateş ederken rastgele mermilerin patlayabilir", "explosiveshot_desc": "Ateş ederken mermin patlayabilir",
"explosiveshot_desc2": "Patlayan mermi şansı: %{0}", "explosiveshot_desc2": "Patlayan mermi şansı: %{0}",
"falconeye": "Şahin Gözü", "falconeye": "Şahin Gözü",
@ -156,31 +161,31 @@
"fastreload_desc": "[css_useSkill] tuşuna basarak şarjörünü hızlıca değiştir", "fastreload_desc": "[css_useSkill] tuşuna basarak şarjörünü hızlıca değiştir",
"firerain": "Ateş Yağmuru", "firerain": "Ateş Yağmuru",
"firerain_desc": "Molotof yağdırmak için bir decoy at", "firerain_desc": "Molotof yağdırmak için yanıltıcı bomba at",
"flash": "Flash", "flash": "Flash",
"flash_desc": "Raund başında rastgele oyuncu hızı", "flash_desc": "Rastgele oyuncu hızı",
"flash_desc2": "Hızın: {0}x", "flash_desc2": "Hızın: {0}x",
"flashlight": "El Feneri", "flashlight": "El Feneri",
"flashlight_desc": "[css_useSkill] tuşuna basarak El fenerini açarsın/kaparsın (Işığı düşmanları kör edebilir)", "flashlight_desc": "[css_useSkill] tuşuna basarak el fenerini aç veya kapat, ışığı düşmanı kör eder",
"fortnite": "Fortnite", "fortnite": "Fortnite",
"fortnite_desc": "[css_useSkill] tuşuna basarak barikat kur", "fortnite_desc": "[css_useSkill] tuşuna basarak barikat kur",
"fragilebomb": "Hassas C4", "fragilebomb": "Hassas C4",
"fragilebomb_desc": "Kurulu C4'e ateş etmek C4'ün canını azaltır ve C4 imha edilir.", "fragilebomb_desc": "Kurulu C4'e ateş etmek canını azaltır ve C4'ü imha eder",
"fragilebomb_bomb_health": "Bombanın canı", "fragilebomb_bomb_health": "Bombanın canı",
"friendlyfire": "Dost Şifası", "friendlyfire": "Dost Şifası",
"friendlyfire_desc": "Takım arkadaşlarına ateş etmek onları iyileştirir", "friendlyfire_desc": "Takım arkadaşına ateş etmek onu iyileştirir",
"frozendecoy": "Buz Kıran", "frozendecoy": "Buz Kıran",
"frozendecoy_desc": "Yanıltıcı bomba (decoy) yakındaki tüm oyuncuları dondurur", "frozendecoy_desc": "Yanıltıcı bomban yakındaki herkesi yavaşlatır",
"gambler": "Kumarbaz", "gambler": "Kumarbaz",
"gambler_desc": "Sunulan listeden bir yetenek seç.", "gambler_desc": "Sunulan listeden bir yetenek seç.",
"gambler_select_info": "Yeteneğini seç:", "gambler_select_info": "Birini seçin:",
"gambler_more": "#00FF00|${0} yenile", "gambler_more": "#00FF00|${0} yenile",
"gambler_no_money": "Yeterli para yok.", "gambler_no_money": "Yeterli para yok.",
@ -188,106 +193,116 @@
"ghost_desc": "Tamamen görünmezsin", "ghost_desc": "Tamamen görünmezsin",
"giant": "Dev", "giant": "Dev",
"giant_desc": "Seçtiğin bir rakibi büyütür", "giant_desc": "Seçtiğin rakibi büyüt",
"giant_desc2": "Seçtiğin bir rakibi {0}x büyütür", "giant_desc2": "Rakibin boyutu: {0}x",
"giant_disable_info": "Normal boyutuna geri döndün.", "giant_disable_info": "Normal boyutuna döndün.",
"giant_enemy_info": "{0}x boyutuna büyütüldün.", "giant_enemy_info": "{0}x boyutuna büyüdün.",
"giant_player_info": "'{0}' oyuncusunu {1}x büyüttün.", "giant_player_info": "'{0}' boyutunu {1}x büyüttün.",
"giant_select_info": "Büyütülecek oyuncu:", "giant_select_info": "Birini seçin:",
"glaz": "Glaz", "glaz": "Glaz",
"glaz_desc": "Sis bombalarının içini görebilirsin", "glaz_desc": "Sis bombasının içini görürsün",
"glitch": "Glitç", "glitch": "Glitç",
"glitch_desc": "Seçilen bir düşmanın radarını kapatır", "glitch_desc": "Bir düşmanın radarını kapat",
"glitch_enemy_info": "Radarın kapandı", "glitch_enemy_info": "Radarın kapandı.",
"glitch_disable_info": "Radarın açıldı", "glitch_disable_info": "Radarın açıldı.",
"glitch_player_info": "'{0}' isimli oyuncunun radarı devre dışı bırakıldı.", "glitch_player_info": "'{0}' radarı kapandı.",
"glitch_select_info": "Radarı kapatılacak oyuncuyu seç:", "glitch_select_info": "Birini seçin:",
"glue": "Yapıştırıcı", "glue": "Yapıştırıcı",
"glue_desc": "Bombaların duvarlara yapışır", "glue_desc": "Bomban duvara yapışır",
"godmode": "Ölümsüz", "godmode": "Ölümsüz",
"godmode_desc": "[css_useSkill] tuşuna basarak kısa süreli ölümsüz ol", "godmode_desc": "[css_useSkill] tuşuna basarak kısa süreli ölümsüz ol",
"godmode_off": "Ölümsüzlük kapandı", "godmode_off": "Ölümsüzlük kapandı",
"godmode_on": "Ölümsüzlük açıldı", "godmode_on": "Ölümsüzlük açıldı",
"grapple": "Kanca",
"grapple_desc": "[css_useSkill] tuşuna basarak baktığın yere kanca at",
"grapple_no_anchor_info": "Kanca atılacak yüzey yok",
"grapple_pulling_info": "ÇEKİLİYOR",
"grenadier": "Bombacı", "grenadier": "Bombacı",
"grenadier_desc": "Sınırsız el bombasına sahipsin", "grenadier_desc": "El bomban sınırsız",
"healingchicken": "Şifacı Tavuk", "healingchicken": "Şifacı Tavuk",
"healingchicken_desc": "Yakınındayken tavukların seni iyileştirir", "healingchicken_desc": "Yakınındayken tavuğun seni iyileştirir",
"healingsmoke": "Şifalı Sis", "healingsmoke": "Şifalı Sis",
"healingsmoke_desc": "Sis bombaların iyileştirir", "healingsmoke_desc": "Sis bomban iyileştirir",
"hermit": "Münzevi", "hermit": "Münzevi",
"hermit_desc": "Birini öldürünce mermin ve canın yenilenir", "hermit_desc": "Birini öldürünce mermin ve canın yenilenir",
"holyhandgrenade": "Kutsal El Bombası", "holyhandgrenade": "Kutsal El Bombası",
"holyhandgrenade_desc": "El bomban iki kat hasara ve menzile sahip", "holyhandgrenade_desc": "El bombanın hasarı ve menzili iki kat",
"homingnades": "Güdümlü Bomba", "homingnades": "Güdümlü Bomba",
"homingnades_desc": "Bombalarınız (sis hariç) düşmanlara yönelir", "homingnades_desc": "Bomban (sis hariç) yakın düşmana yönelir",
"hotbomb": "Sıcak C4", "hotbomb": "Sıcak C4",
"hotbomb_desc": "Yaşadığın sürece bombacının canı azalıyor", "hotbomb_desc": "Yaşadığın sürece bombacının canı azalır",
"hotbomb_hint": "Bomba çok sıcak!", "hotbomb_hint": "C4 ÇOK SICAK!",
"hotbomb_disable_info": "Bomba artık yakmıyor.", "hotbomb_disable_info": "C4 soğudu.",
"iana": "Hologram", "iana": "Hologram",
"iana_desc": "[css_useSkill] tuşuna basarak bir hologram oluştur", "iana_desc": "[css_useSkill] tuşuna basarak bir hologram oluştur",
"illiterate": "Cahiliye", "illiterate": "Cahiliye",
"illiterate_desc": "Yaşadığın sürece rakibin sohbeti (chat) veya oyun yazılarını okuyamaz", "illiterate_desc": "Yaşadığın sürece rakip hiçbir yazıyı okuyamaz",
"illiterate_alert": "Cahiliye aktif! Bu yeteneğin sahibi ortadan kalkana kadar mesajları okuyamazsınız.", "illiterate_alert": "Cahiliye aktif! Bu yeteneğin sahibi ortadan kalkana kadar mesajları okuyamazsınız.",
"illusionist": "İllüzyonist", "illusionist": "İllüzyonist",
"illusionist_desc": "[css_useSkill] tuşuna basarak düz ilerleyen illüzyon oluştur", "illusionist_desc": "[css_useSkill] tuşuna basarak düz ilerleyen illüzyon oluştur",
"impostor": "Sahtekar", "impostor": "Sahtekar",
"impostor_desc": "Düşman oyuncu modeline dönüşürsün", "impostor_desc": "Düşman modeline dönüşürsün",
"infiniteammo": "Sınırsız Mermi", "infiniteammo": "Sınırsız Mermi",
"infiniteammo_desc": "Tüm silahların sınırsız mermisi olur", "infiniteammo_desc": "Silahlarının mermisi sınırsız",
"inheritance": "Miras",
"inheritance_desc": "Bir takım arkadaşın öldüğünde yeteneğini devralabilirsin",
"inheritance_select_info": "Birini seçin:",
"inheritance_player_info": "'{0}' yeteneğini devraldın.",
"jackal": "İzci", "jackal": "İzci",
"jackal_desc": "Her rakip yürüdüğünde ayak izi bırakır", "jackal_desc": "Her rakip yürüdüğünde ayak izi bırakır",
"jammer": "Sinyal Kesici", "jammer": "Sinyal Kesici",
"jammer_desc": "Bir oyuncunun nişangahını (crosshair) kapatmak için seç", "jammer_desc": "Bir düşmanın nişangahını kapat",
"jammer_enemy_info": "Nişangahın kapatıldı.", "jammer_enemy_info": "Nişangahın kapatıldı.",
"jammer_disable_info": "Nişangahın açıldı", "jammer_disable_info": "Nişangahın açıldı.",
"jammer_player_info": "'{0}' isimli oyuncunun nişangahı kapatıldı.", "jammer_player_info": "'{0}' isimli oyuncunun nişangahı kapatıldı.",
"jammer_select_info": "Nişangahı kapatılacak oyuncuyu seç:", "jammer_select_info": "Birini seçin:",
"jester": "Soytarı", "jester": "Soytarı",
"jester_desc": "Soytarı modunda hasar alamazsın ve veremezsin. Bu mod birkaç saniyede bir değişir.", "jester_desc": "Soytarı modunda hasar alamaz ve veremezsin, mod birkaç saniyede bir değişir",
"jester_mode": "Soytarı Modu", "jester_mode": "Soytarı Modu",
"jester_on": "AÇIK", "jester_on": "AÇIK",
"jester_off": "KAPALI", "jester_off": "KAPALI",
"jetkick": "Jetkick", "jetkick": "Jetkick",
"jetkick_desc": "Seçtiğin bir rakibin her atışı onu geriye iter", "jetkick_desc": "Seçtiğin rakibi her atışı geriye iter",
"jetkick_select_info": "Jetkick uygulanacak oyuncu:", "jetkick_select_info": "Birini seçin:",
"jetkick_player_info": "'{0}' adlı oyuncuya jetkick uygulandı.", "jetkick_player_info": "'{0}' adlı oyuncuya jetkick uygulandı.",
"jetkick_enemy_info": "Her atış seni geriye doğru iter", "jetkick_enemy_info": "Her atış seni geriye doğru iter",
"jetkick_disable_info": "Geri tepmen normale döndü.", "jetkick_disable_info": "Geri tepmen normale döndü.",
"jumpban": "Bacaksız", "jumpban": "Bacaksız",
"jumpban_desc": "Zıplayamayacak bir oyuncu seç", "jumpban_desc": "Zıplayamayacak bir düşman seç",
"jumpban_enemy_info": "Bacakların kesildi", "jumpban_enemy_info": "Bacakların kesildi.",
"jumpban_disable_info": "Bacaklarına kavuştun", "jumpban_disable_info": "Tekrar zıplayabilirsin.",
"jumpban_player_info": "'{0}' artık zıplayamaz.", "jumpban_player_info": "'{0}' artık zıplayamaz.",
"jumpban_select_info": "Zıplaması yasaklanacak oyuncu:", "jumpban_select_info": "Birini seçin:",
"jumpcurse": "Zıplama Laneti", "jumpcurse": "Zıplama Laneti",
"jumpcurse_desc": "Seçtiğin rakip, takım arkadaşları her zıpladığında zıplar", "jumpcurse_desc": "Seçtiğin rakip, takım arkadaşlarıyla zıpladıkça zıplar",
"jumpcurse_disable_info": "Bacakların yeniden senin.", "jumpcurse_disable_info": "Kendin için zıplayabilirsin.",
"jumpcurse_enemy_info": "Artık takım arkadaşların zıpladıkça sen de zıplıyorsun.", "jumpcurse_enemy_info": "Takım arkadaşların zıpladıkça sen de zıplıyorsun.",
"jumpcurse_player_info": "'{0}' artık takımıyla birlikte zıplıyor.", "jumpcurse_player_info": "'{0}' takımıyla birlikte zıplıyor.",
"jumpcurse_select_info": "Zıplama laneti verilecek oyuncu:", "jumpcurse_select_info": "Birini seçin:",
"jumpingjack": "Zıpzıp Jack", "jumpingjack": "Zıpzıp Jack",
"jumpingjack_desc": "Zıplamak canını yeniler", "jumpingjack_desc": "Zıplamak canını yeniler",
@ -302,10 +317,10 @@
"lastgasp_desc": "Öldükten sonra seni öldürene hasar verirsin", "lastgasp_desc": "Öldükten sonra seni öldürene hasar verirsin",
"lifeswap": "Can Takası", "lifeswap": "Can Takası",
"lifeswap_desc": "Can değerlerini takas etmek için bir oyuncu seç", "lifeswap_desc": "Bir düşmanla canını takasla",
"lifeswap_enemy_info": "Birisi canını çaldı", "lifeswap_enemy_info": "Birisi canını çaldı.",
"lifeswap_player_info": "'{0}' isimli oyuncuyla canlarını takas ettin.", "lifeswap_player_info": "'{0}' ile canını takasladın.",
"lifeswap_select_info": "Can takası yapılacak oyuncu:", "lifeswap_select_info": "Birini seçin:",
"longknife": "Uzun Bıçak", "longknife": "Uzun Bıçak",
"longknife_desc": "Bıçağın uzaktaki rakibe hasar verebilir", "longknife_desc": "Bıçağın uzaktaki rakibe hasar verebilir",
@ -314,46 +329,46 @@
"longzeus_desc": "Zeus uzaktaki rakibe hasar verebilir", "longzeus_desc": "Zeus uzaktaki rakibe hasar verebilir",
"magneticdecoy": "Manyetik Yanıltıcı", "magneticdecoy": "Manyetik Yanıltıcı",
"magneticdecoy_desc": "Yanıltıcı bombanız yakındaki oyuncuları kendine çeker", "magneticdecoy_desc": "Yanıltıcı bomban yakındaki herkesi kendine çeker",
"magneto": "Mıknatıs", "magneto": "Mıknatıs",
"magneto_desc": "Tüm düşman bombaları sizden uzaklaştırılır", "magneto_desc": "Tüm düşman bombası senden uzaklaşır",
"magnifier": "Büyüteç", "magnifier": "Büyüteç",
"magnifier_desc": "Düşmanın ekranını yakınlaştırarak görüş alanını daraltır", "magnifier_desc": "Bir düşmanın görüş alanını daralt",
"magnifier_enemy_info": "Görüşün bozuldu!", "magnifier_enemy_info": "Görüşün bozuldu!",
"magnifier_disable_info": "Görüşün düzeldi", "magnifier_disable_info": "Görüşün düzeldi",
"magnifier_player_info": "'{0}' isimli oyuncunun ekranı yakınlaştırıldı.", "magnifier_player_info": "'{0}' isimli oyuncunun ekranı yakınlaştırıldı.",
"magnifier_select_info": "Ekranı büyütülecek oyuncuyu seç:", "magnifier_select_info": "Birini seçin:",
"medic": "Sıhhiye", "medic": "Sıhhiye",
"medic_desc": "[css_useSkill] tuşuna basarak kendine anında 50 HP bas", "medic_desc": "[css_useSkill] tuşuna basarak kendine anında 50 HP bas",
"miner": "Mayın", "miner": "Mayın",
"miner_desc": "El bombanız (HE) sadece yakında bir düşman olduğunda patlar", "miner_desc": "El bomban sadece yakında düşman varken patlar",
"bankrupt": "İflas", "bankrupt": "İflas",
"bankrupt_desc": "Tüm parasını kaybedecek bir oyuncu seç", "bankrupt_desc": "Tüm parasını kaybedecek bir düşman seç",
"bankrupt_enemy_info": "İflas ettin!", "bankrupt_enemy_info": "İflas ettin!",
"bankrupt_player_info": "'{0}' isimli oyuncu iflas etti.", "bankrupt_player_info": "'{0}' iflas etti.",
"bankrupt_select_info": "İflas edecek oyuncuyu seç:", "bankrupt_select_info": "Birini seçin:",
"deathbomb": "Canlı Bomba", "deathbomb": "Canlı Bomba",
"deathbomb_desc": "Öldüğünde patlayarak etraftaki oyuncuları öldürürsün", "deathbomb_desc": "Öldüğünde patlayıp etrafındakilere hasar verirsin",
"deathbomb_explosion": "BOOM!!!", "deathbomb_explosion": "BOOM!!!",
"demoneye": "Şeytani Göz", "demoneye": "Şeytani Göz",
"demoneye_desc": "Baktığın tüm düşmanlara hasar verirsin", "demoneye_desc": "Baktığın tüm düşmana hasar verirsin",
"nightmare": "Kabus", "nightmare": "Kabus",
"nightmare_desc": "Seçtiğin bir rakibe kabus görüntüsü verir", "nightmare_desc": "Seçtiğin rakibe kabus gördür",
"nightmare_disable_info": "Kabus sona erdi.", "nightmare_disable_info": "Kabus sona erdi.",
"nightmare_enemy_info": "Gözlerini bir kabus bürüdü.", "nightmare_enemy_info": "Gözlerini bir kabus bürüdü.",
"nightmare_player_info": "'{0}' oyuncusuna kabus gördürdün.", "nightmare_player_info": "'{0}' oyuncusuna kabus gördürdün.",
"nightmare_select_info": "Kabus görecek oyuncu:", "nightmare_select_info": "Birini seçin:",
"ninja": "Ninja", "ninja": "Ninja",
"ninja_desc": "Görünmezliğini sabit durmak %33, eğilmek %33 ve bıçak tutmak %33 artırır", "ninja_desc": "Sabit durmak, eğilmek ve bıçak tutmak görünmezliğini %33 artırır",
"nonades": "Bomba Geçirmez", "nonades": "Bomba Geçirmez",
"nonades_desc": "Bombalar sana hasar vermez", "nonades_desc": "Bombalar sana hasar vermez",
@ -375,38 +390,38 @@
"paweljumper_desc2": "{0} kez ekstra zıplayabilirsin", "paweljumper_desc2": "{0} kez ekstra zıplayabilirsin",
"phoenix": "Anka Kuşu", "phoenix": "Anka Kuşu",
"phoenix_desc": "Öldükten sonra rastgele yeniden doğma şansın olur", "phoenix_desc": "Öldükten sonra yeniden doğma şansın olur",
"phoenix_desc2": "Yeniden doğma şansın: %{0}", "phoenix_desc2": "Yeniden doğma şansın: %{0}",
"phoenix_respawn": "Küllerinden yeniden doğdun!", "phoenix_respawn": "Küllerinden yeniden doğdun!",
"psychicdefusing": "Psişik İmha", "psychicdefusing": "Psişik İmha",
"psychicdefusing_desc": "Bombanın yanındayken onu otomatik imha etmeye başlarsın", "psychicdefusing_desc": "Bombanın yanındayken otomatik imhaya başlarsın",
"psychicdefusing_hud_info": "Bombanın çözülmesi için son {0} saniye", "psychicdefusing_hud_info": "Bombanın çözülmesi için son {0} saniye",
"pilot": "Pilot", "pilot": "Pilot",
"pilot_desc": "Sınırlı bir süre uçun. Uçmak için zıplama tuşuna iki kez basın", "pilot_desc": "Uçmak için zıplama tuşuna iki kez bas",
"pilot_hud_info": "Yakıt", "pilot_hud_info": "Yakıt",
"planter": "Serbest Kurucu", "planter": "Serbest Kurucu",
"planter_desc": "Bombayı her yere kurabilirsin, patlama süresi 60 saniyedir.", "planter_desc": "Bombayı her yere kurabilirsin, patlama süresi 60 saniye",
"planter_planting": "Kuruluyor ({0})...", "planter_planting": "Kuruluyor ({0})...",
"poison": "Zehir", "poison": "Zehir",
"poison_desc": "Birkaç saniyede bir hasar alacak bir oyuncu seç", "poison_desc": "Birkaç saniyede bir hasar alacak bir düşman seç",
"poison_enemy_info": "Zehirlendin.", "poison_enemy_info": "Zehirlendin.",
"poison_disable_info": "Zehire bağışıklık kazandın", "poison_disable_info": "Zehire bağışıklık kazandın",
"poison_player_info": "'{0}' isimli oyuncu zehirlendi.", "poison_player_info": "'{0}' isimli oyuncu zehirlendi.",
"poison_select_info": "Zehirlenecek oyuncuyu seç:", "poison_select_info": "Birini seçin:",
"primaryban": "Tüfek Yasak", "primaryban": "Tüfek Yasak",
"primaryban_desc": "Tüfek kullanamayacak bir oyuncu seç", "primaryban_desc": "Tüfek kullanamayacak bir düşman seç",
"primaryban_enemy_info": "Tüfek kullanmayı unuttun", "primaryban_enemy_info": "Tüfek kullanmayı unuttun",
"primaryban_disable_info": "Tüfek kullanabilirsin", "primaryban_disable_info": "Tüfek kullanabilirsin",
"primaryban_player_info": "'{0}' artık tüfek kullanamaz.", "primaryban_player_info": "'{0}' artık tüfek kullanamaz.",
"primaryban_select_info": "Tüfek kullanımı yasaklanacak oyuncu:", "primaryban_select_info": "Birini seçin:",
"prosthesis": "Protez", "prosthesis": "Protez",
"prosthesis_desc": "Kollar ve bacaklar kurşun geçirmezdir", "prosthesis_desc": "Kolların ve bacakların kurşun geçirmez",
"push": "İtici", "push": "İtici",
"push_desc": "Düşmana vurduğunda onu geri itme şansın olur", "push_desc": "Düşmana vurduğunda onu geri itme şansın olur",
@ -422,43 +437,46 @@
"radarhack_desc": "Düşmanlar radarda görünür", "radarhack_desc": "Düşmanlar radarda görünür",
"rambo": "Rambo", "rambo": "Rambo",
"rambo_desc": "Raund başında rastgele miktarda can alırsın", "rambo_desc": "Rastgele miktarda canın olur",
"randomweapon": "Silah Kumarı", "randomweapon": "Silah Kumarı",
"randomweapon_desc": "[css_useSkill] tuşuna basarak rastgele bir silah al", "randomweapon_desc": "[css_useSkill] tuşuna basarak rastgele bir silah al",
"rezombie": "Zombi", "rezombie": "Zombi",
"rezombie_desc": "Öldükten sonra daha fazla canla ve silahsız zombi olarak doğarsın", "rezombie_desc": "Öldüğünde silahsız zombi olarak daha çok canla dirilirsin",
"reactivearmor": "Reaktif Zırh", "reactivearmor": "Reaktif Zırh",
"reactivearmor_desc": "Zırhın alınan ilk hasarı emmer", "reactivearmor_desc": "Zırhın ilk hasarı emer",
"regeneration": "Yenilenme", "regeneration": "Yenilenme",
"regeneration_desc": "Birkaç saniyede bir canın yenilenir", "regeneration_desc": "Birkaç saniyede bir canın yenilenir",
"replicator": "Klon", "replicator": "Klon",
"replicator_desc": "[css_useSkill] tuşuna basarak klon oluştur ve öldürene hasar verir", "replicator_desc": "[css_useSkill] tuşuna basarak klon oluştur, klonu öldürene hasar verir",
"retreat": "Geri Çekil", "retreat": "Geri Çekil",
"retreat_desc": "[css_useSkill] tuşuna basarak başlangıç noktasına ışınlan", "retreat_desc": "[css_useSkill] tuşuna basarak başlangıcına ışınlan",
"returntosender": "İade", "returntosender": "İade",
"returntosender_desc": "Düşmana ilk vuruşun onu kendi başlangıç noktasına ışınlar", "returntosender_desc": "Düşmana ilk vuruşun onu kendi başlangıcına ışınlar",
"richboy": "Zengin Çocuk", "richboy": "Zengin Çocuk",
"richboy_desc": "Raund başında rastgele miktarda para alırsın", "richboy_desc": "Rastgele miktarda paran olur",
"ricochet": "Seken Mermi",
"ricochet_desc": "Mermin duvardan seker ve düşmana isabet edebilir",
"robinhood": "Robin Hood", "robinhood": "Robin Hood",
"robinhood_desc": "Düşmana hasar vermek onun parasını çalar", "robinhood_desc": "Düşmana hasar vermek onun parasını çalar",
"rubber": "Lastik Mermi", "rubber": "Lastik Mermi",
"rubber_desc": "Mermilerin oyuncuları önemli ölçüde yavaşlatır", "rubber_desc": "Mermin isabet edeni yavaşlatır",
"saper": "İstihkamcı", "saper": "İstihkamcı",
"saper_desc": "Bombayı daha hızlı kurabilir ve imha edebilirsin", "saper_desc": "Bombayı daha hızlı kurar ve imha edersin",
"secondlife": "İkinci Şans", "secondlife": "İkinci Şans",
"secondlife_desc": "Öldükten sonra aynı miktarda canla yeniden doğarsın", "secondlife_desc": "Öldüğünde aynı canla yeniden doğarsın",
"shade": "Gölge", "shade": "Gölge",
"shade_desc": "Vurduğun düşmanın arkasına ışınlanma şansın olur", "shade_desc": "Vurduğun düşmanın arkasına ışınlanma şansın olur",
@ -466,24 +484,24 @@
"shade_nospace": "Uygun alan yok", "shade_nospace": "Uygun alan yok",
"shortbomb": "Kısa Fünye", "shortbomb": "Kısa Fünye",
"shortbomb_desc": "Bomba çok daha hızlı patlar", "shortbomb_desc": "C4 çok daha hızlı patlar",
"silent": "Sessiz", "silent": "Sessiz",
"silent_desc": "Ayak seslerini ve zıplamalarını DİĞER oyuncular duyamaz", "silent_desc": "Ayak ve zıplama sesini kimse duyamaz",
"smoker": "Tiryaki", "smoker": "Tiryaki",
"smoker_desc": "Attığın Sis asla bitmez", "smoker_desc": "Attığın sis asla bitmez",
"sniperelite": "Keskin Nişancı", "sniperelite": "Keskin Nişancı",
"sniperelite_customname": "Keskin Nişancı", "sniperelite_customname": "Keskin Nişancı",
"sniperelite_desc": "[css_useSkill] tuşuna basarak silahını AWP ile değiştir", "sniperelite_desc": "[css_useSkill] tuşuna basarak silahını AWP ile değiştir",
"soldier": "Teğmen", "soldier": "Teğmen",
"soldier_desc": "Rastgele bir oranda fazla hasar verirsin", "soldier_desc": "Rastgele hasar verme çarpanın olur",
"soldier_desc2": "Hasarın: {0}x", "soldier_desc2": "Hasarın: {0}x",
"soundmaker": "Çığlık", "soundmaker": "Çığlık",
"soundmaker_desc": "Rakiplerinin çığlıklarını duyarsın", "soundmaker_desc": "Rakibin çığlığını duyarsın",
"spectator": "Röntgen", "spectator": "Röntgen",
"spectator_desc": "[css_useSkill] tuşuna basarak rakibinin gözünden gör", "spectator_desc": "[css_useSkill] tuşuna basarak rakibinin gözünden gör",
@ -492,47 +510,47 @@
"swapposition_desc": "[css_useSkill] tuşuna basarak vurduğun düşmanla yer değiştir", "swapposition_desc": "[css_useSkill] tuşuna basarak vurduğun düşmanla yer değiştir",
"takeammo": "Cephane Hırsızı", "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_desc": "[css_useSkill] tuşuna basarak rastgele bir düşmanın şarjörünü çal",
"takeammo_hud_info1": "Cephanesi olan bir oyuncu bulunamadı.", "takeammo_hud_info1": "Şarjörü olan bir oyuncu bulunamadı.",
"takeammo_hud_info2": "Düşmanın cephanesi yok.", "takeammo_hud_info2": "Düşmanın şarjörü yok.",
"takeammo_enemy_info": "Birisi cephaneni çaldı.", "takeammo_enemy_info": "Birisi şarjörünü çaldı.",
"teamteleport": "Takıma Işınlanma", "teamteleport": "Takıma Işınlanma",
"teamteleport_desc": "[css_useSkill] tuşuna basarak baktığın takım arkadaşına ışınlanırsın", "teamteleport_desc": "[css_useSkill] tuşuna basarak baktığın takım arkadaşına ışınlan",
"teamteleport_noenemy": "Takım arkadaşı bulunamadı", "teamteleport_noenemy": "Takım arkadaşı bulunamadı",
"teamteleport_hud_info": "Bulundu: {0}", "teamteleport_hud_info": "Bulundu: {0}",
"teleporter": "Işınlayıcı", "teleporter": "Işınlayıcı",
"teleporter_desc": "Vurulan bir düşmanla yer değiştirme şansınız var", "teleporter_desc": "Vurduğun düşmanla yer değiştirme şansın olur",
"teleporter_desc2": "Yer değiştirme şansın: %{0}", "teleporter_desc2": "Yer değiştirme şansın: %{0}",
"thief": "Hırsız", "thief": "Hırsız",
"thief_desc": "Seçilen bir oyuncudan yeteneğini çalabilirsin", "thief_desc": "Bir düşmanın yeteneğini çal",
"thief_enemy_info": "Yeteneğin çalındı.", "thief_enemy_info": "Yeteneğin çalındı.",
"thief_player_info": "'{0}' isimli oyuncunun yeteneği çalındı.", "thief_player_info": "'{0}' isimli oyuncunun yeteneği çalındı.",
"thief_select_info": "Yetenek çalınacak oyuncu:", "thief_select_info": "Birini seçin:",
"thief_incorrect_skill": "Bu yetenek çalınamaz!", "thief_incorrect_skill": "Bu yetenek çalınamaz!",
"thirdeye": "Üçüncü Göz", "thirdeye": "Üçüncü Göz",
"thirdeye_desc": "[css_useSkill] tuşuna basarak üçüncü göze(thirdperson) geç", "thirdeye_desc": "[css_useSkill] tuşuna basarak üçüncü şahıs görünümüne geç",
"thorns": "Dikenler", "thorns": "Dikenler",
"thorns_desc": "Rakibin, sana verdiği hasarın bir kısmını geri alır", "thorns_desc": "Sana verilen hasarın bir kısmı rakibe döner",
"throwingknife": "Fırlatma Bıçağı", "throwingknife": "Fırlatma Bıçağı",
"throwingknife_desc": "Bıçak fırlatmak için [css_useSkill] tuşuna basın. Ama başkalarına dikkat edin", "throwingknife_desc": "[css_useSkill] tuşuna basarak bıçak fırlat",
"toxicsmoke": "Zehirli Sis", "toxicsmoke": "Zehirli Sis",
"toxicsmoke_desc": "Sis bombaların hasar verir", "toxicsmoke_desc": "Sis bomban hasar verir",
"tripwire": "Tel Tuzağı", "tripwire": "Tel Tuzağı",
"tripwire_desc": "[css_useSkill] ile iki duvar arasına tel ger. Tele değen düşman radarında görünür", "tripwire_desc": "[css_useSkill] tuşuna basarak iki duvar arasına tel ger, değen düşman radarda görünür",
"tripwire_no_wall_info": "İki yanında da yeterince yakın duvar yok.", "tripwire_no_wall_info": "İki yanında da yeterince yakın duvar yok.",
"tripwire_placed_info": "Tel gerildi.", "tripwire_placed_info": "Tel gerildi.",
"tripwire_triggered_info": "'{0}' teline takıldı.", "tripwire_triggered_info": "'{0}' teline takıldı.",
"wallhack": "Wallhack", "wallhack": "Wallhack",
"wallhack_desc": "Düşmanları duvarların arkasından görebilirsin", "wallhack_desc": "Düşmanları duvar arkasından görürsün",
"watchmaker": "Saat Ustası", "watchmaker": "Saat Ustası",
"watchmaker_desc": "Atılan her bomba raund süresini değiştirir", "watchmaker_desc": "Atılan her bomba raund süresini değiştirir",
@ -544,21 +562,21 @@
"weaponsswap_hud_info2": "Takas edilecek silahın yok", "weaponsswap_hud_info2": "Takas edilecek silahın yok",
"weightless": "Yerçekimsiz", "weightless": "Yerçekimsiz",
"weightless_desc": "El bombalarınız yerçekiminden etkilenmez ve dümdüz gider", "weightless_desc": "El bomban yerçekiminden etkilenmez ve dümdüz gider",
"wildthrow": "Unutkan Bombacı", "wildthrow": "Unutkan Bombacı",
"wildthrow_desc": "El bombası atmakta zorluk çekecek bir oyuncu seçin", "wildthrow_desc": "El bombası atmakta zorlanacak bir düşman seç",
"wildthrow_player_info": "'{0}' adlı oyuncu tüm taktiklerini unuttu", "wildthrow_player_info": "'{0}' tüm taktiklerini unuttu.",
"wildthrow_enemy_info": "Bomba atarken çok heyecanlanıyorsun.", "wildthrow_enemy_info": "Bomba atarken çok heyecanlanıyorsun.",
"wildthrow_disable_info": "Bombaların düzeldi.", "wildthrow_disable_info": "Bomban tekrardan düzgün.",
"wildthrow_select_info": "Bir oyuncu seçin:", "wildthrow_select_info": "Birini seçin:",
"zeus": "Zeus", "zeus": "Zeus",
"zeus_desc": "Zeus x27 anında şarj olur", "zeus_desc": "Zeus x27 anında şarj olur",
"your_skill": "Yeteneğin", "your_skill": "Yeteneğin",
"enemy_skill": "Düşmanın yeteneği", "enemy_skill": "Düşmanın yeteneği",
"observer_skill": "Oyuncunun yeteneği", "observer_skill": "Yeteneği",
"welcome_message": "{PLAYER}, {SERVER_NAME} sunucusuna hoş geldin!\nGüncel jRandomSkills versiyonu: {VERSION} ({SKILLS_COUNT} yetenek).\n\nOrijinal yapımcı:\n{AUTHOR1}\nGeliştiren:\n{AUTHOR2}\nResmi Discord: https://discord.gg/9H8EZYBpPF", "welcome_message": "{PLAYER}, {SERVER_NAME} sunucusuna hoş geldin!\nGüncel jRandomSkills versiyonu: {VERSION} ({SKILLS_COUNT} yetenek).\n\nOrijinal yapımcı:\n{AUTHOR1}\nGeliştiren:\n{AUTHOR2}\nResmi Discord: https://discord.gg/9H8EZYBpPF",
"drawing_skill": "Yetenek çarkı dönüyor...", "drawing_skill": "Yetenek çarkı dönüyor...",
"disabled_weapon": "Bu silahı kullanamazsın", "disabled_weapon": "Bu silahı kullanamazsın",

View file

@ -71,6 +71,11 @@
"catapult_desc": "你有随机几率将敌人向上弹射", "catapult_desc": "你有随机几率将敌人向上弹射",
"catapult_desc2": "你击中敌人将其弹射的几率是:{0}%", "catapult_desc2": "你击中敌人将其弹射的几率是:{0}%",
"chameleon": "变色龙",
"chameleon_desc": "你击杀的第一名玩家会把技能传给你",
"chameleon_copied_info": "已复制技能:{0}",
"chameleon_wrong_team_info": "'{0}' 的技能你的队伍无法使用。",
"chicken": "小鸡", "chicken": "小鸡",
"chicken_desc": "你获得小鸡模型 + 移动速度提高10% - 50生命值", "chicken_desc": "你获得小鸡模型 + 移动速度提高10% - 50生命值",
@ -201,6 +206,11 @@
"godmode_off": "无敌状态已禁用", "godmode_off": "无敌状态已禁用",
"godmode_on": "无敌状态已启用", "godmode_on": "无敌状态已启用",
"grapple": "钩爪",
"grapple_desc": "按 [css_useSkill] 向准星所指位置发射钩爪并将自己拉过去",
"grapple_no_anchor_info": "没有可以钩住的表面。",
"grapple_pulling_info": "拉动中",
"grenadier": "投弹手", "grenadier": "投弹手",
"grenadier_desc": "你拥有无限高爆手雷", "grenadier_desc": "你拥有无限高爆手雷",
@ -237,6 +247,11 @@
"infiniteammo": "无限弹药", "infiniteammo": "无限弹药",
"infiniteammo_desc": "你为所有武器获得无限弹药", "infiniteammo_desc": "你为所有武器获得无限弹药",
"inheritance": "继承",
"inheritance_desc": "当队友阵亡时,你可以接管他的技能",
"inheritance_select_info": "选择要继承的技能:",
"inheritance_player_info": "你继承了 '{0}' 的技能。",
"jackal": "追踪者", "jackal": "追踪者",
"jackal_desc": "每个对手都会留下痕迹", "jackal_desc": "每个对手都会留下痕迹",
@ -418,6 +433,9 @@
"richboy": "富少", "richboy": "富少",
"richboy_desc": "回合开始时你获得随机数量的钱", "richboy_desc": "回合开始时你获得随机数量的钱",
"ricochet": "跳弹",
"ricochet_desc": "你的子弹会从墙上弹开,并且仍能击中敌人",
"robinhood": "罗宾汉", "robinhood": "罗宾汉",
"robinhood_desc": "对敌人造成伤害会偷取他们的钱", "robinhood_desc": "对敌人造成伤害会偷取他们的钱",