mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-08 00:46:34 -08:00
Compare commits
11 Commits
v1.0.150
...
docs/menu-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39b476ccad | ||
|
|
5695c3f922 | ||
|
|
9071d51ecd | ||
|
|
0a32962f4a | ||
|
|
271705b377 | ||
|
|
cdcddbb5f3 | ||
|
|
91f51d0c5c | ||
|
|
e97f804294 | ||
|
|
4f805b18e2 | ||
|
|
e1f9b5635e | ||
|
|
59bff4f500 |
10
.github/workflows/cmake-single-platform.yml
vendored
10
.github/workflows/cmake-single-platform.yml
vendored
@@ -196,6 +196,7 @@ jobs:
|
||||
(cd build/windows && zip -qq -r ../../counterstrikesharp-with-runtime-build-${{ needs.build_managed.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
|
||||
- name: Release
|
||||
id: release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: v${{ needs.build_managed.outputs.buildnumber }}
|
||||
@@ -208,4 +209,11 @@ jobs:
|
||||
- name: Publish NuGet package
|
||||
run: |
|
||||
dotnet nuget push build/api/CounterStrikeSharp.API.1.0.${{ needs.build_managed.outputs.buildnumber }}.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
dotnet nuget push build/api/CounterStrikeSharp.API.1.0.${{ needs.build_managed.outputs.buildnumber }}.snupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
dotnet nuget push build/api/CounterStrikeSharp.API.1.0.${{ needs.build_managed.outputs.buildnumber }}.snupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
|
||||
- name: Send Notification to Discord
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.3.2
|
||||
with:
|
||||
args: "A new release of CS# has been tagged (v${{ needs.build_managed.outputs.buildnumber }}) at ${{ steps.release.outputs.url }}"
|
||||
@@ -74,6 +74,13 @@
|
||||
"linux": "\\x55\\x48\\x89\\xF2\\x48\\x89\\xE5\\x41\\x54\\x49\\x89\\xFC\\x48\\x8D\\x2A\\x2A\\x48\\x83\\x2A\\x2A\\x2A\\x8D\\x05\\x2A\\x2A\\x2A\\x00\\x48\\x8B\\x30\\x48\\x8B\\x06\\xFF\\x2A\\x2A\\x48\\x8B\\x45\\x2A\\x48\\x8D\\x2A\\x2A\\x4C\\x89\\x2A\\x48\\x89\\x45\\x2A\\x2A\\x68\\xFC"
|
||||
}
|
||||
},
|
||||
"CCSPlayer_WeaponServices_CanUse": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x10\\x48\\x89\\x6C\\x24\\x18\\x56\\x57\\x41\\x56\\x48\\x83\\xEC\\x30\\x80\\xB9\\xA8\\x00\\x00\\x00\\x00",
|
||||
"linux": "\\x48\\x85\\xF6\\x0F\\x84\\x2A\\x2A\\x2A\\x2A\\x55\\x31\\xC9\\x48\\x89\\xE5\\x41\\x55\\x49\\x89\\xFD"
|
||||
}
|
||||
},
|
||||
"CCSPlayer_ItemServices_DropActivePlayerWeapon": {
|
||||
"offsets": {
|
||||
"windows": 18,
|
||||
|
||||
4
examples/WithMenus/README.md
Normal file
4
examples/WithMenus/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# With Commands
|
||||
This is an example that shows how to register chat & console commands.
|
||||
|
||||
All commands that are prefixed with "css_" will automatically be registered as a chat command without the prefix. i.e. `css_ping` can be called with `!ping` or `/ping`.
|
||||
12
examples/WithMenus/WithCommands.csproj
Normal file
12
examples/WithMenus/WithCommands.csproj
Normal file
@@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\managed\CounterStrikeSharp.API\CounterStrikeSharp.API.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
63
examples/WithMenus/WithCommandsPlugin.cs
Normal file
63
examples/WithMenus/WithCommandsPlugin.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Core.Attributes.Registration;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
|
||||
namespace WithCommands;
|
||||
|
||||
[MinimumApiVersion(80)]
|
||||
public class WithCommandsPlugin : BasePlugin
|
||||
{
|
||||
public override string ModuleName => "Example: With Commands";
|
||||
public override string ModuleVersion => "1.0.0";
|
||||
public override string ModuleAuthor => "CounterStrikeSharp & Contributors";
|
||||
public override string ModuleDescription => "A simple plugin that registers some commands";
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
// All commands that are prefixed with "css_" will automatically be registered as a chat command without the prefix.
|
||||
// i.e. `css_ping` can be called with `!ping` or `/ping`.
|
||||
// Commands can be registered using the instance `AddCommand` method.
|
||||
AddCommand("css_ping", "Responds to the caller with \"pong\"", (player, commandInfo) =>
|
||||
{
|
||||
// The player is null, then the command has been called by the server console.
|
||||
if (player == null)
|
||||
{
|
||||
commandInfo.ReplyToCommand("pong server");
|
||||
return;
|
||||
}
|
||||
|
||||
commandInfo.ReplyToCommand("pong");
|
||||
});
|
||||
}
|
||||
|
||||
// Commands can also be registered using the `Command` attribute.
|
||||
[ConsoleCommand("css_hello", "Responds to the caller with \"pong\"")]
|
||||
// The `CommandHelper` attribute can be used to provide additional information about the command.
|
||||
[CommandHelper(minArgs: 1, usage: "[name]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
[RequiresPermissions("@css/cvar")]
|
||||
public void OnHelloCommand(CCSPlayerController? player, CommandInfo commandInfo)
|
||||
{
|
||||
// The first argument is the command name, in this case "css_hello".
|
||||
commandInfo.GetArg(0); // css_hello
|
||||
|
||||
// The second argument is the first argument passed to the command, in this case "name".
|
||||
// The `minArgs` helper parameter is used to ensure that the second argument is present.
|
||||
var name = commandInfo.GetArg(1);
|
||||
|
||||
commandInfo.ReplyToCommand($"Hello {name}");
|
||||
}
|
||||
|
||||
// Permissions can be added to commands using the `RequiresPermissions` attribute.
|
||||
// See the admin documentation for more information on permissions.
|
||||
[RequiresPermissions("@css/kick")]
|
||||
[CommandHelper(minArgs: 1, usage: "[id]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
public void OnSpecialCommand(CCSPlayerController? player, CommandInfo commandInfo)
|
||||
{
|
||||
var id = commandInfo.GetArg(1);
|
||||
|
||||
Server.ExecuteCommand($"kick {id}");
|
||||
}
|
||||
}
|
||||
Binary file not shown.
BIN
managed/CounterStrikeSharp.API/ApiCompat/v151.dll
Normal file
BIN
managed/CounterStrikeSharp.API/ApiCompat/v151.dll
Normal file
Binary file not shown.
@@ -182,7 +182,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
info.ReplyToCommand($"Could not load plugin \"{path}\")", true);
|
||||
info.ReplyToCommand($"Could not load plugin \"{path}\"", true);
|
||||
Logger.LogError(e, "Could not load plugin \"{Path}\"", path);
|
||||
}
|
||||
}
|
||||
@@ -209,7 +209,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
IPluginContext? plugin = _pluginContextQueryHandler.FindPluginByIdOrName(pluginIdentifier);
|
||||
if (plugin == null)
|
||||
{
|
||||
info.ReplyToCommand($"Could not unload plugin \"{pluginIdentifier}\")", true);
|
||||
info.ReplyToCommand($"Could not unload plugin \"{pluginIdentifier}\"", true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
|
||||
if (plugin == null)
|
||||
{
|
||||
info.ReplyToCommand($"Could not reload plugin \"{pluginIdentifier}\")", true);
|
||||
info.ReplyToCommand($"Could not reload plugin \"{pluginIdentifier}\"", true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,19 +10,13 @@ namespace CounterStrikeSharp.API.Core;
|
||||
|
||||
public partial class CCSPlayerController
|
||||
{
|
||||
public int? UserId
|
||||
{
|
||||
get
|
||||
{
|
||||
return NativeAPI.GetUseridFromIndex((int)this.Index);
|
||||
}
|
||||
}
|
||||
|
||||
public CsTeam Team => (CsTeam)this.TeamNum;
|
||||
public int? UserId => NativeAPI.GetUseridFromIndex((int)Index);
|
||||
public CsTeam Team => (CsTeam)TeamNum;
|
||||
|
||||
public IntPtr GiveNamedItem(string item)
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return 0;
|
||||
if (PlayerPawn.Value == null) return 0;
|
||||
if (!PlayerPawn.Value.IsValid) return 0;
|
||||
if (PlayerPawn.Value.ItemServices == null) return 0;
|
||||
|
||||
@@ -37,7 +31,7 @@ public partial class CCSPlayerController
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
return this.GiveNamedItem(itemString);
|
||||
return GiveNamedItem(itemString);
|
||||
}
|
||||
|
||||
public void PrintToConsole(string message)
|
||||
@@ -47,12 +41,12 @@ public partial class CCSPlayerController
|
||||
|
||||
public void PrintToChat(string message)
|
||||
{
|
||||
VirtualFunctions.ClientPrint(this.Handle, HudDestination.Chat, message, 0, 0, 0, 0);
|
||||
VirtualFunctions.ClientPrint(Handle, HudDestination.Chat, message, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public void PrintToCenter(string message)
|
||||
{
|
||||
VirtualFunctions.ClientPrint(this.Handle, HudDestination.Center, message, 0, 0, 0, 0);
|
||||
VirtualFunctions.ClientPrint(Handle, HudDestination.Center, message, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public void PrintToCenterHtml(string message) => PrintToCenterHtml(message, 5);
|
||||
@@ -74,14 +68,16 @@ public partial class CCSPlayerController
|
||||
public void DropActiveWeapon()
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return;
|
||||
if (PlayerPawn.Value == null) return;
|
||||
if (!PlayerPawn.Value.IsValid) return;
|
||||
if (PlayerPawn.Value.ItemServices == null) return;
|
||||
if (PlayerPawn.Value.WeaponServices == null) return;
|
||||
if (!PlayerPawn.Value.WeaponServices.ActiveWeapon.IsValid) return;
|
||||
|
||||
CCSPlayer_ItemServices itemServices = new CCSPlayer_ItemServices(PlayerPawn.Value.ItemServices.Handle);
|
||||
CCSPlayer_WeaponServices weponServices = new CCSPlayer_WeaponServices(PlayerPawn.Value.WeaponServices.Handle);
|
||||
itemServices.DropActivePlayerWeapon(weponServices.ActiveWeapon.Value);
|
||||
CCSPlayer_WeaponServices weaponServices = new CCSPlayer_WeaponServices(PlayerPawn.Value.WeaponServices.Handle);
|
||||
|
||||
itemServices.DropActivePlayerWeapon(weaponServices.ActiveWeapon.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -90,6 +86,7 @@ public partial class CCSPlayerController
|
||||
public void RemoveWeapons()
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return;
|
||||
if (PlayerPawn.Value == null) return;
|
||||
if (!PlayerPawn.Value.IsValid) return;
|
||||
if (PlayerPawn.Value.ItemServices == null) return;
|
||||
|
||||
@@ -105,6 +102,7 @@ public partial class CCSPlayerController
|
||||
public void CommitSuicide(bool explode, bool force)
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return;
|
||||
if (PlayerPawn.Value == null) return;
|
||||
if (!PlayerPawn.Value.IsValid) return;
|
||||
|
||||
PlayerPawn.Value.CommitSuicide(explode, force);
|
||||
@@ -116,6 +114,7 @@ public partial class CCSPlayerController
|
||||
public void Respawn()
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return;
|
||||
if (PlayerPawn.Value == null) return;
|
||||
if (!PlayerPawn.Value.IsValid) return;
|
||||
|
||||
VirtualFunctions.CCSPlayerPawn_Respawn(PlayerPawn.Value.Handle);
|
||||
@@ -130,7 +129,7 @@ public partial class CCSPlayerController
|
||||
/// <param name="team">The team to switch to</param>
|
||||
public void SwitchTeam(CsTeam team)
|
||||
{
|
||||
VirtualFunctions.SwitchTeam(this.Handle, (byte)team);
|
||||
VirtualFunctions.SwitchTeam(Handle, (byte)team);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -153,7 +152,7 @@ public partial class CCSPlayerController
|
||||
/// <returns>ConVar string value</returns>
|
||||
public string GetConVarValue(string conVar)
|
||||
{
|
||||
return NativeAPI.GetClientConvarValue(this.Slot, conVar);
|
||||
return NativeAPI.GetClientConvarValue(Slot, conVar);
|
||||
}
|
||||
|
||||
public string GetConVarValue(ConVar? conVar)
|
||||
@@ -179,7 +178,7 @@ public partial class CCSPlayerController
|
||||
throw new InvalidOperationException("'SetFakeClientConVar' can only be called for fake clients (bots)");
|
||||
}
|
||||
|
||||
NativeAPI.SetFakeClientConvarValue(this.Slot, conVar, value);
|
||||
NativeAPI.SetFakeClientConvarValue(Slot, conVar, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -228,8 +227,8 @@ public partial class CCSPlayerController
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.IsValid) return null;
|
||||
var authorizedSteamId = NativeAPI.GetPlayerAuthorizedSteamid(this.Slot);
|
||||
if (!IsValid) return null;
|
||||
var authorizedSteamId = NativeAPI.GetPlayerAuthorizedSteamid(Slot);
|
||||
if ((long)authorizedSteamId == -1) return null;
|
||||
|
||||
return (SteamID)authorizedSteamId;
|
||||
@@ -244,8 +243,8 @@ public partial class CCSPlayerController
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.IsValid) return null;
|
||||
var ipAddress = NativeAPI.GetPlayerIpAddress(this.Slot);
|
||||
if (!IsValid) return null;
|
||||
var ipAddress = NativeAPI.GetPlayerIpAddress(Slot);
|
||||
if (string.IsNullOrWhiteSpace(ipAddress)) return null;
|
||||
|
||||
return ipAddress;
|
||||
@@ -258,9 +257,6 @@ public partial class CCSPlayerController
|
||||
public VoiceFlags VoiceFlags
|
||||
{
|
||||
get => (VoiceFlags)NativeAPI.GetClientVoiceFlags(Handle);
|
||||
set
|
||||
{
|
||||
NativeAPI.SetClientVoiceFlags(Handle, (Byte)value);
|
||||
}
|
||||
set => NativeAPI.SetClientVoiceFlags(Handle, (Byte)value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApiCompatValidateAssemblies>true</ApiCompatValidateAssemblies>
|
||||
<ApiCompatContractAssembly>.\ApiCompat\v133.dll</ApiCompatContractAssembly>
|
||||
<ApiCompatContractAssembly>.\ApiCompat\v151.dll</ApiCompatContractAssembly>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Modules\Commands\CommandInfo" />
|
||||
|
||||
@@ -68,6 +68,9 @@ public static class VirtualFunctions
|
||||
public static MemoryFunctionVoid<CEntityInstance, CTakeDamageInfo> CBaseEntity_TakeDamageOldFunc = new (GameData.GetSignature("CBaseEntity_TakeDamageOld"));
|
||||
public static Action<CEntityInstance, CTakeDamageInfo> CBaseEntity_TakeDamageOld = CBaseEntity_TakeDamageOldFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionWithReturn<CCSPlayer_WeaponServices, CBasePlayerWeapon, bool> CCSPlayer_WeaponServices_CanUseFunc = new(GameData.GetSignature("CCSPlayer_WeaponServices_CanUse"));
|
||||
public static Func<CCSPlayer_WeaponServices, CBasePlayerWeapon, bool> CCSPlayer_WeaponServices_CanUse = CCSPlayer_WeaponServices_CanUseFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionVoid<CCSPlayerPawnBase> CCSPlayerPawnBase_PostThinkFunc = new (GameData.GetSignature("CCSPlayerPawnBase_PostThink"));
|
||||
public static Action<CCSPlayerPawnBase> CCSPlayerPawnBase_PostThink = CCSPlayerPawnBase_PostThinkFunc.Invoke;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
|
||||
public abstract class BaseMenuInstance : IMenuInstance
|
||||
{
|
||||
public int NumPerPage => 6;
|
||||
public virtual int NumPerPage => 6;
|
||||
public Stack<int> PrevPageOffsets { get; } = new();
|
||||
public IMenu Menu { get; }
|
||||
public CCSPlayerController Player { get; }
|
||||
@@ -86,7 +86,7 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
return;
|
||||
}
|
||||
|
||||
if (key == 1 && HasPrevButton)
|
||||
if (key == 7 && HasPrevButton)
|
||||
{
|
||||
PrevPage();
|
||||
return;
|
||||
@@ -99,7 +99,6 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
}
|
||||
|
||||
var desiredValue = key;
|
||||
if (HasPrevButton) desiredValue = key - 1;
|
||||
|
||||
var menuItemIndex = CurrentOffset + desiredValue - 1;
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
public class CenterHtmlMenuInstance : BaseMenuInstance
|
||||
{
|
||||
private readonly BasePlugin _plugin;
|
||||
public override int NumPerPage => 5; // one less than the actual number of items per page to avoid truncated options
|
||||
|
||||
public CenterHtmlMenuInstance(BasePlugin plugin, CCSPlayerController player, IMenu menu) : base(player, menu)
|
||||
{
|
||||
@@ -80,17 +81,17 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
|
||||
var keyOffset = 1;
|
||||
|
||||
if (HasPrevButton)
|
||||
{
|
||||
builder.AppendFormat("<font color='green'>!1</font> -> Prev");
|
||||
builder.AppendLine("<br>");
|
||||
keyOffset++;
|
||||
}
|
||||
|
||||
for (var i = CurrentOffset; i < Math.Min(CurrentOffset + MenuItemsPerPage, Menu.MenuOptions.Count); i++)
|
||||
{
|
||||
var option = Menu.MenuOptions[i];
|
||||
builder.Append($"<font color='green'>!{keyOffset++}</font> {option.Text}");
|
||||
string color = option.Disabled ? "grey" : "green";
|
||||
builder.Append($"<font color='{color}'>!{keyOffset++}</font> {option.Text}");
|
||||
builder.AppendLine("<br>");
|
||||
}
|
||||
|
||||
if (HasPrevButton)
|
||||
{
|
||||
builder.AppendFormat("<font color='yellow'>!7</font> <- Prev");
|
||||
builder.AppendLine("<br>");
|
||||
}
|
||||
|
||||
@@ -122,4 +123,4 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
_plugin.RemoveListener("OnTick", onTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,12 +38,6 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
|
||||
var keyOffset = 1;
|
||||
|
||||
if (HasPrevButton)
|
||||
{
|
||||
Player.PrintToChat($" {ChatColors.Yellow}!1 {ChatColors.Default}-> Prev");
|
||||
keyOffset++;
|
||||
}
|
||||
|
||||
for (var i = CurrentOffset;
|
||||
i < Math.Min(CurrentOffset + MenuItemsPerPage, Menu.MenuOptions.Count);
|
||||
i++)
|
||||
@@ -54,6 +48,11 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
$" {(option.Disabled ? ChatColors.Grey : ChatColors.Green)} !{keyOffset++} {ChatColors.Default}{option.Text}");
|
||||
}
|
||||
|
||||
if (HasPrevButton)
|
||||
{
|
||||
Player.PrintToChat($" {ChatColors.Yellow}!7 {ChatColors.Default}-> Prev");
|
||||
}
|
||||
|
||||
if (HasNextButton)
|
||||
{
|
||||
Player.PrintToChat($" {ChatColors.Yellow}!8 {ChatColors.Default}-> Next");
|
||||
|
||||
@@ -36,12 +36,6 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
|
||||
var keyOffset = 1;
|
||||
|
||||
if (HasPrevButton)
|
||||
{
|
||||
Player.PrintToConsole($"!1 -> Prev");
|
||||
keyOffset++;
|
||||
}
|
||||
|
||||
for (var i = CurrentOffset;
|
||||
i < Math.Min(CurrentOffset + MenuItemsPerPage, Menu.MenuOptions.Count);
|
||||
i++)
|
||||
@@ -51,6 +45,11 @@ namespace CounterStrikeSharp.API.Modules.Menu
|
||||
Player.PrintToConsole(
|
||||
$" {(option.Disabled ? "[Enabled]" : "[Disabled] - ")} !{keyOffset++} {option.Text}");
|
||||
}
|
||||
|
||||
if (HasPrevButton)
|
||||
{
|
||||
Player.PrintToConsole($"!7 -> Prev");
|
||||
}
|
||||
|
||||
if (HasNextButton)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user