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