This commit is contained in:
Juzlus 2025-09-15 23:58:34 +02:00
parent 714624d96a
commit 2102f0581f
96 changed files with 1279 additions and 413 deletions

View file

@ -14,14 +14,15 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.337" /> <PackageReference Include="CounterStrikeSharp.API" Version="1.0.339" />
<PackageReference Include="CS2TraceRay" Version="1.0.5" /> <PackageReference Include="CS2TraceRay" Version="1.0.7" />
<PackageReference Include="MaxMind.Db" Version="4.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="WASDMenuAPI"> <Reference Include="WASDMenuAPI">
<HintPath>F:\CS2 Server\server\game\csgo\addons\counterstrikesharp\plugins\jRandomSkills\WASDMenuAPI.dll</HintPath> <HintPath>F:\CS2 Server\server\game\csgo\addons\counterstrikesharp\plugins\!jRandomSkills\WASDMenuAPI.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
</Project>

View file

@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123 VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "jRandomSkills", "jRandomSkills.csproj", "{1412DD25-558C-425A-A7F6-347C970136E5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "!jRandomSkills", "!jRandomSkills.csproj", "{1412DD25-558C-425A-A7F6-347C970136E5}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View file

@ -31,6 +31,8 @@ namespace jRandomSkills
{ SplitCommands(config.HealCommands.Alias), ("Heal", Command_Heal) }, { SplitCommands(config.HealCommands.Alias), ("Heal", Command_Heal) },
{ SplitCommands(config.SetScoreCommands.Alias), ("Set teams score", Command_SetScore) }, { SplitCommands(config.SetScoreCommands.Alias), ("Set teams score", Command_SetScore) },
{ SplitCommands(config.SetStaticSkillCommands.Alias), ("Set static skill", Command_SetStaticSkill) }, { SplitCommands(config.SetStaticSkillCommands.Alias), ("Set static skill", Command_SetStaticSkill) },
{ SplitCommands(config.ChangeLanguageCommands.Alias), ("Change language", Command_ChangeLanguage) },
{ SplitCommands(config.ReloadCommands.Alias), ("Reaload configs", Command_Reload) },
}; };
foreach (var commandPair in commands) foreach (var commandPair in commands)
@ -79,7 +81,7 @@ namespace jRandomSkills
return; return;
} }
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, Localization.GetTranslation("correct_form_setskill"), true); SkillUtils.PrintToChat(player, player.GetTranslation("correct_form_setskill"), true);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
return; return;
} }
@ -92,13 +94,13 @@ namespace jRandomSkills
return; return;
} }
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, Localization.GetTranslation("player_not_found_setskill"), true); SkillUtils.PrintToChat(player, player.GetTranslation("player_not_found_setskill"), true);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
return; return;
} }
var skillName = command.ArgCount > 3 ? $"{command.GetArg(2)} {command.GetArg(3)}" : command.GetArg(2); var skillName = command.ArgCount > 3 ? $"{command.GetArg(2)} {command.GetArg(3)}" : command.GetArg(2);
var skill = SkillData.Skills.FirstOrDefault(s => s.Name.Equals(skillName, StringComparison.OrdinalIgnoreCase) || s.Skill.ToString().Equals(skillName, StringComparison.OrdinalIgnoreCase)); var skill = SkillData.Skills.FirstOrDefault(s => (player != null && player.GetSkillName(s.Skill).Equals(skillName, StringComparison.OrdinalIgnoreCase)) || s.Skill.ToString().Equals(skillName, StringComparison.OrdinalIgnoreCase));
if (skill == null) if (skill == null)
{ {
@ -108,7 +110,7 @@ namespace jRandomSkills
return; return;
} }
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, Localization.GetTranslation("skill_not_found_setskill"), true); SkillUtils.PrintToChat(player, player.GetTranslation("skill_not_found_setskill"), true);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
return; return;
} }
@ -129,10 +131,10 @@ namespace jRandomSkills
} }
if (skill.Display) if (skill.Display)
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{skill.Name}{ChatColors.Lime}: {skill.Description}", false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(skill.Skill)}", false);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, $"{Localization.GetTranslation("done_setskill")}: {ChatColors.LightRed}{skill.Name} {ChatColors.Lime}{Localization.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}", false); SkillUtils.PrintToChat(player, $"{player.GetTranslation("done_setskill")}: {ChatColors.LightRed}{player.GetSkillName(skill.Skill)} {ChatColors.Lime}{player.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}", false);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
} }
else else
@ -144,7 +146,7 @@ namespace jRandomSkills
} }
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, Localization.GetTranslation("error_setskill"), true); SkillUtils.PrintToChat(player, player.GetTranslation("error_setskill"), true);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
} }
} }
@ -176,16 +178,16 @@ namespace jRandomSkills
if (string.IsNullOrEmpty(map)) if (string.IsNullOrEmpty(map))
{ {
command.ReplyToCommand($" {ChatColors.Red}{Localization.GetTranslation("invalid_map")}"); command.ReplyToCommand($" {ChatColors.Red}{command.CallingPlayer?.GetTranslation("invalid_map")}");
return; return;
} }
Server.PrintToChatAll($" {ChatColors.Yellow}{Localization.GetTranslation("loading_map")} ({ChatColors.Green}{map}{ChatColors.Yellow})..."); Localization.PrintTranslationToChatAll($" {ChatColors.Yellow}{{0}} ({ChatColors.Green}{map}{ChatColors.Yellow})...", ["loading_map"]);
if (uint.TryParse(map, out _)) if (uint.TryParse(map, out _))
Server.ExecuteCommand($"host_workshop_map {map}"); Server.ExecuteCommand($"host_workshop_map {map}");
else if (!Server.IsMapValid(map)) else if (!Server.IsMapValid(map))
command.ReplyToCommand($" {ChatColors.Red}{Localization.GetTranslation("invalid_map")}"); command.ReplyToCommand($" {ChatColors.Red}{command.CallingPlayer?.GetTranslation("invalid_map")}");
else else
Server.ExecuteCommand($"changelevel {map}"); Server.ExecuteCommand($"changelevel {map}");
} }
@ -214,12 +216,12 @@ namespace jRandomSkills
if (Instance?.GameRules?.WarmupPeriod == true) if (Instance?.GameRules?.WarmupPeriod == true)
{ {
Server.ExecuteCommand("mp_warmup_end"); Server.ExecuteCommand("mp_warmup_end");
Server.PrintToChatAll($" {ChatColors.Green}{Localization.GetTranslation("game_start")}"); Localization.PrintTranslationToChatAll($" {ChatColors.Green}{{0}}", ["game_start"]);
} }
else else
{ {
Server.ExecuteCommand("mp_restartgame 2"); Server.ExecuteCommand("mp_restartgame 2");
Instance?.AddTimer(2.0f, () => Server.PrintToChatAll($" {ChatColors.Green}{Localization.GetTranslation("game_start")}")); Instance?.AddTimer(2.0f, () => Localization.PrintTranslationToChatAll($" {ChatColors.Green}{{0}}", ["game_start"]));
} }
} }
@ -285,7 +287,7 @@ namespace jRandomSkills
private static void Pause() private static void Pause()
{ {
Server.PrintToChatAll($" {(gamePaused ? ChatColors.Green : ChatColors.Red)}{Localization.GetTranslation(gamePaused ? "unpause" : "pause")}"); Localization.PrintTranslationToChatAll($" {(gamePaused ? ChatColors.Green : ChatColors.Red)}{{0}}", [gamePaused ? "unpause" : "pause"]);
Server.ExecuteCommand(gamePaused ? "mp_unpause_match" : "mp_pause_match"); Server.ExecuteCommand(gamePaused ? "mp_unpause_match" : "mp_pause_match");
gamePaused = !gamePaused; gamePaused = !gamePaused;
} }
@ -297,7 +299,7 @@ namespace jRandomSkills
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
if (!AdminManager.PlayerHasPermissions(player, config.HealCommands.Permissions)) return; if (!AdminManager.PlayerHasPermissions(player, config.HealCommands.Permissions)) return;
SkillUtils.AddHealth(player.PlayerPawn.Value, 100); SkillUtils.AddHealth(player.PlayerPawn.Value, 100);
player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("healed")}"); player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("healed")}");
} }
[CommandHelper(minArgs: 2, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] [CommandHelper(minArgs: 2, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
@ -318,7 +320,7 @@ namespace jRandomSkills
if (!int.TryParse(command.GetArg(1), out int ctScore) || !int.TryParse(command.GetArg(2), out int tScore)) if (!int.TryParse(command.GetArg(1), out int ctScore) || !int.TryParse(command.GetArg(2), out int tScore))
{ {
if (player != null && player.IsValid) if (player != null && player.IsValid)
SkillUtils.PrintToChat(player, Localization.GetTranslation("correct_form_setscore"), true); SkillUtils.PrintToChat(player, player.GetTranslation("correct_form_setscore"), true);
return; return;
} }
@ -352,7 +354,7 @@ namespace jRandomSkills
} }
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, Localization.GetTranslation("correct_form_setskill"), true); SkillUtils.PrintToChat(player, player.GetTranslation("correct_form_setskill"), true);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
return; return;
} }
@ -366,13 +368,13 @@ namespace jRandomSkills
} }
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, Localization.GetTranslation("player_not_found_setskill"), true); SkillUtils.PrintToChat(player, player.GetTranslation("player_not_found_setskill"), true);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
return; return;
} }
var skillName = command.ArgCount > 3 ? $"{command.GetArg(2)} {command.GetArg(3)}" : command.GetArg(2); var skillName = command.ArgCount > 3 ? $"{command.GetArg(2)} {command.GetArg(3)}" : command.GetArg(2);
var skill = SkillData.Skills.FirstOrDefault(s => s.Name.Equals(skillName, StringComparison.OrdinalIgnoreCase) || s.Skill.ToString().Equals(skillName, StringComparison.OrdinalIgnoreCase)); var skill = SkillData.Skills.FirstOrDefault(s => (player != null && player.GetSkillName(s.Skill).Equals(skillName, StringComparison.OrdinalIgnoreCase)) || s.Skill.ToString().Equals(skillName, StringComparison.OrdinalIgnoreCase));
if (skill == null) if (skill == null)
{ {
@ -383,7 +385,7 @@ namespace jRandomSkills
} }
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, Localization.GetTranslation("skill_not_found_setskill"), true); SkillUtils.PrintToChat(player, player.GetTranslation("skill_not_found_setskill"), true);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
return; return;
} }
@ -409,10 +411,10 @@ namespace jRandomSkills
} }
if (skill.Display) if (skill.Display)
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{skill.Name}{ChatColors.Lime}: {skill.Description}", false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(skill.Skill)}", false);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, $"{Localization.GetTranslation("done_setskill")}: {ChatColors.LightRed}{skill.Name} {ChatColors.Lime}{Localization.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}", false); SkillUtils.PrintToChat(player, $"{player.GetTranslation("done_setskill")}: {ChatColors.LightRed}{player.GetSkillName(skill.Skill)} {ChatColors.Lime}{player.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}", false);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
} }
else else
@ -424,9 +426,41 @@ namespace jRandomSkills
} }
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
SkillUtils.PrintToChat(player, Localization.GetTranslation("error_setskill"), true); SkillUtils.PrintToChat(player, player.GetTranslation("error_setskill"), true);
player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――");
} }
} }
[CommandHelper(minArgs: 1, whoCanExecute: CommandUsage.CLIENT_ONLY)]
private static void Command_ChangeLanguage(CCSPlayerController? player, CommandInfo command)
{
Debug.WriteToDebug($"Player {player?.PlayerPawn} used the css_lang {command.ArgString} command.");
if (player == null || !player.IsValid) return;
if (!AdminManager.PlayerHasPermissions(player, config.ChangeLanguageCommands.Permissions)) return;
string newLangCode = command.GetArg(1);
if (Localization.portugalIsoCodes.Contains(newLangCode.ToUpper()))
newLangCode = "pt-br";
if (Localization.chinaIsoCodes.Contains(newLangCode.ToUpper()))
newLangCode = "zh";
newLangCode = newLangCode.ToLower();
if (!Localization.HasTranslation(newLangCode))
newLangCode = "en";
Localization.ChangePlayerLanguage(player, newLangCode);
}
[CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
private static void Command_Reload(CCSPlayerController? player, CommandInfo command)
{
Debug.WriteToDebug($"Player {player?.PlayerPawn} used the css_lang {command.ArgString} command.");
if (!AdminManager.PlayerHasPermissions(player, config.ReloadCommands.Permissions)) return;
Config.LoadConfig();
Localization.Load();
if (player != null && player.IsValid)
player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("reload")}");
else
Server.PrintToConsole($" {ChatColors.Green}{Localization.GetTranslation("reload")}");
}
} }
} }

View file

@ -22,7 +22,7 @@ namespace jRandomSkills
votes.Add(vote); votes.Add(vote);
string commandName = $"!{VoteTypeCommands.GetCommand(vote.Type)?.Replace("css_", "")}{(!string.IsNullOrEmpty(vote?.Args) ? $" {vote?.Args}" : "")}"; string commandName = $"!{VoteTypeCommands.GetCommand(vote.Type)?.Replace("css_", "")}{(!string.IsNullOrEmpty(vote?.Args) ? $" {vote?.Args}" : "")}";
Server.PrintToChatAll($" {ChatColors.Lime}{Localization.GetTranslation("vote_started", commandName)}"); Localization.PrintTranslationToChatAll($" {ChatColors.Lime}{{0}}", ["vote_started"], [commandName]);
foreach (var player in Utilities.GetPlayers()) foreach (var player in Utilities.GetPlayers())
player.EmitSound("UIPanorama.tab_mainmenu_news"); player.EmitSound("UIPanorama.tab_mainmenu_news");
@ -32,7 +32,7 @@ namespace jRandomSkills
if (!votes.Contains(vote) || !vote.GetActive()) return; if (!votes.Contains(vote) || !vote.GetActive()) return;
vote.SetActive(false); vote.SetActive(false);
vote.TimeToNextSameVoting = vote.TimeToNextVoting; vote.TimeToNextSameVoting = vote.TimeToNextVoting;
Server.PrintToChatAll($" {ChatColors.Red}{Localization.GetTranslation("vote_timeout", commandName)}"); Localization.PrintTranslationToChatAll($" {ChatColors.Red}{{0}}", ["vote_timeout"], [commandName]);
}); });
float[] times = [vote.TimeToVote, vote.TimeToVote + vote.TimeToNextVoting, vote.TimeToVote + vote.TimeToNextSameVoting]; float[] times = [vote.TimeToVote, vote.TimeToVote + vote.TimeToNextVoting, vote.TimeToVote + vote.TimeToNextSameVoting];
@ -51,12 +51,12 @@ namespace jRandomSkills
{ {
if (votes.Any(v => v.NextVoting() > DateTime.Now)) if (votes.Any(v => v.NextVoting() > DateTime.Now))
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("vote_wait")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("vote_wait")}");
return; return;
} }
else if (votes.Any(v => v.Type == voteType && v.NextSameVoting() > DateTime.Now)) else if (votes.Any(v => v.Type == voteType && v.NextSameVoting() > DateTime.Now))
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("vote_same_wait")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("vote_same_wait")}");
return; return;
} }
@ -65,12 +65,12 @@ namespace jRandomSkills
if (vote == null) if (vote == null)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("vote_not_enough_players")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("vote_not_enough_players")}");
return; return;
} }
if (!vote.PlayersVoted.Add(player.SteamID)) if (!vote.PlayersVoted.Add(player.SteamID))
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("vote_alredy_voted")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("vote_alredy_voted")}");
else CheckVote(vote); else CheckVote(vote);
} }
@ -86,7 +86,7 @@ namespace jRandomSkills
vote.SetActive(false); vote.SetActive(false);
} }
else else
Server.PrintToChatAll($" {ChatColors.Yellow}{Localization.GetTranslation("vote_vote")} '!{VoteTypeCommands.GetCommand(vote.Type)?.Replace("css_", "")}{(!string.IsNullOrEmpty(vote?.Args) ? $" {vote?.Args}" : "")}': {ChatColors.Green}{voted}/{playersNeeded}"); Localization.PrintTranslationToChatAll($" {ChatColors.Yellow}{{0}} '!{VoteTypeCommands.GetCommand(vote.Type)?.Replace("css_", "")}{(!string.IsNullOrEmpty(vote?.Args) ? $" {vote?.Args}" : "")}': {ChatColors.Green}{voted}/{playersNeeded}", ["vote_vote"]);
} }
} }

View file

@ -13,9 +13,7 @@ namespace jRandomSkills
public partial class jRandomSkills : BasePlugin public partial class jRandomSkills : BasePlugin
#pragma warning restore IDE1006 // Style nazewnictwa #pragma warning restore IDE1006 // Style nazewnictwa
{ {
#pragma warning disable CS8618 // Pole niedopuszczające wartości null musi zawierać wartość inną niż null podczas kończenia działania konstruktora. Rozważ zadeklarowanie pola jako dopuszczającego wartość null. public static jRandomSkills Instance { get; private set; }
public static jRandomSkills Instance { get; private set; }
#pragma warning restore CS8618 // Pole niedopuszczające wartości null musi zawierać wartość inną niż null podczas kończenia działania konstruktora. Rozważ zadeklarowanie pola jako dopuszczającego wartość null.
public List<jSkill_PlayerInfo> SkillPlayer { get; } = []; public List<jSkill_PlayerInfo> SkillPlayer { get; } = [];
public Random Random { get; } = new Random(); public Random Random { get; } = new Random();
@ -25,13 +23,13 @@ namespace jRandomSkills
public override string ModuleName => "[CS2] [ jRandomSkills ]"; public override string ModuleName => "[CS2] [ jRandomSkills ]";
public override string ModuleAuthor => "D3X, Juzlus"; public override string ModuleAuthor => "D3X, Juzlus";
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.1.4"; public override string ModuleVersion => "1.1.5";
public override void Load(bool hotReload) public override void Load(bool hotReload)
{ {
Instance = this; Instance = this;
Config.Initialize(); Config.LoadConfig();
Localization.Load(); Localization.Load();
Debug.Load(); Debug.Load();
PlayerOnTick.Load(); PlayerOnTick.Load();
@ -115,10 +113,7 @@ namespace jRandomSkills
#pragma warning restore IDE1006 #pragma warning restore IDE1006
{ {
public Skills Skill { get; } = skill; public Skills Skill { get; } = skill;
public string Name { get; } = Localization.GetTranslation(skill.ToString().ToLower());
public string Description { get; } = Localization.GetTranslation($"{skill.ToString().ToLower()}_desc");
public string Color { get; } = color; public string Color { get; } = color;
public bool Display { get; } = display; public bool Display { get; } = display;
public static implicit operator Skills(jSkill_SkillInfo v) public static implicit operator Skills(jSkill_SkillInfo v)

View file

@ -93,6 +93,9 @@
"distancer": "Rangefinder", "distancer": "Rangefinder",
"distancer_desc": "You can see the distance to the nearest enemy", "distancer_desc": "You can see the distance to the nearest enemy",
"dash": "Dash",
"dash_desc": "Perform a second jump to dash",
"dracula": "Dracula", "dracula": "Dracula",
"dracula_desc": "Hitting an enemy restores health equal to a percentage of the damage dealt", "dracula_desc": "Hitting an enemy restores health equal to a percentage of the damage dealt",
@ -160,6 +163,9 @@
"godmode_off": "Immortality disabled", "godmode_off": "Immortality disabled",
"godmode_on": "Immortality enabled", "godmode_on": "Immortality enabled",
"grenadier": "Grenadier",
"grenadier_desc": "You have infinite hegranade",
"healingsmoke": "Healing Smoke", "healingsmoke": "Healing Smoke",
"healingsmoke_desc": "Your smoke grenades heal", "healingsmoke_desc": "Your smoke grenades heal",
@ -371,6 +377,7 @@
"thief_enemy_info": "Your skill has been stolen.", "thief_enemy_info": "Your skill has been stolen.",
"thief_player_info": "Player '{0}'s skill has been stolen.", "thief_player_info": "Player '{0}'s skill has been stolen.",
"thief_select_info": "Steal a player's skill:", "thief_select_info": "Steal a player's skill:",
"thief_incorrect_skill": "This skill cannot be selected!",
"thirdeye": "Third Eye", "thirdeye": "Third Eye",
"thirdeye_desc": "Click [css_useSkill] to activate third-person view", "thirdeye_desc": "Click [css_useSkill] to activate third-person view",
@ -428,6 +435,7 @@
"unpause": "Match has been resumed.", "unpause": "Match has been resumed.",
"healed": "You have been healed.", "healed": "You have been healed.",
"game_start": "Game started!", "game_start": "Game started!",
"reload": "Languages and configs have been reloaded.",
"vote_started": "Vote started: '{0}'", "vote_started": "Vote started: '{0}'",
"vote_timeout": "Vote '{0}' timed out!", "vote_timeout": "Vote '{0}' timed out!",

View file

@ -93,6 +93,9 @@
"distancer": "Odległościomierz", "distancer": "Odległościomierz",
"distancer_desc": "Możesz zobaczyć odległość do najbliższego przeciwnika", "distancer_desc": "Możesz zobaczyć odległość do najbliższego przeciwnika",
"dash": "Doskok",
"dash_desc": "Wykonaj drugi skok, aby wykonać doskok",
"dracula": "Drakula", "dracula": "Drakula",
"dracula_desc": "Po trafieniu ofiary odzyskujesz zdrowie równe pewnemu procentowi zadanych obrażeń", "dracula_desc": "Po trafieniu ofiary odzyskujesz zdrowie równe pewnemu procentowi zadanych obrażeń",
@ -160,6 +163,9 @@
"godmode_off": "Nieśmiertelność wyłączona", "godmode_off": "Nieśmiertelność wyłączona",
"godmode_on": "Nieśmiertelność włączona", "godmode_on": "Nieśmiertelność włączona",
"grenadier": "Granatnik",
"grenadier_desc": "Masz nieskończone granaty odłamkowe",
"healingsmoke": "Leczący Dym", "healingsmoke": "Leczący Dym",
"healingsmoke_desc": "Twoje granaty dymne leczą", "healingsmoke_desc": "Twoje granaty dymne leczą",
@ -371,6 +377,7 @@
"thief_enemy_info": "Twoja supermoc została skradziona.", "thief_enemy_info": "Twoja supermoc została skradziona.",
"thief_player_info": "Moc gracza '{0}' została skradziona.", "thief_player_info": "Moc gracza '{0}' została skradziona.",
"thief_select_info": "Ukradnij moc gracza:", "thief_select_info": "Ukradnij moc gracza:",
"thief_incorrect_skill": "Tej umiejętności nie można wybrać!",
"thirdeye": "Trzecie Oko", "thirdeye": "Trzecie Oko",
"thirdeye_desc": "Kliknij [css_useSkill], aby aktywować trzecią osobę", "thirdeye_desc": "Kliknij [css_useSkill], aby aktywować trzecią osobę",
@ -428,6 +435,7 @@
"unpause": "Mecz został wznowiony.", "unpause": "Mecz został wznowiony.",
"healed": "Zostałeś uleczony.", "healed": "Zostałeś uleczony.",
"game_start": "Gra rozpoczęta!", "game_start": "Gra rozpoczęta!",
"reload": "Tłumaczenia i konfigi zostały ponownie załadowane.",
"vote_started": "Głosowanie rozpoczęte: '{0}'", "vote_started": "Głosowanie rozpoczęte: '{0}'",
"vote_timeout": "Głosowanie '{0}' przekroczyło limit czasu!", "vote_timeout": "Głosowanie '{0}' przekroczyło limit czasu!",

View file

@ -93,6 +93,9 @@
"distancer": "Medidor de Distância", "distancer": "Medidor de Distância",
"distancer_desc": "Você pode ver a distância até o inimigo mais próximo", "distancer_desc": "Você pode ver a distância até o inimigo mais próximo",
"dash": "Dash",
"dash_desc": "Execute um segundo salto para dar um dash",
"dracula": "Drácula", "dracula": "Drácula",
"dracula_desc": "Acertar um inimigo restaura saúde igual a uma porcentagem do dano causado", "dracula_desc": "Acertar um inimigo restaura saúde igual a uma porcentagem do dano causado",
@ -160,6 +163,9 @@
"godmode_off": "Imortalidade desativada", "godmode_off": "Imortalidade desativada",
"godmode_on": "Imortalidade ativada", "godmode_on": "Imortalidade ativada",
"grenadier": "Grenadier",
"grenadier_desc": "Você tem granadas HE infinitas",
"healingsmoke": "Fumaça Curativa", "healingsmoke": "Fumaça Curativa",
"healingsmoke_desc": "Suas granadas de fumaça curam", "healingsmoke_desc": "Suas granadas de fumaça curam",
@ -371,6 +377,7 @@
"thief_enemy_info": "Sua habilidade foi roubada.", "thief_enemy_info": "Sua habilidade foi roubada.",
"thief_player_info": "A habilidade do jogador '{0}' foi roubada.", "thief_player_info": "A habilidade do jogador '{0}' foi roubada.",
"thief_select_info": "Roubar skill do jogador:", "thief_select_info": "Roubar skill do jogador:",
"thief_incorrect_skill": "Esta habilidade não pode ser selecionada!",
"thirdeye": "Terceiro Olho", "thirdeye": "Terceiro Olho",
"thirdeye_desc": "Clique em [css_useSkill] para ativar a visão em terceira pessoa", "thirdeye_desc": "Clique em [css_useSkill] para ativar a visão em terceira pessoa",
@ -428,6 +435,7 @@
"unpause": "Partida retomada.", "unpause": "Partida retomada.",
"healed": "Você foi curado.", "healed": "Você foi curado.",
"game_start": "Jogo iniciado!", "game_start": "Jogo iniciado!",
"reload": "Os idiomas e as configurações foram recarregados.",
"vote_started": "Votação iniciada: '{0}'", "vote_started": "Votação iniciada: '{0}'",
"vote_timeout": "Votação '{0}' expirou!", "vote_timeout": "Votação '{0}' expirou!",

View file

@ -93,6 +93,9 @@
"distancer": "测距仪", "distancer": "测距仪",
"distancer_desc": "你可以看到与最近敌人的距离", "distancer_desc": "你可以看到与最近敌人的距离",
"dash": "冲刺",
"dash_desc": "执行第二次跳跃来进行冲刺",
"dracula": "德古拉", "dracula": "德古拉",
"dracula_desc": "击中敌人会根据造成的伤害百分比恢复你的生命值", "dracula_desc": "击中敌人会根据造成的伤害百分比恢复你的生命值",
@ -160,6 +163,9 @@
"godmode_off": "无敌状态已禁用", "godmode_off": "无敌状态已禁用",
"godmode_on": "无敌状态已启用", "godmode_on": "无敌状态已启用",
"grenadier": "掷弹兵",
"grenadier_desc": "你拥有无限高爆手雷",
"healingsmoke": "治疗烟雾", "healingsmoke": "治疗烟雾",
"healingsmoke_desc": "你的烟雾弹会治疗", "healingsmoke_desc": "你的烟雾弹会治疗",
@ -371,6 +377,7 @@
"thief_enemy_info": "你的技能被偷走了。", "thief_enemy_info": "你的技能被偷走了。",
"thief_player_info": "玩家 '{0}' 的技能被偷走了。", "thief_player_info": "玩家 '{0}' 的技能被偷走了。",
"thief_select_info": "选择你想偷取其技能的玩家:", "thief_select_info": "选择你想偷取其技能的玩家:",
"thief_incorrect_skill": "此技能无法选择!",
"thirdeye": "第三只眼", "thirdeye": "第三只眼",
"thirdeye_desc": "点击 [css_useSkill] 激活第三人称视角", "thirdeye_desc": "点击 [css_useSkill] 激活第三人称视角",
@ -428,6 +435,7 @@
"unpause": "比赛已恢复。", "unpause": "比赛已恢复。",
"healed": "你已被治疗。", "healed": "你已被治疗。",
"game_start": "游戏开始!", "game_start": "游戏开始!",
"reload": "语言和配置已重新加载。",
"vote_started": "投票开始:'{0}'", "vote_started": "投票开始:'{0}'",
"vote_timeout": "投票'{0}'超时!", "vote_timeout": "投票'{0}'超时!",

View file

@ -11,20 +11,20 @@ namespace jRandomSkills
{ {
public static void DisplaySkillsList(CCSPlayerController player) public static void DisplaySkillsList(CCSPlayerController player)
{ {
CenterHtmlMenu menu = new($"[ ★ {Localization.GetTranslation("skills_menu")} ★ ]"); CenterHtmlMenu menu = new($"[ ★ {player.GetTranslation("skills_menu")} ★ ]");
for (int i = 0; i < SkillData.Skills.Count; i++) for (int i = 0; i < SkillData.Skills.Count; i++)
{ {
var skill = SkillData.Skills[i]; var skill = SkillData.Skills[i];
string skillName = $"{skill.Name}"; string skillName = $"{player.GetSkillName(skill.Skill)}";
menu.AddMenuOption($" ★ {skillName}", (player, option) => menu.AddMenuOption($" ★ {skillName}", (player, option) =>
{ {
string selectedSkillName = option.Text; string selectedSkillName = option.Text;
string pattern = "\\[/?color\\b[^\\]]*\\]"; string pattern = "\\[/?color\\b[^\\]]*\\]";
string cleanSkillName = Regex.Replace(selectedSkillName, pattern, ""); string cleanSkillName = Regex.Replace(selectedSkillName, pattern, "");
string skillName = cleanSkillName.Replace($" ★ ", ""); string skillName = cleanSkillName.Replace($" ★ ", "");
int intValue = Array.IndexOf(SkillData.Skills.Select(r => r.Name).ToArray(), skillName); int intValue = Array.IndexOf(SkillData.Skills.Select(r => player.GetSkillName(r.Skill)).ToArray(), skillName);
string skillDesc = SkillData.Skills[intValue].Description; string skillDesc = player.GetSkillDescription(SkillData.Skills[intValue].Skill);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{skillName}{ChatColors.Lime}: {skillDesc}", false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{skillName}{ChatColors.Lime}: {skillDesc}", false);
MenuManager.CloseActiveMenu(player); MenuManager.CloseActiveMenu(player);
}); });

View file

@ -11,6 +11,7 @@ namespace jRandomSkills
public static class Debug public static class Debug
{ {
private static string sessionId = "00000"; private static string sessionId = "00000";
private static readonly string debugFolder = Path.Combine(Instance.ModuleDirectory, "logs");
public static void Load() public static void Load()
{ {
@ -129,9 +130,7 @@ namespace jRandomSkills
if (Config.LoadedConfig.Settings.DebugMode != true) if (Config.LoadedConfig.Settings.DebugMode != true)
return; return;
string filename = $"Debug_{sessionId}.txt"; string filename = $"debug_{sessionId}.txt";
string pluginFolder = Path.Combine(Server.GameDirectory, "csgo", "addons", "counterstrikesharp", "plugins", "jRandomSkills");
string debugFolder = Path.Combine(pluginFolder, "Debug");
string path = Path.Combine(debugFolder, filename); string path = Path.Combine(debugFolder, filename);
Directory.CreateDirectory(debugFolder); Directory.CreateDirectory(debugFolder);

View file

@ -70,9 +70,11 @@ public enum Skills
Deaf, Deaf,
Disarmament, Disarmament,
Distancer, Distancer,
Dash,
Dracula, Dracula,
Duplicator, Duplicator,
Dwarf, Dwarf,
Earthquake,
EnemySpawn, EnemySpawn,
ExplosiveShot, ExplosiveShot,
FalconEye, FalconEye,
@ -88,6 +90,7 @@ public enum Skills
Glitch, Glitch,
Glue, Glue,
GodMode, GodMode,
Grenadier,
HealingSmoke, HealingSmoke,
Hermit, Hermit,
HolyHandGrenade, HolyHandGrenade,

View file

@ -8,7 +8,6 @@ using CounterStrikeSharp.API.Modules.UserMessages;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.player; using jRandomSkills.src.player;
using jRandomSkills.src.utils; using jRandomSkills.src.utils;
using System.Text.RegularExpressions;
using static CounterStrikeSharp.API.Core.Listeners; using static CounterStrikeSharp.API.Core.Listeners;
using static jRandomSkills.jRandomSkills; using static jRandomSkills.jRandomSkills;
@ -16,7 +15,7 @@ namespace jRandomSkills
{ {
public static partial class Event public static partial class Event
{ {
public static bool enableTransmit = false; public static bool isTransmitRegistered = false;
public static readonly jSkill_SkillInfo noneSkill = new(Skills.None, Config.GetValue<string>(Skills.None, "color"), false); public static readonly jSkill_SkillInfo noneSkill = new(Skills.None, Config.GetValue<string>(Skills.None, "color"), false);
private static jSkill_SkillInfo ctSkill = noneSkill; private static jSkill_SkillInfo ctSkill = noneSkill;
@ -232,13 +231,7 @@ namespace jRandomSkills
SkillChance = 1, SkillChance = 1,
}); });
const string defaultWelcomeMsg = "Welcome {PLAYER}, to the {SERVER_NAME} server!\n" string welcomeMsg = player.GetTranslation("welcome_message", "welcome");
+ "The current version of the jRandomSkills: {VERSION} ({SKILLS_COUNT} skills).\n\n"
+ "Original plugin created by:\n{AUTHOR1}\n"
+ "Modified and improved by:\n{AUTHOR2}";
string langWelcomeMsg = Localization.GetTranslation("welcome_message", "welcome");
string welcomeMsg = MyRegex().IsMatch(langWelcomeMsg) && MyRegex1().IsMatch(langWelcomeMsg) ? langWelcomeMsg : defaultWelcomeMsg;
foreach (string line in welcomeMsg.Split("\n")) foreach (string line in welcomeMsg.Split("\n"))
player.PrintToChat($" {ChatColors.Green}" + line.Replace("{PLAYER}", $" {ChatColors.Red}{player.PlayerName}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) player.PrintToChat($" {ChatColors.Green}" + line.Replace("{PLAYER}", $" {ChatColors.Red}{player.PlayerName}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase)
.Replace("{SERVER_NAME}", $" {ChatColors.Red}{ConVar.Find("hostname")?.StringValue ?? "Default Server"}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) .Replace("{SERVER_NAME}", $" {ChatColors.Red}{ConVar.Find("hostname")?.StringValue ?? "Default Server"}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase)
@ -246,7 +239,6 @@ namespace jRandomSkills
.Replace("{SKILLS_COUNT}", $" {ChatColors.Red}{SkillData.Skills.Count - 1}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) .Replace("{SKILLS_COUNT}", $" {ChatColors.Red}{SkillData.Skills.Count - 1}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase)
.Replace("{AUTHOR1}", $" {ChatColors.Red}Jakub Bartosik (D3X){ChatColors.Green} ({ChatColors.Red}https://github.com/jakubbartosik/dRandomSkills{ChatColors.Green})", StringComparison.OrdinalIgnoreCase) .Replace("{AUTHOR1}", $" {ChatColors.Red}Jakub Bartosik (D3X){ChatColors.Green} ({ChatColors.Red}https://github.com/jakubbartosik/dRandomSkills{ChatColors.Green})", StringComparison.OrdinalIgnoreCase)
.Replace("{AUTHOR2}", $" {ChatColors.Red}Juzlus{ChatColors.Green} ({ChatColors.Red}https://github.com/Juzlus/jRandomSkills{ChatColors.Green})", StringComparison.OrdinalIgnoreCase)); .Replace("{AUTHOR2}", $" {ChatColors.Red}Juzlus{ChatColors.Green} ({ChatColors.Red}https://github.com/Juzlus/jRandomSkills{ChatColors.Green})", StringComparison.OrdinalIgnoreCase));
return HookResult.Continue; return HookResult.Continue;
} }
@ -263,7 +255,7 @@ namespace jRandomSkills
private static HookResult RoundStart(EventRoundStart @event, GameEventInfo info) private static HookResult RoundStart(EventRoundStart @event, GameEventInfo info)
{ {
enableTransmit = false; isTransmitRegistered = false;
Instance.AddTimer(.1f, () => DisableAll()); Instance.AddTimer(.1f, () => DisableAll());
foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist))
{ {
@ -306,18 +298,18 @@ namespace jRandomSkills
var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == _playerSkill.Skill); var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == _playerSkill.Skill);
var specialSkillInfo = SkillData.Skills.FirstOrDefault(s => s.Skill == _playerSkill.SpecialSkill); var specialSkillInfo = SkillData.Skills.FirstOrDefault(s => s.Skill == _playerSkill.SpecialSkill);
if (skillInfo == null) continue; if (skillInfo == null) continue;
skillsText += $" {ChatColors.DarkRed}{_player.PlayerName}{ChatColors.Lime}: {(_playerSkill.SpecialSkill == Skills.None || specialSkillInfo == null ? skillInfo.Name : $"{specialSkillInfo.Name} -> {skillInfo.Name}")}\n"; skillsText += $" {ChatColors.DarkRed}{_player.PlayerName}{ChatColors.Lime}: {(_playerSkill.SpecialSkill == Skills.None || specialSkillInfo == null ? player.GetSkillName(skillInfo.Skill) : $"{player.GetSkillName(specialSkillInfo.Skill)} -> {player.GetSkillName(skillInfo.Skill)}")}\n";
} }
} }
if (Config.LoadedConfig.Settings.SummaryAfterTheRound && !string.IsNullOrEmpty(skillsText)) if (Config.LoadedConfig.Settings.SummaryAfterTheRound && !string.IsNullOrEmpty(skillsText))
{ {
player.PrintToChat(" "); player.PrintToChat(" ");
player.PrintToChat($" {ChatColors.Lime}{Localization.GetTranslation("summary_start")}"); player.PrintToChat($" {ChatColors.Lime}{player.GetTranslation("summary_start")}");
foreach (string text in skillsText.Split("\n")) foreach (string text in skillsText.Split("\n"))
if (!string.IsNullOrEmpty(text)) if (!string.IsNullOrEmpty(text))
player.PrintToChat(text); player.PrintToChat(text);
player.PrintToChat($" {ChatColors.Lime}{Localization.GetTranslation("summary_end")}"); player.PrintToChat($" {ChatColors.Lime}{player.GetTranslation("summary_end")}");
player.PrintToChat(" \n"); player.PrintToChat(" \n");
} }
}); });
@ -348,10 +340,10 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == attackerInfo.Skill); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == attackerInfo.Skill);
var specialSkillData = SkillData.Skills.FirstOrDefault(s => s.Skill == attackerInfo.SpecialSkill); var specialSkillData = SkillData.Skills.FirstOrDefault(s => s.Skill == attackerInfo.SpecialSkill);
if (skillData == null || specialSkillData == null) return HookResult.Continue; if (skillData == null || specialSkillData == null) return HookResult.Continue;
string skillDesc = skillData.Description; string skillDesc = victim.GetSkillDescription(skillData.Skill);
SkillUtils.PrintToChat(victim, $"{Localization.GetTranslation("enemy_skill")} {ChatColors.DarkRed}{attacker.PlayerName}{ChatColors.Lime}:", false); SkillUtils.PrintToChat(victim, $"{victim.GetTranslation("enemy_skill")} {ChatColors.DarkRed}{attacker.PlayerName}{ChatColors.Lime}:", false);
SkillUtils.PrintToChat(victim, $"{ChatColors.DarkRed}{(attackerInfo.SpecialSkill == Skills.None ? skillData.Name : $"{specialSkillData.Name} -> {skillData.Name}")}{ChatColors.Lime} - {skillDesc}", false); SkillUtils.PrintToChat(victim, $"{ChatColors.DarkRed}{(attackerInfo.SpecialSkill == Skills.None ? victim.GetSkillName(skillData.Skill) : $"{victim.GetSkillName(specialSkillData.Skill)} -> {victim.GetSkillName(skillData.Skill)}")}{ChatColors.Lime} - {skillDesc}", false);
} }
} }
return HookResult.Continue; return HookResult.Continue;
@ -394,17 +386,17 @@ namespace jRandomSkills
{ {
List<jSkill_SkillInfo> tSkills = new(SkillData.Skills); List<jSkill_SkillInfo> tSkills = new(SkillData.Skills);
tSkills.RemoveAll(s => s.Skill == tSkill.Skill || s.Skill == Skills.None || counterterroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); tSkills.RemoveAll(s => s.Skill == tSkill.Skill || s.Skill == Skills.None || counterterroristSkills.Any(s2 => s2.Name == s.Skill.ToString()));
tSkill = tSkills.Count == 0 ? new(Skills.None, Config.GetValue<string>(Skills.None, "color"), false) : tSkills[Instance.Random.Next(tSkills.Count)]; tSkill = tSkills.Count == 0 ? noneSkill : tSkills[Instance.Random.Next(tSkills.Count)];
List<jSkill_SkillInfo> ctSkills = new(SkillData.Skills); List<jSkill_SkillInfo> ctSkills = new(SkillData.Skills);
ctSkills.RemoveAll(s => s.Skill == ctSkill.Skill || s.Skill == Skills.None || terroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); ctSkills.RemoveAll(s => s.Skill == ctSkill.Skill || s.Skill == Skills.None || terroristSkills.Any(s2 => s2.Name == s.Skill.ToString()));
ctSkill = ctSkills.Count == 0 ? new(Skills.None, Config.GetValue<string>(Skills.None, "color"), false) : ctSkills[Instance.Random.Next(ctSkills.Count)]; ctSkill = ctSkills.Count == 0 ? noneSkill : ctSkills[Instance.Random.Next(ctSkills.Count)];
} }
else if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.SameSkills) else if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.SameSkills)
{ {
List<jSkill_SkillInfo> allSkills = new(SkillData.Skills); List<jSkill_SkillInfo> allSkills = new(SkillData.Skills);
allSkills.RemoveAll(s => s.Skill == allSkill.Skill || s.Skill == Skills.None || !allTeamsSkills.Any(s2 => s2.Name == s.Skill.ToString())); allSkills.RemoveAll(s => s.Skill == allSkill.Skill || s.Skill == Skills.None || !allTeamsSkills.Any(s2 => s2.Name == s.Skill.ToString()));
allSkill = allSkills.Count == 0 ? new(Skills.None, Config.GetValue<string>(Skills.None, "color"), false) : allSkills[Instance.Random.Next(allSkills.Count)]; allSkill = allSkills.Count == 0 ? noneSkill : allSkills[Instance.Random.Next(allSkills.Count)];
} }
else if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.Debug && debugSkills.Count == 0) else if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.Debug && debugSkills.Count == 0)
debugSkills = new(SkillData.Skills); debugSkills = new(SkillData.Skills);
@ -425,7 +417,7 @@ namespace jRandomSkills
} }
skillPlayer.IsDrawing = false; skillPlayer.IsDrawing = false;
jSkill_SkillInfo randomSkill = new(Skills.None, Config.GetValue<string>(Skills.None, "color"), false); jSkill_SkillInfo randomSkill = noneSkill;
if (Instance?.GameRules != null && Instance?.GameRules.WarmupPeriod == false) if (Instance?.GameRules != null && Instance?.GameRules.WarmupPeriod == false)
{ {
@ -478,12 +470,12 @@ namespace jRandomSkills
} }
if (randomSkill.Display) if (randomSkill.Display)
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{randomSkill.Name}{ChatColors.Lime}: {randomSkill.Description}", false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}", false);
skillPlayer.Skill = randomSkill.Skill; skillPlayer.Skill = randomSkill.Skill;
skillPlayer.SpecialSkill = Skills.None; skillPlayer.SpecialSkill = Skills.None;
Instance?.SkillAction(randomSkill.Skill.ToString(), "EnableSkill", new [] { player }); Instance?.SkillAction(randomSkill.Skill.ToString(), "EnableSkill", new [] { player });
Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{randomSkill.Name}\"."); Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{player.GetSkillName(randomSkill.Skill)}\".");
skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.Settings.SkillDescriptionDuration); skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.Settings.SkillDescriptionDuration);
if (Config.LoadedConfig.Settings.TeamMateSkillInfo) if (Config.LoadedConfig.Settings.TeamMateSkillInfo)
@ -496,13 +488,13 @@ namespace jRandomSkills
if (teammateSkill != null) if (teammateSkill != null)
{ {
var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == teammateSkill); var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == teammateSkill);
teammateSkills += $" {ChatColors.DarkRed}{teammate.PlayerName}{ChatColors.Lime}: {(skillInfo == null ? Skills.None : skillInfo.Name)}\n"; teammateSkills += $" {ChatColors.DarkRed}{teammate.PlayerName}{ChatColors.Lime}: {(skillInfo == null ? player.GetSkillName(Skills.None) : player.GetSkillName(skillInfo.Skill))}\n";
} }
} }
if (!string.IsNullOrEmpty(teammateSkills)) if (!string.IsNullOrEmpty(teammateSkills))
{ {
SkillUtils.PrintToChat(player, $" {ChatColors.Lime}{Localization.GetTranslation("teammate_skills")}:", false); SkillUtils.PrintToChat(player, $" {ChatColors.Lime}{player.GetTranslation("teammate_skills")}:", false);
foreach (string text in teammateSkills.Split("\n")) foreach (string text in teammateSkills.Split("\n"))
if (!string.IsNullOrEmpty(text)) if (!string.IsNullOrEmpty(text))
player.PrintToChat(text); player.PrintToChat(text);
@ -510,8 +502,84 @@ namespace jRandomSkills
}); });
} }
} }
if (enableTransmit) }
Instance?.RegisterListener<CheckTransmit>(CheckTransmit);
public static void SetRandomSkill(CCSPlayerController player)
{
var validPlayers = Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist).ToList();
if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.TeamSkills)
{
List<jSkill_SkillInfo> tSkills = new(SkillData.Skills);
tSkills.RemoveAll(s => s.Skill == tSkill.Skill || s.Skill == Skills.None || counterterroristSkills.Any(s2 => s2.Name == s.Skill.ToString()));
tSkill = tSkills.Count == 0 ? noneSkill : tSkills[0];
List<jSkill_SkillInfo> ctSkills = new(SkillData.Skills);
ctSkills.RemoveAll(s => s.Skill == ctSkill.Skill || s.Skill == Skills.None || terroristSkills.Any(s2 => s2.Name == s.Skill.ToString()));
ctSkill = ctSkills.Count == 0 ? noneSkill : ctSkills[0];
}
if (player == null) return;
var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (skillPlayer == null) return;
if (player.PlayerPawn.Value == null || !player.PlayerPawn.IsValid)
{
skillPlayer.Skill = Skills.None;
return;
}
jSkill_SkillInfo randomSkill = noneSkill;
if (Instance?.GameRules != null && Instance?.GameRules.WarmupPeriod == false)
{
Config.GameModes gameMode = (Config.GameModes)Config.LoadedConfig.Settings.GameMode;
if (staticSkills.TryGetValue(player.SteamID, out var staticSkill))
randomSkill = staticSkill;
else if (gameMode == Config.GameModes.Normal || gameMode == Config.GameModes.NoRepeat)
{
List<jSkill_SkillInfo> skillList = new(SkillData.Skills);
skillList.RemoveAll(s => s?.Skill == skillPlayer?.Skill || s?.Skill == skillPlayer?.SpecialSkill || s?.Skill == Skills.None);
if (validPlayers.Count(p => p.Team == player.Team) == 1)
{
Config.DefaultSkillInfo[] skillsNeedsTeammates = Config.LoadedConfig.SkillsInfo.Where(s => s.NeedsTeammates).ToArray();
skillList.RemoveAll(s => skillsNeedsTeammates.Any(s2 => s2.Name == s.Skill.ToString()));
}
if (player.Team == CsTeam.Terrorist)
skillList.RemoveAll(s => counterterroristSkills.Any(s2 => s2.Name == s.Skill.ToString()));
else
skillList.RemoveAll(s => terroristSkills.Any(s2 => s2.Name == s.Skill.ToString()));
if (gameMode == Config.GameModes.NoRepeat && playersSkills.TryGetValue(player.SteamID, out List<jSkill_SkillInfo>? skills))
{
skillList.RemoveAll(s => skills.Any(s2 => s2.Skill == s.Skill));
if (skillList.Count == 0) skills.Clear();
}
randomSkill = skillList.Count == 0 ? noneSkill : skillList[Instance.Random.Next(skillList.Count)];
if (gameMode == Config.GameModes.NoRepeat)
{
if (playersSkills.TryGetValue(player.SteamID, out List<jSkill_SkillInfo>? value))
value.Add(randomSkill);
else
playersSkills.Add(player.SteamID, [randomSkill]);
}
}
else if (gameMode == Config.GameModes.TeamSkills)
randomSkill = player.Team == CsTeam.Terrorist ? tSkill : ctSkill;
else if (gameMode == Config.GameModes.Debug)
return;
}
if (randomSkill.Display)
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}", false);
skillPlayer.Skill = randomSkill.Skill;
skillPlayer.SpecialSkill = Skills.None;
Instance?.SkillAction(randomSkill.Skill.ToString(), "EnableSkill", new[] { player });
Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{player.GetSkillName(randomSkill.Skill)}\".");
skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.Settings.SkillDescriptionDuration);
} }
public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList)
@ -533,22 +601,17 @@ namespace jRandomSkills
var skillName = playerInfo.Skill.ToString().ToLower(); var skillName = playerInfo.Skill.ToString().ToLower();
var value = Math.Round((double)(playerInfo.SkillChance ?? 1), 2); var value = Math.Round((double)(playerInfo.SkillChance ?? 1), 2);
var desc2 = Localization.GetTranslation($"{skillName}_desc2", value); var desc2 = player.GetTranslation($"{skillName}_desc2", value);
var skilLDescription = desc2 == $"{skillName}_desc2" var skilLDescription = desc2 == $"{skillName}_desc2"
? Localization.GetTranslation($"{skillName}_desc") ? player.GetTranslation($"{skillName}_desc")
: (desc2.Contains('%') ? desc2.Replace(value.ToString(), (value * 100).ToString()) : desc2); : (desc2.Contains('%') ? desc2.Replace(value.ToString(), (value * 100).ToString()) : desc2);
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = $"<font size='0.2' color='#999999'>{skilLDescription} <br>"; string remainingLine = $"<font size='0.2' color='#999999'>{skilLDescription} <br>";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);
} }
[GeneratedRegex(@"\{AUTHOR1\}", RegexOptions.IgnoreCase, "pl-PL")]
private static partial Regex MyRegex();
[GeneratedRegex(@"\{AUTHOR2\}", RegexOptions.IgnoreCase, "pl-PL")]
private static partial Regex MyRegex1();
} }
} }

View file

@ -40,7 +40,7 @@ namespace jRandomSkills
{ {
if (Instance?.GameRules == null || Instance?.GameRules?.Handle == IntPtr.Zero) if (Instance?.GameRules == null || Instance?.GameRules?.Handle == IntPtr.Zero)
InitializeGameRules(); InitializeGameRules();
else if (Instance != null) else if (Instance != null && Config.LoadedConfig.Settings.FlashingHtmlHudFix)
Instance.GameRules.GameRestart = Instance.GameRules?.RestartRoundTime < Server.CurrentTime; Instance.GameRules.GameRestart = Instance.GameRules?.RestartRoundTime < Server.CurrentTime;
} }
@ -55,14 +55,14 @@ namespace jRandomSkills
if (SkillData.Skills.Count == 0) if (SkillData.Skills.Count == 0)
{ {
infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("none")}</font> <br>"; skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("none")}</font> <br>";
} }
else if (skillPlayer.IsDrawing) else if (skillPlayer.IsDrawing)
{ {
var randomSkill = SkillData.Skills[Instance.Random.Next(SkillData.Skills.Count)]; var randomSkill = SkillData.Skills[Instance.Random.Next(SkillData.Skills.Count)];
infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("drawing_skill")}:</font> <br>"; infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("drawing_skill")}:</font> <br>";
skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{randomSkill.Color}'>{randomSkill.Name}</font> <br>"; skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{randomSkill.Color}'>{player.GetSkillName(randomSkill.Skill)}</font> <br>";
} }
else if (!skillPlayer.IsDrawing) else if (!skillPlayer.IsDrawing)
{ {
@ -71,10 +71,10 @@ namespace jRandomSkills
var skillInfo = SkillData.Skills.FirstOrDefault(s => s.Skill == skillPlayer.Skill); var skillInfo = SkillData.Skills.FirstOrDefault(s => s.Skill == skillPlayer.Skill);
if (skillInfo != null) if (skillInfo != null)
{ {
infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillInfo.Color}'>{skillInfo.Name}</font> <br>"; skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillInfo.Color}'>{player.GetSkillName(skillInfo.Skill)}</font> <br>";
} }
} else if (player?.IsValid == true) } else if (player?.IsValid == true && Config.LoadedConfig.Settings.DisableSpectateHUD)
{ {
var pawn = player.Pawn.Value; var pawn = player.Pawn.Value;
if (pawn == null) return; if (pawn == null) return;
@ -94,8 +94,8 @@ namespace jRandomSkills
string pName = observeredPlayerSkill.PlayerName; string pName = observeredPlayerSkill.PlayerName;
if (pName.Length > 18) if (pName.Length > 18)
pName = $"{pName[..17]}..."; pName = $"{pName[..17]}...";
infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("observer_skill")} {pName}:</font> <br>"; infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("observer_skill")} {pName}:</font> <br>";
skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{observeredPlayerSkillInfo.Color}'>{(observeredPlayerSkill.SpecialSkill == Skills.None ? observeredPlayerSkillInfo.Name : $"{observeredPlayerSpecialSkillInfo.Name}({observeredPlayerSkillInfo.Name})")}</font> <br>"; skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{observeredPlayerSkillInfo.Color}'>{(observeredPlayerSkill.SpecialSkill == Skills.None ? player.GetSkillName(observeredPlayerSkillInfo.Skill) : $"{player.GetSkillName(observeredPlayerSpecialSkillInfo.Skill)}({player.GetSkillName(observeredPlayerSkillInfo.Skill)})")}</font> <br>";
} }
} }

View file

@ -83,9 +83,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -32,13 +32,13 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
int site = bombsiteA.Contains(commands[0]) ? 0 : bombsiteB.Contains(commands[0]) ? 1 : -1; int site = bombsiteA.Contains(commands[0]) ? 0 : bombsiteB.Contains(commands[0]) ? 1 : -1;
if (site == -1) { if (site == -1) {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_incorrect_site")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_incorrect_site")}");
return; return;
} }
@ -47,10 +47,10 @@ namespace jRandomSkills
{ {
bombTargets[site].AcceptInput("Disable"); bombTargets[site].AcceptInput("Disable");
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("areareaper_site_disabled", (site == 0 ? 'A' : 'B'))}"); player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("areareaper_site_disabled", (site == 0 ? 'A' : 'B'))}");
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_no_site")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_no_site")}");
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -59,7 +59,7 @@ namespace jRandomSkills
if (playerInfo == null) return; if (playerInfo == null) return;
playerInfo.SkillChance = 0; playerInfo.SkillChance = 0;
HashSet<(string, string)> menuItems = [(Localization.GetTranslation("bombsite_a"), "a"), (Localization.GetTranslation("bombsite_b"), "b")]; HashSet<(string, string)> menuItems = [(player.GetTranslation("bombsite_a"), "a"), (player.GetTranslation("bombsite_b"), "b")];
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }

View file

@ -24,7 +24,7 @@ namespace jRandomSkills
float newScale = (float)Instance.Random.NextDouble() * (Config.GetValue<float>(skillName, "ChanceTo") - Config.GetValue<float>(skillName, "ChanceFrom")) + Config.GetValue<float>(skillName, "ChanceFrom"); float newScale = (float)Instance.Random.NextDouble() * (Config.GetValue<float>(skillName, "ChanceTo") - Config.GetValue<float>(skillName, "ChanceFrom")) + Config.GetValue<float>(skillName, "ChanceFrom");
playerInfo.SkillChance = newScale; playerInfo.SkillChance = newScale;
newScale = (float)Math.Round(newScale, 2); newScale = (float)Math.Round(newScale, 2);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("armored")}{ChatColors.Lime}: " + Localization.GetTranslation("armored_desc2", newScale), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("armored")}{ChatColors.Lime}: " + player.GetTranslation("armored_desc2", newScale), false);
} }
public static void OnTakeDamage(DynamicHook h) public static void OnTakeDamage(DynamicHook h)

View file

@ -30,14 +30,22 @@ namespace jRandomSkills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo == null) return;
player.PlayerPawn.Value.ActualGravityScale = 1; player.PlayerPawn.Value.ActualGravityScale = 1;
playerInfo.SkillChance = 1;
} }
private static void ApplyGravityModifier(CCSPlayerController player) private static void ApplyGravityModifier(CCSPlayerController player)
{ {
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo == null) return;
float gravityModifier = (float)Math.Round(Instance.Random.NextDouble() * (Config.GetValue<float>(skillName, "ChanceTo") - Config.GetValue<float>(skillName, "chanceFrom")) + Config.GetValue<float>(skillName, "chanceFrom"), 1); float gravityModifier = (float)Math.Round(Instance.Random.NextDouble() * (Config.GetValue<float>(skillName, "ChanceTo") - Config.GetValue<float>(skillName, "chanceFrom")) + Config.GetValue<float>(skillName, "chanceFrom"), 1);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("astronaut")}{ChatColors.Lime}: " + Localization.GetTranslation("astronaut_desc2", gravityModifier), false); playerInfo.SkillChance = gravityModifier;
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("astronaut")}{ChatColors.Lime}: " + player.GetTranslation("astronaut_desc2", gravityModifier), false);
player.PlayerPawn.Value.ActualGravityScale = gravityModifier; player.PlayerPawn.Value.ActualGravityScale = gravityModifier;
} }

View file

@ -46,7 +46,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -55,14 +55,14 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
ResetMoney(enemy); ResetMoney(enemy);
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("bankrupt_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("bankrupt_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("bankrupt_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("bankrupt_enemy_info"));
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -78,7 +78,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
private static void ResetMoney(CCSPlayerController enemy) private static void ResetMoney(CCSPlayerController enemy)

View file

@ -36,7 +36,7 @@ namespace jRandomSkills
playerInfo.SkillChance = newChance; playerInfo.SkillChance = newChance;
newChance = (float)Math.Round(newChance, 2) * 100; newChance = (float)Math.Round(newChance, 2) * 100;
newChance = (float)Math.Round(newChance); newChance = (float)Math.Round(newChance);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("behind")}{ChatColors.Lime}: " + Localization.GetTranslation("behind_desc2", newChance), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("behind")}{ChatColors.Lime}: " + player.GetTranslation("behind_desc2", newChance), false);
} }
private static void RotateEnemy(CCSPlayerController player) private static void RotateEnemy(CCSPlayerController player)

View file

@ -62,7 +62,7 @@ namespace jRandomSkills
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
{ {
Event.enableTransmit = true; SkillUtils.EnableTransmit();
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
var playerPawn = player.PlayerPawn.Value; var playerPawn = player.PlayerPawn.Value;

View file

@ -40,7 +40,7 @@ namespace jRandomSkills
playerInfo.SkillChance = newChance; playerInfo.SkillChance = newChance;
newChance = (float)Math.Round(newChance, 2) * 100; newChance = (float)Math.Round(newChance, 2) * 100;
newChance = (float)Math.Round(newChance); newChance = (float)Math.Round(newChance);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("catapult")}{ChatColors.Lime}: " + Localization.GetTranslation("catapult_desc2", newChance), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("catapult")}{ChatColors.Lime}: " + player.GetTranslation("catapult_desc2", newChance), false);
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FF4500", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float chanceFrom = .2f, float chanceTo = .4f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FF4500", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float chanceFrom = .2f, float chanceTo = .4f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)

View file

@ -60,7 +60,7 @@ namespace jRandomSkills
var playerPawn = player.PlayerPawn?.Value; var playerPawn = player.PlayerPawn?.Value;
if (playerPawn != null && playerPawn.IsValid) if (playerPawn != null && playerPawn.IsValid)
{ {
Event.enableTransmit = true; SkillUtils.EnableTransmit();
playerPawn.VelocityModifier = 1.1f; playerPawn.VelocityModifier = 1.1f;
playerPawn.Health = 50; playerPawn.Health = 50;
@ -176,9 +176,9 @@ namespace jRandomSkills
var weapon = pawn.WeaponServices.ActiveWeapon.Value; var weapon = pawn.WeaponServices.ActiveWeapon.Value;
if (weapon == null || !disabledWeapons.Contains(weapon.DesignerName)) return; if (weapon == null || !disabledWeapons.Contains(weapon.DesignerName)) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = $"<font class='fontSize-m' color='#FF0000'>{Localization.GetTranslation("disabled_weapon")}</font> <br>"; string remainingLine = $"<font class='fontSize-m' color='#FF0000'>{player.GetTranslation("disabled_weapon")}</font> <br>";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -62,7 +62,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -71,14 +71,14 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
SetUpPostProcessing(enemy); SetUpPostProcessing(enemy);
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("darkness_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("darkness_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("darkness_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("darkness_enemy_info"));
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -94,7 +94,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -0,0 +1,75 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.player;
using static jRandomSkills.jRandomSkills;
namespace jRandomSkills
{
public class Dash : ISkill
{
private const Skills skillName = Skills.Dash;
private static readonly PlayerFlags[] LF = new PlayerFlags[64];
private static readonly int?[] J = new int?[64];
private static readonly PlayerButtons[] LB = new PlayerButtons[64];
private static readonly float jumpVelocity = Config.GetValue<float>(skillName, "jumpVelocity");
private static readonly float pushVelocity = Config.GetValue<float>(skillName, "pushVelocity");
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, Config.GetValue<string>(skillName, "color"));
}
public static void OnTick()
{
foreach (var player in Utilities.GetPlayers())
{
if (!Instance.IsPlayerValid(player)) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName)
GiveAdditionalJump(player);
}
}
private static void GiveAdditionalJump(CCSPlayerController player)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid) return;
var flags = (PlayerFlags)playerPawn.Flags;
var buttons = player.Buttons;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerPawn == null || playerInfo == null) return;
if ((LF[player.Slot] & PlayerFlags.FL_ONGROUND) != 0 && (flags & PlayerFlags.FL_ONGROUND) == 0 && (LB[player.Slot] & PlayerButtons.Jump) == 0 && (buttons & PlayerButtons.Jump) != 0)
{
}
else if ((flags & PlayerFlags.FL_ONGROUND) != 0)
{
J[player.Slot] = 0;
}
else if ((LB[player.Slot] & PlayerButtons.Jump) == 0 && (buttons & PlayerButtons.Jump) != 0 && J[player.Slot] < 1)
{
J[player.Slot]++;
Vector newVelocity = SkillUtils.GetForwardVector(playerPawn.EyeAngles) * pushVelocity;
newVelocity.Z = playerPawn.AbsVelocity.Z + jumpVelocity;
playerPawn.AbsVelocity.X = newVelocity.X;
playerPawn.AbsVelocity.Y = newVelocity.Y;
playerPawn.AbsVelocity.Z = newVelocity.Z;
}
LF[player.Slot] = flags;
LB[player.Slot] = buttons;
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#42bbfc", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float jumpVelocity = 150f, float pushVelocity = 600f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)
{
public float JumpVelocity { get; set; } = jumpVelocity;
public float PushVelocity { get; set; } = pushVelocity;
}
}
}

View file

@ -32,19 +32,17 @@ namespace jRandomSkills
if (playerInfo == null || playerInfo.Skill != skillName) continue; if (playerInfo == null || playerInfo.Skill != skillName) continue;
var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
if (enemies.Length > 0)
HashSet<(string, string)> menuItems = [];
foreach (var enemy in enemies)
{ {
HashSet<(string, string)> menuItems = []; var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID);
foreach (var enemy in enemies) if (enemyInfo == null) continue;
{ var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); if (skillData == null) continue;
if (enemyInfo == null) continue; menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString()));
}
SkillUtils.CreateMenu(player, menuItems);
} }
SkillUtils.UpdateMenu(player, menuItems);
} }
} }
@ -64,7 +62,7 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
@ -83,12 +81,12 @@ namespace jRandomSkills
if (enemyInfo == null) continue; if (enemyInfo == null) continue;
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue; if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString())); menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
} }
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
@ -108,7 +106,7 @@ namespace jRandomSkills
{ {
playerInfo.Skill = Skills.None; playerInfo.Skill = Skills.None;
playerInfo.SpecialSkill = skillName; playerInfo.SpecialSkill = skillName;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("deactivator_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("deactivator_player_info", enemy.PlayerName));
} }
if (enemyInfo != null) if (enemyInfo != null)
@ -116,7 +114,7 @@ namespace jRandomSkills
Instance.SkillAction(enemyInfo.Skill.ToString(), "DisableSkill", [enemy]); Instance.SkillAction(enemyInfo.Skill.ToString(), "DisableSkill", [enemy]);
enemyInfo.SpecialSkill = enemyInfo.Skill; enemyInfo.SpecialSkill = enemyInfo.Skill;
enemyInfo.Skill = Skills.None; enemyInfo.Skill = Skills.None;
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("deactivator_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("deactivator_enemy_info"));
} }
} }

View file

@ -57,7 +57,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -66,14 +66,14 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
deafPlayers.Add(enemy); deafPlayers.Add(enemy);
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("deaf_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("deaf_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("deaf_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("deaf_enemy_info"));
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -89,7 +89,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -46,7 +46,7 @@ namespace jRandomSkills
playerInfo.SkillChance = newChance; playerInfo.SkillChance = newChance;
newChance = (float)Math.Round(newChance, 2) * 100; newChance = (float)Math.Round(newChance, 2) * 100;
newChance = (float)Math.Round(newChance); newChance = (float)Math.Round(newChance);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("disarmament")}{ChatColors.Lime}: " + Localization.GetTranslation("disarmament_desc2", newChance), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("disarmament")}{ChatColors.Lime}: " + player.GetTranslation("disarmament_desc2", newChance), false);
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FF4500", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float chanceFrom = .2f, float chanceTo = .5f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FF4500", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float chanceFrom = .2f, float chanceTo = .5f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)

View file

@ -48,8 +48,8 @@ namespace jRandomSkills
string distanceColor = closetDistance > 1500 ? "#00FF00" : closetDistance > 600 ? "#FFFF00" : "#FF0000"; string distanceColor = closetDistance > 1500 ? "#00FF00" : closetDistance > 600 ? "#FFFF00" : "#FF0000";
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = $"<font class='fontSize-m' color='#FFFFFF'>{closetEnemy}: <font color='{distanceColor}'>{closetDistance}</font></font> <br>"; string remainingLine = $"<font class='fontSize-m' color='#FFFFFF'>{closetEnemy}: <font color='{distanceColor}'>{closetDistance}</font></font> <br>";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;

View file

@ -13,7 +13,7 @@ namespace jRandomSkills
public static void LoadSkill() public static void LoadSkill()
{ {
SkillUtils.RegisterSkill(skillName, Config.GetValue<string>(skillName, "color")); SkillUtils.RegisterSkill(skillName, Config.GetValue<string>(skillName, "color"), false);
} }
public static void NewRound() public static void NewRound()
@ -32,19 +32,17 @@ namespace jRandomSkills
if (playerInfo == null || playerInfo.Skill != skillName) continue; if (playerInfo == null || playerInfo.Skill != skillName) continue;
var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p != player && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p != player && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
if (enemies.Length > 0)
HashSet<(string, string)> menuItems = [];
foreach (var enemy in enemies)
{ {
HashSet<(string, string)> menuItems = []; var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID);
foreach (var enemy in enemies) if (enemyInfo == null) continue;
{ var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); if (skillData == null) continue;
if (enemyInfo == null) continue; menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString()));
}
SkillUtils.CreateMenu(player, menuItems);
} }
SkillUtils.UpdateMenu(player, menuItems);
} }
} }
@ -64,7 +62,7 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
@ -76,6 +74,7 @@ namespace jRandomSkills
var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p != player && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p != player && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
if (enemies.Length > 0) if (enemies.Length > 0)
{ {
List<string> skills = [];
HashSet<(string, string)> menuItems = []; HashSet<(string, string)> menuItems = [];
foreach (var enemy in enemies) foreach (var enemy in enemies)
{ {
@ -83,12 +82,23 @@ namespace jRandomSkills
if (enemyInfo == null) continue; if (enemyInfo == null) continue;
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue; if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString())); skills.Add(skillData.Skill.ToString());
menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
} }
int ctSkills = Event.counterterroristSkills.Count(s => skills.Contains(s.Name));
int ttSkills = Event.terroristSkills.Count(s => skills.Contains(s.Name));
if ((player.Team == CsTeam.Terrorist && ctSkills == skills.Count) || (player.Team == CsTeam.CounterTerrorist && ttSkills == skills.Count))
{
Event.SetRandomSkill(player);
return;
}
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName)}", false);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
@ -103,17 +113,31 @@ namespace jRandomSkills
{ {
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID);
if (playerInfo == null || enemyInfo == null) return;
if (playerInfo != null && enemyInfo != null) var enemySkill = enemyInfo.Skill;
bool ctSkill = Event.counterterroristSkills.Any(s => s.Name == enemySkill.ToString());
bool ttSkill = Event.terroristSkills.Any(s => s.Name == enemySkill.ToString());
if ((player.Team == CsTeam.Terrorist && ctSkill) || (player.Team == CsTeam.CounterTerrorist && ttSkill))
{ {
Instance.AddTimer(.1f, () => Instance.AddTimer(.1f, () =>
{ {
playerInfo.Skill = enemyInfo.Skill; Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]);
playerInfo.SpecialSkill = skillName; player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemy.PlayerName));
Instance.SkillAction(enemyInfo.Skill.ToString(), "EnableSkill", [player]);
}); });
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("duplicator_player_info", enemy.PlayerName)); return;
} }
SkillUtils.CloseMenu(player);
Instance.AddTimer(.1f, () =>
{
playerInfo.Skill = enemySkill;
playerInfo.SpecialSkill = skillName;
SkillUtils.CloseMenu(player);
Instance.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
});
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("duplicator_player_info", enemy.PlayerName));
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ffb73b", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ffb73b", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)

View file

@ -38,7 +38,7 @@ namespace jRandomSkills
playerInfo.SkillChance = newSize; playerInfo.SkillChance = newSize;
SkillUtils.ChangePlayerScale(player, newSize); SkillUtils.ChangePlayerScale(player, newSize);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("dwarf")}{ChatColors.Lime}: " + Localization.GetTranslation("dwarf_desc2", newSize), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("dwarf")}{ChatColors.Lime}: " + player.GetTranslation("dwarf_desc2", newSize), false);
} }
} }

View file

@ -0,0 +1,148 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.player;
using jRandomSkills.src.utils;
using static jRandomSkills.jRandomSkills;
namespace jRandomSkills
{
public class Earthquake : ISkill
{
private const Skills skillName = Skills.Earthquake;
private static readonly float timerCooldown = Config.GetValue<float>(skillName, "cooldown");
private static readonly float amplitude = Config.GetValue<float>(skillName, "amplitude");
private static readonly float frequency = Config.GetValue<float>(skillName, "frequency");
private static readonly float duration = Config.GetValue<float>(skillName, "duration");
private static readonly float radius = Config.GetValue<float>(skillName, "radius");
private static readonly Dictionary<ulong, PlayerSkillInfo> SkillPlayerInfo = [];
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, Config.GetValue<string>(skillName, "color"));
}
public static void NewRound()
{
SkillPlayerInfo.Clear();
}
public static void EnableSkill(CCSPlayerController player)
{
SkillPlayerInfo[player.SteamID] = new PlayerSkillInfo
{
SteamID = player.SteamID,
CanUse = true,
Cooldown = DateTime.MinValue,
};
}
public static void DisableSkill(CCSPlayerController player)
{
SkillPlayerInfo.Remove(player.SteamID);
}
public static void PlayerDeath(EventPlayerDeath @event)
{
var player = @event.Userid;
if (player == null || !player.IsValid) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName)
SkillPlayerInfo.Remove(player.SteamID);
}
public static void OnTick()
{
foreach (var player in Utilities.GetPlayers())
{
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName)
if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo))
UpdateHUD(player, skillInfo);
}
}
private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo)
{
float cooldown = 0;
if (skillInfo != null)
{
float time = (int)(skillInfo.Cooldown.AddSeconds(timerCooldown) - DateTime.Now).TotalSeconds;
cooldown = Math.Max(time, 0);
if (cooldown == 0 && skillInfo?.CanUse == false)
skillInfo.CanUse = true;
}
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent);
}
public static void UseSkill(CCSPlayerController player)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn?.CBodyComponent == null) return;
if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo))
{
if (!player.IsValid || !player.PawnIsAlive) return;
if (skillInfo.CanUse)
{
skillInfo.CanUse = false;
skillInfo.Cooldown = DateTime.Now;
MakeShake(player);
}
}
}
private static void MakeShake(CCSPlayerController player)
{
foreach (var enemy in Utilities.GetPlayers().Where(p => p != null && p.IsValid && p.PawnIsAlive))
CreateShake(player);
}
private static void CreateShake(CCSPlayerController player)
{
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return;
var shake = Utilities.CreateEntityByName<CEnvShake>("env_shake");
if (shake == null) return;
shake.DispatchSpawn();
if (!shake.IsValid) return;
shake.Amplitude = amplitude;
shake.Frequency = frequency;
shake.Duration = duration;
shake.Radius = radius;
shake.Teleport(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z));
shake.AcceptInput("SetParent", pawn, pawn, "!activator");
shake.AcceptInput("StartShake");
}
public class PlayerSkillInfo
{
public ulong SteamID { get; set; }
public bool CanUse { get; set; }
public DateTime Cooldown { get; set; }
}
public class SkillConfig(Skills skill = skillName, bool active = false, string color = "#42f59b", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float cooldown = 16f, float amplitude = 15f, float frequency = 500f, float duration = 8f, float radius = 50f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)
{
public float Cooldown { get; set; } = cooldown;
public float Amplitude { get; set; } = amplitude;
public float Frequency { get; set; } = frequency;
public float Duration { get; set; } = duration;
public float Radius { get; set; } = radius;
}
}
}

View file

@ -64,9 +64,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -27,7 +27,7 @@ namespace jRandomSkills
playerInfo.SkillChance = newChance; playerInfo.SkillChance = newChance;
newChance = (float)Math.Round(newChance, 2) * 100; newChance = (float)Math.Round(newChance, 2) * 100;
newChance = (float)Math.Round(newChance); newChance = (float)Math.Round(newChance);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("explosiveshot")}{ChatColors.Lime}: " + Localization.GetTranslation("explosiveshot_desc2", newChance), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("explosiveshot")}{ChatColors.Lime}: " + player.GetTranslation("explosiveshot_desc2", newChance), false);
} }
private static void SpawnExplosion(Vector vector) private static void SpawnExplosion(Vector vector)

View file

@ -64,7 +64,7 @@ namespace jRandomSkills
jumpedPlayers.TryAdd(player.SteamID, 0); jumpedPlayers.TryAdd(player.SteamID, 0);
playerPawn.VelocityModifier = newSpeed; playerPawn.VelocityModifier = newSpeed;
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("flash")}{ChatColors.Lime}: " + Localization.GetTranslation("flash_desc2", newSpeed), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("flash")}{ChatColors.Lime}: " + player.GetTranslation("flash_desc2", newSpeed), false);
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -72,9 +72,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -107,7 +107,7 @@ namespace jRandomSkills
return; return;
} }
Server.PrintToChatAll($" {ChatColors.Gold}{Localization.GetTranslation("fragilebomb_bomb_health")}: {ChatColors.Red}{bombHealth}{ChatColors.Gold}/{ChatColors.Green}{maxBombHealth}"); Localization.PrintTranslationToChatAll($" {ChatColors.Gold}{{0}}: {ChatColors.Red}{bombHealth}{ChatColors.Gold}/{ChatColors.Green}{maxBombHealth}", ["fragilebomb_bomb_health"]);
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#5d00ff", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool needsTeammates = false, int maxBombHealth = 1000) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#5d00ff", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool needsTeammates = false, int maxBombHealth = 1000) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)

View file

@ -31,14 +31,14 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
var skill = SkillData.Skills.FirstOrDefault(s => s.Name.Equals(commands[0], StringComparison.OrdinalIgnoreCase) || s.Skill.ToString().Equals(commands[0], StringComparison.OrdinalIgnoreCase)); var skill = SkillData.Skills.FirstOrDefault(s => player.GetSkillName(s.Skill).Equals(commands[0], StringComparison.OrdinalIgnoreCase) || s.Skill.ToString().Equals(commands[0], StringComparison.OrdinalIgnoreCase));
if (skill == null) if (skill == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("skill_not_found_setskill")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("skill_not_found_setskill"));
return; return;
} }
@ -73,9 +73,9 @@ namespace jRandomSkills
skills.Remove(firstSkill); skills.Remove(firstSkill);
var secondSkill = skills[Instance.Random.Next(skills.Count)]; var secondSkill = skills[Instance.Random.Next(skills.Count)];
HashSet<(string, string)> menuItems = [(firstSkill.Name, firstSkill.Skill.ToString()), HashSet<(string, string)> menuItems = [(player.GetSkillName(firstSkill.Skill), firstSkill.Skill.ToString()),
(secondSkill.Name, secondSkill.Skill.ToString()), (player.GetSkillName(secondSkill.Skill), secondSkill.Skill.ToString()),
(Localization.GetTranslation("gambler_more", refreshPrice), skillName.ToString())]; (player.GetTranslation("gambler_more", refreshPrice), skillName.ToString())];
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }

View file

@ -77,7 +77,7 @@ namespace jRandomSkills
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
{ {
Event.enableTransmit = true; SkillUtils.EnableTransmit();
SetPlayerVisibility(player, false); SetPlayerVisibility(player, false);
SetWeaponVisibility(player, false); SetWeaponVisibility(player, false);
SetWeaponAttack(player, true); SetWeaponAttack(player, true);
@ -180,9 +180,9 @@ namespace jRandomSkills
var weapon = pawn.WeaponServices.ActiveWeapon.Value; var weapon = pawn.WeaponServices.ActiveWeapon.Value;
if (weapon == null || !weapon.IsValid || !disabledWeapons.Contains(weapon.DesignerName)) return; if (weapon == null || !weapon.IsValid || !disabledWeapons.Contains(weapon.DesignerName)) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = $"<font class='fontSize-m' color='#FF0000'>{Localization.GetTranslation("disabled_weapon")}</font> <br>"; string remainingLine = $"<font class='fontSize-m' color='#FF0000'>{player.GetTranslation("disabled_weapon")}</font> <br>";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -51,7 +51,7 @@ namespace jRandomSkills
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
{ {
Event.enableTransmit = true; SkillUtils.EnableTransmit();
SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade); SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade);
} }

View file

@ -57,7 +57,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -66,15 +66,15 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
glitchedPlayers.Add(enemy); glitchedPlayers.Add(enemy);
enemy.ReplicateConVar("sv_disable_radar", "1"); enemy.ReplicateConVar("sv_disable_radar", "1");
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("glitch_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("glitch_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("glitch_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("glitch_enemy_info"));
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -90,7 +90,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -65,9 +65,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);
@ -86,14 +86,14 @@ namespace jRandomSkills
skillInfo.CanUse = false; skillInfo.CanUse = false;
skillInfo.Cooldown = DateTime.Now; skillInfo.Cooldown = DateTime.Now;
player.PrintToChat($" {ChatColors.Green} {Localization.GetTranslation("godmode_on")}"); player.PrintToChat($" {ChatColors.Green} {player.GetTranslation("godmode_on")}");
player.PlayerPawn.Value.TakesDamage = false; player.PlayerPawn.Value.TakesDamage = false;
Instance.AddTimer(duration, () => { Instance.AddTimer(duration, () => {
if (player.IsValid && player.PawnIsAlive) if (player.IsValid && player.PawnIsAlive)
{ {
player.PlayerPawn.Value.TakesDamage = true; player.PlayerPawn.Value.TakesDamage = true;
player.PrintToChat($" {ChatColors.Red} {Localization.GetTranslation("godmode_off")}"); player.PrintToChat($" {ChatColors.Red} {player.GetTranslation("godmode_off")}");
} }
}); });
} }

View file

@ -0,0 +1,39 @@
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.player;
using static jRandomSkills.jRandomSkills;
namespace jRandomSkills
{
public class Grenadier : ISkill
{
private const Skills skillName = Skills.Grenadier;
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, Config.GetValue<string>(skillName, "color"));
}
public static void EnableSkill(CCSPlayerController player)
{
if (!Instance.IsPlayerValid(player)) return;
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
}
public static void GrenadeThrown(EventGrenadeThrown @event)
{
var player = @event.Userid;
var weapon = @event.Weapon;
if (weapon != "hegrenade" || !Instance.IsPlayerValid(player)) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID);
if (playerInfo?.Skill == skillName)
player!.GiveNamedItem($"weapon_{weapon}");
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#4a6e21", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)
{
}
}
}

View file

@ -12,7 +12,6 @@ namespace jRandomSkills
{ {
private const Skills skillName = Skills.Jackal; private const Skills skillName = Skills.Jackal;
private static readonly int maxStepBeam = Config.GetValue<int>(skillName, "maxStepBeam"); private static readonly int maxStepBeam = Config.GetValue<int>(skillName, "maxStepBeam");
private static bool exists = false;
private static readonly Dictionary<CCSPlayerController, List<CBeam>> stepBeams = []; private static readonly Dictionary<CCSPlayerController, List<CBeam>> stepBeams = [];
public static void LoadSkill() public static void LoadSkill()
@ -27,8 +26,6 @@ namespace jRandomSkills
if (beam != null && beam.IsValid) if (beam != null && beam.IsValid)
beam.AcceptInput("Kill"); beam.AcceptInput("Kill");
stepBeams.Clear(); stepBeams.Clear();
Instance.RemoveListener<Listeners.CheckTransmit>(CheckTransmit);
exists = false;
} }
public static void OnTick() public static void OnTick()
@ -44,21 +41,20 @@ namespace jRandomSkills
} }
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) continue; if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE || pawn.AbsOrigin == null) continue;
var beams = step.Value; var beams = step.Value;
if (pawn.AbsOrigin == null) continue; Vector lastBeamVector = (beams != null && beams.Count > 0 && beams.Last() != null)
Vector lastBeamVector = beams.Count > 0 ? beams.Last().EndPos : pawn.AbsOrigin;
? beams.LastOrDefault()!.EndPos : pawn.AbsOrigin;
var newBeam = CreateBeamStep(step.Key.Team, lastBeamVector, pawn.AbsOrigin); var newBeam = CreateBeamStep(step.Key.Team, lastBeamVector, pawn.AbsOrigin);
if (newBeam != null) if (newBeam != null)
beams.Add(newBeam); step.Value.Add(newBeam);
if (beams.Count >= maxStepBeam) if (beams?.Count >= maxStepBeam)
{ {
beams[0].AcceptInput("Kill"); beams[0].AcceptInput("Kill");
beams.RemoveAt(0); step.Value.RemoveAt(0);
} }
} }
} }
@ -91,6 +87,9 @@ namespace jRandomSkills
CBeam beam = Utilities.CreateEntityByName<CBeam>("beam")!; CBeam beam = Utilities.CreateEntityByName<CBeam>("beam")!;
if (beam == null) return null; if (beam == null) return null;
beam.DispatchSpawn();
if (!beam.IsValid) return null;
beam.Render = team == CsTeam.Terrorist ? Color.FromArgb(100, 255, 165, 0) : Color.FromArgb(100, 173, 216, 230); beam.Render = team == CsTeam.Terrorist ? Color.FromArgb(100, 255, 165, 0) : Color.FromArgb(100, 173, 216, 230);
beam.Width = 2.0f; beam.Width = 2.0f;
beam.EndWidth = 2.0f; beam.EndWidth = 2.0f;
@ -99,25 +98,28 @@ namespace jRandomSkills
beam.EndPos.X = stop.X; beam.EndPos.X = stop.X;
beam.EndPos.Y = stop.Y; beam.EndPos.Y = stop.Y;
beam.EndPos.Z = stop.Z; beam.EndPos.Z = stop.Z;
beam.DispatchSpawn();
beam.AcceptInput("FollowEntity", beam, null!, "");
return beam; return beam;
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController _)
{ {
if (!exists) SkillUtils.EnableTransmit();
{ foreach (var _player in Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator))
Instance.RegisterListener<Listeners.CheckTransmit>(CheckTransmit); if (!stepBeams.ContainsKey(_player))
foreach (var _player in Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator))
stepBeams.Add(_player, []); stepBeams.Add(_player, []);
}
exists = true;
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f542ef", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, int maxStepBeam = 50) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) public static void DisableSkill(CCSPlayerController player)
{
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo == null) return;
playerInfo.Skill = Skills.None;
if (!Instance.SkillPlayer.Any(s => s.Skill == skillName))
NewRound();
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f542ef", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, int maxStepBeam = 100) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)
{ {
public int MaxStepBeam { get; set; } = maxStepBeam; public int MaxStepBeam { get; set; } = maxStepBeam;
} }

View file

@ -50,7 +50,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -59,15 +59,15 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
jammedPlayers.Add(enemy); jammedPlayers.Add(enemy);
SetCrosshair(enemy, false); SetCrosshair(enemy, false);
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("jammer_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jammer_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("jammer_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("jammer_enemy_info"));
} }
private static void SetCrosshair(CCSPlayerController player, bool enabled) private static void SetCrosshair(CCSPlayerController player, bool enabled)
@ -93,7 +93,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -106,9 +106,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("jester_mode")}: <font color='{(jesterMode ? "#00ff00" : "#ff0000")}'>{Localization.GetTranslation(jesterMode ? "jester_on" : "jester_off")}</font></font> <br>"; string remainingLine = $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("jester_mode")}: <font color='{(jesterMode ? "#00ff00" : "#ff0000")}'>{player.GetTranslation(jesterMode ? "jester_on" : "jester_off")}</font></font> <br>";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -65,7 +65,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -74,14 +74,14 @@ namespace jRandomSkills
if (enemy == null || !enemy.IsValid || enemy.PlayerPawn.Value == null || !enemy.PlayerPawn.Value.IsValid) if (enemy == null || !enemy.IsValid || enemy.PlayerPawn.Value == null || !enemy.PlayerPawn.Value.IsValid)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
bannedPlayers[enemy.PlayerPawn.Value] = 0; bannedPlayers[enemy.PlayerPawn.Value] = 0;
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("jumpban_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jumpban_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("jumpban_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("jumpban_enemy_info"));
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -97,7 +97,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -46,7 +46,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -55,14 +55,14 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
SwapHealth(player, enemy); SwapHealth(player, enemy);
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("lifeswap_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("lifeswap_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("lifeswap_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("lifeswap_enemy_info"));
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -78,7 +78,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
private static void SwapHealth(CCSPlayerController player, CCSPlayerController enemy) private static void SwapHealth(CCSPlayerController player, CCSPlayerController enemy)

View file

@ -1,9 +1,12 @@
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using CS2TraceRay.Class; using CS2TraceRay.Class;
using CS2TraceRay.Enum;
using CS2TraceRay.Struct; using CS2TraceRay.Struct;
using jRandomSkills.src.player; using jRandomSkills.src.player;
using System.Drawing;
using System.Numerics; using System.Numerics;
using static jRandomSkills.jRandomSkills; using static jRandomSkills.jRandomSkills;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
@ -52,7 +55,22 @@ namespace jRandomSkills
filter.m_nHierarchyIds[0] = pawn.GetHierarchyId(); filter.m_nHierarchyIds[0] = pawn.GetHierarchyId();
filter.m_nHierarchyIds[1] = 0; filter.m_nHierarchyIds[1] = 0;
CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray); CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray);
if (Config.LoadedConfig.Settings.CS2TraceRayDebug)
{
CreateLine(eyePos, endPos, Color.FromArgb(255, 255, 255, 0));
CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.EndPos.X, trace.EndPos.Y, trace.EndPos.Z), Color.FromArgb(255, 255, 0, 0));
CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.Position.X, trace.Position.Y, trace.Position.Z), Color.FromArgb(255, 0, 0, 255));
if (trace.DidHit())
{
var val = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity;
player.PrintToChat($"Hit: {trace.DidHit()}, Entity: {(val == null ? "null" : val.DesignerName)}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}");
}
else
player.PrintToChat($"Hit: {trace.DidHit()}, Entity: {trace.HitEntity}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}");
}
if (!trace.HitPlayer(out CCSPlayerController? target) || target == null) if (!trace.HitPlayer(out CCSPlayerController? target) || target == null)
return; return;
@ -62,6 +80,24 @@ namespace jRandomSkills
SkillUtils.TakeHealth(target.PlayerPawn.Value, Instance.Random.Next(21, 34)); SkillUtils.TakeHealth(target.PlayerPawn.Value, Instance.Random.Next(21, 34));
} }
private static void CreateLine(Vector start, Vector end, Color color)
{
CBeam beam = Utilities.CreateEntityByName<CBeam>("beam")!;
if (beam == null) return;
beam.Render = color;
beam.Width = 2.0f;
beam.EndWidth = 2.0f;
beam.Teleport(start);
beam.EndPos.X = end.X;
beam.EndPos.Y = end.Y;
beam.EndPos.Z = end.Z;
beam.DispatchSpawn();
beam.AcceptInput("FollowEntity", beam, null!, "");
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#c9f8ff", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float maxDistance = 4096f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#c9f8ff", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float maxDistance = 4096f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)
{ {
public float MaxDistance { get; set; } = maxDistance; public float MaxDistance { get; set; } = maxDistance;

View file

@ -1,9 +1,12 @@
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using CS2TraceRay.Class; using CS2TraceRay.Class;
using CS2TraceRay.Enum;
using CS2TraceRay.Struct; using CS2TraceRay.Struct;
using jRandomSkills.src.player; using jRandomSkills.src.player;
using System.Drawing;
using System.Numerics; using System.Numerics;
using static jRandomSkills.jRandomSkills; using static jRandomSkills.jRandomSkills;
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
@ -54,6 +57,21 @@ namespace jRandomSkills
filter.m_nHierarchyIds[1] = 0; filter.m_nHierarchyIds[1] = 0;
CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray); CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray);
if (Config.LoadedConfig.Settings.CS2TraceRayDebug)
{
CreateLine(eyePos, endPos, Color.FromArgb(255, 255, 255, 0));
CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.EndPos.X, trace.EndPos.Y, trace.EndPos.Z), Color.FromArgb(255, 255, 0, 0));
CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.Position.X, trace.Position.Y, trace.Position.Z), Color.FromArgb(255, 0, 0, 255));
if (trace.DidHit())
{
var val = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity;
player.PrintToChat($"Hit: {trace.DidHit()}, Entity: {(val == null ? "null" : val.DesignerName)}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}");
}
else
player.PrintToChat($"Hit: {trace.DidHit()}, Entity: {trace.HitEntity}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}");
}
if (!trace.HitPlayer(out CCSPlayerController? target) || target == null) if (!trace.HitPlayer(out CCSPlayerController? target) || target == null)
return; return;
@ -66,6 +84,24 @@ namespace jRandomSkills
SkillUtils.TryGiveWeapon(player, CsItem.Zeus); SkillUtils.TryGiveWeapon(player, CsItem.Zeus);
} }
private static void CreateLine(Vector start, Vector end, Color color)
{
CBeam beam = Utilities.CreateEntityByName<CBeam>("beam")!;
if (beam == null) return;
beam.Render = color;
beam.Width = 2.0f;
beam.EndWidth = 2.0f;
beam.Teleport(start);
beam.EndPos.X = end.X;
beam.EndPos.Y = end.Y;
beam.EndPos.Z = end.Z;
beam.DispatchSpawn();
beam.AcceptInput("FollowEntity", beam, null!, "");
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#6effc7", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float maxDistance = 4096f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#6effc7", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float maxDistance = 4096f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)
{ {
public float MaxDistance { get; set; } = maxDistance; public float MaxDistance { get; set; } = maxDistance;

View file

@ -58,7 +58,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -67,7 +67,7 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
@ -77,8 +77,8 @@ namespace jRandomSkills
Utilities.SetStateChanged(enemy, "CBasePlayerController", "m_iDesiredFOV"); Utilities.SetStateChanged(enemy, "CBasePlayerController", "m_iDesiredFOV");
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("magnifier_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("magnifier_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("magnifier_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("magnifier_enemy_info"));
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -94,7 +94,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -67,10 +67,10 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 string remainingLine = cooldown != 0
? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>"
: $"<font class='fontSize-m' color='#{(skillInfo == null || skillInfo.Count == 0 ? "FF0000" : "00FF00")}'>{(skillInfo == null ? 0 : skillInfo.Count)}/{healthShotLimit}</font> <br>"; : $"<font class='fontSize-m' color='#{(skillInfo == null || skillInfo.Count == 0 ? "FF0000" : "00FF00")}'>{(skillInfo == null ? 0 : skillInfo.Count)}/{healthShotLimit}</font> <br>";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;

View file

@ -46,7 +46,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -55,14 +55,14 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
SwapMoney(player, enemy); SwapMoney(player, enemy);
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("moneyswap_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("moneyswap_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("moneyswap_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("moneyswap_enemy_info"));
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -78,7 +78,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
private static void SwapMoney(CCSPlayerController player, CCSPlayerController enemy) private static void SwapMoney(CCSPlayerController player, CCSPlayerController enemy)

View file

@ -3,6 +3,7 @@ using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.player; using jRandomSkills.src.player;
using jRandomSkills.src.utils;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using static jRandomSkills.jRandomSkills; using static jRandomSkills.jRandomSkills;
@ -48,7 +49,7 @@ namespace jRandomSkills
heProjectile.DispatchSpawn(); heProjectile.DispatchSpawn();
heProjectile.AcceptInput("InitializeSpawnFromWorld", player.PlayerPawn.Value, player.PlayerPawn.Value, ""); heProjectile.AcceptInput("InitializeSpawnFromWorld", player.PlayerPawn.Value, player.PlayerPawn.Value, "");
heProjectile.DetonateTime = 0; heProjectile.DetonateTime = 0;
Server.PrintToChatAll($" {ChatColors.DarkRed}► {ChatColors.Green}[{ChatColors.DarkRed} qRandomSkills {ChatColors.Green}] {ChatColors.DarkRed}{player.PlayerName}: {ChatColors.Lime}ALLAHU AKBAR!!!"); Server.PrintToChatAll($" {ChatColors.DarkRed}► {ChatColors.Green}[{ChatColors.DarkRed} jRandomSkills {ChatColors.Green}] {ChatColors.DarkRed}{player.PlayerName}: {ChatColors.Lime}ALLAHU AKBAR!!!");
var fileNames = new[] { "radiobotfallback01", "radiobotfallback02", "radiobotfallback04" }; var fileNames = new[] { "radiobotfallback01", "radiobotfallback02", "radiobotfallback04" };
Instance.AddTimer(0.1f, () => Instance.AddTimer(0.1f, () =>

View file

@ -71,7 +71,7 @@ namespace jRandomSkills
public static void EnableSkill(CCSPlayerController _) public static void EnableSkill(CCSPlayerController _)
{ {
Event.enableTransmit = true; SkillUtils.EnableTransmit();
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -69,13 +69,13 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 string remainingLine = cooldown != 0
? ( ? (
flying != 0 flying != 0
? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("active_hud_info", $"<font color='#00FF00'>{Math.Round(flying / 100, 2)}</font>")}</font> <br>" ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("active_hud_info", $"<font color='#00FF00'>{Math.Round(flying / 100, 2)}</font>")}</font> <br>"
: $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>"
) : ""; ) : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;

View file

@ -44,7 +44,7 @@ namespace jRandomSkills
float extraJumps = (float)Instance.Random.Next(extraJumpsMin, extraJumpsMax + 1); float extraJumps = (float)Instance.Random.Next(extraJumpsMin, extraJumpsMax + 1);
playerInfo.SkillChance = extraJumps; playerInfo.SkillChance = extraJumps;
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("paweljumper")}{ChatColors.Lime}: " + Localization.GetTranslation("paweljumper_desc2", extraJumps), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("paweljumper")}{ChatColors.Lime}: " + player.GetTranslation("paweljumper_desc2", extraJumps), false);
} }
private static void GiveAdditionalJump(CCSPlayerController player) private static void GiveAdditionalJump(CCSPlayerController player)

View file

@ -27,7 +27,7 @@ namespace jRandomSkills
{ {
player.Respawn(); player.Respawn();
Instance.AddTimer(.2f, () => player.Respawn()); Instance.AddTimer(.2f, () => player.Respawn());
SkillUtils.PrintToChat(player, Localization.GetTranslation("phoenix_respawn"), false); ; SkillUtils.PrintToChat(player, player.GetTranslation("phoenix_respawn"), false); ;
} }
} }
} }
@ -40,7 +40,7 @@ namespace jRandomSkills
playerInfo.SkillChance = newChance; playerInfo.SkillChance = newChance;
newChance = (float)Math.Round(newChance, 2) * 100; newChance = (float)Math.Round(newChance, 2) * 100;
newChance = (float)Math.Round(newChance); newChance = (float)Math.Round(newChance);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("phoenix")}{ChatColors.Lime}: " + Localization.GetTranslation("phoenix_desc2", newChance), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("phoenix")}{ChatColors.Lime}: " + player.GetTranslation("phoenix_desc2", newChance), false);
} }
private static bool IsDeadPlayerValid(CCSPlayerController player) private static bool IsDeadPlayerValid(CCSPlayerController player)

View file

@ -71,9 +71,9 @@ namespace jRandomSkills
if (skillData == null) return; if (skillData == null) return;
string fuelColor = GetFuelColor(pilotInfo.Fuel); string fuelColor = GetFuelColor(pilotInfo.Fuel);
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = $"<font class='fontSize-m' color='#ffffff'>{Localization.GetTranslation("pilot_hud_info")}:</font> <font color='{fuelColor}'>{(pilotInfo.Fuel/maximumFuel)*100:F0}%</font> <br>"; string remainingLine = $"<font class='fontSize-m' color='#ffffff'>{player.GetTranslation("pilot_hud_info")}:</font> <font color='{fuelColor}'>{(pilotInfo.Fuel/maximumFuel)*100:F0}%</font> <br>";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -43,7 +43,7 @@ namespace jRandomSkills
if (!Instance.IsPlayerValid(player)) continue; if (!Instance.IsPlayerValid(player)) continue;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName) if (playerInfo?.Skill == skillName && Instance?.GameRules?.FreezePeriod == false)
Schema.SetSchemaValue<bool>(player!.PlayerPawn.Value!.Handle, "CCSPlayerPawn", "m_bInBombZone", true); Schema.SetSchemaValue<bool>(player!.PlayerPawn.Value!.Handle, "CCSPlayerPawn", "m_bInBombZone", true);
} }
} }

View file

@ -58,7 +58,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -67,14 +67,14 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
poisonedPlayers.Add(enemy); poisonedPlayers.Add(enemy);
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("poison_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("poison_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("poison_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("poison_enemy_info"));
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
@ -90,7 +90,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -62,7 +62,7 @@ namespace jRandomSkills
if (playerInfo.SkillChance == 1) if (playerInfo.SkillChance == 1)
{ {
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
return; return;
} }
@ -71,15 +71,15 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
bannedPlayers.Add(enemy.SteamID); bannedPlayers.Add(enemy.SteamID);
CheckWeapon(enemy); CheckWeapon(enemy);
playerInfo.SkillChance = 1; playerInfo.SkillChance = 1;
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("primaryban_player_info", enemy.PlayerName)); player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("primaryban_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("primaryban_enemy_info")); enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("primaryban_enemy_info"));
} }
private static void CheckWeapon(CCSPlayerController player) private static void CheckWeapon(CCSPlayerController player)
@ -105,7 +105,7 @@ namespace jRandomSkills
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)

View file

@ -112,9 +112,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("psychicdefusing_hud_info", $"<font color='#00d5ff'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("psychicdefusing_hud_info", $"<font color='#00d5ff'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -42,7 +42,7 @@ namespace jRandomSkills
playerInfo.SkillChance = newChance; playerInfo.SkillChance = newChance;
newChance = (float)Math.Round(newChance, 2) * 100; newChance = (float)Math.Round(newChance, 2) * 100;
newChance = (float)Math.Round(newChance); newChance = (float)Math.Round(newChance);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("push")}{ChatColors.Lime}: " + Localization.GetTranslation("push_desc2", newChance), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("push")}{ChatColors.Lime}: " + player.GetTranslation("push_desc2", newChance), false);
} }
private static void PushEnemy(CCSPlayerController player, QAngle attackerAngle) private static void PushEnemy(CCSPlayerController player, QAngle attackerAngle)

View file

@ -9,8 +9,8 @@ namespace jRandomSkills
public class Rambo : ISkill public class Rambo : ISkill
{ {
private const Skills skillName = Skills.Rambo; private const Skills skillName = Skills.Rambo;
private static int minExtraHealth = Config.GetValue<int>(skillName, "minExtraHealth"); private static readonly int minExtraHealth = Config.GetValue<int>(skillName, "minExtraHealth");
private static int maxExtraHealth = Config.GetValue<int>(skillName, "maxExtraHealth"); private static readonly int maxExtraHealth = Config.GetValue<int>(skillName, "maxExtraHealth");
public static void LoadSkill() public static void LoadSkill()
{ {
@ -52,15 +52,10 @@ namespace jRandomSkills
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth"); Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth");
} }
public class SkillConfig : Config.DefaultSkillInfo public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#009905", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, int minExtraHealth = 50, int maxExtraHealth = 501) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)
{ {
public int MinExtraHealth { get; set; } public int MinExtraHealth { get; set; } = minExtraHealth;
public int MaxExtraHealth { get; set; } public int MaxExtraHealth { get; set; } = maxExtraHealth;
public SkillConfig(Skills skill = skillName, bool active = true, string color = "#009905", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, int minExtraHealth = 50, int maxExtraHealth = 501) : base(skill, active, color, onlyTeam, needsTeammates)
{
MinExtraHealth = minExtraHealth;
MaxExtraHealth = maxExtraHealth;
}
} }
} }
} }

View file

@ -73,9 +73,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -80,9 +80,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -65,9 +65,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -64,9 +64,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -50,6 +50,8 @@ namespace jRandomSkills
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
secondLifePlayers.Remove(player.Handle); secondLifePlayers.Remove(player.Handle);
if (player.PlayerPawn.Value == null) return;
SetHealth(player, Math.Min(player.PlayerPawn.Value.Health + secondLifeHealth, 100));
} }
private static void SetHealth(CCSPlayerController player, int health) private static void SetHealth(CCSPlayerController player, int health)
@ -58,9 +60,7 @@ namespace jRandomSkills
if (pawn == null || !pawn.IsValid) return; if (pawn == null || !pawn.IsValid) return;
pawn.Health = health; pawn.Health = health;
pawn.MaxHealth = health;
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth"); Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth");
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iMaxHealth");
pawn.ArmorValue = 0; pawn.ArmorValue = 0;
Utilities.SetStateChanged(pawn, "CCSPlayerPawn", "m_ArmorValue"); Utilities.SetStateChanged(pawn, "CCSPlayerPawn", "m_ArmorValue");

View file

@ -59,9 +59,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = $"<font class='fontSize-m' color='#FF0000'>{Localization.GetTranslation("shade_nospace")}</font> <br>"; string remainingLine = $"<font class='fontSize-m' color='#FF0000'>{player.GetTranslation("shade_nospace")}</font> <br>";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);
} }

View file

@ -9,6 +9,7 @@ namespace jRandomSkills
public class SniperElite : ISkill public class SniperElite : ISkill
{ {
private const Skills skillName = Skills.SniperElite; private const Skills skillName = Skills.SniperElite;
private static readonly Dictionary<ulong, List<CEntityInstance>> playerAWPs = [];
private static readonly Dictionary<ulong, string> sniperElites = []; private static readonly Dictionary<ulong, string> sniperElites = [];
private static readonly string[] rifles = [ "weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90", private static readonly string[] rifles = [ "weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7", "weapon_ump45", "weapon_p90",
@ -24,6 +25,7 @@ namespace jRandomSkills
public static void NewRound() public static void NewRound()
{ {
sniperElites.Clear(); sniperElites.Clear();
playerAWPs.Clear();
} }
public static void PlayerDeath(EventPlayerDeath @event) public static void PlayerDeath(EventPlayerDeath @event)
@ -32,18 +34,27 @@ namespace jRandomSkills
if (player == null || !player.IsValid) return; if (player == null || !player.IsValid) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName) if (playerInfo?.Skill == skillName)
sniperElites.Remove(player.SteamID); DisableSkill(player);
}
public static void WeaponEquip(EventItemEquip @event)
{
var player = @event.Userid;
if (player == null || !player.IsValid) return;
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo?.Skill == skillName)
DeleteDroppedAWP(player);
} }
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
{ {
sniperElites.Add(player.SteamID, "weapon_awp"); sniperElites.TryAdd(player.SteamID, "weapon_awp");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
{ {
sniperElites.Remove(player.SteamID); sniperElites.Remove(player.SteamID);
playerAWPs.Remove(player.SteamID);
} }
public static void UseSkill(CCSPlayerController player) public static void UseSkill(CCSPlayerController player)
@ -64,18 +75,58 @@ namespace jRandomSkills
try try
{ {
string? activeRifle = GetActiveRifle(player); CBasePlayerWeapon? activeRifle = GetActiveRifle(player);
if (!string.IsNullOrEmpty(activeRifle)) if (activeRifle != null && activeRifle.IsValid)
player.RemoveItemByDesignerName(activeRifle, true); RemoveWeapon(player, activeRifle.DesignerName);
sniperElites[player.SteamID] = activeRifle ?? "weapon_awp";
Server.NextFrame(() => player.GiveNamedItem(holdedWeapon ?? "weapon_awp") ); sniperElites[player.SteamID] = (activeRifle != null && activeRifle.IsValid) ? SkillUtils.GetDesignerName(activeRifle) : "weapon_awp";
Server.NextFrame(() => {
string weapon = holdedWeapon ?? "weapon_awp";
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
var createdWeapon = player.PlayerPawn.Value?.ItemServices?.As<CCSPlayer_ItemServices>().GiveNamedItem<CEntityInstance>(weapon);
if (createdWeapon != null && createdWeapon.IsValid && createdWeapon.DesignerName == "weapon_awp")
{
if (playerAWPs.TryGetValue(player.SteamID, out List<CEntityInstance>? value))
value.Add(createdWeapon);
else
playerAWPs.Add(player.SteamID, [createdWeapon]);
}
DeleteDroppedAWP(player);
});
} }
catch { } catch { }
} }
private static string? GetActiveRifle(CCSPlayerController player) private static void DeleteDroppedAWP(CCSPlayerController player)
{ {
string rifle = string.Empty; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return;
var weaponServices = pawn.WeaponServices;
if (weaponServices == null) return;
List<uint> playerWeapons = weaponServices.MyWeapons.Where(w => w != null && w.IsValid && w.Value != null && w.Value.IsValid)
.Select(w => w.Value!.Index).ToList();
if (playerAWPs.TryGetValue(player.SteamID, out var AWPs))
foreach (var awp in AWPs.ToList())
{
if (awp != null && awp.IsValid)
{
if (!playerWeapons.Contains(awp.Index))
{
awp.AcceptInput("Kill");
AWPs.Remove(awp);
}
}
else
AWPs.Remove(awp!);
}
}
private static CBasePlayerWeapon? GetActiveRifle(CCSPlayerController player)
{
CBasePlayerWeapon? rifle = null;
var pawn = player.PlayerPawn.Value; var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid) return rifle; if (pawn == null || !pawn.IsValid) return rifle;
var weaponServices = pawn.WeaponServices; var weaponServices = pawn.WeaponServices;
@ -84,11 +135,21 @@ namespace jRandomSkills
foreach (var weapon in weaponServices.MyWeapons) foreach (var weapon in weaponServices.MyWeapons)
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid) if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
if (rifles.Contains(weapon.Value.DesignerName)) if (rifles.Contains(weapon.Value.DesignerName))
rifle = SkillUtils.GetDesignerName(weapon.Value); rifle = weapon.Value;
return rifle; return rifle;
} }
public class SkillConfig(Skills skill = skillName, bool active = false, string color = "#e0873a", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) private static void RemoveWeapon(CCSPlayerController player, string designerName)
{
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return;
foreach (var item in pawn.WeaponServices.MyWeapons)
if (item != null && item.IsValid && item.Value != null && item.Value.IsValid && item.Value.DesignerName == designerName)
item.Value.AcceptInput("Kill");
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#e0873a", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)
{ {
} }
} }

View file

@ -23,7 +23,7 @@ namespace jRandomSkills
float newScale = (float)Instance.Random.NextDouble() * (Config.GetValue<float>(skillName, "ChanceTo") - Config.GetValue<float>(skillName, "ChanceFrom")) + Config.GetValue<float>(skillName, "ChanceFrom"); float newScale = (float)Instance.Random.NextDouble() * (Config.GetValue<float>(skillName, "ChanceTo") - Config.GetValue<float>(skillName, "ChanceFrom")) + Config.GetValue<float>(skillName, "ChanceFrom");
playerInfo.SkillChance = newScale; playerInfo.SkillChance = newScale;
newScale = (float)Math.Round(newScale, 2); newScale = (float)Math.Round(newScale, 2);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("soldier")}{ChatColors.Lime}: " + Localization.GetTranslation("soldier_desc2", newScale), false); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetTranslation("soldier")}{ChatColors.Lime}: " + player.GetTranslation("soldier_desc2", newScale), false);
} }
public static void OnTakeDamage(DynamicHook h) public static void OnTakeDamage(DynamicHook h)

View file

@ -73,9 +73,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; string remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -69,16 +69,16 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = ""; string remainingLine = "";
if (showInfo) if (showInfo)
remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>"
: skillInfo != null && !skillInfo.FindedEnemy ? $"<font class='fontSize-m' color='#FF0000'>{Localization.GetTranslation("hud_info_no_enemy")}</font> <br>" : skillInfo != null && !skillInfo.FindedEnemy ? $"<font class='fontSize-m' color='#FF0000'>{player.GetTranslation("hud_info_no_enemy")}</font> <br>"
: ""; : "";
else else
remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);

View file

@ -13,7 +13,7 @@ namespace jRandomSkills
public static void LoadSkill() public static void LoadSkill()
{ {
SkillUtils.RegisterSkill(skillName, Config.GetValue<string>(skillName, "color")); SkillUtils.RegisterSkill(skillName, Config.GetValue<string>(skillName, "color"), false);
} }
public static void OnTick() public static void OnTick()
@ -26,19 +26,17 @@ namespace jRandomSkills
if (playerInfo == null || playerInfo.Skill != skillName) continue; if (playerInfo == null || playerInfo.Skill != skillName) continue;
var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
if (enemies.Length > 0)
HashSet<(string, string)> menuItems = [];
foreach (var enemy in enemies)
{ {
HashSet<(string, string)> menuItems = []; var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID);
foreach (var enemy in enemies) if (enemyInfo == null) continue;
{ var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); if (skillData == null) continue;
if (enemyInfo == null) continue; menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString()));
}
SkillUtils.CreateMenu(player, menuItems);
} }
SkillUtils.UpdateMenu(player, menuItems);
} }
} }
@ -64,7 +62,7 @@ namespace jRandomSkills
if (enemy == null) if (enemy == null)
{ {
player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
return; return;
} }
@ -76,6 +74,7 @@ namespace jRandomSkills
var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
if (enemies.Length > 0) if (enemies.Length > 0)
{ {
List<string> skills = [];
HashSet<(string, string)> menuItems = []; HashSet<(string, string)> menuItems = [];
foreach (var enemy in enemies) foreach (var enemy in enemies)
{ {
@ -83,12 +82,23 @@ namespace jRandomSkills
if (enemyInfo == null) continue; if (enemyInfo == null) continue;
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill);
if (skillData == null) continue; if (skillData == null) continue;
menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString())); skills.Add(skillData.Skill.ToString());
menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString()));
} }
int ctSkills = Event.counterterroristSkills.Count(s => skills.Contains(s.Name));
int ttSkills = Event.terroristSkills.Count(s => skills.Contains(s.Name));
if ((player.Team == CsTeam.Terrorist && ctSkills == skills.Count) || (player.Team == CsTeam.CounterTerrorist && ttSkills == skills.Count))
{
Event.SetRandomSkill(player);
return;
}
SkillUtils.CreateMenu(player, menuItems); SkillUtils.CreateMenu(player, menuItems);
SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName)}", false);
} }
else else
player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
} }
public static void DisableSkill(CCSPlayerController player) public static void DisableSkill(CCSPlayerController player)
@ -104,29 +114,38 @@ namespace jRandomSkills
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID);
if (playerInfo == null || enemyInfo == null) return; if (playerInfo == null || enemyInfo == null) return;
var enemySkill = enemyInfo.Skill; var enemySkill = enemyInfo.Skill;
bool ctSkill = Event.counterterroristSkills.Any(s => s.Name == enemySkill.ToString());
bool ttSkill = Event.terroristSkills.Any(s => s.Name == enemySkill.ToString());
if (playerInfo != null) if ((player.Team == CsTeam.Terrorist && ctSkill) || (player.Team == CsTeam.CounterTerrorist && ttSkill))
{ {
Instance.AddTimer(.1f, () => Instance.AddTimer(.1f, () =>
{ {
playerInfo.Skill = enemySkill; Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]);
playerInfo.SpecialSkill = skillName; player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemy.PlayerName));
Instance.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("thief_player_info", enemy.PlayerName));
}); });
return;
} }
if (enemyInfo != null) SkillUtils.CloseMenu(player);
Instance.AddTimer(.1f, () =>
{ {
Instance.AddTimer(.1f, () => playerInfo.Skill = enemySkill;
{ playerInfo.SpecialSkill = skillName;
Instance.SkillAction(enemySkill.ToString(), "DisableSkill", [enemy]); SkillUtils.CloseMenu(player);
enemyInfo.SpecialSkill = enemySkill; Instance.SkillAction(enemySkill.ToString(), "EnableSkill", [player]);
enemyInfo.Skill = Skills.None; player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("thief_player_info", enemy.PlayerName));
enemy.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("thief_enemy_info")); });
});
} Instance.AddTimer(.1f, () =>
{
Instance.SkillAction(enemySkill.ToString(), "DisableSkill", [enemy]);
enemyInfo.SpecialSkill = enemySkill;
enemyInfo.Skill = Skills.None;
enemy.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_enemy_info"));
});
} }
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#adaec7", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#adaec7", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates)

View file

@ -53,10 +53,20 @@ namespace jRandomSkills
public static void EnableSkill(CCSPlayerController player) public static void EnableSkill(CCSPlayerController player)
{ {
Event.enableTransmit = true; SkillUtils.EnableTransmit();
SetGlowEffectForEnemies(player); SetGlowEffectForEnemies(player);
} }
public static void DisableSkill(CCSPlayerController player)
{
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
if (playerInfo == null) return;
playerInfo.Skill = Skills.None;
if (!Instance.SkillPlayer.Any(s => s.Skill == skillName))
NewRound();
}
private static void SetGlowEffectForEnemies(CCSPlayerController player) private static void SetGlowEffectForEnemies(CCSPlayerController player)
{ {
CsTeam originalTeam = player.Team; CsTeam originalTeam = player.Team;

View file

@ -47,9 +47,9 @@ namespace jRandomSkills
Instance.GameRules.RoundTime += player.Team == CsTeam.Terrorist ? roundTime : -roundTime; Instance.GameRules.RoundTime += player.Team == CsTeam.Terrorist ? roundTime : -roundTime;
if (player.Team == CsTeam.Terrorist) if (player.Team == CsTeam.Terrorist)
Server.PrintToChatAll($" {ChatColors.Orange}{Localization.GetTranslation("watchmaker_tt", roundTime)}"); Localization.PrintTranslationToChatAll($" {ChatColors.Orange}{{0}}", ["watchmaker_tt"], [roundTime]);
else else
Server.PrintToChatAll($" {ChatColors.LightBlue}{Localization.GetTranslation("watchmaker_ct", roundTime)}"); Localization.PrintTranslationToChatAll($" {ChatColors.LightBlue}{{0}}", ["watchmaker_ct"], [roundTime]);
} }
public static void OnTick() public static void OnTick()
@ -70,8 +70,8 @@ namespace jRandomSkills
int seconds = 1 + (int)(Instance.GameRules.RoundTime - (Server.CurrentTime - Instance.GameRules.RoundStartTime)); int seconds = 1 + (int)(Instance.GameRules.RoundTime - (Server.CurrentTime - Instance.GameRules.RoundStartTime));
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = $"<font class='fontSize-m' color='#FFFFFF'>{SkillUtils.SecondsToTimer(seconds)}</font> <br>"; string remainingLine = $"<font class='fontSize-m' color='#FFFFFF'>{SkillUtils.SecondsToTimer(seconds)}</font> <br>";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;

View file

@ -77,17 +77,17 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>"; string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>";
string remainingLine = ""; string remainingLine = "";
if (showInfo) if (showInfo)
remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>"
: skillInfo != null && !skillInfo.FindedEnemy ? $"<font class='fontSize-m' color='#FF0000'>{Localization.GetTranslation("hud_info_no_enemy")}</font> <br>" : skillInfo != null && !skillInfo.FindedEnemy ? $"<font class='fontSize-m' color='#FF0000'>{player.GetTranslation("hud_info_no_enemy")}</font> <br>"
: skillInfo != null && !skillInfo.HaveWeapon ? $"<font class='fontSize-m' color='#FF0000'>{Localization.GetTranslation("weaponsswap_hud_info2")}</font> <br>" : skillInfo != null && !skillInfo.HaveWeapon ? $"<font class='fontSize-m' color='#FF0000'>{player.GetTranslation("weaponsswap_hud_info2")}</font> <br>"
: ""; : "";
else else
remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{Localization.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : ""; remainingLine = cooldown != 0 ? $"<font class='fontSize-m' color='#FFFFFF'>{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}</font> <br>" : "";
var hudContent = infoLine + skillLine + remainingLine; var hudContent = infoLine + skillLine + remainingLine;
player.PrintToCenterHtml(hudContent); player.PrintToCenterHtml(hudContent);
@ -127,10 +127,16 @@ namespace jRandomSkills
skillInfo.CanUse = false; skillInfo.CanUse = false;
skillInfo.Cooldown = DateTime.Now; skillInfo.Cooldown = DateTime.Now;
player.RemoveWeapons(); RemoveC4(player);
enemy.RemoveWeapons(); RemoveC4(enemy);
GiveWeapons(player, enemyWeapon, playerWeapon.Contains("weapon_c4"));
GiveWeapons(enemy, playerWeapon, (enemyWeapon != null && enemyWeapon.Contains("weapon_c4"))); Server.NextFrame(() =>
{
player.RemoveWeapons();
enemy.RemoveWeapons();
GiveWeapons(player, enemyWeapon, playerWeapon.Contains("weapon_c4"));
GiveWeapons(enemy, playerWeapon, (enemyWeapon != null && enemyWeapon.Contains("weapon_c4")));
});
} }
else else
skillInfo.LastClick = DateTime.Now; skillInfo.LastClick = DateTime.Now;
@ -167,6 +173,16 @@ namespace jRandomSkills
return enemies[Instance.Random.Next(enemies.Length)]; return enemies[Instance.Random.Next(enemies.Length)];
} }
private static void RemoveC4(CCSPlayerController player)
{
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return;
foreach (var item in pawn.WeaponServices.MyWeapons)
if (item != null && item.IsValid && item.Value != null && item.Value.IsValid && item.Value.DesignerName == "weapon_c4")
item.Value.AcceptInput("Kill");
}
public class PlayerSkillInfo public class PlayerSkillInfo
{ {
public ulong SteamID { get; set; } public ulong SteamID { get; set; }

View file

@ -10,18 +10,13 @@ namespace jRandomSkills
{ {
public static class Config public static class Config
{ {
private static readonly string configPath = Path.Combine(Instance.ModuleDirectory, "Config.json"); private static readonly string configsFolder = Path.Combine(Instance.ModuleDirectory, "configs");
private static readonly string configPath = Path.Combine(configsFolder, "config.json");
private static ConfigModel config = LoadConfig(); private static ConfigModel config = LoadConfig();
private static FileSystemWatcher? fileWatcher;
public static ConfigModel LoadedConfig => config; public static ConfigModel LoadedConfig => config;
public static void Initialize() public static ConfigModel LoadConfig()
{
SetupFileWatcher();
}
private static ConfigModel LoadConfig()
{ {
if (!File.Exists(configPath)) if (!File.Exists(configPath))
{ {
@ -64,6 +59,7 @@ namespace jRandomSkills
{ {
try try
{ {
Directory.CreateDirectory(configsFolder);
string json = JsonConvert.SerializeObject(config, Formatting.Indented); string json = JsonConvert.SerializeObject(config, Formatting.Indented);
File.WriteAllText(configPath, json); File.WriteAllText(configPath, json);
} }
@ -73,20 +69,6 @@ namespace jRandomSkills
} }
} }
private static void SetupFileWatcher()
{
string? path = Path.GetDirectoryName(configPath);
if (string.IsNullOrEmpty(path)) return;
fileWatcher = new FileSystemWatcher(path)
{
Filter = Path.GetFileName(configPath),
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size
};
fileWatcher.Changed += (sender, e) => config = LoadConfig();
fileWatcher.EnableRaisingEvents = true;
}
public static T GetValue<T>(object skill, string key) public static T GetValue<T>(object skill, string key)
{ {
var skillConfig = config.SkillsInfo.FirstOrDefault(s => s.Name == skill.ToString()); var skillConfig = config.SkillsInfo.FirstOrDefault(s => s.Name == skill.ToString());
@ -143,12 +125,18 @@ namespace jRandomSkills
public string? AlternativeSkillButton { get; set; } public string? AlternativeSkillButton { get; set; }
public float SkillTimeBeforeStart { get; set; } public float SkillTimeBeforeStart { get; set; }
public float SkillDescriptionDuration { get; set; } public float SkillDescriptionDuration { get; set; }
public bool DisableSpectateHUD { get; set; }
public bool FlashingHtmlHudFix { get; set; }
public bool CS2TraceRayDebug { get; set; }
public NormalCommand SetSkillCommands { get; set; } public NormalCommand SetSkillCommands { get; set; }
public NormalCommand SkillsListCommands { get; set; } public NormalCommand SkillsListCommands { get; set; }
public NormalCommand UseSkillCommands { get; set; } public NormalCommand UseSkillCommands { get; set; }
public NormalCommand HealCommands { get; set; } public NormalCommand HealCommands { get; set; }
public NormalCommand ConsoleCommands { get; set; } public NormalCommand ConsoleCommands { get; set; }
public NormalCommand SetStaticSkillCommands { get; set; } public NormalCommand SetStaticSkillCommands { get; set; }
public NormalCommand ChangeLanguageCommands { get; set; }
public NormalCommand ReloadCommands { get; set; }
public VotingCommand StartGameCommands { get; set; } public VotingCommand StartGameCommands { get; set; }
public VotingCommand ChangeMapCommands { get; set; } public VotingCommand ChangeMapCommands { get; set; }
public VotingCommand SwapCommands { get; set; } public VotingCommand SwapCommands { get; set; }
@ -167,6 +155,9 @@ namespace jRandomSkills
AlternativeSkillButton = null; AlternativeSkillButton = null;
SkillTimeBeforeStart = 7; SkillTimeBeforeStart = 7;
SkillDescriptionDuration = 7; SkillDescriptionDuration = 7;
FlashingHtmlHudFix = true;
CS2TraceRayDebug = false;
DisableSpectateHUD = false;
SetSkillCommands = new NormalCommand("ustawskill, ustaw_skill, setskill, set_skill, definirhabilidade, configurarhabilidade, 设置技能, 配置技能", "@jRandmosSkills/admin"); SetSkillCommands = new NormalCommand("ustawskill, ustaw_skill, setskill, set_skill, definirhabilidade, configurarhabilidade, 设置技能, 配置技能", "@jRandmosSkills/admin");
SkillsListCommands = new NormalCommand("supermoc, skille, listamocy, supermoce, skills, listaHabilidades, habilidades, 技能列表, 超能力列表", "@jRandmosSkills/admin"); SkillsListCommands = new NormalCommand("supermoc, skille, listamocy, supermoce, skills, listaHabilidades, habilidades, 技能列表, 超能力列表", "@jRandmosSkills/admin");
@ -174,6 +165,8 @@ namespace jRandomSkills
HealCommands = new NormalCommand("heal, ulecz, curar, tratar, 治疗, 治愈", "@jRandmosSkills/admin"); HealCommands = new NormalCommand("heal, ulecz, curar, tratar, 治疗, 治愈", "@jRandmosSkills/admin");
ConsoleCommands = new NormalCommand("console, sv, 控制台, 服务器", "@jRandmosSkills/root"); ConsoleCommands = new NormalCommand("console, sv, 控制台, 服务器", "@jRandmosSkills/root");
SetStaticSkillCommands = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandmosSkills/admin"); SetStaticSkillCommands = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandmosSkills/admin");
ChangeLanguageCommands = new NormalCommand("lang, language, changelang, change_lang, jezyk, język", "");
ReloadCommands = new NormalCommand("reload, refresh", "@jRandmosSkills/admin");
StartGameCommands = new VotingCommand(true, "start, go, começar, iniciar, 开始, 启动", "@jRandmosSkills/admin", 15, 60, 15, 500, 2); StartGameCommands = new VotingCommand(true, "start, go, começar, iniciar, 开始, 启动", "@jRandmosSkills/admin", 15, 60, 15, 500, 2);
ChangeMapCommands = new VotingCommand( true, "map, mapa, changemap, zmienmape, zmienmape, mudarMapa, trocarMapa, 更换地图, 更改地图", "@jRandmosSkills/admin", 25, 90, 15, 500, 2); ChangeMapCommands = new VotingCommand( true, "map, mapa, changemap, zmienmape, zmienmape, mudarMapa, trocarMapa, 更换地图, 更改地图", "@jRandmosSkills/admin", 25, 90, 15, 500, 2);

View file

@ -25,16 +25,15 @@ public class FindTarget
if (targetresult.Players.Count == 0) if (targetresult.Players.Count == 0)
{ {
if (!ignoreMessage) if (!ignoreMessage && command.CallingPlayer != null)
{ command.ReplyToCommand(command.CallingPlayer.GetTranslation("no_player"));
command.ReplyToCommand(Localization.GetTranslation("no_player"));
}
return (new List<CCSPlayerController>(), string.Empty); return (new List<CCSPlayerController>(), string.Empty);
} }
else if (singletarget && targetresult.Players.Count > 1) else if (singletarget && targetresult.Players.Count > 1)
{ {
command.ReplyToCommand(Localization.GetTranslation("duplicate_player")); if (command.CallingPlayer != null)
command.ReplyToCommand(command.CallingPlayer.GetTranslation("duplicate_player"));
return (new List<CCSPlayerController>(), string.Empty); return (new List<CCSPlayerController>(), string.Empty);
} }

View file

@ -1,33 +1,47 @@
using CounterStrikeSharp.API.Modules.Utils; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using jRandomSkills.src.player;
using MaxMind.Db;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Text.Json; using System.Net;
namespace jRandomSkills.src.utils namespace jRandomSkills.src.utils
{ {
public static class Localization public static class Localization
{ {
private static readonly string path = Path.Combine(jRandomSkills.Instance.ModuleDirectory, "lang"); private static readonly string languagesFolderPath = Path.Combine(jRandomSkills.Instance.ModuleDirectory, "languages");
private static readonly Dictionary<string, Dictionary<string, string>> _translations = []; private static readonly Dictionary<string, Dictionary<string, string>> _translations = [];
private static string langCode = "pl";
private static readonly string playersLanguageFileName = "playersLanguage.json";
private static readonly string configsFolderPath = Path.Combine(jRandomSkills.Instance.ModuleDirectory, "configs");
private static Dictionary<ulong, string> _playersLanguage = [];
private static readonly string geoliteFilePath = Path.Combine(jRandomSkills.Instance.ModuleDirectory, "packages", "GeoLite2-Country.mmdb");
public static readonly string[] chinaIsoCodes = ["CN", "TW", "HK", "MO", "SG"];
public static readonly string[] portugalIsoCodes = ["PT", "BR", "AO", "CV", "GW", "MZ", "ST", "TL"];
private static string defaultLangCode = "en";
public static void Load() public static void Load()
{ {
_translations.Clear(); _translations.Clear();
_playersLanguage.Clear();
SetLangCode(); SetLangCode();
LoadAllLanguages(); LoadAllLanguages();
LoadPlayersLanguage();
} }
private static void SetLangCode() private static void SetLangCode()
{ {
langCode = Config.LoadedConfig.Settings.LangCode; defaultLangCode = Config.LoadedConfig.Settings.LangCode;
} }
private static void LoadAllLanguages() private static void LoadAllLanguages()
{ {
if (!Directory.Exists(path)) if (!Directory.Exists(languagesFolderPath))
return; return;
foreach (var file in Directory.GetFiles(path, "*.json")) foreach (var file in Directory.GetFiles(languagesFolderPath, "*.json"))
LoadLanguage(file); LoadLanguage(file);
} }
@ -44,8 +58,54 @@ namespace jRandomSkills.src.utils
_translations[code] = translations; _translations[code] = translations;
} }
public static string GetTranslation(string key, params object[] args) public static bool HasTranslation(string code)
{ {
return _translations.ContainsKey(code);
}
public static string GetSkillName(this CCSPlayerController player, Skills skill)
{
string langCode = GetLangCode(player);
return GetTranslation(skill.ToString().ToLower(), langCode);
}
public static string GetSkillDescription(this CCSPlayerController player, Skills skill)
{
string langCode = GetLangCode(player);
return GetTranslation($"{skill.ToString().ToLower()}_desc", langCode);
}
public static void PrintTranslationToChatAll(string message, string[]? key, params object[][]? args)
{
foreach (var player in Utilities.GetPlayers().Where(p => !p.IsBot))
{
string langCode = GetLangCode(player);
if (key == null)
{
player.PrintToChat(message);
return;
}
List<string> translations = [];
for (int i = 0; i < key.Length; i++)
{
object[] currentArgs = (args != null && i < args.Length) ? args[i] : [];
string translation = GetTranslation(key[i], langCode, currentArgs);
translations.Add(translation);
}
player.PrintToChat(string.Format(message, translations.ToArray()));
}
}
public static string GetTranslation(this CCSPlayerController player, string key, params object[] args)
{
string langCode = GetLangCode(player);
return GetTranslation(key, langCode, args);
}
public static string GetTranslation(string key, string? langCode = null, params object[] args)
{
langCode ??= defaultLangCode;
if (_translations.TryGetValue(langCode, out var langDict) && langDict.TryGetValue(key, out var translation)) if (_translations.TryGetValue(langCode, out var langDict) && langDict.TryGetValue(key, out var translation))
if (args.Length != 0 && args[0].ToString() == "welcome") if (args.Length != 0 && args[0].ToString() == "welcome")
return translation; return translation;
@ -59,5 +119,84 @@ namespace jRandomSkills.src.utils
return key; return key;
} }
private static string GetLangCode(CCSPlayerController? player)
{
if (player == null || !player.IsValid) return defaultLangCode;
string? fileLangCode = GetLangCodeFromFile(player.SteamID);
if (!string.IsNullOrEmpty(fileLangCode))
return fileLangCode;
string? geoliteLandCode = GetLangCodeFromDatabase(GetPlayerIP(player)) ?? defaultLangCode;
ChangePlayerLanguage(player, geoliteLandCode);
return geoliteLandCode;
}
private static string? GetPlayerIP(CCSPlayerController? player)
{
if (player == null) return null;
var playerIP = player.IpAddress;
if (playerIP == null) return null;
string[] parts = playerIP.Split(':');
return parts.Length > 1 ? parts[0] : playerIP;
}
private static string? GetLangCodeFromDatabase(string? playerIP)
{
if (string.IsNullOrEmpty(playerIP)) return null;
if (!File.Exists(geoliteFilePath)) return null;
using var reader = new Reader(geoliteFilePath);
var ip = IPAddress.Parse(playerIP);
var data = reader.Find<Dictionary<string, object>>(ip);
if (data == null || data.Count == 0) return null;
if (data.TryGetValue("country", out var _country) && _country is Dictionary<string, object> country)
if (country.TryGetValue("iso_code", out var _isoCode) && _isoCode is string isoCode)
{
if (portugalIsoCodes.Contains(isoCode))
isoCode = "pt-br";
if (chinaIsoCodes.Contains(isoCode))
isoCode = "zh";
isoCode = isoCode.ToLower();
if (_translations.ContainsKey(isoCode))
return isoCode;
}
return null;
}
private static void LoadPlayersLanguage()
{
string filePath = Path.Combine(configsFolderPath, playersLanguageFileName);
if (!File.Exists(filePath))
return;
var jsonText = File.ReadAllText(filePath);
_playersLanguage = JsonConvert.DeserializeObject<Dictionary<ulong, string>>(jsonText) ?? [];
}
private static void SavePlayersLanguage()
{
Directory.CreateDirectory(configsFolderPath);
string filePath = Path.Combine(configsFolderPath, playersLanguageFileName);
var json = JsonConvert.SerializeObject(_playersLanguage);
if (json != null)
File.WriteAllText(filePath, json);
}
private static string? GetLangCodeFromFile(ulong? playerSteamID)
{
if (playerSteamID == null || playerSteamID == 0) return null;
if (_playersLanguage.TryGetValue((ulong)playerSteamID, out var langCode))
return langCode;
return null;
}
public static void ChangePlayerLanguage(CCSPlayerController? player, string language)
{
if (player == null || !player.IsValid) return;
_playersLanguage[player.SteamID] = language;
SavePlayersLanguage();
}
} }
} }

View file

@ -1,7 +1,6 @@
using CounterStrikeSharp.API; using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Cvars;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
@ -11,6 +10,7 @@ using jRandomSkills.src.utils;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using WASDMenuAPI.Classes; using WASDMenuAPI.Classes;
using WASDSharedAPI; using WASDSharedAPI;
using static CounterStrikeSharp.API.Core.Listeners;
namespace jRandomSkills namespace jRandomSkills
{ {
@ -111,8 +111,9 @@ namespace jRandomSkills
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iMaxHealth"); Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iMaxHealth");
} }
public static string GetDesignerName(CBasePlayerWeapon weapon) public static string GetDesignerName(CBasePlayerWeapon? weapon)
{ {
if (weapon == null || !weapon.IsValid) return string.Empty;
string designerName = weapon.DesignerName; string designerName = weapon.DesignerName;
ushort index = weapon.AttributeManager.Item.ItemDefinitionIndex; ushort index = weapon.AttributeManager.Item.ItemDefinitionIndex;
@ -128,6 +129,15 @@ namespace jRandomSkills
return designerName; return designerName;
} }
public static void EnableTransmit()
{
if (!Event.isTransmitRegistered)
{
jRandomSkills.Instance?.RegisterListener<CheckTransmit>(Event.CheckTransmit);
Event.isTransmitRegistered = true;
}
}
private static IWasdMenuManager? GetMenuManager() private static IWasdMenuManager? GetMenuManager()
{ {
if (jRandomSkills.Instance.MenuManager == null) if (jRandomSkills.Instance.MenuManager == null)
@ -180,9 +190,9 @@ namespace jRandomSkills
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == playerInfo.Skill); var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == playerInfo.Skill);
if (skillData == null) return; if (skillData == null) return;
string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{Localization.GetTranslation("your_skill")}:</font> <br>"; string infoLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='#FFFFFF'>{player.GetTranslation("your_skill")}:</font> <br>";
string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{skillData.Name}</font> <br>" string skillLine = $"<font class='fontSize-l' class='fontWeight-Bold' color='{skillData.Color}'>{player.GetSkillName(skillData.Skill)}</font> <br>"
+ $"<font color='green'>{Localization.GetTranslation($"{playerInfo.Skill.ToString().ToLower()}_select_info")}</font>"; + $"<font color='green'>{player.GetTranslation($"{playerInfo.Skill.ToString().ToLower()}_select_info")}</font>";
var manager = GetMenuManager(); var manager = GetMenuManager();
if (manager == null) return; if (manager == null) return;

View file

@ -9,6 +9,9 @@
"AlternativeSkillButton": null, "AlternativeSkillButton": null,
"SkillTimeBeforeStart": 7.0, "SkillTimeBeforeStart": 7.0,
"SkillDescriptionDuration": 7.0, "SkillDescriptionDuration": 7.0,
"DisableSpectateHUD": false,
"FlashingHtmlHudFix": true,
"CS2TraceRayDebug": false,
"SetSkillCommands": { "SetSkillCommands": {
"Alias": "ustawskill, ustaw_skill, setskill, set_skill, definirhabilidade, configurarhabilidade, 设置技能, 配置技能", "Alias": "ustawskill, ustaw_skill, setskill, set_skill, definirhabilidade, configurarhabilidade, 设置技能, 配置技能",
"Permissions": "@jRandmosSkills/admin" "Permissions": "@jRandmosSkills/admin"
@ -33,6 +36,14 @@
"Alias": "ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "Alias": "ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill",
"Permissions": "@jRandmosSkills/admin" "Permissions": "@jRandmosSkills/admin"
}, },
"ChangeLanguageCommands": {
"Alias": "lang, language, changelang, change_lang, jezyk, język",
"Permissions": ""
},
"ReloadCommands": {
"Alias": "reload, refresh",
"Permissions": "@jRandmosSkills/admin"
},
"StartGameCommands": { "StartGameCommands": {
"EnableVoting": true, "EnableVoting": true,
"TimeToVote": 15.0, "TimeToVote": 15.0,
@ -250,6 +261,15 @@
"Active": true, "Active": true,
"Name": "Darkness" "Name": "Darkness"
}, },
{
"JumpVelocity": 150.0,
"PushVelocity": 600.0,
"NeedsTeammates": false,
"OnlyTeam": 0,
"Color": "#42bbfc",
"Active": true,
"Name": "Dash"
},
{ {
"NeedsTeammates": false, "NeedsTeammates": false,
"OnlyTeam": 0, "OnlyTeam": 0,
@ -304,6 +324,18 @@
"Active": true, "Active": true,
"Name": "Dwarf" "Name": "Dwarf"
}, },
{
"Cooldown": 16.0,
"Amplitude": 15.0,
"Frequency": 500.0,
"Duration": 8.0,
"Radius": 50.0,
"NeedsTeammates": false,
"OnlyTeam": 0,
"Color": "#42f59b",
"Active": false,
"Name": "Earthquake"
},
{ {
"Cooldown": 15.0, "Cooldown": 15.0,
"NeedsTeammates": false, "NeedsTeammates": false,
@ -427,6 +459,13 @@
"Active": true, "Active": true,
"Name": "GodMode" "Name": "GodMode"
}, },
{
"NeedsTeammates": false,
"OnlyTeam": 0,
"Color": "#4a6e21",
"Active": true,
"Name": "Grenadier"
},
{ {
"SmokeHeal": 1, "SmokeHeal": 1,
"SmokeRadius": 180.0, "SmokeRadius": 180.0,
@ -468,7 +507,7 @@
"Name": "InfiniteAmmo" "Name": "InfiniteAmmo"
}, },
{ {
"MaxStepBeam": 50, "MaxStepBeam": 100,
"NeedsTeammates": false, "NeedsTeammates": false,
"OnlyTeam": 0, "OnlyTeam": 0,
"Color": "#f542ef", "Color": "#f542ef",
@ -859,7 +898,7 @@
"NeedsTeammates": false, "NeedsTeammates": false,
"OnlyTeam": 0, "OnlyTeam": 0,
"Color": "#e0873a", "Color": "#e0873a",
"Active": false, "Active": true,
"Name": "SniperElite" "Name": "SniperElite"
}, },
{ {

View file

@ -93,6 +93,9 @@
"distancer": "Rangefinder", "distancer": "Rangefinder",
"distancer_desc": "You can see the distance to the nearest enemy", "distancer_desc": "You can see the distance to the nearest enemy",
"dash": "Dash",
"dash_desc": "Perform a second jump to dash",
"dracula": "Dracula", "dracula": "Dracula",
"dracula_desc": "Hitting an enemy restores health equal to a percentage of the damage dealt", "dracula_desc": "Hitting an enemy restores health equal to a percentage of the damage dealt",
@ -160,6 +163,9 @@
"godmode_off": "Immortality disabled", "godmode_off": "Immortality disabled",
"godmode_on": "Immortality enabled", "godmode_on": "Immortality enabled",
"grenadier": "Grenadier",
"grenadier_desc": "You have infinite hegranade",
"healingsmoke": "Healing Smoke", "healingsmoke": "Healing Smoke",
"healingsmoke_desc": "Your smoke grenades heal", "healingsmoke_desc": "Your smoke grenades heal",
@ -371,6 +377,7 @@
"thief_enemy_info": "Your skill has been stolen.", "thief_enemy_info": "Your skill has been stolen.",
"thief_player_info": "Player '{0}'s skill has been stolen.", "thief_player_info": "Player '{0}'s skill has been stolen.",
"thief_select_info": "Steal a player's skill:", "thief_select_info": "Steal a player's skill:",
"thief_incorrect_skill": "This skill cannot be selected!",
"thirdeye": "Third Eye", "thirdeye": "Third Eye",
"thirdeye_desc": "Click [css_useSkill] to activate third-person view", "thirdeye_desc": "Click [css_useSkill] to activate third-person view",
@ -428,6 +435,7 @@
"unpause": "Match has been resumed.", "unpause": "Match has been resumed.",
"healed": "You have been healed.", "healed": "You have been healed.",
"game_start": "Game started!", "game_start": "Game started!",
"reload": "Languages and configs have been reloaded.",
"vote_started": "Vote started: '{0}'", "vote_started": "Vote started: '{0}'",
"vote_timeout": "Vote '{0}' timed out!", "vote_timeout": "Vote '{0}' timed out!",

View file

@ -93,6 +93,9 @@
"distancer": "Odległościomierz", "distancer": "Odległościomierz",
"distancer_desc": "Możesz zobaczyć odległość do najbliższego przeciwnika", "distancer_desc": "Możesz zobaczyć odległość do najbliższego przeciwnika",
"dash": "Doskok",
"dash_desc": "Wykonaj drugi skok, aby wykonać doskok",
"dracula": "Drakula", "dracula": "Drakula",
"dracula_desc": "Po trafieniu ofiary odzyskujesz zdrowie równe pewnemu procentowi zadanych obrażeń", "dracula_desc": "Po trafieniu ofiary odzyskujesz zdrowie równe pewnemu procentowi zadanych obrażeń",
@ -160,6 +163,9 @@
"godmode_off": "Nieśmiertelność wyłączona", "godmode_off": "Nieśmiertelność wyłączona",
"godmode_on": "Nieśmiertelność włączona", "godmode_on": "Nieśmiertelność włączona",
"grenadier": "Granatnik",
"grenadier_desc": "Masz nieskończone granaty odłamkowe",
"healingsmoke": "Leczący Dym", "healingsmoke": "Leczący Dym",
"healingsmoke_desc": "Twoje granaty dymne leczą", "healingsmoke_desc": "Twoje granaty dymne leczą",
@ -371,6 +377,7 @@
"thief_enemy_info": "Twoja supermoc została skradziona.", "thief_enemy_info": "Twoja supermoc została skradziona.",
"thief_player_info": "Moc gracza '{0}' została skradziona.", "thief_player_info": "Moc gracza '{0}' została skradziona.",
"thief_select_info": "Ukradnij moc gracza:", "thief_select_info": "Ukradnij moc gracza:",
"thief_incorrect_skill": "Tej umiejętności nie można wybrać!",
"thirdeye": "Trzecie Oko", "thirdeye": "Trzecie Oko",
"thirdeye_desc": "Kliknij [css_useSkill], aby aktywować trzecią osobę", "thirdeye_desc": "Kliknij [css_useSkill], aby aktywować trzecią osobę",
@ -428,6 +435,7 @@
"unpause": "Mecz został wznowiony.", "unpause": "Mecz został wznowiony.",
"healed": "Zostałeś uleczony.", "healed": "Zostałeś uleczony.",
"game_start": "Gra rozpoczęta!", "game_start": "Gra rozpoczęta!",
"reload": "Tłumaczenia i konfigi zostały ponownie załadowane.",
"vote_started": "Głosowanie rozpoczęte: '{0}'", "vote_started": "Głosowanie rozpoczęte: '{0}'",
"vote_timeout": "Głosowanie '{0}' przekroczyło limit czasu!", "vote_timeout": "Głosowanie '{0}' przekroczyło limit czasu!",

View file

@ -93,6 +93,9 @@
"distancer": "Medidor de Distância", "distancer": "Medidor de Distância",
"distancer_desc": "Você pode ver a distância até o inimigo mais próximo", "distancer_desc": "Você pode ver a distância até o inimigo mais próximo",
"dash": "Dash",
"dash_desc": "Execute um segundo salto para dar um dash",
"dracula": "Drácula", "dracula": "Drácula",
"dracula_desc": "Acertar um inimigo restaura saúde igual a uma porcentagem do dano causado", "dracula_desc": "Acertar um inimigo restaura saúde igual a uma porcentagem do dano causado",
@ -160,6 +163,9 @@
"godmode_off": "Imortalidade desativada", "godmode_off": "Imortalidade desativada",
"godmode_on": "Imortalidade ativada", "godmode_on": "Imortalidade ativada",
"grenadier": "Grenadier",
"grenadier_desc": "Você tem granadas HE infinitas",
"healingsmoke": "Fumaça Curativa", "healingsmoke": "Fumaça Curativa",
"healingsmoke_desc": "Suas granadas de fumaça curam", "healingsmoke_desc": "Suas granadas de fumaça curam",
@ -371,6 +377,7 @@
"thief_enemy_info": "Sua habilidade foi roubada.", "thief_enemy_info": "Sua habilidade foi roubada.",
"thief_player_info": "A habilidade do jogador '{0}' foi roubada.", "thief_player_info": "A habilidade do jogador '{0}' foi roubada.",
"thief_select_info": "Roubar skill do jogador:", "thief_select_info": "Roubar skill do jogador:",
"thief_incorrect_skill": "Esta habilidade não pode ser selecionada!",
"thirdeye": "Terceiro Olho", "thirdeye": "Terceiro Olho",
"thirdeye_desc": "Clique em [css_useSkill] para ativar a visão em terceira pessoa", "thirdeye_desc": "Clique em [css_useSkill] para ativar a visão em terceira pessoa",
@ -428,6 +435,7 @@
"unpause": "Partida retomada.", "unpause": "Partida retomada.",
"healed": "Você foi curado.", "healed": "Você foi curado.",
"game_start": "Jogo iniciado!", "game_start": "Jogo iniciado!",
"reload": "Os idiomas e as configurações foram recarregados.",
"vote_started": "Votação iniciada: '{0}'", "vote_started": "Votação iniciada: '{0}'",
"vote_timeout": "Votação '{0}' expirou!", "vote_timeout": "Votação '{0}' expirou!",

View file

@ -93,6 +93,9 @@
"distancer": "测距仪", "distancer": "测距仪",
"distancer_desc": "你可以看到与最近敌人的距离", "distancer_desc": "你可以看到与最近敌人的距离",
"dash": "冲刺",
"dash_desc": "执行第二次跳跃来进行冲刺",
"dracula": "德古拉", "dracula": "德古拉",
"dracula_desc": "击中敌人会根据造成的伤害百分比恢复你的生命值", "dracula_desc": "击中敌人会根据造成的伤害百分比恢复你的生命值",
@ -160,6 +163,9 @@
"godmode_off": "无敌状态已禁用", "godmode_off": "无敌状态已禁用",
"godmode_on": "无敌状态已启用", "godmode_on": "无敌状态已启用",
"grenadier": "掷弹兵",
"grenadier_desc": "你拥有无限高爆手雷",
"healingsmoke": "治疗烟雾", "healingsmoke": "治疗烟雾",
"healingsmoke_desc": "你的烟雾弹会治疗", "healingsmoke_desc": "你的烟雾弹会治疗",
@ -371,6 +377,7 @@
"thief_enemy_info": "你的技能被偷走了。", "thief_enemy_info": "你的技能被偷走了。",
"thief_player_info": "玩家 '{0}' 的技能被偷走了。", "thief_player_info": "玩家 '{0}' 的技能被偷走了。",
"thief_select_info": "选择你想偷取其技能的玩家:", "thief_select_info": "选择你想偷取其技能的玩家:",
"thief_incorrect_skill": "此技能无法选择!",
"thirdeye": "第三只眼", "thirdeye": "第三只眼",
"thirdeye_desc": "点击 [css_useSkill] 激活第三人称视角", "thirdeye_desc": "点击 [css_useSkill] 激活第三人称视角",
@ -428,6 +435,7 @@
"unpause": "比赛已恢复。", "unpause": "比赛已恢复。",
"healed": "你已被治疗。", "healed": "你已被治疗。",
"game_start": "游戏开始!", "game_start": "游戏开始!",
"reload": "语言和配置已重新加载。",
"vote_started": "投票开始:'{0}'", "vote_started": "投票开始:'{0}'",
"vote_timeout": "投票'{0}'超时!", "vote_timeout": "投票'{0}'超时!",

View file

@ -274,6 +274,55 @@ This plugin uses content from the following projects:
## 📋 Changelog ## 📋 Changelog
<details>
<summary><b>v1.1.5</b></summary>
- #### General:
- ###### Added language recognition based on geolocation (MaxMind GeoLite2).
- ###### Each player can choose a different language.
- ###### Directory names have been changed.
- ###### Automatic config refresh has been removed.
- ###### Added the `FlashingHtmlHudFix` option to the config.
- ###### Added the `CS2TraceRayDebug` option to the config, showing the "bullet" path for the LongKnife and LongZeus skills.
- ###### Added the `DisableSpectateHUD` option to the config, allowing the HTML HUD to be disabled for spectators.
- ###### The name of the project has been changed from `jRandomSkills` to `!jRandomSkills` to allow other plugins to load into memory later.
- ###### Added the command `!lang en` to change the language
- ###### Added the `!reload` command to reload translations.
- ######
- ######
- ######
- ######
- #### Skill improvements:
- ##### Weapon Swap:
- ###### Fixed a bug with bomb duplication on the HUD.
- ##### Thief:
- ###### The ability to steal skill that is unavailable to your team has been blocked.
- ##### Rich Boy:
- ###### The ability to steal skill that is unavailable to your team has been blocked.
- ##### Sniper Elite:
- ###### Fixed all bugs and enabled the skill.
- ##### Second Chance:
- ###### Return to original health when skill are deactivated.
- ##### Planter:
- ###### Planting a bomb during freezing has been blocked.
- ##### Jackal:
- ###### Added 'null' check.
- ##### Astronaut:
- ###### Fixed gravity scale not showing on HTML.
- ##### Duplicator:
- ###### The HTML Menu is disabled when no players are found.
- ##### Deactivator:
- ###### The HTML Menu is disabled when no players are found.
- ##### Jackal:
- ###### The HTML Menu is disabled when no players are found.
- #### New skills:
- ##### Grenadier:
- ###### You have infinite hegranade.
- ##### Dash:
- ###### Perform a second jump to dash.
</details>
<details> <details>
<summary><b>v1.1.4</b></summary> <summary><b>v1.1.4</b></summary>
@ -287,6 +336,7 @@ This plugin uses content from the following projects:
- ###### Skill descriptions added at the start of the round using PrintToCenterHtml. - ###### Skill descriptions added at the start of the round using PrintToCenterHtml.
- ###### Skill descriptions with player selection have been shortened. - ###### Skill descriptions with player selection have been shortened.
- ###### Fixed a problem where the css_setskill and css_setstaticskill commands could not be executed from the server. - ###### Fixed a problem where the css_setskill and css_setstaticskill commands could not be executed from the server.
- ###### The parameters of the `!start` command have been changed.
- #### Skill improvements: - #### Skill improvements:
- ##### Legless: - ##### Legless:
- ###### Legless's skill completely disables Bunny's skill. - ###### Legless's skill completely disables Bunny's skill.