feat: Panorama skill HUD and menu, CSS 1.0.375
- Skill card and W/S/E target menu drawn as CCSCustomHudLayout panels via PanoramaManager (panorama/ sources), replacing PrintToCenterHtml and WASDMenuAPI; WASDMenuAPI.dll dropped - Custom status lines (cooldowns, charges) overwrite the description on the card; Medic keeps its description with the charge count below - css_setoverride toggles a per-player cooldown bypass - YourSkillChatInfo also gates the round-start skill description in chat - Language: "[css_useSkill]" becomes the configured button name, "Press ... key" wording, welcome message trimmed to its first line - Build against CounterStrikeSharp.API 1.0.375
This commit is contained in:
parent
20dafd2a7c
commit
793370a55f
37 changed files with 1076 additions and 415 deletions
|
|
@ -37,6 +37,7 @@ namespace src.command
|
|||
var commands = new Dictionary<IEnumerable<string>, (string description, CommandInfo.CommandCallback handler)>
|
||||
{
|
||||
{ SplitCommands(config.NormalCommands.SetSkillCommand.Alias), ("Set skill", Command_SetSkill) },
|
||||
{ SplitCommands(config.NormalCommands.SetOverrideCommand.Alias), ("Toggle cooldown bypass", Command_SetOverride) },
|
||||
{ SplitCommands(config.NormalCommands.SkillsListCommand.Alias), ("Delete all records", Command_SkillsListMenu) },
|
||||
{ SplitCommands(config.NormalCommands.UseSkillCommand.Alias), ("Use/Type skill", Command_UseTypeSkill) },
|
||||
{ SplitCommands(config.NormalCommands.ConsoleCommand.Alias), ("Console command", Command_CustomCommand) },
|
||||
|
|
@ -101,6 +102,38 @@ namespace src.command
|
|||
}
|
||||
|
||||
[CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
private static void Command_SetOverride(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
Debug.WriteToDebug($"Player {player?.PlayerName} used the css_setoverride {command.ArgString} command.");
|
||||
if (!string.IsNullOrEmpty(config.NormalCommands.SetOverrideCommand.Permissions) && !AdminManager.PlayerHasPermissions(player, config.NormalCommands.SetOverrideCommand.Permissions)) return;
|
||||
|
||||
void Reply(string message)
|
||||
{
|
||||
if (player == null) Server.PrintToConsole(message);
|
||||
else SkillUtils.PrintToChat(player, message);
|
||||
}
|
||||
|
||||
if (command.ArgCount < 2)
|
||||
{
|
||||
Reply("Usage: css_setoverride <name or steamid64>");
|
||||
return;
|
||||
}
|
||||
|
||||
var targetPlayer = Utilities.GetPlayers().FirstOrDefault(p => p != null && p.IsValid
|
||||
&& (p.SteamID.ToString().Equals(command.GetArg(1), StringComparison.CurrentCultureIgnoreCase)
|
||||
|| p.PlayerName.Equals(command.GetArg(1), StringComparison.OrdinalIgnoreCase)));
|
||||
if (targetPlayer == null)
|
||||
{
|
||||
Reply(player == null
|
||||
? Localization.GetTranslationWithoutIlliterate("player_not_found_setskill")
|
||||
: player.GetTranslationWithoutIlliterate("player_not_found_setskill"));
|
||||
return;
|
||||
}
|
||||
|
||||
bool enabled = CooldownOverride.Toggle(targetPlayer);
|
||||
Reply($"Cooldown override {(enabled ? $"{ChatColors.Lime}ON" : $"{ChatColors.LightRed}OFF")}{ChatColors.Default} for {ChatColors.LightRed}\u202A{targetPlayer.PlayerName}\u202C");
|
||||
}
|
||||
|
||||
private static void Command_SetSkill(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
Debug.WriteToDebug($"Player {player?.PlayerName} used the css_setskill {command.ArgString} command.");
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ using CounterStrikeSharp.API.Core;
|
|||
using CounterStrikeSharp.API.Core.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using PanoramaManager;
|
||||
using src.command;
|
||||
using src.player;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using WASDSharedAPI;
|
||||
using static CounterStrikeSharp.API.Core.Listeners;
|
||||
|
||||
namespace src
|
||||
|
|
@ -22,8 +22,21 @@ namespace src
|
|||
public IEnumerable<jSkill_PlayerInfo> SkillPlayer => PlayerManager.GetAllPlayers();
|
||||
public Random Random => Random.Shared;
|
||||
public CCSGameRules? GameRules { get; set; }
|
||||
// The entity backing GameRules above. SetStateChanged needs the entity itself,
|
||||
// not the GameRules subobject, so this is kept alongside it.
|
||||
public CCSGameRulesProxy? GameRulesProxy { get; set; }
|
||||
private ConcurrentBag<string> ManifestResources { get; set; } = ["models/sprays/spray_plane.vmdl"];
|
||||
public IWasdMenuManager? MenuManager;
|
||||
// Stage 1 of the Panorama HUD replacement (see PlayerEvents.cs's UpdateSkillHUD and
|
||||
// CLAUDE.md's "Panorama HUD" section) - drives skill_hud.xml for skills that don't set a
|
||||
// custom PrintHTML override. Own LayoutContract, not LayoutContract.Default: PanoramaManager
|
||||
// warns two layouts sharing a root id silently share dialog variables across plugins.
|
||||
public static readonly LayoutContract SkillHudContract = new()
|
||||
{
|
||||
RootPanelId = "SkillHudRoot",
|
||||
RowCount = 0,
|
||||
CaptureInput = false,
|
||||
};
|
||||
public PanelHandle? SkillHud;
|
||||
// Skills that were enabled at least once this round; used to reset only those on round change (not all 124).
|
||||
public static readonly ConcurrentDictionary<string, byte> ActiveSkillsThisRound = new();
|
||||
public static readonly ConcurrentDictionary<string, byte> SkillsUsedThisMap = new();
|
||||
|
|
@ -44,10 +57,13 @@ namespace src
|
|||
PlayerOnTick.Load();
|
||||
Event.Load();
|
||||
Command.Load();
|
||||
WASDMenuAPI.WASDMenuAPI.LoadPlugin(Instance, hotReload);
|
||||
LoadAllSkills();
|
||||
PlayerManager.SyncWithPlugin(Instance);
|
||||
|
||||
Panorama.Init(this);
|
||||
SkillHud = Panorama.Spawn("panorama/layout/custom_game/skill_hud.vxml_c", SkillHudContract);
|
||||
PanoramaMenu.Load(this);
|
||||
|
||||
Instance.RegisterListener<OnServerPrecacheResources>(LoadManifest);
|
||||
|
||||
Task.Run(async () =>
|
||||
|
|
@ -65,6 +81,10 @@ namespace src
|
|||
Event.Unload();
|
||||
Debug.Unload();
|
||||
|
||||
SkillHud?.Dispose();
|
||||
PanoramaMenu.Unload();
|
||||
Panorama.Shutdown();
|
||||
|
||||
base.Unload(hotReload);
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +180,10 @@ namespace src
|
|||
|
||||
if (method == null) return null;
|
||||
|
||||
if (methodName == "UseSkill" && param?.Length > 0 && param[0] is CCSPlayerController user
|
||||
&& user.IsValid && CooldownOverride.Has(user))
|
||||
CooldownOverride.ResetBeforeUse(method.DeclaringType!, user);
|
||||
|
||||
if (!PerfLog.Enabled)
|
||||
return method.Invoke(null, param);
|
||||
|
||||
|
|
@ -277,7 +301,6 @@ namespace src
|
|||
Console.WriteLine($"\nDependences:");
|
||||
var files = new Dictionary<string, string> {
|
||||
{ "Newtonsoft Json", "./Newtonsoft.Json.dll" },
|
||||
{ "WASDMenuAPI", "./WASDMenuAPI.dll" },
|
||||
{ "MaxMind", "./MaxMind.Db.dll" },
|
||||
{ "GeoLite2", "./packages/GeoLite2-Country.mmdb" },
|
||||
{ "RayTraceApi", "./../../shared/RayTraceApi/RayTraceApi.dll" },
|
||||
|
|
@ -385,6 +408,23 @@ namespace src
|
|||
public string? Content;
|
||||
}
|
||||
|
||||
// Change-detection so SetVariableFor/SetClassFor are only called when something actually
|
||||
// changed, same principle as HudCacheEntry above (its cache.Content re-send is the same idea,
|
||||
// just at a coarser granularity since PrintToCenterHtml takes one blob, not per-field writes).
|
||||
// TouchedThisTick is reset and checked once per HUD frame in PlayerOnTick.cs - it's what closes
|
||||
// the panel for a player who stopped being updated (warmup started, menu opened, HUD
|
||||
// suppressed, ...) instead of it silently showing stale content forever, which a Panorama panel
|
||||
// would otherwise do - PrintToCenterHtml expires on its own after a few seconds; this doesn't.
|
||||
public sealed class PanoramaHudCache
|
||||
{
|
||||
public bool Open;
|
||||
public bool TouchedThisTick;
|
||||
public string? Skill;
|
||||
public string? Extra;
|
||||
public string? RarityClass;
|
||||
public bool? IsInfo;
|
||||
}
|
||||
|
||||
public class jSkill_SkillInfo(Skills skill, string color, bool display)
|
||||
{
|
||||
public Skills Skill { get; } = skill;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"aimbot_desc": "Jede Kugel, die du triffst, zählt als Kopfschuss",
|
||||
|
||||
"aimlock": "Aim-Lock",
|
||||
"aimlock_desc": "Klicke [css_useSkill], um dein Visier auf den nächsten Gegner zu fixieren",
|
||||
"aimlock_desc": "Drücke [css_useSkill], um dein Visier auf den nächsten Gegner zu fixieren",
|
||||
|
||||
"anomaly": "Anomalie",
|
||||
"anomaly_desc": "Drücke [css_useSkill], um einige Sekunden in der Zeit zurückzuspringen",
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
"cutter_desc": "Sofortiger Tod mit einem Messer",
|
||||
|
||||
"cypher": "Kamera",
|
||||
"cypher_desc": "Klicken Sie auf [css_useSkill], um eine Kamera zu erstellen/zu wechseln",
|
||||
"cypher_desc": "Drücken Sie [css_useSkill], um eine Kamera zu erstellen/zu wechseln",
|
||||
"cypher_nospace": "Die Kamera muss im rechten Winkel zur Wand positioniert werden",
|
||||
|
||||
"darkness": "Dunkelheit",
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
"empgrenade_enemy_info": "Eine EMP-Granate hat dein Radar und Fadenkreuz lahmgelegt.",
|
||||
|
||||
"enemyspawn": "Feindes-Spawn",
|
||||
"enemyspawn_desc": "Klicke auf [css_useSkill], um zum Feindes-Spawn zu teleportieren",
|
||||
"enemyspawn_desc": "Drücke [css_useSkill], um zum Feindes-Spawn zu teleportieren",
|
||||
|
||||
"expensiveammo": "Teure Munition",
|
||||
"expensiveammo_desc": "Ein ausgewählter Gegner muss für jeden Schuss bezahlen",
|
||||
|
|
@ -166,17 +166,17 @@
|
|||
"expensiveammo_select_info": "Wähle einen Spieler, dessen Munition teuer wird:",
|
||||
|
||||
"explodingbarrel": "Explosives Fass",
|
||||
"explodingbarrel_desc": "Klicke auf [css_useSkill], um ein Fass zu platzieren, das beim Beschuss explodiert",
|
||||
"explodingbarrel_desc": "Drücke [css_useSkill], um ein Fass zu platzieren, das beim Beschuss explodiert",
|
||||
|
||||
"explosiveshot": "Explosiver Schuss",
|
||||
"explosiveshot_desc": "Zufällige Chance, beim Schießen eine explosive Kugel abzufeuern",
|
||||
"explosiveshot_desc2": "Deine Chance, eine explosive Kugel abzufeuern: {0} %",
|
||||
|
||||
"falconeye": "Falkenauge",
|
||||
"falconeye_desc": "Klicke auf [css_useSkill], um eine Vogelperspektive zu aktivieren",
|
||||
"falconeye_desc": "Drücke [css_useSkill], um eine Vogelperspektive zu aktivieren",
|
||||
|
||||
"fastreload": "Schnellnachladen",
|
||||
"fastreload_desc": "Klicke auf [css_useSkill], um die Waffe, die du gerade hältst, nachzuladen",
|
||||
"fastreload_desc": "Drücke [css_useSkill], um die Waffe, die du gerade hältst, nachzuladen",
|
||||
|
||||
"firerain": "Feuerregen",
|
||||
"firerain_desc": "Wirf einen Köder, um einen Regen aus Molotows auszulösen",
|
||||
|
|
@ -186,10 +186,10 @@
|
|||
"flash_desc2": "Dein Geschwindigkeitsmultiplikator beträgt: {0}x",
|
||||
|
||||
"flashlight": "Taschenlampe",
|
||||
"flashlight_desc": "Klicke auf [css_useSkill], um die Taschenlampe ein- oder auszuschalten. Ihr Licht kann Gegner blenden",
|
||||
"flashlight_desc": "Drücke [css_useSkill], um die Taschenlampe ein- oder auszuschalten. Ihr Licht kann Gegner blenden",
|
||||
|
||||
"fortnite": "Fortnite",
|
||||
"fortnite_desc": "Klicke auf [css_useSkill], um eine zerstörbare Barrikade zu erstellen",
|
||||
"fortnite_desc": "Drücke [css_useSkill], um eine zerstörbare Barrikade zu erstellen",
|
||||
|
||||
"fragilebomb": "Fragile Bombe",
|
||||
"fragilebomb_desc": "Das Schießen auf die Bombe beschädigt sie",
|
||||
|
|
@ -232,7 +232,7 @@
|
|||
"glue_desc": "Deine Granaten haften an Wänden",
|
||||
|
||||
"godmode": "Gott-Modus",
|
||||
"godmode_desc": "Klicke auf [css_useSkill], um für kurze Zeit unsterblich zu werden",
|
||||
"godmode_desc": "Drücke [css_useSkill], um für kurze Zeit unsterblich zu werden",
|
||||
"godmode_off": "Unsterblichkeit deaktiviert",
|
||||
"godmode_on": "Unsterblichkeit aktiviert",
|
||||
|
||||
|
|
@ -271,14 +271,14 @@
|
|||
"hotbomb_disable_info": "Die Bombe ist nicht mehr heiß.",
|
||||
|
||||
"iana": "Hologramm",
|
||||
"iana_desc": "Klicken Sie auf [css_useSkill], um Ihr Hologramm für einige Sekunden zu steuern",
|
||||
"iana_desc": "Drücken Sie [css_useSkill], um Ihr Hologramm für einige Sekunden zu steuern",
|
||||
|
||||
"illiterate": "Analphabet",
|
||||
"illiterate_desc": "Solange du am Leben bist, können deine Feinde nichts lesen",
|
||||
"illiterate_alert": "Analphabet ist aktiv! Du kannst keine Nachrichten lesen, bis der Besitzer dieser Fähigkeit eliminiert ist",
|
||||
|
||||
"illusionist": "Illusionist",
|
||||
"illusionist_desc": "Klicke [css_useSkill], um ein Abbild zu schicken, das geradeaus läuft",
|
||||
"illusionist_desc": "Drücke [css_useSkill], um ein Abbild zu schicken, das geradeaus läuft",
|
||||
|
||||
"impostor": "Betrüger",
|
||||
"impostor_desc": "Du beginnst die Runde mit einem feindlichen Spielermodell",
|
||||
|
|
@ -366,7 +366,7 @@
|
|||
"magnifier_select_info": "Bildschirm des Spielers vergrößern:",
|
||||
|
||||
"medic": "Sanitäter",
|
||||
"medic_desc": "Klicke auf [css_useSkill], um eine Heilungsladung zu verwenden, die 50 Gesundheitspunkte wiederherstellt",
|
||||
"medic_desc": "Drücke [css_useSkill], um eine Heilungsladung zu verwenden, die 50 Gesundheitspunkte wiederherstellt",
|
||||
|
||||
"miner": "Bomben-Miner",
|
||||
"miner_desc": "Deine HE-Granate explodiert nur, wenn ein Gegner in der Nähe ist",
|
||||
|
|
@ -400,7 +400,7 @@
|
|||
"norecoil_desc": "Kein Rückstoß beim Schießen",
|
||||
|
||||
"noclip": "NoClip",
|
||||
"noclip_desc": "Klicke auf [css_useSkill], um NoClip für kurze Zeit zu aktivieren",
|
||||
"noclip_desc": "Drücke [css_useSkill], um NoClip für kurze Zeit zu aktivieren",
|
||||
|
||||
"oneshot": "One-Shot",
|
||||
"oneshot_desc": "Ein Treffer tötet einen Gegner sofort",
|
||||
|
|
@ -467,7 +467,7 @@
|
|||
"rambo_desc": "Du erhältst zu Beginn der Runde eine zufällige Menge an Gesundheit",
|
||||
|
||||
"randomweapon": "Zufällige Waffe",
|
||||
"randomweapon_desc": "Klicke auf [css_useSkill], um eine zufällige Waffe zu erhalten",
|
||||
"randomweapon_desc": "Drücke [css_useSkill], um eine zufällige Waffe zu erhalten",
|
||||
|
||||
"rezombie": "Re-Zombie",
|
||||
"rezombie_desc": "Nach dem Tod spawnst du als Zombie mit erhöhter Gesundheit und ohne Waffen",
|
||||
|
|
@ -479,10 +479,10 @@
|
|||
"regeneration_desc": "Du stellst alle paar Sekunden Gesundheit wieder her",
|
||||
|
||||
"replicator": "Replikator",
|
||||
"replicator_desc": "Klicke auf [css_useSkill], um eine Replik zu erstellen, die bei Treffer Schaden verursacht",
|
||||
"replicator_desc": "Drücke [css_useSkill], um eine Replik zu erstellen, die bei Treffer Schaden verursacht",
|
||||
|
||||
"retreat": "Rückzug",
|
||||
"retreat_desc": "Klicke auf [css_useSkill], um zum Spawn zurückzukehren",
|
||||
"retreat_desc": "Drücke [css_useSkill], um zum Spawn zurückzukehren",
|
||||
|
||||
"returntosender": "Zurück zum Absender",
|
||||
"returntosender_desc": "Der erste Treffer eines Gegners schickt ihn zurück zu seinem Spawn",
|
||||
|
|
@ -525,7 +525,7 @@
|
|||
|
||||
"sniperelite": "Sniper Elite",
|
||||
"sniperelite_customname": "Sniper-Elite-Skill",
|
||||
"sniperelite_desc": "Klicke auf [css_useSkill], um deine aktuelle Waffe gegen eine AWP auszutauschen",
|
||||
"sniperelite_desc": "Drücke [css_useSkill], um deine aktuelle Waffe gegen eine AWP auszutauschen",
|
||||
|
||||
"soldier": "Soldat",
|
||||
"soldier_desc": "Du hast einen zufälligen Schadensmultiplikator",
|
||||
|
|
@ -535,13 +535,13 @@
|
|||
"soundmaker_desc": "Von Zeit zu Zeit hörst du die Schreie von Spielern",
|
||||
|
||||
"spectator": "Zuschauer",
|
||||
"spectator_desc": "Klicke auf [css_useSkill], um einen zufälligen Gegner zu beobachten",
|
||||
"spectator_desc": "Drücke [css_useSkill], um einen zufälligen Gegner zu beobachten",
|
||||
|
||||
"swapposition": "Positionstausch",
|
||||
"swapposition_desc": "Klicke auf [css_useSkill], um mit einem zufälligen Gegner die Plätze zu tauschen",
|
||||
"swapposition_desc": "Drücke [css_useSkill], um mit einem zufälligen Gegner die Plätze zu tauschen",
|
||||
|
||||
"takeammo": "Munition nehmen",
|
||||
"takeammo_desc": "Klicke auf [css_useSkill], um das Magazin der aktiven Waffe eines zufälligen Gegners zu nehmen",
|
||||
"takeammo_desc": "Drücke [css_useSkill], um das Magazin der aktiven Waffe eines zufälligen Gegners zu nehmen",
|
||||
"takeammo_hud_info1": "Kein Spieler mit einem aktiven Magazin gefunden.",
|
||||
"takeammo_hud_info2": "Der Gegner hat keine Magazine.",
|
||||
"takeammo_enemy_info": "Du hast etwas Munition verloren.",
|
||||
|
|
@ -563,19 +563,19 @@
|
|||
"thief_incorrect_skill": "Diese Fähigkeit kann nicht ausgewählt werden!",
|
||||
|
||||
"thirdeye": "Drittes Auge",
|
||||
"thirdeye_desc": "Klicke auf [css_useSkill], um die Third-Person-Ansicht zu aktivieren",
|
||||
"thirdeye_desc": "Drücke [css_useSkill], um die Third-Person-Ansicht zu aktivieren",
|
||||
|
||||
"thorns": "Dornen",
|
||||
"thorns_desc": "Dein Gegner erhält einen Teil des Schadens, den er dir zugefügt hat",
|
||||
|
||||
"throwingknife": "Wurfmesser",
|
||||
"throwingknife_desc": "Klicke [css_useSkill], um ein Messer zu werfen. Aber nimm dich vor anderen in Acht",
|
||||
"throwingknife_desc": "Drücke [css_useSkill], um ein Messer zu werfen. Aber nimm dich vor anderen in Acht",
|
||||
|
||||
"toxicsmoke": "Giftiger Rauch",
|
||||
"toxicsmoke_desc": "Deine Rauchgranaten verursachen Schaden",
|
||||
|
||||
"tripwire": "Stolperdraht",
|
||||
"tripwire_desc": "Klicke auf [css_useSkill], um einen Draht zwischen zwei Wänden zu spannen. Gegner, die ihn berühren, werden auf deinem Radar angezeigt",
|
||||
"tripwire_desc": "Drücke [css_useSkill], um einen Draht zwischen zwei Wänden zu spannen. Gegner, die ihn berühren, werden auf deinem Radar angezeigt",
|
||||
"tripwire_no_wall_info": "Auf beiden Seiten sind keine Wände nah genug.",
|
||||
"tripwire_placed_info": "Stolperdraht platziert.",
|
||||
"tripwire_triggered_info": "'{0}' hat deinen Stolperdraht ausgelöst.",
|
||||
|
|
@ -597,7 +597,7 @@
|
|||
"watchmaker_tt": "Rundenzeit um {0} Sekunden verlängert",
|
||||
|
||||
"weaponsswap": "Waffenwechsel",
|
||||
"weaponsswap_desc": "Klicke auf [css_useSkill], um mit einem zufälligen Gegner die Waffen zu tauschen",
|
||||
"weaponsswap_desc": "Drücke [css_useSkill], um mit einem zufälligen Gegner die Waffen zu tauschen",
|
||||
"weaponsswap_hud_info2": "Du hast keine Waffe zum Tauschen",
|
||||
|
||||
"weightless": "Schwerelosigkeit",
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
"aimbot_desc": "Every bullet you hit counts as a headshot",
|
||||
|
||||
"aimlock": "Aim Lock",
|
||||
"aimlock_desc": "Click [css_useSkill] to lock your aim on the nearest enemy",
|
||||
"aimlock_desc": "Press [css_useSkill] key to lock your aim on the nearest enemy",
|
||||
|
||||
"anomaly": "Anomaly",
|
||||
"anomaly_desc": "Click [css_useSkill] to rewind a few seconds back in time",
|
||||
"anomaly_desc": "Press [css_useSkill] key to rewind a few seconds back in time",
|
||||
|
||||
"antyflash": "Anti-Flash",
|
||||
"antyflash_desc": "You are immune to flashbangs, and your flashbangs last 7 seconds",
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
"cutter_desc": "Instant kill with a knife",
|
||||
|
||||
"cypher": "Cypher",
|
||||
"cypher_desc": "Click [css_useSkill] to create/switch to a camera",
|
||||
"cypher_desc": "Press [css_useSkill] key to create/switch to a camera",
|
||||
"cypher_nospace": "The camera must be positioned at right angles to the wall",
|
||||
|
||||
"darkness": "Darkness",
|
||||
|
|
@ -149,7 +149,7 @@
|
|||
"empgrenade_enemy_info": "An EMP grenade knocked out your radar and crosshair.",
|
||||
|
||||
"enemyspawn": "Enemy Spawn",
|
||||
"enemyspawn_desc": "Click [css_useSkill] to teleport to the enemy spawn",
|
||||
"enemyspawn_desc": "Press [css_useSkill] key to teleport to the enemy spawn",
|
||||
|
||||
"expensiveammo": "Expensive Ammo",
|
||||
"expensiveammo_desc": "A chosen enemy has to pay for every shot",
|
||||
|
|
@ -159,17 +159,17 @@
|
|||
"expensiveammo_select_info": "Select a player whose ammo will become expensive:",
|
||||
|
||||
"explodingbarrel": "Exploding Barrel",
|
||||
"explodingbarrel_desc": "Click [css_useSkill] to place a barrel that explodes when shot",
|
||||
"explodingbarrel_desc": "Press [css_useSkill] key to place a barrel that explodes when shot",
|
||||
|
||||
"explosiveshot": "Explosive Shot",
|
||||
"explosiveshot_desc": "Random chance to fire an explosive bullet while shooting",
|
||||
"explosiveshot_desc2": "Your chance to fire an explosive bullet: {0}%",
|
||||
|
||||
"falconeye": "Falcon Eye",
|
||||
"falconeye_desc": "Click [css_useSkill] to activate a bird's-eye view camera",
|
||||
"falconeye_desc": "Press [css_useSkill] key to activate a bird's-eye view camera",
|
||||
|
||||
"fastreload": "Fastreload",
|
||||
"fastreload_desc": "Click [css_useSkill] to reload the weapon you are currently holding",
|
||||
"fastreload_desc": "Press [css_useSkill] key to reload the weapon you are currently holding",
|
||||
|
||||
"firerain": "Fire Rain",
|
||||
"firerain_desc": "Throw a decoy to call down a rain of Molotovs",
|
||||
|
|
@ -179,10 +179,10 @@
|
|||
"flash_desc2": "Your speed multiplier is: {0}x",
|
||||
|
||||
"flashlight": "Flashlight",
|
||||
"flashlight_desc": "Click [css_useSkill] to turn the flashlight on or off. Its light can blind enemies",
|
||||
"flashlight_desc": "Press [css_useSkill] key to turn the flashlight on or off. Its light can blind enemies",
|
||||
|
||||
"fortnite": "Fortnite",
|
||||
"fortnite_desc": "Click [css_useSkill] to create a destructible barricade",
|
||||
"fortnite_desc": "Press [css_useSkill] key to create a destructible barricade",
|
||||
|
||||
"fragilebomb": "Fragile Bomb",
|
||||
"fragilebomb_desc": "Shooting the bomb damages it",
|
||||
|
|
@ -225,12 +225,12 @@
|
|||
"glue_desc": "Your grenades stick to walls",
|
||||
|
||||
"godmode": "God Mode",
|
||||
"godmode_desc": "Click [css_useSkill] to become immortal for a short time",
|
||||
"godmode_desc": "Press [css_useSkill] key to become immortal for a short time",
|
||||
"godmode_off": "Immortality disabled",
|
||||
"godmode_on": "Immortality enabled",
|
||||
|
||||
"grapple": "Grapple Hook",
|
||||
"grapple_desc": "Press [css_useSkill] to fire a hook at the point you are aiming at and pull yourself there",
|
||||
"grapple_desc": "Press [css_useSkill] key to fire a hook at the point you are aiming at and pull yourself there",
|
||||
"grapple_no_anchor_info": "No surface to hook onto.",
|
||||
"grapple_pulling_info": "PULLING",
|
||||
|
||||
|
|
@ -264,14 +264,14 @@
|
|||
"hotbomb_disable_info": "The bomb is no longer hot.",
|
||||
|
||||
"iana": "Hologram",
|
||||
"iana_desc": "Click [css_useSkill] to control your hologram for a few seconds",
|
||||
"iana_desc": "Press [css_useSkill] key to control your hologram for a few seconds",
|
||||
|
||||
"illiterate": "Illiterate",
|
||||
"illiterate_desc": "As long as you are alive, your enemies cannot read",
|
||||
"illiterate_alert": "Illiterate is active! You cannot read messages until the owner of this skill is eliminated",
|
||||
|
||||
"illusionist": "Illusionist",
|
||||
"illusionist_desc": "Click [css_useSkill] to deploy a replica that walks straight ahead",
|
||||
"illusionist_desc": "Press [css_useSkill] key to deploy a replica that walks straight ahead",
|
||||
|
||||
"impostor": "Impostor",
|
||||
"impostor_desc": "You start the round with an enemy player model",
|
||||
|
|
@ -359,7 +359,7 @@
|
|||
"magnifier_select_info": "Magnify player's screen:",
|
||||
|
||||
"medic": "Medic",
|
||||
"medic_desc": "Click [css_useSkill] to use a healing charge that restores 50 health",
|
||||
"medic_desc": "Press [css_useSkill] key to use a healing charge that restores 50 health",
|
||||
|
||||
"miner": "Bomb Miner",
|
||||
"miner_desc": "Your HE grenade only explode when there is an enemy nearby",
|
||||
|
|
@ -400,7 +400,7 @@
|
|||
"norecoil_desc": "No recoil while shooting",
|
||||
|
||||
"noclip": "NoClip",
|
||||
"noclip_desc": "Click [css_useSkill] to enable noclip for a short time",
|
||||
"noclip_desc": "Press [css_useSkill] key to enable noclip for a short time",
|
||||
|
||||
"oneshot": "One-Shot",
|
||||
"oneshot_desc": "Hitting an enemy instantly kills them",
|
||||
|
|
@ -467,7 +467,7 @@
|
|||
"rambo_desc": "You receive a random amount of health at the start of the round",
|
||||
|
||||
"randomweapon": "Random Weapon",
|
||||
"randomweapon_desc": "Click [css_useSkill] to receive a random weapon",
|
||||
"randomweapon_desc": "Press [css_useSkill] key to receive a random weapon",
|
||||
|
||||
"rezombie": "Re-Zombie",
|
||||
"rezombie_desc": "After death, you respawn as a zombie with increased health and no weapons",
|
||||
|
|
@ -479,16 +479,16 @@
|
|||
"regeneration_desc": "You restore health every few seconds",
|
||||
|
||||
"replicator": "Replicator",
|
||||
"replicator_desc": "Click [css_useSkill] to create a replica that deals damage on hit",
|
||||
"replicator_desc": "Press [css_useSkill] key to create a replica that deals damage on hit",
|
||||
|
||||
"retreat": "Retreat",
|
||||
"retreat_desc": "Click [css_useSkill] to return to spawn",
|
||||
"retreat_desc": "Press [css_useSkill] key to return to spawn",
|
||||
|
||||
"returntosender": "Return to Sender",
|
||||
"returntosender_desc": "The first hit on an enemy sends them back to their spawn",
|
||||
|
||||
"rewind": "Rewind",
|
||||
"rewind_desc": "Click [css_useSkill] to drop a marker where you stand and return to it shortly after",
|
||||
"rewind_desc": "Press [css_useSkill] key to drop a marker where you stand and return to it shortly after",
|
||||
"rewind_pending_info": "RETURN: {0}",
|
||||
|
||||
"richboy": "Rich Boy",
|
||||
|
|
@ -525,7 +525,7 @@
|
|||
|
||||
"sniperelite": "Sniper Elite",
|
||||
"sniperelite_customname": "Sniper Elite Skill",
|
||||
"sniperelite_desc": "Click [css_useSkill] to swap your current weapon for an AWP",
|
||||
"sniperelite_desc": "Press [css_useSkill] key to swap your current weapon for an AWP",
|
||||
|
||||
"soldier": "Soldier",
|
||||
"soldier_desc": "You have a random damage multiplier",
|
||||
|
|
@ -535,19 +535,19 @@
|
|||
"soundmaker_desc": "Every now and then, you hear player screams",
|
||||
|
||||
"spectator": "Spectator",
|
||||
"spectator_desc": "Click [css_useSkill] to spectate a random enemy",
|
||||
"spectator_desc": "Press [css_useSkill] key to spectate a random enemy",
|
||||
|
||||
"swapposition": "Position Swap",
|
||||
"swapposition_desc": "Click [css_useSkill] to swap places with a random enemy",
|
||||
"swapposition_desc": "Press [css_useSkill] key to swap places with a random enemy",
|
||||
|
||||
"takeammo": "Take Ammo",
|
||||
"takeammo_desc": "Click [css_useSkill] to take the active weapon's magazine from a random enemy",
|
||||
"takeammo_desc": "Press [css_useSkill] key to take the active weapon's magazine from a random enemy",
|
||||
"takeammo_hud_info1": "No player with an active magazine was found.",
|
||||
"takeammo_hud_info2": "The enemy has no magazines.",
|
||||
"takeammo_enemy_info": "You lost some ammo.",
|
||||
|
||||
"teamteleport": "Team Teleport",
|
||||
"teamteleport_desc": "Press [css_useSkill] to teleport to the teammate you're looking at",
|
||||
"teamteleport_desc": "Press [css_useSkill] key to teleport to the teammate you're looking at",
|
||||
"teamteleport_noenemy": "No teammate found",
|
||||
"teamteleport_hud_info": "Found: {0}",
|
||||
|
||||
|
|
@ -563,19 +563,19 @@
|
|||
"thief_incorrect_skill": "This skill cannot be selected!",
|
||||
|
||||
"thirdeye": "Third Eye",
|
||||
"thirdeye_desc": "Click [css_useSkill] to activate third-person view",
|
||||
"thirdeye_desc": "Press [css_useSkill] key to activate third-person view",
|
||||
|
||||
"thorns": "Thorns",
|
||||
"thorns_desc": "Your opponent will receive a portion of the damage that they inflicted on you",
|
||||
|
||||
"throwingknife": "Throwing Knife",
|
||||
"throwingknife_desc": "Click [css_useSkill] to throw a knife. But watch out for others",
|
||||
"throwingknife_desc": "Press [css_useSkill] key to throw a knife. But watch out for others",
|
||||
|
||||
"toxicsmoke": "Toxic Smoke",
|
||||
"toxicsmoke_desc": "Your smoke grenades deal damage",
|
||||
|
||||
"tripwire": "Tripwire",
|
||||
"tripwire_desc": "Click [css_useSkill] to string a wire between two walls. Enemies who touch it appear on your radar",
|
||||
"tripwire_desc": "Press [css_useSkill] key to string a wire between two walls. Enemies who touch it appear on your radar",
|
||||
"tripwire_no_wall_info": "There are no walls close enough on both sides.",
|
||||
"tripwire_placed_info": "Tripwire placed.",
|
||||
"tripwire_triggered_info": "'{0}' triggered your tripwire.",
|
||||
|
|
@ -597,7 +597,7 @@
|
|||
"watchmaker_tt": "Round time extended by {0} seconds.",
|
||||
|
||||
"weaponsswap": "Weapon Swap",
|
||||
"weaponsswap_desc": "Click [css_useSkill] to swap weapons with a random enemy",
|
||||
"weaponsswap_desc": "Press [css_useSkill] key to swap weapons with a random enemy",
|
||||
"weaponsswap_hud_info2": "You have no weapon to swap",
|
||||
|
||||
"weightless": "Weightlessness",
|
||||
|
|
@ -616,7 +616,7 @@
|
|||
"your_skill": "Your current skill",
|
||||
"enemy_skill": "Enemy's skill",
|
||||
"observer_skill": "Player's skill",
|
||||
"welcome_message": "Welcome {PLAYER} to {SERVER_NAME}!\nCurrent jRandomSkills version: {VERSION} ({SKILLS_COUNT} skills).\n\nOriginally created by:\n{AUTHOR1}\nModified and improved by:\n{AUTHOR2}\nOfficial Discord: https://discord.gg/9H8EZYBpPF",
|
||||
"welcome_message": "Welcome {PLAYER} to {SERVER_NAME}!",
|
||||
"drawing_skill": "Drawing a skill",
|
||||
"disabled_weapon": "You cannot use this weapon",
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"aimbot_desc": "Chaque balle que vous touchez compte comme un headshot",
|
||||
|
||||
"aimlock": "Verrouillage de visée",
|
||||
"aimlock_desc": "Cliquez sur [css_useSkill] pour verrouiller votre visée sur l'ennemi le plus proche",
|
||||
"aimlock_desc": "Appuyez sur [css_useSkill] pour verrouiller votre visée sur l'ennemi le plus proche",
|
||||
|
||||
"anomaly": "Anomalie",
|
||||
"anomaly_desc": "Appuyez sur [css_useSkill] pour remonter de quelques secondes dans le temps",
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
"cutter_desc": "Coup de couteau = mort instantanée",
|
||||
|
||||
"cypher": "Caméra",
|
||||
"cypher_desc": "Cliquez sur [css_useSkill] pour créer/passer à une caméra.",
|
||||
"cypher_desc": "Appuyez sur [css_useSkill] pour créer/passer à une caméra.",
|
||||
"cypher_nospace": "La caméra doit être positionnée à angle droit par rapport au mur",
|
||||
|
||||
"darkness": "Obscurité",
|
||||
|
|
@ -166,7 +166,7 @@
|
|||
"expensiveammo_select_info": "Sélectionnez un joueur dont les munitions deviendront coûteuses :",
|
||||
|
||||
"explodingbarrel": "Baril explosif",
|
||||
"explodingbarrel_desc": "Cliquez sur [css_useSkill] pour placer un baril qui explose lorsqu'il est touché",
|
||||
"explodingbarrel_desc": "Appuyez sur [css_useSkill] pour placer un baril qui explose lorsqu'il est touché",
|
||||
|
||||
"explosiveshot": "Tir Explosif",
|
||||
"explosiveshot_desc": "Chance aléatoire de tirer une balle explosive en tirant",
|
||||
|
|
@ -186,7 +186,7 @@
|
|||
"flash_desc2": "Votre multiplicateur de vitesse est : {0}x",
|
||||
|
||||
"flashlight": "Lampe torche",
|
||||
"flashlight_desc": "Cliquez sur [css_useSkill] pour allumer ou éteindre la lampe torche. Sa lumière peut aveugler les ennemis",
|
||||
"flashlight_desc": "Appuyez sur [css_useSkill] pour allumer ou éteindre la lampe torche. Sa lumière peut aveugler les ennemis",
|
||||
|
||||
"fortnite": "Fortnite",
|
||||
"fortnite_desc": "Appuyez sur [css_useSkill] pour créer une barricade destructible",
|
||||
|
|
@ -271,14 +271,14 @@
|
|||
"hotbomb_disable_info": "La bombe ne brûle plus.",
|
||||
|
||||
"iana": "Hologramme",
|
||||
"iana_desc": "Cliquez sur [css_useSkill] pour contrôler votre hologramme pendant quelques secondes",
|
||||
"iana_desc": "Appuyez sur [css_useSkill] pour contrôler votre hologramme pendant quelques secondes",
|
||||
|
||||
"illiterate": "Illettré",
|
||||
"illiterate_desc": "Tant que vous êtes en vie, vos ennemis ne peuvent pas lire",
|
||||
"illiterate_alert": "Illettré est actif ! Vous ne pouvez pas lire les messages tant que le propriétaire de cette compétence n'est pas éliminé",
|
||||
|
||||
"illusionist": "Illusionniste",
|
||||
"illusionist_desc": "Cliquez sur [css_useSkill] pour déployer une réplique qui marche droit devant",
|
||||
"illusionist_desc": "Appuyez sur [css_useSkill] pour déployer une réplique qui marche droit devant",
|
||||
|
||||
"impostor": "Imposteur",
|
||||
"impostor_desc": "Vous commencez le round avec un modèle de joueur ennemi",
|
||||
|
|
@ -541,7 +541,7 @@
|
|||
"swapposition_desc": "Appuyez sur [css_useSkill] pour échanger de place avec un ennemi aléatoire",
|
||||
|
||||
"takeammo": "Prendre des munitions",
|
||||
"takeammo_desc": "Cliquez sur [css_useSkill] pour prendre le chargeur de l'arme active d'un ennemi aléatoire",
|
||||
"takeammo_desc": "Appuyez sur [css_useSkill] pour prendre le chargeur de l'arme active d'un ennemi aléatoire",
|
||||
"takeammo_hud_info1": "Aucun joueur avec un chargeur actif n'a été trouvé.",
|
||||
"takeammo_hud_info2": "L'ennemi n'a pas de chargeur.",
|
||||
"takeammo_enemy_info": "Vous avez perdu des munitions.",
|
||||
|
|
@ -569,13 +569,13 @@
|
|||
"thorns_desc": "Votre adversaire recevra une partie des dégâts qu’il vous a infligés",
|
||||
|
||||
"throwingknife": "Couteau de lancer",
|
||||
"throwingknife_desc": "Cliquez sur [css_useSkill] pour lancer un couteau. Mais attention aux autres",
|
||||
"throwingknife_desc": "Appuyez sur [css_useSkill] pour lancer un couteau. Mais attention aux autres",
|
||||
|
||||
"toxicsmoke": "Fumée Toxique",
|
||||
"toxicsmoke_desc": "Vos grenades fumigènes infligent des dégâts",
|
||||
|
||||
"tripwire": "Fil-piège",
|
||||
"tripwire_desc": "Cliquez sur [css_useSkill] pour tendre un fil entre deux murs. Les ennemis qui le touchent apparaissent sur votre radar",
|
||||
"tripwire_desc": "Appuyez sur [css_useSkill] pour tendre un fil entre deux murs. Les ennemis qui le touchent apparaissent sur votre radar",
|
||||
"tripwire_no_wall_info": "Aucun mur n'est suffisamment proche des deux côtés.",
|
||||
"tripwire_placed_info": "Fil-piège placé.",
|
||||
"tripwire_triggered_info": "'{0}' a déclenché votre fil-piège.",
|
||||
|
|
@ -616,7 +616,7 @@
|
|||
"your_skill": "Votre compétence",
|
||||
"enemy_skill": "Compétence de l’ennemi",
|
||||
"observer_skill": "Compétence du joueur",
|
||||
"welcome_message": "Bienvenue {PLAYER} sur {SERVER_NAME}!\nVersion actuelle de jRandomSkills : {VERSION} ({SKILLS_COUNT} compétences).\n\nCréé à l’origine par :\n{AUTHOR1}\nModifié et amélioré par :\n{AUTHOR2}\nDiscord officiel : https://discord.gg/9H8EZYBpPF",
|
||||
"welcome_message": "Bienvenue {PLAYER} sur {SERVER_NAME}!",
|
||||
"drawing_skill": "Attribution d’une compétence",
|
||||
"disabled_weapon": "Vous ne pouvez pas utiliser cette arme",
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
"aimbot_desc": "Każdy twój trafiony pocisk liczy się jako strzał w głowę",
|
||||
|
||||
"aimlock": "Aim Lock",
|
||||
"aimlock_desc": "Kliknij [css_useSkill], aby wycelować na najbliższego wroga",
|
||||
"aimlock_desc": "Naciśnij [css_useSkill], aby wycelować na najbliższego wroga",
|
||||
|
||||
"anomaly": "Anomalia",
|
||||
"anomaly_desc": "Kliknij [css_useSkill], aby cofnąć się o kilka sekund w czasie",
|
||||
"anomaly_desc": "Naciśnij [css_useSkill], aby cofnąć się o kilka sekund w czasie",
|
||||
|
||||
"antyflash": "Anty Flash",
|
||||
"antyflash_desc": "Posiadasz odporność na flash'e, a twoje flash'e trwają 7 sekund",
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
"cutter_desc": "Natychmiastowe zabójstwo nożem",
|
||||
|
||||
"cypher": "Kamera",
|
||||
"cypher_desc": "Kliknij [css_useSkill], aby utworzyć/przełączyć się na kamerę",
|
||||
"cypher_desc": "Naciśnij [css_useSkill], aby utworzyć/przełączyć się na kamerę",
|
||||
"cypher_nospace": "Kamera musi być ustawiona pod kątem prostym do ściany",
|
||||
|
||||
"darkness": "Mrok",
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
"empgrenade_enemy_info": "Granat EMP wyłączył twój radar i celownik.",
|
||||
|
||||
"enemyspawn": "Resp Wroga",
|
||||
"enemyspawn_desc": "Kliknij [css_useSkill], aby teleportować się na resp wroga",
|
||||
"enemyspawn_desc": "Naciśnij [css_useSkill], aby teleportować się na resp wroga",
|
||||
|
||||
"expensiveammo": "Droga Amunicja",
|
||||
"expensiveammo_desc": "Wybrany przeciwnik musi płacić za każdy oddany strzał",
|
||||
|
|
@ -166,17 +166,17 @@
|
|||
"expensiveammo_select_info": "Wybierz gracza, którego amunicja stanie się droga:",
|
||||
|
||||
"explodingbarrel": "Wybuchowa Beczka",
|
||||
"explodingbarrel_desc": "Kliknij [css_useSkill], aby postawić beczkę, która wybucha po trafieniu",
|
||||
"explodingbarrel_desc": "Naciśnij [css_useSkill], aby postawić beczkę, która wybucha po trafieniu",
|
||||
|
||||
"explosiveshot": "Strzał Wybuchowy",
|
||||
"explosiveshot_desc": "Losowa szansa wystrzelenia pocisku wybuchowego podczas strzelania",
|
||||
"explosiveshot_desc2": "Twoja szansa na wystrzelenie pocisku wybuchowego: {0}%",
|
||||
|
||||
"falconeye": "Oko Sokoła",
|
||||
"falconeye_desc": "Kliknij [css_useSkill], aby aktywować kamerę z lotu ptaka",
|
||||
"falconeye_desc": "Naciśnij [css_useSkill], aby aktywować kamerę z lotu ptaka",
|
||||
|
||||
"fastreload": "Szybkie Rączki",
|
||||
"fastreload_desc": "Kliknij [css_useSkill], aby przeładować broń, którą obecnie trzymasz",
|
||||
"fastreload_desc": "Naciśnij [css_useSkill], aby przeładować broń, którą obecnie trzymasz",
|
||||
|
||||
"firerain": "Deszcz Ognia",
|
||||
"firerain_desc": "Rzuć wabik, aby przywołać deszcz koktajli Mołotowa",
|
||||
|
|
@ -186,10 +186,10 @@
|
|||
"flash_desc2": "Twój mnożnik prędkości to {0}x",
|
||||
|
||||
"flashlight": "Latarka",
|
||||
"flashlight_desc": "Kliknij [css_useSkill], aby włączyć lub wyłączyć latarkę. Jej światło może oślepić przeciwników",
|
||||
"flashlight_desc": "Naciśnij [css_useSkill], aby włączyć lub wyłączyć latarkę. Jej światło może oślepić przeciwników",
|
||||
|
||||
"fortnite": "Fortnite",
|
||||
"fortnite_desc": "Kliknij [css_useSkill], aby stworzyć barykadę, którą można zniszczyć",
|
||||
"fortnite_desc": "Naciśnij [css_useSkill], aby stworzyć barykadę, którą można zniszczyć",
|
||||
|
||||
"fragilebomb": "Krucha Bomba",
|
||||
"fragilebomb_desc": "Strzelanie do bomby powoduje jej uszkodzenie",
|
||||
|
|
@ -232,7 +232,7 @@
|
|||
"glue_desc": "Twoje granaty przyklejają się do ścian",
|
||||
|
||||
"godmode": "Nieśmiertelność",
|
||||
"godmode_desc": "Kliknij [css_useSkill], aby stać się nieśmiertelnym na krótką chwilę",
|
||||
"godmode_desc": "Naciśnij [css_useSkill], aby stać się nieśmiertelnym na krótką chwilę",
|
||||
"godmode_off": "Nieśmiertelność wyłączona",
|
||||
"godmode_on": "Nieśmiertelność włączona",
|
||||
|
||||
|
|
@ -271,7 +271,7 @@
|
|||
"hotbomb_disable_info": "Bomba już nie parzy.",
|
||||
|
||||
"iana": "Hologram",
|
||||
"iana_desc": "Kliknij [css_useSkill], aby sterować hologramem przez kilka sekund",
|
||||
"iana_desc": "Naciśnij [css_useSkill], aby sterować hologramem przez kilka sekund",
|
||||
|
||||
"illiterate": "Analfabeta",
|
||||
"illiterate_desc": "Dopóki żyjesz, Twoi wrogowie nie potrafią czytać",
|
||||
|
|
@ -366,7 +366,7 @@
|
|||
"magnifier_select_info": "Powiększ ekran gracza:",
|
||||
|
||||
"medic": "Medyk",
|
||||
"medic_desc": "Kliknij [css_useSkill], aby użyć ładunku leczniczego, który przywraca 50 punktów zdrowia",
|
||||
"medic_desc": "Naciśnij [css_useSkill], aby użyć ładunku leczniczego, który przywraca 50 punktów zdrowia",
|
||||
|
||||
"miner": "Bomberman",
|
||||
"miner_desc": "Twoje granaty HE wybuchają tylko wtedy, gdy w pobliżu jest wróg",
|
||||
|
|
@ -400,7 +400,7 @@
|
|||
"norecoil_desc": "Brak odrzutu podczas strzelania",
|
||||
|
||||
"noclip": "NoClip",
|
||||
"noclip_desc": "Kliknij [css_useSkill], aby włączyć noclip na krótki czas",
|
||||
"noclip_desc": "Naciśnij [css_useSkill], aby włączyć noclip na krótki czas",
|
||||
|
||||
"oneshot": "Jednostrzałowiec",
|
||||
"oneshot_desc": "Po trafieniu natychmiast zabijasz przeciwnika",
|
||||
|
|
@ -467,7 +467,7 @@
|
|||
"rambo_desc": "Na początku rundy otrzymujesz losową ilość zdrowia",
|
||||
|
||||
"randomweapon": "Losowa Broń",
|
||||
"randomweapon_desc": "Kliknij [css_useSkill], aby otrzymać losową broń",
|
||||
"randomweapon_desc": "Naciśnij [css_useSkill], aby otrzymać losową broń",
|
||||
|
||||
"rezombie": "Re-Zombie",
|
||||
"rezombie_desc": "Po śmierci odradzasz się jako zombie z większym zdrowiem i bez broni",
|
||||
|
|
@ -479,10 +479,10 @@
|
|||
"regeneration_desc": "Co kilka sekund odnawiasz zdrowie",
|
||||
|
||||
"replicator": "Replikator",
|
||||
"replicator_desc": "Kliknij [css_useSkill], aby stworzyć swoją replikę, która zadaje obrażenia po trafieniu",
|
||||
"replicator_desc": "Naciśnij [css_useSkill], aby stworzyć swoją replikę, która zadaje obrażenia po trafieniu",
|
||||
|
||||
"retreat": "Odwrót",
|
||||
"retreat_desc": "Kliknij [css_useSkill], aby powrócić na resp",
|
||||
"retreat_desc": "Naciśnij [css_useSkill], aby powrócić na resp",
|
||||
|
||||
"returntosender": "Zwrot do Nadawcy",
|
||||
"returntosender_desc": "Pierwsze trafienie wroga powoduje, że wraca on na swój resp",
|
||||
|
|
@ -525,7 +525,7 @@
|
|||
|
||||
"sniperelite": "Papito",
|
||||
"sniperelite_customname": "Mityczna AWP",
|
||||
"sniperelite_desc": "Kliknij [css_useSkill], aby zamienić aktualną broń na AWP",
|
||||
"sniperelite_desc": "Naciśnij [css_useSkill], aby zamienić aktualną broń na AWP",
|
||||
|
||||
"soldier": "Żołnierz",
|
||||
"soldier_desc": "Masz losowy mnożnik obrażeń",
|
||||
|
|
@ -535,13 +535,13 @@
|
|||
"soundmaker_desc": "Co jakiś czas słyszysz krzyki graczy",
|
||||
|
||||
"spectator": "Obserwator",
|
||||
"spectator_desc": "Kliknij [css_useSkill], aby obserwować losowego przeciwnika",
|
||||
"spectator_desc": "Naciśnij [css_useSkill], aby obserwować losowego przeciwnika",
|
||||
|
||||
"swapposition": "Zamiana Miejsc",
|
||||
"swapposition_desc": "Kliknij [css_useSkill], aby zamienić się miejscami z losowym przeciwnikiem",
|
||||
"swapposition_desc": "Naciśnij [css_useSkill], aby zamienić się miejscami z losowym przeciwnikiem",
|
||||
|
||||
"takeammo": "Zabierz Amunicję",
|
||||
"takeammo_desc": "Kliknij [css_useSkill], aby zabrać magazynek aktywnej broni losowego przeciwnika",
|
||||
"takeammo_desc": "Naciśnij [css_useSkill], aby zabrać magazynek aktywnej broni losowego przeciwnika",
|
||||
"takeammo_hud_info1": "Nie znaleziono gracza z aktywnym magazynkiem.",
|
||||
"takeammo_hud_info2": "Przeciwnik nie ma magazynków.",
|
||||
"takeammo_enemy_info": "Straciłeś trochę amunicji.",
|
||||
|
|
@ -563,7 +563,7 @@
|
|||
"thief_incorrect_skill": "Tej umiejętności nie można wybrać!",
|
||||
|
||||
"thirdeye": "Trzecie Oko",
|
||||
"thirdeye_desc": "Kliknij [css_useSkill], aby aktywować trzecią osobę",
|
||||
"thirdeye_desc": "Naciśnij [css_useSkill], aby aktywować trzecią osobę",
|
||||
|
||||
"thorns": "Ciernie",
|
||||
"thorns_desc": "Twój przeciwnik otrzymuje część obrażeń, które zadał ci",
|
||||
|
|
@ -575,7 +575,7 @@
|
|||
"toxicsmoke_desc": "Twoje granaty dymny zadają obrażenia",
|
||||
|
||||
"tripwire": "Linka z Drutu",
|
||||
"tripwire_desc": "Kliknij [css_useSkill], aby rozciągnąć drut między dwiema ścianami. Wrogowie, którzy go dotkną, pojawią się na Twoim radarze",
|
||||
"tripwire_desc": "Naciśnij [css_useSkill], aby rozciągnąć drut między dwiema ścianami. Wrogowie, którzy go dotkną, pojawią się na Twoim radarze",
|
||||
"tripwire_no_wall_info": "Po obu stronach nie ma wystarczająco blisko położonych ścian.",
|
||||
"tripwire_placed_info": "Linka została rozstawiona.",
|
||||
"tripwire_triggered_info": "'{0}' uruchomił Twoją linkę.",
|
||||
|
|
@ -597,7 +597,7 @@
|
|||
"watchmaker_tt": "Czas rundy został wydłużony o {0} sekund",
|
||||
|
||||
"weaponsswap": "Zamiana Broni",
|
||||
"weaponsswap_desc": "Kliknij [css_useSkill], aby zamienić się bronią z losowym przeciwnikiem",
|
||||
"weaponsswap_desc": "Naciśnij [css_useSkill], aby zamienić się bronią z losowym przeciwnikiem",
|
||||
"weaponsswap_hud_info2": "Nie posiadasz broni na zamiane",
|
||||
|
||||
"weightless": "Nieważkość",
|
||||
|
|
@ -616,7 +616,7 @@
|
|||
"your_skill": "Twoja aktualna moc",
|
||||
"enemy_skill": "Supermoc przeciwnika",
|
||||
"observer_skill": "Moc gracza",
|
||||
"welcome_message": "Witaj {PLAYER} na serwerze {SERVER_NAME}!\nAktualna wersja jRandomSkills: {VERSION} ({SKILLS_COUNT} supermocy).\n\nPierwotnie plugin stworzona przez:\n{AUTHOR1}\nZmodyfikowany i ulepszony przez:\n{AUTHOR2}\nOficjalny discord: https://discord.gg/9H8EZYBpPF",
|
||||
"welcome_message": "Witaj {PLAYER} na serwerze {SERVER_NAME}!",
|
||||
"drawing_skill": "Losowanie mocy",
|
||||
"disabled_weapon": "Nie możesz używać tej broni",
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"aimbot_desc": "Toda bala que você acertar conta como um hs",
|
||||
|
||||
"aimlock": "Aim Lock",
|
||||
"aimlock_desc": "Clique em [css_useSkill] para travar a mira no inimigo mais próximo",
|
||||
"aimlock_desc": "Pressione [css_useSkill] para travar a mira no inimigo mais próximo",
|
||||
|
||||
"anomaly": "Máquina do Tempo",
|
||||
"anomaly_desc": "Pressione [css_useSkill] para voltar alguns segundos no tempo",
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
"cutter_desc": "Você mata instantaneamente com a faca",
|
||||
|
||||
"cypher": "CFTV",
|
||||
"cypher_desc": "Clique em [css_useSkill] para criar/mudar para uma câmera",
|
||||
"cypher_desc": "Pressione [css_useSkill] para criar/mudar para uma câmera",
|
||||
"cypher_nospace": "A câmera deve ser posicionada em ângulo reto com a parede",
|
||||
|
||||
"darkness": "Escuridão",
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
"empgrenade_enemy_info": "Uma granada EMP derrubou seu radar e sua mira.",
|
||||
|
||||
"enemyspawn": "Spawn Inimigo",
|
||||
"enemyspawn_desc": "Clique em [css_useSkill] para se teletransportar para a base inimiga",
|
||||
"enemyspawn_desc": "Pressione [css_useSkill] para se teletransportar para a base inimiga",
|
||||
|
||||
"expensiveammo": "Munição Cara",
|
||||
"expensiveammo_desc": "Um inimigo escolhido precisa pagar por cada disparo",
|
||||
|
|
@ -166,17 +166,17 @@
|
|||
"expensiveammo_select_info": "Selecione um jogador cuja munição ficará cara:",
|
||||
|
||||
"explodingbarrel": "Barril Explosivo",
|
||||
"explodingbarrel_desc": "Clique em [css_useSkill] para colocar um barril que explode quando atingido",
|
||||
"explodingbarrel_desc": "Pressione [css_useSkill] para colocar um barril que explode quando atingido",
|
||||
|
||||
"explosiveshot": "Tiro Explosivo",
|
||||
"explosiveshot_desc": "Chance aleatória de disparar uma bala explosiva enquanto atira",
|
||||
"explosiveshot_desc2": "Sua chance de disparar uma bala explosiva: {0}%",
|
||||
|
||||
"falconeye": "Olho de Águia",
|
||||
"falconeye_desc": "Clique em [css_useSkill] para ativar uma câmera 360 com visão aérea",
|
||||
"falconeye_desc": "Pressione [css_useSkill] para ativar uma câmera 360 com visão aérea",
|
||||
|
||||
"fastreload": "Recarga Rápida",
|
||||
"fastreload_desc": "Clique em [css_useSkill] para recarregar a arma que você está segurando",
|
||||
"fastreload_desc": "Pressione [css_useSkill] para recarregar a arma que você está segurando",
|
||||
|
||||
"firerain": "Chuva de Fogo",
|
||||
"firerain_desc": "Jogue uma isca para chamar uma chuva de Molotovs",
|
||||
|
|
@ -186,10 +186,10 @@
|
|||
"flash_desc2": "Seu multiplicador de velocidade é: {0}x",
|
||||
|
||||
"flashlight": "Lanterna",
|
||||
"flashlight_desc": "Clique em [css_useSkill] para ligar ou desligar a lanterna. Sua luz pode cegar os inimigos",
|
||||
"flashlight_desc": "Pressione [css_useSkill] para ligar ou desligar a lanterna. Sua luz pode cegar os inimigos",
|
||||
|
||||
"fortnite": "Fortnite",
|
||||
"fortnite_desc": "Clique em [css_useSkill] para criar uma barreira destrutível",
|
||||
"fortnite_desc": "Pressione [css_useSkill] para criar uma barreira destrutível",
|
||||
|
||||
"fragilebomb": "Bomba Frágil",
|
||||
"fragilebomb_desc": "Atirar na bomba a danifica",
|
||||
|
|
@ -232,7 +232,7 @@
|
|||
"glue_desc": "Suas granadas grudam nas paredes",
|
||||
|
||||
"godmode": "Modo Deus",
|
||||
"godmode_desc": "Clique em [css_useSkill] para se tornar imortal por alguns segundos",
|
||||
"godmode_desc": "Pressione [css_useSkill] para se tornar imortal por alguns segundos",
|
||||
"godmode_off": "Imortalidade desativada",
|
||||
"godmode_on": "Imortalidade ativada",
|
||||
|
||||
|
|
@ -271,14 +271,14 @@
|
|||
"hotbomb_disable_info": "A bomba não está mais queimando.",
|
||||
|
||||
"iana": "Holograma",
|
||||
"iana_desc": "Clique em [css_useSkill] para controlar seu holograma por alguns segundos",
|
||||
"iana_desc": "Pressione [css_useSkill] para controlar seu holograma por alguns segundos",
|
||||
|
||||
"illiterate": "Analfabeto",
|
||||
"illiterate_desc": "Enquanto você estiver vivo, seus inimigos não conseguem ler",
|
||||
"illiterate_alert": "Analfabeto está ativo! Você não pode ler mensagens até que o proprietário desta habilidade seja eliminado",
|
||||
|
||||
"illusionist": "Ilusionista",
|
||||
"illusionist_desc": "Clique em [css_useSkill] para enviar uma réplica que caminha em frente",
|
||||
"illusionist_desc": "Pressione [css_useSkill] para enviar uma réplica que caminha em frente",
|
||||
|
||||
"impostor": "Impostor",
|
||||
"impostor_desc": "Você começa a rodada vestido do time inimigo",
|
||||
|
|
@ -366,7 +366,7 @@
|
|||
"magnifier_select_info": "Ampliar tela do jogador:",
|
||||
|
||||
"medic": "Médico",
|
||||
"medic_desc": "Clique em [css_useSkill] para usar uma injeção que restaura 50 de vida",
|
||||
"medic_desc": "Pressione [css_useSkill] para usar uma injeção que restaura 50 de vida",
|
||||
|
||||
"miner": "Mineiro de Bombas",
|
||||
"miner_desc": "Sua granada HE só explode quando há um inimigo por perto",
|
||||
|
|
@ -400,7 +400,7 @@
|
|||
"norecoil_desc": "Sem recoil ao atirar",
|
||||
|
||||
"noclip": "NoClip",
|
||||
"noclip_desc": "Clique em [css_useSkill] para ativar noclip por poucos segundos",
|
||||
"noclip_desc": "Pressione [css_useSkill] para ativar noclip por poucos segundos",
|
||||
|
||||
"oneshot": "Ignorante",
|
||||
"oneshot_desc": "Acertar um inimigo o mata instantaneamente",
|
||||
|
|
@ -467,7 +467,7 @@
|
|||
"rambo_desc": "Você recebe uma quantidade aleatória de vida no início da rodada",
|
||||
|
||||
"randomweapon": "Arma Aleatória",
|
||||
"randomweapon_desc": "Clique em [css_useSkill] para receber uma arma aleatória",
|
||||
"randomweapon_desc": "Pressione [css_useSkill] para receber uma arma aleatória",
|
||||
|
||||
"rezombie": "Walking Dead",
|
||||
"rezombie_desc": "Após morrer, você renasce como um zumbi com mais vida porém sem armas",
|
||||
|
|
@ -479,16 +479,16 @@
|
|||
"regeneration_desc": "Você restaura vida a cada poucos segundos",
|
||||
|
||||
"replicator": "Clone",
|
||||
"replicator_desc": "Clique em [css_useSkill] para criar um clone que causa dano ao ser atingido",
|
||||
"replicator_desc": "Pressione [css_useSkill] para criar um clone que causa dano ao ser atingido",
|
||||
|
||||
"retreat": "De Volta as Origens",
|
||||
"retreat_desc": "Clique em [css_useSkill] para retornar ao spawn",
|
||||
"retreat_desc": "Pressione [css_useSkill] para retornar ao spawn",
|
||||
|
||||
"returntosender": "Devolução ao Remetente",
|
||||
"returntosender_desc": "O primeiro tiro em um inimigo o envia de volta a sua base",
|
||||
|
||||
"rewind": "Retroceder",
|
||||
"rewind_desc": "Clique em [css_useSkill] para deixar uma marca aqui e voltar a ela logo depois",
|
||||
"rewind_desc": "Pressione [css_useSkill] para deixar uma marca aqui e voltar a ela logo depois",
|
||||
"rewind_pending_info": "RETORNO: {0}",
|
||||
|
||||
"richboy": "Filhinho de Papai",
|
||||
|
|
@ -524,7 +524,7 @@
|
|||
"smoker_desc": "Sis bombalarınız asla bitmez",
|
||||
|
||||
"sniperelite": "Sniper do BOPE",
|
||||
"sniperelite_desc": "Clique em [css_useSkill] para trocar sua arma atual por uma AWP",
|
||||
"sniperelite_desc": "Pressione [css_useSkill] para trocar sua arma atual por uma AWP",
|
||||
"sniperelite_customname": "Keskin Nişancı Elit Yeteneği",
|
||||
|
||||
"soldier": "Soldado",
|
||||
|
|
@ -535,13 +535,13 @@
|
|||
"soundmaker_desc": "De vez em quando, você ouve gritos de jogadores",
|
||||
|
||||
"spectator": "Espectador",
|
||||
"spectator_desc": "Clique em [css_useSkill] para ver a tela de um inimigo aleatório",
|
||||
"spectator_desc": "Pressione [css_useSkill] para ver a tela de um inimigo aleatório",
|
||||
|
||||
"swapposition": "Troca de Posição",
|
||||
"swapposition_desc": "Clique em [css_useSkill] para trocar de lugar com um inimigo aleatório",
|
||||
"swapposition_desc": "Pressione [css_useSkill] para trocar de lugar com um inimigo aleatório",
|
||||
|
||||
"takeammo": "Pegar Munição",
|
||||
"takeammo_desc": "Clique em [css_useSkill] para pegar o carregador da arma ativa de um inimigo aleatório",
|
||||
"takeammo_desc": "Pressione [css_useSkill] para pegar o carregador da arma ativa de um inimigo aleatório",
|
||||
"takeammo_hud_info1": "Nenhum jogador com um carregador ativo foi encontrado.",
|
||||
"takeammo_hud_info2": "O inimigo não possui carregadores.",
|
||||
"takeammo_enemy_info": "Você perdeu um pouco de munição.",
|
||||
|
|
@ -563,19 +563,19 @@
|
|||
"thief_incorrect_skill": "Esta habilidade não pode ser selecionada!",
|
||||
|
||||
"thirdeye": "Terceiro Olho",
|
||||
"thirdeye_desc": "Clique em [css_useSkill] para ativar a terceira pessoa",
|
||||
"thirdeye_desc": "Pressione [css_useSkill] para ativar a terceira pessoa",
|
||||
|
||||
"thorns": "Porco Espinho",
|
||||
"thorns_desc": "Seu oponente receberá uma parte do dano que causou a você",
|
||||
|
||||
"throwingknife": "Faca de Arremesso",
|
||||
"throwingknife_desc": "Clique em [css_useSkill] para lançar uma faca. Mas cuidado com os outros",
|
||||
"throwingknife_desc": "Pressione [css_useSkill] para lançar uma faca. Mas cuidado com os outros",
|
||||
|
||||
"toxicsmoke": "Smoke Tóxica",
|
||||
"toxicsmoke_desc": "Suas smokes causam dano",
|
||||
|
||||
"tripwire": "Fio de Armadilha",
|
||||
"tripwire_desc": "Clique em [css_useSkill] para estender um fio entre duas paredes. Inimigos que tocarem nele aparecerão no seu radar",
|
||||
"tripwire_desc": "Pressione [css_useSkill] para estender um fio entre duas paredes. Inimigos que tocarem nele aparecerão no seu radar",
|
||||
"tripwire_no_wall_info": "Não há paredes próximas o suficiente dos dois lados.",
|
||||
"tripwire_placed_info": "Fio de armadilha colocado.",
|
||||
"tripwire_triggered_info": "'{0}' acionou seu fio.",
|
||||
|
|
@ -597,7 +597,7 @@
|
|||
"watchmaker_tt": "Tempo da rodada estendido em {0} segundos.",
|
||||
|
||||
"weaponsswap": "Troca de Armas",
|
||||
"weaponsswap_desc": "Clique em [css_useSkill] para trocar armas com um inimigo aleatório",
|
||||
"weaponsswap_desc": "Pressione [css_useSkill] para trocar armas com um inimigo aleatório",
|
||||
"weaponsswap_hud_info2": "Você não tem arma para trocar",
|
||||
|
||||
"weightless": "Gravidade Zero",
|
||||
|
|
@ -616,7 +616,7 @@
|
|||
"your_skill": "Sua habilidade atual",
|
||||
"enemy_skill": "Habilidade do inimigo",
|
||||
"observer_skill": "Habilidade do jogador",
|
||||
"welcome_message": "Bem-vindo {PLAYER} ao {SERVER_NAME}!\nVersão atual do jRandomSkills: {VERSION} ({SKILLS_COUNT} habilidades).\n\nCriado originalmente por:\n{AUTHOR1}\nModificado e aprimorado por:\n{AUTHOR2}\nDiscord oficial: https://discord.gg/9H8EZYBpPF",
|
||||
"welcome_message": "Bem-vindo {PLAYER} ao {SERVER_NAME}!",
|
||||
"drawing_skill": "Sorteando uma habilidade",
|
||||
"disabled_weapon": "Você não pode usar esta arma",
|
||||
|
||||
|
|
|
|||
|
|
@ -616,7 +616,7 @@
|
|||
"your_skill": "Ваш текущий навык",
|
||||
"enemy_skill": "Навык врага",
|
||||
"observer_skill": "Навык игрока",
|
||||
"welcome_message": "Добро пожаловать {PLAYER} на {SERVER_NAME}!\nТекущая версия jRandomSkills: {VERSION} ({SKILLS_COUNT} навыков).\n\nОригинал создан:\n{AUTHOR1}\nМодифицирован и улучшен:\n{AUTHOR2}\nОфициальный Discord: https://discord.gg/9H8EZYBpPF",
|
||||
"welcome_message": "Добро пожаловать {PLAYER} на {SERVER_NAME}!",
|
||||
"drawing_skill": "Получение навыка",
|
||||
"disabled_weapon": "Вы не можете использовать это оружие",
|
||||
|
||||
|
|
|
|||
|
|
@ -616,7 +616,7 @@
|
|||
"your_skill": "Yeteneğin",
|
||||
"enemy_skill": "Düşmanın yeteneği",
|
||||
"observer_skill": "Yeteneği",
|
||||
"welcome_message": "{PLAYER}, {SERVER_NAME} sunucusuna hoş geldin!\nGüncel jRandomSkills versiyonu: {VERSION} ({SKILLS_COUNT} yetenek).\n\nOrijinal yapımcı:\n{AUTHOR1}\nGeliştiren:\n{AUTHOR2}\nResmi Discord: https://discord.gg/9H8EZYBpPF",
|
||||
"welcome_message": "{PLAYER}, {SERVER_NAME} sunucusuna hoş geldin!",
|
||||
"drawing_skill": "Yetenek çarkı dönüyor...",
|
||||
"disabled_weapon": "Bu silahı kullanamazsın",
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
"aimbot_desc": "你击中的每颗子弹都算作爆头",
|
||||
|
||||
"aimlock": "自",
|
||||
"aimlock_desc": "点击 [css_useSkill] 瞄准距离最近的敌人",
|
||||
"aimlock_desc": "按 [css_useSkill] 瞄准距离最近的敌人",
|
||||
|
||||
"anomaly": "异常",
|
||||
"anomaly_desc": "点击 [css_useSkill] 回到几秒钟前",
|
||||
"anomaly_desc": "按 [css_useSkill] 回到几秒钟前",
|
||||
|
||||
"antyflash": "防闪",
|
||||
"antyflash_desc": "你对闪光弹免疫,你的闪光弹持续7秒",
|
||||
|
|
@ -93,7 +93,7 @@
|
|||
"cutter_desc": "用刀刀人可立即杀死敌人",
|
||||
|
||||
"cypher": "相机",
|
||||
"cypher_desc": "点击 [css_useSkill] 创建/切换摄像机",
|
||||
"cypher_desc": "按 [css_useSkill] 创建/切换摄像机",
|
||||
"cypher_nospace": "相机必须与墙壁呈直角放置",
|
||||
|
||||
"darkness": "黑暗",
|
||||
|
|
@ -143,7 +143,7 @@
|
|||
"empgrenade_enemy_info": "电磁脉冲手雷让你的雷达和准星失效了。",
|
||||
|
||||
"enemyspawn": "传送敌人出生点",
|
||||
"enemyspawn_desc": "点击 [css_useSkill] 传送到敌人出生点",
|
||||
"enemyspawn_desc": "按 [css_useSkill] 传送到敌人出生点",
|
||||
|
||||
"expensiveammo": "expensiveammo",
|
||||
"expensiveammo_desc": "expensiveammo_desc",
|
||||
|
|
@ -160,17 +160,17 @@
|
|||
"explosiveshot_desc2": "你发射爆炸子弹的几率是:{0}%",
|
||||
|
||||
"falconeye": "鹰眼",
|
||||
"falconeye_desc": "点击 [css_useSkill] 激活俯视视角",
|
||||
"falconeye_desc": "按 [css_useSkill] 激活俯视视角",
|
||||
|
||||
"fastreload": "快速装弹",
|
||||
"fastreload_desc": "点击 [css_useSkill] 重新装填你当前持有的武器",
|
||||
"fastreload_desc": "按 [css_useSkill] 重新装填你当前持有的武器",
|
||||
|
||||
"flash": "闪电",
|
||||
"flash_desc": "回合开始时获得随机玩家速度",
|
||||
"flash_desc2": "你的速度倍率是:{0}x",
|
||||
|
||||
"fortnite": "堡垒之夜玩家",
|
||||
"fortnite_desc": "点击[css_useSkill]创建可破坏路障",
|
||||
"fortnite_desc": "按[css_useSkill]创建可破坏路障",
|
||||
|
||||
"fragilebomb": "脆弱炸弹",
|
||||
"fragilebomb_desc": "射击炸弹会对其造成伤害",
|
||||
|
|
@ -213,7 +213,7 @@
|
|||
"glue_desc": "你的手榴弹会粘在墙上",
|
||||
|
||||
"godmode": "我就是神",
|
||||
"godmode_desc": "点击 [css_useSkill] 在短时间内变得无敌",
|
||||
"godmode_desc": "按 [css_useSkill] 在短时间内变得无敌",
|
||||
"godmode_off": "无敌状态已禁用",
|
||||
"godmode_on": "无敌状态已启用",
|
||||
|
||||
|
|
@ -249,14 +249,14 @@
|
|||
"hotbomb_disable_info": "炸弹不再烫手了。",
|
||||
|
||||
"iana": "全息图",
|
||||
"iana_desc": "点击 [css_useSkill] 可控制你的全息影像数秒",
|
||||
"iana_desc": "按 [css_useSkill] 可控制你的全息影像数秒",
|
||||
|
||||
"illiterate": "文盲",
|
||||
"illiterate_desc": "只要你还活着,你的敌人就无法阅读",
|
||||
"illiterate_alert": "文盲已激活!在该技能的拥有者被消灭之前,你无法阅读消息。",
|
||||
|
||||
"illusionist": "幻术师",
|
||||
"illusionist_desc": "点击 [css_useSkill] 部署一个直线行走的幻象",
|
||||
"illusionist_desc": "按 [css_useSkill] 部署一个直线行走的幻象",
|
||||
|
||||
"impostor": "间谍",
|
||||
"impostor_desc": "回合开始时你获得敌方玩家模型",
|
||||
|
|
@ -332,7 +332,7 @@
|
|||
"magnifier_select_info": "选择需要放大的玩家:",
|
||||
|
||||
"medic": "医疗兵",
|
||||
"medic_desc": "点击 [css_useSkill] 使用治疗装置恢复50点生命值",
|
||||
"medic_desc": "按 [css_useSkill] 使用治疗装置恢复50点生命值",
|
||||
|
||||
"miner": "炸弹矿工",
|
||||
"miner_desc": "你的高爆手雷仅在附近有敌人时才会爆炸",
|
||||
|
|
@ -370,7 +370,7 @@
|
|||
"norecoil_desc": "射击时无后坐力",
|
||||
|
||||
"noclip": "无碰撞",
|
||||
"noclip_desc": "点击 [css_useSkill] 在短时间内启用无碰撞模式",
|
||||
"noclip_desc": "按 [css_useSkill] 在短时间内启用无碰撞模式",
|
||||
|
||||
"oneshot": "一击必杀",
|
||||
"oneshot_desc": "击中敌人立即杀死他们",
|
||||
|
|
@ -437,7 +437,7 @@
|
|||
"rambo_desc": "回合开始时你获得随机数量的生命值",
|
||||
|
||||
"randomweapon": "随机武器",
|
||||
"randomweapon_desc": "点击 [css_useSkill] 获得随机武器",
|
||||
"randomweapon_desc": "按 [css_useSkill] 获得随机武器",
|
||||
|
||||
"rezombie": "重生僵尸",
|
||||
"rezombie_desc": "死亡后你将作为僵尸复活,拥有更多生命值但无武器",
|
||||
|
|
@ -449,10 +449,10 @@
|
|||
"regeneration_desc": "每隔几秒恢复生命值",
|
||||
|
||||
"replicator": "复制者",
|
||||
"replicator_desc": "点击 [css_useSkill] 创建一个造成伤害的复制体",
|
||||
"replicator_desc": "按 [css_useSkill] 创建一个造成伤害的复制体",
|
||||
|
||||
"retreat": "撤退",
|
||||
"retreat_desc": "点击 [css_useSkill] 返回出生点",
|
||||
"retreat_desc": "按 [css_useSkill] 返回出生点",
|
||||
|
||||
"returntosender": "发送他们房子!!!",
|
||||
"returntosender_desc": "首次击中敌人会将其送回出生点",
|
||||
|
|
@ -495,7 +495,7 @@
|
|||
|
||||
"sniperelite": "狙击精英",
|
||||
"sniperelite_customname": "狙击精英技能",
|
||||
"sniperelite_desc": "点击 [css_useSkill] 将当前武器替换为AWP",
|
||||
"sniperelite_desc": "按 [css_useSkill] 将当前武器替换为AWP",
|
||||
|
||||
"soldier": "士兵",
|
||||
"soldier_desc": "你有随机伤害倍率",
|
||||
|
|
@ -505,10 +505,10 @@
|
|||
"soundmaker_desc": "你会不时听到玩家的惨叫声",
|
||||
|
||||
"spectator": "观察者",
|
||||
"spectator_desc": "点击 [css_useSkill] 旁观一个随机敌人",
|
||||
"spectator_desc": "按 [css_useSkill] 旁观一个随机敌人",
|
||||
|
||||
"swapposition": "位置交换",
|
||||
"swapposition_desc": "点击 [css_useSkill] 与随机敌人交换位置",
|
||||
"swapposition_desc": "按 [css_useSkill] 与随机敌人交换位置",
|
||||
|
||||
"teleporter": "传送者",
|
||||
"teleporter_desc": "你与被击中的敌人交换位置",
|
||||
|
|
@ -521,13 +521,13 @@
|
|||
"thief_incorrect_skill": "此技能无法选择!",
|
||||
|
||||
"thirdeye": "第三只眼",
|
||||
"thirdeye_desc": "点击 [css_useSkill] 激活第三人称视角",
|
||||
"thirdeye_desc": "按 [css_useSkill] 激活第三人称视角",
|
||||
|
||||
"thorns": "荊棘",
|
||||
"thorns_desc": "你的对手将承受其对你造成伤害的一部分",
|
||||
|
||||
"throwingknife": "投掷飞刀",
|
||||
"throwingknife_desc": "点击 [css_useSkill] 扔出飞刀。但要小心其他人",
|
||||
"throwingknife_desc": "按 [css_useSkill] 扔出飞刀。但要小心其他人",
|
||||
|
||||
"toxicsmoke": "毒烟",
|
||||
"toxicsmoke_desc": "你的烟雾弹会造成伤害",
|
||||
|
|
@ -555,7 +555,7 @@
|
|||
"watchmaker_tt": "回合时间延长了 {0} 秒。",
|
||||
|
||||
"weaponsswap": "武器交换",
|
||||
"weaponsswap_desc": "点击 [css_useSkill] 与随机敌人交换武器",
|
||||
"weaponsswap_desc": "按 [css_useSkill] 与随机敌人交换武器",
|
||||
"weaponsswap_hud_info2": "你没有可交换的武器",
|
||||
|
||||
"weightless": "失重",
|
||||
|
|
@ -574,7 +574,7 @@
|
|||
"your_skill": "你当前的技能",
|
||||
"enemy_skill": "敌人的技能",
|
||||
"observer_skill": "玩家的技能",
|
||||
"welcome_message": "欢迎 {PLAYER} 来到 {SERVER_NAME}!\n当前 jRandomSkills 版本:{VERSION}({SKILLS_COUNT} 个技能)。\n\n最初由以下人员创建:\n{AUTHOR1}\n由以下人员修改和改进:\n{AUTHOR2}\n官方Discord:https://discord.gg/9H8EZYBpPF",
|
||||
"welcome_message": "欢迎 {PLAYER} 来到 {SERVER_NAME}!",
|
||||
"drawing_skill": "抽取技能",
|
||||
"disabled_weapon": "你无法使用这把武器",
|
||||
|
||||
|
|
|
|||
|
|
@ -863,7 +863,16 @@ namespace src.player
|
|||
|
||||
private static readonly Dictionary<uint, jSkill_SkillInfo> nextRoundPicks = [];
|
||||
|
||||
public static void UpdateSkillHUD(CCSPlayerController? player, jSkill_PlayerInfo? skillPlayer, string? headerLine, string? centerLine, string? extraLine, bool isDescription)
|
||||
// Matches any <tag> or </tag> - used only to strip the HTML jRandomSkills already builds
|
||||
// into centerLine/extraLine (<font color=...>) before handing plain text to Panorama, which
|
||||
// can't render injected HTML and can only take a color via a CSS class instead.
|
||||
private static readonly Dictionary<int, PanoramaHudCache> panoramaHudCaches = [];
|
||||
|
||||
private static readonly Regex HtmlTagPattern = new("<[^>]+>", RegexOptions.Compiled);
|
||||
|
||||
public static void UpdateSkillHUD(
|
||||
CCSPlayerController? player, jSkill_PlayerInfo? skillPlayer, string? headerLine, string? centerLine,
|
||||
string? extraLine, bool isDescription, Skills skillForColor = Skills.None)
|
||||
{
|
||||
lock (setLock)
|
||||
{
|
||||
|
|
@ -875,6 +884,15 @@ namespace src.player
|
|||
extraLine = Illiterate.GetRandomText(extraLine);
|
||||
}
|
||||
|
||||
// Every skill draws through the Panorama card now. A skill's PrintHTML (cooldowns,
|
||||
// fuel, countdowns - isDescription false) replaces the description line; the
|
||||
// PrintToCenterHtml path below is only a fallback if the panel failed to spawn.
|
||||
if (Instance.SkillHud != null)
|
||||
{
|
||||
UpdatePanoramaSkillHud(player, skillPlayer, centerLine, extraLine, isDescription, skillForColor);
|
||||
return;
|
||||
}
|
||||
|
||||
var config = Config.LoadedConfig.HtmlHudCustomisation;
|
||||
|
||||
var cache = skillPlayer?.HudCache;
|
||||
|
|
@ -922,5 +940,99 @@ namespace src.player
|
|||
player.PrintToCenterHtml(hudContent);
|
||||
}
|
||||
}
|
||||
|
||||
// The Panorama half of UpdateSkillHUD above. Change-detected per field via
|
||||
// panoramaHudCaches, the same idea as HudCacheEntry but per-field rather than one content blob, since
|
||||
// SetVariableFor/SetClassFor are separate native calls rather than one PrintToCenterHtml.
|
||||
private static void UpdatePanoramaSkillHud(
|
||||
CCSPlayerController player, jSkill_PlayerInfo? skillPlayer, string? centerLine,
|
||||
string? extraLine, bool isDescription, Skills skillForColor)
|
||||
{
|
||||
var skillHud = Instance.SkillHud;
|
||||
if (skillHud == null || skillPlayer == null) return;
|
||||
|
||||
// centerLine/extraLine arrive pre-wrapped in <font color=...> for the PrintToCenterHtml
|
||||
// path above - Panorama can't render injected HTML, and color comes from the
|
||||
// rarity-* class below instead, so the markup is just stripped rather than parsed.
|
||||
string skillText = ToPlainText(centerLine);
|
||||
string extraText = ToPlainText(extraLine);
|
||||
string rarityClass = "rarity-" + SkillsInfo.GetValue<string>(skillForColor, "Rarity").ToLowerInvariant();
|
||||
|
||||
// Keyed by the viewer's slot, not skillPlayer: while controlling a bot (or spectating)
|
||||
// skillPlayer is someone else's record, but the panel being drawn is this player's.
|
||||
if (!panoramaHudCaches.TryGetValue(player.Slot, out var cache))
|
||||
panoramaHudCaches[player.Slot] = cache = new PanoramaHudCache();
|
||||
cache.TouchedThisTick = true;
|
||||
|
||||
// Open() before any SetVariableFor/SetClassFor - both silently no-op without a session,
|
||||
// and Open() is what creates it (same lesson as PanoramaHudDemo's own OpenSkillMenu).
|
||||
if (!cache.Open)
|
||||
{
|
||||
skillHud.Open(player);
|
||||
cache.Open = true;
|
||||
}
|
||||
|
||||
if (cache.Skill != skillText || cache.RarityClass != rarityClass)
|
||||
{
|
||||
skillHud.SetVariableFor(player, "hud_skill", skillText);
|
||||
// Take the old rarity class off before adding the new one - Panorama has no
|
||||
// mutually-exclusive class group, so both would otherwise stay on and whichever the
|
||||
// stylesheet happens to list last would win, not whichever was set last.
|
||||
if (cache.RarityClass != null)
|
||||
skillHud.SetClassFor(player, "skillhud_skill", cache.RarityClass, false);
|
||||
skillHud.SetClassFor(player, "skillhud_skill", rarityClass, true);
|
||||
cache.Skill = skillText;
|
||||
cache.RarityClass = rarityClass;
|
||||
}
|
||||
|
||||
if (cache.Extra != extraText)
|
||||
{
|
||||
skillHud.SetVariableFor(player, "hud_extra", extraText);
|
||||
skillHud.SetClassFor(player, "skillhud_extra", "empty", string.IsNullOrWhiteSpace(extraText));
|
||||
cache.Extra = extraText;
|
||||
}
|
||||
|
||||
if (cache.IsInfo != !isDescription)
|
||||
{
|
||||
skillHud.SetClassFor(player, "skillhud_extra", "info", !isDescription);
|
||||
cache.IsInfo = !isDescription;
|
||||
}
|
||||
}
|
||||
|
||||
// Closes the Panorama skill HUD for anyone whose cache says it's open but who wasn't
|
||||
// touched this HUD frame - warmup started, a menu opened, HUD got suppressed, or any of
|
||||
// PlayerOnTick.cs's other early-return conditions before it ever reaches UpdateSkillHUD.
|
||||
// Without this the panel would just keep showing stale content indefinitely, unlike
|
||||
// PrintToCenterHtml which expires on its own after a few seconds. Called once per HUD frame
|
||||
// from PlayerOnTick.cs, after the per-player loop, for exactly this reason.
|
||||
private static string ToPlainText(string? html)
|
||||
=> System.Net.WebUtility.HtmlDecode(
|
||||
HtmlTagPattern.Replace((html ?? "").Replace("<br>", "\n", StringComparison.OrdinalIgnoreCase), ""));
|
||||
|
||||
public static void ClosePanoramaSkillHudForUntouched()
|
||||
{
|
||||
var skillHud = Instance.SkillHud;
|
||||
if (skillHud == null) return;
|
||||
|
||||
foreach (var (slot, cache) in panoramaHudCaches)
|
||||
{
|
||||
if (!cache.Open) continue;
|
||||
|
||||
if (cache.TouchedThisTick)
|
||||
{
|
||||
cache.TouchedThisTick = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
var player = Utilities.GetPlayerFromSlot(slot);
|
||||
if (player is { IsValid: true }) skillHud.Close(player);
|
||||
|
||||
cache.Open = false;
|
||||
cache.Skill = null;
|
||||
cache.Extra = null;
|
||||
cache.RarityClass = null;
|
||||
cache.IsInfo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
|
@ -33,6 +33,9 @@ namespace src.player
|
|||
if (player != null && player.IsValid)
|
||||
UpdatePlayerHud(player, now);
|
||||
}
|
||||
// Closes the Panorama skill HUD for anyone whose panel is open but who wasn't
|
||||
// touched this frame - see its own doc comment for why that's needed at all.
|
||||
Event.ClosePanoramaSkillHudForUntouched();
|
||||
PerfLog.Sample("OnTick(hud)", perfStart);
|
||||
});
|
||||
|
||||
|
|
@ -62,7 +65,10 @@ namespace src.player
|
|||
var gameRulesProxy = Utilities.FindAllEntitiesByDesignerName<CCSGameRulesProxy>("cs_gamerules").FirstOrDefault();
|
||||
|
||||
if (gameRulesProxy != null)
|
||||
{
|
||||
Instance.GameRules = gameRulesProxy.GameRules;
|
||||
Instance.GameRulesProxy = gameRulesProxy;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateGameRules()
|
||||
|
|
@ -70,7 +76,17 @@ namespace src.player
|
|||
if (Instance?.GameRules == null || Instance.GameRules.Handle == IntPtr.Zero)
|
||||
InitializeGameRules();
|
||||
else if (Instance != null && Config.LoadedConfig.EnableFlashingHtmlHudFix && !Instance.GameRules.WarmupPeriod)
|
||||
Instance.GameRules.GameRestart = Instance.GameRules.RestartRoundTime < Server.CurrentTime;
|
||||
{
|
||||
bool restart = Instance.GameRules.RestartRoundTime < Server.CurrentTime;
|
||||
if (Instance.GameRules.GameRestart == restart) return;
|
||||
Instance.GameRules.GameRestart = restart;
|
||||
|
||||
// The schema write has no networking hook of its own. GameRules isn't embedded in the
|
||||
// proxy entity, so a CCSGameRules field offset can't be resolved against it ("N not
|
||||
// resolved" spam) - mark the proxy's m_pGameRules pointer changed instead.
|
||||
if (Instance.GameRulesProxy != null && Instance.GameRulesProxy.Handle != IntPtr.Zero)
|
||||
Utilities.SetStateChanged(Instance.GameRulesProxy, "CCSGameRulesProxy", "m_pGameRules");
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdatePlayerHud(CCSPlayerController player, DateTime now)
|
||||
|
|
@ -97,6 +113,10 @@ namespace src.player
|
|||
string infoLine = string.Empty;
|
||||
string skillLine = string.Empty;
|
||||
string remainingLine = string.Empty;
|
||||
// Which skill's Rarity should color the Panorama HUD (see UpdatePanoramaSkillHud) -
|
||||
// not always skillPlayer.Skill, since the observer branch below shows a DIFFERENT
|
||||
// player's skill, and the drawing-flicker branch shows a random one each frame.
|
||||
Skills skillForColor = Skills.None;
|
||||
|
||||
bool showDescriptionHUD = skillPlayer.SkillDescriptionHudExpired >= now || Config.LoadedConfig.DisplayAlwaysDescription;
|
||||
bool isDescription = true;
|
||||
|
|
@ -114,6 +134,7 @@ namespace src.player
|
|||
|
||||
infoLine = player.GetTranslationWithoutIlliterate("drawing_skill");
|
||||
skillLine = $"<font color='{randomSkill.Color}'>{player.GetSkillName(randomSkill.Skill)}</font>";
|
||||
skillForColor = randomSkill.Skill;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -123,8 +144,8 @@ namespace src.player
|
|||
|
||||
if (skillInfo != null)
|
||||
{
|
||||
infoLine = player.GetTranslationWithoutIlliterate("your_skill");
|
||||
skillLine = $"<font color='{skillInfo.Color}'>{player.GetSkillName(skillInfo.Skill, skillPlayer.SkillChance)}</font>";
|
||||
skillForColor = skillInfo.Skill;
|
||||
|
||||
if (skillInfo.Skill != Skills.None)
|
||||
{
|
||||
|
|
@ -175,11 +196,17 @@ namespace src.player
|
|||
infoLine = string.IsNullOrEmpty(observerSkill) ? pName : $"{observerSkill} {pName}";
|
||||
|
||||
if (observedSkill.SpecialSkill == Skills.None || observedSpecialInfo == null)
|
||||
{
|
||||
skillLine = $"<font color='{primaryColor}'>{primaryName}</font>";
|
||||
skillForColor = observedSkill.Skill;
|
||||
}
|
||||
else
|
||||
{
|
||||
string specialName = player.GetSkillName(observedSpecialInfo.Skill);
|
||||
skillLine = $"<font color='{observedSpecialInfo.Color}'>{specialName}({primaryName})</font>";
|
||||
// The special skill's color is what wraps the WHOLE combined line above,
|
||||
// not the primary skill's - matches that for the Panorama rarity class too.
|
||||
skillForColor = observedSpecialInfo.Skill;
|
||||
}
|
||||
|
||||
if (observedSkill.Skill != Skills.None && !string.IsNullOrEmpty(observedSkill.PrintHTML))
|
||||
|
|
@ -194,7 +221,7 @@ namespace src.player
|
|||
|
||||
if (string.IsNullOrEmpty(skillLine)) return;
|
||||
|
||||
Event.UpdateSkillHUD(player, skillPlayer, infoLine, skillLine, remainingLine, isDescription);
|
||||
Event.UpdateSkillHUD(player, skillPlayer, infoLine, skillLine, remainingLine, isDescription, skillForColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -620,7 +620,7 @@ namespace src.player
|
|||
UpdateSkillHudExpired(skillPlayer, randomSkill.Skill);
|
||||
assigned++;
|
||||
|
||||
if (randomSkill.Display)
|
||||
if (randomSkill.Display && Config.LoadedConfig.YourSkillChatInfo)
|
||||
Instance?.AddTimer(.6f, () =>
|
||||
{
|
||||
var descTarget = Utilities.GetPlayerFromIndex((int)playerIndex);
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ namespace src.player.skills
|
|||
|
||||
string remainingLine = cooldown != 0
|
||||
? $"{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}"
|
||||
: $"<font color='#{(skillInfo == null || skillInfo.Count == 0 ? "FF0000" : "00FF00")}'>{(skillInfo == null ? 0 : skillInfo.Count)}/{SkillsInfo.GetValue<int>(skillName, "healthShotLimit")}</font>";
|
||||
: $"{player.GetSkillDescription(skillName)}<br><font color='#{(skillInfo == null || skillInfo.Count == 0 ? "FF0000" : "00FF00")}'>{(skillInfo == null ? 0 : skillInfo.Count)}/{SkillsInfo.GetValue<int>(skillName, "healthShotLimit")}</font>";
|
||||
|
||||
playerInfo.PrintHTML = remainingLine;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,6 +311,7 @@ namespace src.utils
|
|||
NormalCommands = new NormalCommands
|
||||
{
|
||||
SetSkillCommand = new NormalCommand("ustawskill, ustaw_skill, setskill, set_skill, definirhabilidade, configurarhabilidade, 设置技能, 配置技能", "@jRandomSkills/admin"),
|
||||
SetOverrideCommand = new NormalCommand("setoverride, set_override", "@jRandomSkills/admin"),
|
||||
SkillsListCommand = new NormalCommand("supermoc, skille, listamocy, supermoce, skills, listaHabilidades, habilidades, 技能列表, 超能力列表", "@jRandomSkills/admin"),
|
||||
UseSkillCommand = new NormalCommand("t, useSkill, usarHabilidade, 技能使用, 使用技能", "@jRandomSkills/admin"),
|
||||
HealCommand = new NormalCommand("heal, ulecz, curar, tratar, 治疗, 治愈", "@jRandomSkills/admin"),
|
||||
|
|
@ -403,6 +404,7 @@ namespace src.utils
|
|||
public class NormalCommands
|
||||
{
|
||||
public required NormalCommand SetSkillCommand { get; set; }
|
||||
public required NormalCommand SetOverrideCommand { get; set; }
|
||||
public required NormalCommand SkillsListCommand { get; set; }
|
||||
public required NormalCommand UseSkillCommand { get; set; }
|
||||
public required NormalCommand HealCommand { get; set; }
|
||||
|
|
|
|||
67
jRandomSkills - SRC Files/src/utils/CooldownOverride.cs
Normal file
67
jRandomSkills - SRC Files/src/utils/CooldownOverride.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
using CounterStrikeSharp.API.Core;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
|
||||
namespace src.utils
|
||||
{
|
||||
// Per-player cooldown bypass (css_setoverride). Skills keep their cooldown in their own static
|
||||
// per-player state, so instead of touching every skill this clears that state just before the
|
||||
// skill's UseSkill runs. Resetting only at use time (not every tick) matters: AimLock and Noclip
|
||||
// reuse their Cooldown timestamp as the start of the active effect.
|
||||
public static class CooldownOverride
|
||||
{
|
||||
private static readonly HashSet<ulong> _players = [];
|
||||
private static readonly ConcurrentDictionary<Type, FieldInfo[]> _stateFields = new();
|
||||
|
||||
// Toggles the override and returns the new state.
|
||||
public static bool Toggle(CCSPlayerController player)
|
||||
{
|
||||
if (_players.Remove(player.SteamID)) return false;
|
||||
_players.Add(player.SteamID);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool Has(CCSPlayerController player) => _players.Contains(player.SteamID);
|
||||
|
||||
public static void ResetBeforeUse(Type skillType, CCSPlayerController player)
|
||||
{
|
||||
foreach (var field in _stateFields.GetOrAdd(skillType, FindStateFields))
|
||||
{
|
||||
if (field.GetValue(null) is not IDictionary state) continue;
|
||||
|
||||
// Spectator keeps a plain index -> last-use time map.
|
||||
if (field.FieldType.GetGenericArguments()[1] == typeof(DateTime))
|
||||
{
|
||||
state.Remove(player.Index);
|
||||
continue;
|
||||
}
|
||||
|
||||
var entry = state[player.Index];
|
||||
if (entry == null) continue;
|
||||
|
||||
foreach (var prop in entry.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
if (!prop.CanWrite) continue;
|
||||
|
||||
if (prop.Name == "Cooldown" && prop.PropertyType == typeof(DateTime))
|
||||
prop.SetValue(entry, DateTime.MinValue);
|
||||
else if (prop.Name == "CanUse" && prop.PropertyType == typeof(bool))
|
||||
prop.SetValue(entry, true);
|
||||
else if (prop.Name is "NextUse" or "NextCamera" && prop.PropertyType == typeof(float))
|
||||
prop.SetValue(entry, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Static ConcurrentDictionary<uint, T> fields keyed by player index - the per-player skill
|
||||
// state every cooldown skill uses. DateTime-valued ones only when they are last-use maps.
|
||||
private static FieldInfo[] FindStateFields(Type skillType)
|
||||
=> [.. skillType.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
.Where(f => f.FieldType.IsGenericType
|
||||
&& f.FieldType.GetGenericTypeDefinition() == typeof(ConcurrentDictionary<,>)
|
||||
&& f.FieldType.GetGenericArguments()[0] == typeof(uint)
|
||||
&& (f.FieldType.GetGenericArguments()[1] != typeof(DateTime)
|
||||
|| f.Name.Contains("use", StringComparison.OrdinalIgnoreCase)))];
|
||||
}
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ namespace src.utils
|
|||
{
|
||||
var val = translations[tkey].Replace("CHATCOLORS.RED", redColor);
|
||||
if (!string.IsNullOrEmpty(altButton))
|
||||
val = val.Replace("css_useSkill", $"css_useSkill/{altButton}");
|
||||
val = val.Replace("css_useSkill", altButton);
|
||||
translations[tkey] = val;
|
||||
}
|
||||
_translations.AddOrUpdate(code, translations, (k, v) => translations);
|
||||
|
|
|
|||
195
jRandomSkills - SRC Files/src/utils/PanoramaMenu.cs
Normal file
195
jRandomSkills - SRC Files/src/utils/PanoramaMenu.cs
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using PanoramaManager;
|
||||
using System.Text.RegularExpressions;
|
||||
using static CounterStrikeSharp.API.Core.Listeners;
|
||||
|
||||
namespace src.utils
|
||||
{
|
||||
// W/S/E target picker on a real Panorama panel (jrs_menu.xml), replacing WASDMenuAPI's
|
||||
// PrintToCenterHtml menu. Driven only through SkillUtils.CreateMenu/UpdateMenu/CloseMenu/HasMenu.
|
||||
public static class PanoramaMenu
|
||||
{
|
||||
public sealed record Item(string Id, string Text, bool Special, Action<CCSPlayerController> OnChoose);
|
||||
|
||||
private const int MaxRows = 10;
|
||||
private static readonly string[] RarityClasses =
|
||||
["rarity-common", "rarity-uncommon", "rarity-rare", "rarity-epic", "rarity-legendary"];
|
||||
|
||||
private static readonly LayoutContract Contract = new()
|
||||
{
|
||||
RootPanelId = "JrsMenuRoot",
|
||||
RowCount = 0,
|
||||
CaptureInput = false,
|
||||
};
|
||||
|
||||
private static readonly Regex HtmlTag = new("<[^>]+>", RegexOptions.Compiled);
|
||||
|
||||
private sealed class MenuState(List<Item> items)
|
||||
{
|
||||
public List<Item> Items = items;
|
||||
public int Selected;
|
||||
public int WindowStart;
|
||||
// Last value written per physical row; null forces a write.
|
||||
public readonly string?[] Text = new string?[MaxRows];
|
||||
public readonly bool?[] Shown = new bool?[MaxRows];
|
||||
public readonly bool?[] IsSelected = new bool?[MaxRows];
|
||||
public readonly bool?[] IsSpecial = new bool?[MaxRows];
|
||||
}
|
||||
|
||||
private static PanelHandle? _panel;
|
||||
private static readonly Dictionary<int, MenuState> _menus = [];
|
||||
|
||||
// Must run after Event.Load: listeners fire in registration order, and CheckUseSkill has to
|
||||
// see the menu still open on the E press that selects from it, or the same press would also
|
||||
// fire the player's skill.
|
||||
public static void Load(BasePlugin plugin)
|
||||
{
|
||||
_panel = Panorama.Spawn("panorama/layout/custom_game/jrs_menu.vxml_c", Contract);
|
||||
plugin.RegisterListener<OnPlayerButtonsChanged>(OnButtons);
|
||||
plugin.RegisterListener<OnClientDisconnect>(slot => _menus.Remove(slot));
|
||||
}
|
||||
|
||||
public static void Unload()
|
||||
{
|
||||
_panel?.Dispose();
|
||||
_panel = null;
|
||||
_menus.Clear();
|
||||
}
|
||||
|
||||
public static string StripHtml(string? text) => HtmlTag.Replace(text ?? "", "");
|
||||
|
||||
private static int VisibleRows()
|
||||
{
|
||||
int configured = Config.LoadedConfig.HtmlHudCustomisation.WSADMenuVisibleItems;
|
||||
return configured < 1 ? 3 : Math.Min(configured, MaxRows);
|
||||
}
|
||||
|
||||
public static bool HasMenu(CCSPlayerController? player)
|
||||
=> player is { IsValid: true } && _menus.ContainsKey(player.Slot);
|
||||
|
||||
public static void Open(
|
||||
CCSPlayerController player, string skillName, string rarityClass,
|
||||
string subtitle, string hint, List<Item> items)
|
||||
{
|
||||
if (_panel == null || items.Count == 0) return;
|
||||
|
||||
var state = new MenuState(items);
|
||||
bool alreadyOpen = _menus.ContainsKey(player.Slot);
|
||||
_menus[player.Slot] = state;
|
||||
|
||||
if (!alreadyOpen)
|
||||
_panel.Open(player);
|
||||
|
||||
_panel.SetVariableFor(player, "menu_skill", skillName);
|
||||
_panel.SetVariableFor(player, "menu_subtitle", subtitle);
|
||||
_panel.SetClassFor(player, "jrsmenu_subtitle", "empty", string.IsNullOrWhiteSpace(subtitle));
|
||||
_panel.SetVariableFor(player, "menu_hint", hint);
|
||||
foreach (var rarity in RarityClasses)
|
||||
_panel.SetClassFor(player, "jrsmenu_skill", rarity, rarity == rarityClass);
|
||||
|
||||
Render(player, state);
|
||||
}
|
||||
|
||||
// Replaces the item list in place, keeping the selection on the same item id when it still
|
||||
// exists (skills call this every tick with refreshed labels such as money or health).
|
||||
public static void Update(CCSPlayerController player, List<Item> items)
|
||||
{
|
||||
if (!_menus.TryGetValue(player.Slot, out var state)) return;
|
||||
|
||||
if (items.Count == 0)
|
||||
{
|
||||
Close(player);
|
||||
return;
|
||||
}
|
||||
|
||||
string? selectedId = state.Selected < state.Items.Count ? state.Items[state.Selected].Id : null;
|
||||
int selected = selectedId == null ? -1 : items.FindIndex(i => i.Id == selectedId);
|
||||
|
||||
state.Items = items;
|
||||
state.Selected = selected < 0 ? 0 : selected;
|
||||
state.WindowStart = WindowFor(state.Selected, state.WindowStart, items.Count);
|
||||
Render(player, state);
|
||||
}
|
||||
|
||||
public static void Close(CCSPlayerController? player)
|
||||
{
|
||||
if (player is not { IsValid: true }) return;
|
||||
if (_menus.Remove(player.Slot))
|
||||
_panel?.Close(player);
|
||||
}
|
||||
|
||||
private static void OnButtons(CCSPlayerController player, PlayerButtons pressed, PlayerButtons released)
|
||||
{
|
||||
if (player is not { IsValid: true } || !_menus.TryGetValue(player.Slot, out var state)) return;
|
||||
|
||||
if ((pressed & PlayerButtons.Back) != 0)
|
||||
Move(player, state, +1);
|
||||
else if ((pressed & PlayerButtons.Forward) != 0)
|
||||
Move(player, state, -1);
|
||||
else if ((pressed & PlayerButtons.Use) != 0 && state.Selected < state.Items.Count)
|
||||
state.Items[state.Selected].OnChoose(player);
|
||||
}
|
||||
|
||||
private static void Move(CCSPlayerController player, MenuState state, int direction)
|
||||
{
|
||||
int count = state.Items.Count;
|
||||
if (count == 0) return;
|
||||
|
||||
state.Selected = (state.Selected + direction + count) % count;
|
||||
state.WindowStart = WindowFor(state.Selected, state.WindowStart, count);
|
||||
Render(player, state);
|
||||
}
|
||||
|
||||
private static int WindowFor(int selected, int windowStart, int count)
|
||||
{
|
||||
int rows = VisibleRows();
|
||||
if (selected < windowStart)
|
||||
windowStart = selected;
|
||||
else if (selected >= windowStart + rows)
|
||||
windowStart = selected - rows + 1;
|
||||
return Math.Clamp(windowStart, 0, Math.Max(0, count - rows));
|
||||
}
|
||||
|
||||
// Writes only what changed per physical row - Update runs every tick for some skills.
|
||||
private static void Render(CCSPlayerController player, MenuState state)
|
||||
{
|
||||
if (_panel == null) return;
|
||||
int rows = VisibleRows();
|
||||
|
||||
for (int i = 0; i < MaxRows; i++)
|
||||
{
|
||||
string rowId = $"mrow{i}";
|
||||
int index = state.WindowStart + i;
|
||||
bool shown = i < rows && index < state.Items.Count;
|
||||
|
||||
if (state.Shown[i] != shown)
|
||||
{
|
||||
_panel.SetClassFor(player, rowId, "hidden", !shown);
|
||||
state.Shown[i] = shown;
|
||||
}
|
||||
if (!shown) continue;
|
||||
|
||||
var item = state.Items[index];
|
||||
if (state.Text[i] != item.Text)
|
||||
{
|
||||
_panel.SetVariableFor(player, $"mrow{i}_title", item.Text);
|
||||
state.Text[i] = item.Text;
|
||||
}
|
||||
|
||||
bool isSelected = index == state.Selected;
|
||||
if (state.IsSelected[i] != isSelected)
|
||||
{
|
||||
_panel.SetClassFor(player, rowId, "selected", isSelected);
|
||||
state.IsSelected[i] = isSelected;
|
||||
}
|
||||
|
||||
if (state.IsSpecial[i] != item.Special)
|
||||
{
|
||||
_panel.SetClassFor(player, rowId, "special", item.Special);
|
||||
state.IsSpecial[i] = item.Special;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Cvars;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
|
|
@ -14,8 +14,6 @@ using System.Collections.Concurrent;
|
|||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using WASDMenuAPI.Classes;
|
||||
using WASDSharedAPI;
|
||||
|
||||
namespace src.utils
|
||||
{
|
||||
|
|
@ -1060,83 +1058,36 @@ namespace src.utils
|
|||
return designerName;
|
||||
}
|
||||
|
||||
private static IWasdMenuManager? GetMenuManager()
|
||||
{
|
||||
if (jRandomSkills.Instance.MenuManager == null)
|
||||
jRandomSkills.Instance.MenuManager = new WasdManager();
|
||||
public static void CloseMenu(CCSPlayerController? player) => PanoramaMenu.Close(player);
|
||||
|
||||
ApplyMenuVisibleItems();
|
||||
return jRandomSkills.Instance.MenuManager;
|
||||
}
|
||||
public static bool HasMenu(CCSPlayerController? player) => PanoramaMenu.HasMenu(player);
|
||||
|
||||
private static void ApplyMenuVisibleItems()
|
||||
{
|
||||
int visibleItems = Config.LoadedConfig.HtmlHudCustomisation.WSADMenuVisibleItems;
|
||||
WASDMenuAPI.WasdMenuPlayer.DefaultVisibleOptions = visibleItems < 1 ? 3 : Math.Min(visibleItems, 10);
|
||||
}
|
||||
// WASDMenuAPI's pause flag was only ever cleared, never set, so this stays a no-op.
|
||||
public static bool SetMenuPaused(CCSPlayerController? player, bool pause) => PanoramaMenu.HasMenu(player);
|
||||
|
||||
public static void CloseMenu(CCSPlayerController? player)
|
||||
{
|
||||
var manager = GetMenuManager();
|
||||
if (manager == null) return;
|
||||
manager.CloseMenu(player);
|
||||
}
|
||||
|
||||
public static bool HasMenu(CCSPlayerController? player)
|
||||
{
|
||||
var manager = GetMenuManager();
|
||||
if (manager == null) return false;
|
||||
return manager.HasMenu(player);
|
||||
}
|
||||
|
||||
public static bool SetMenuPaused(CCSPlayerController? player, bool pause)
|
||||
{
|
||||
var manager = GetMenuManager();
|
||||
if (manager == null) return false;
|
||||
return manager.SetMenuPaused(player, pause);
|
||||
}
|
||||
|
||||
private static string GetInvisibleSignature(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id)) return "";
|
||||
var sb = new System.Text.StringBuilder();
|
||||
|
||||
foreach (char c in id)
|
||||
for (int i = 0; i < 8; i++)
|
||||
sb.Append(((c >> i) & 1) == 1 ? "\u200B" : "\u200C");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
private static string MenuText(CCSPlayerController player, string text)
|
||||
=> Illiterate.CheckIlliterateSkill(player) ? Illiterate.GetRandomText(text) ?? text : text;
|
||||
|
||||
public static void UpdateMenu(CCSPlayerController? player, ConcurrentBag<(string, string)> items)
|
||||
{
|
||||
if (player == null) return;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var manager = GetMenuManager();
|
||||
if (manager == null) return;
|
||||
|
||||
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
|
||||
var playerInfo = PlayerManager.GetPlayerByIndex(player.Index);
|
||||
if (playerInfo == null) return;
|
||||
|
||||
bool isIlliterate = Illiterate.CheckIlliterateSkill(player);
|
||||
|
||||
Dictionary<string, Action<CCSPlayerController, IWasdMenuOption>> list = [];
|
||||
var list = new List<PanoramaMenu.Item>();
|
||||
foreach (var item in items)
|
||||
{
|
||||
string encodedText = isIlliterate
|
||||
? System.Net.WebUtility.HtmlEncode(Illiterate.GetRandomText(item.Item1)!)
|
||||
: System.Net.WebUtility.HtmlEncode(item.Item1);
|
||||
|
||||
string uniqueKey = GetInvisibleSignature(item.Item2) + $"\u202A{encodedText}\u202C";
|
||||
|
||||
list.TryAdd(uniqueKey, (p, option) =>
|
||||
if (list.Any(i => i.Id == item.Item2)) continue;
|
||||
var id = item.Item2;
|
||||
list.Add(new PanoramaMenu.Item(id, MenuText(player, item.Item1), false, p =>
|
||||
{
|
||||
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { item.Item2 }]);
|
||||
manager.CloseMenu(p);
|
||||
});
|
||||
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { id }]);
|
||||
PanoramaMenu.Close(p);
|
||||
}));
|
||||
}
|
||||
|
||||
manager.UpdateActiveMenu(player, list);
|
||||
PanoramaMenu.Update(player, list);
|
||||
}
|
||||
|
||||
public static void CreateMenu(CCSPlayerController? player, ConcurrentBag<(string, string)> enemies, (string, string, bool)? lastElement = null)
|
||||
|
|
@ -1169,78 +1120,48 @@ namespace src.utils
|
|||
var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == playerInfo.Skill);
|
||||
if (skillData == null) return;
|
||||
|
||||
var manager = GetMenuManager();
|
||||
if (manager == null) return;
|
||||
|
||||
var config = Config.LoadedConfig.HtmlHudCustomisation;
|
||||
var your_skill = player.GetTranslationWithoutIlliterate("your_skill");
|
||||
var emptySymbol = $"<font class='fontSize-{(string.IsNullOrEmpty(your_skill) ? "l" : "ml")}'> </font>";
|
||||
|
||||
string infoLine = string.IsNullOrEmpty(your_skill) || string.IsNullOrEmpty(config.HeaderLineSize)
|
||||
? ""
|
||||
: $"<font class='fontWeight-Bold fontSize-{config.HeaderLineSize}' color='{config.HeaderLineColor}'>\u202A{your_skill}:\u202C</font><br>";
|
||||
|
||||
string skillLine = Illiterate.CheckIlliterateSkill(player)
|
||||
? $"<font class='fontWeight-Bold fontSize-{config.SkillLineSize}'>\u202A{Illiterate.GetRandomText(player.GetSkillName(skillData.Skill))}\u202C</font><br>"
|
||||
: $"<font class='fontWeight-Bold fontSize-{config.SkillLineSize}' color='{skillData.Color}'>\u202A{player.GetSkillName(skillData.Skill)}\u202C</font><br>";
|
||||
|
||||
var skill_select_info = player.GetTranslation($"{playerInfo.Skill.ToString().ToLowerInvariant()}_select_info");
|
||||
string remainingLine = string.IsNullOrWhiteSpace(skill_select_info) || string.IsNullOrEmpty(config.WSADMenuSelectInfoLineSize)
|
||||
? ""
|
||||
: $"<font class='fontSize-{config.WSADMenuSelectInfoLineSize}' color='{config.WSADMenuSelectInfoLineColor}'>{skill_select_info}</font><br>";
|
||||
|
||||
var hudContent = infoLine + skillLine + remainingLine;
|
||||
|
||||
string controllsLine = string.IsNullOrEmpty(config.WSADMenuControllsLineSize) ? "" :
|
||||
$"{emptySymbol}<font class='fontSize-{config.WSADMenuControllsLineSize}' color='{config.WSADMenuControllsLineColor1}'>{player.GetTranslationWithoutIlliterate($"menu_controlls_scroll")}</font>"
|
||||
+ $"<font class='fontSize-{config.WSADMenuControllsLineSize}' color='{config.WSADMenuControllsLineColor2}'>{player.GetTranslationWithoutIlliterate($"menu_controlls_padding")}</font>"
|
||||
+ $"<font class='fontSize-{config.WSADMenuControllsLineSize}' color='{config.WSADMenuControllsLineColor3}'>{player.GetTranslationWithoutIlliterate($"menu_controlls_select")}</font>{emptySymbol}<br>";
|
||||
|
||||
string itemText = $"<font class='fontSize-{config.WSADMenuItemLineSize}' color='{config.WSADMenuItemLineColor}'>{{0}}</font><br>";
|
||||
string itemHoverText = $"<font class='fontSize-{config.WSADMenuItemLineSize}'><font color='purple'>[ </font><font color='{config.WSADMenuItemHoverLineColor}'>{{0}}</font><font color='purple'> ]</font></font><br>";
|
||||
|
||||
bool isIlliterate = Illiterate.CheckIlliterateSkill(player);
|
||||
|
||||
IWasdMenu menu = manager.CreateMenu(hudContent, itemText, itemHoverText, controllsLine);
|
||||
var items = new List<PanoramaMenu.Item>();
|
||||
foreach (var enemy in enemies)
|
||||
{
|
||||
string encodedEnemyName = isIlliterate
|
||||
? System.Net.WebUtility.HtmlEncode(Illiterate.GetRandomText(enemy.Item1)!)
|
||||
: System.Net.WebUtility.HtmlEncode(enemy.Item1);
|
||||
|
||||
string uniqueKey = GetInvisibleSignature(enemy.Item2) + $"\u202A{encodedEnemyName}\u202C";
|
||||
|
||||
menu.Add(uniqueKey, (p, option) =>
|
||||
if (items.Any(i => i.Id == enemy.Item2)) continue;
|
||||
var id = enemy.Item2;
|
||||
items.Add(new PanoramaMenu.Item(id, MenuText(player, enemy.Item1), false, p =>
|
||||
{
|
||||
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { enemy.Item2 }]);
|
||||
manager.CloseMenu(p);
|
||||
});
|
||||
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { id }]);
|
||||
PanoramaMenu.Close(p);
|
||||
}));
|
||||
}
|
||||
|
||||
if (lastElement != null)
|
||||
{
|
||||
string lastText = lastElement.Value.Item1;
|
||||
string lastColor = string.Empty;
|
||||
var last = lastElement.Value;
|
||||
string lastText = last.Item1;
|
||||
bool special = false;
|
||||
|
||||
// "#rrggbb|text" colored the entry under WASDMenuAPI; Panorama can only take a class.
|
||||
if (lastText.Length > 8 && lastText[0] == '#' && lastText[7] == '|')
|
||||
{
|
||||
lastColor = lastText[..8];
|
||||
lastText = lastText[8..];
|
||||
special = true;
|
||||
}
|
||||
|
||||
string encodedLastElement = isIlliterate
|
||||
? System.Net.WebUtility.HtmlEncode(Illiterate.GetRandomText(lastText)!)
|
||||
: System.Net.WebUtility.HtmlEncode(lastText);
|
||||
|
||||
menu.Add($"{lastColor}\u202A{encodedLastElement}\u202C", (p, option) =>
|
||||
items.Add(new PanoramaMenu.Item(last.Item2, MenuText(player, lastText), special, p =>
|
||||
{
|
||||
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { lastElement.Value.Item2 }]);
|
||||
if (lastElement.Value.Item3)
|
||||
manager.CloseMenu(p);
|
||||
});
|
||||
jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { last.Item2 }]);
|
||||
if (last.Item3)
|
||||
PanoramaMenu.Close(p);
|
||||
}));
|
||||
}
|
||||
|
||||
manager.OpenMainMenu(player, menu);
|
||||
string skillName = MenuText(player, player.GetSkillName(skillData.Skill));
|
||||
string rarityClass = "rarity-" + SkillsInfo.GetValue<string>(skillData.Skill, "Rarity").ToLowerInvariant();
|
||||
string subtitle = PanoramaMenu.StripHtml(player.GetTranslation($"{playerInfo.Skill.ToString().ToLowerInvariant()}_select_info"));
|
||||
string hint = PanoramaMenu.StripHtml(
|
||||
player.GetTranslationWithoutIlliterate("menu_controlls_scroll")
|
||||
+ player.GetTranslationWithoutIlliterate("menu_controlls_padding")
|
||||
+ player.GetTranslationWithoutIlliterate("menu_controlls_select"));
|
||||
|
||||
PanoramaMenu.Open(player, skillName, rarityClass, subtitle, hint, items);
|
||||
}
|
||||
|
||||
public static void ToogleDoor(CBaseEntity entity, CBasePlayerPawn pawn)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue