First commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
bin
|
||||||
|
obj
|
||||||
199
_old_plugin.cs
Normal file
199
_old_plugin.cs
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Core.Attributes.Registration;
|
||||||
|
using CounterStrikeSharp.API.Modules.Commands;
|
||||||
|
using CounterStrikeSharp.API.Modules.Memory;
|
||||||
|
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||||
|
using CounterStrikeSharp.API.Modules.Utils;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace OPorning;
|
||||||
|
|
||||||
|
public class OPorning : BasePlugin
|
||||||
|
{
|
||||||
|
public override string ModuleName => "p0rning";
|
||||||
|
public override string ModuleVersion => "1.0.0";
|
||||||
|
|
||||||
|
private static readonly ulong WeaponId = 16384;
|
||||||
|
|
||||||
|
private static readonly HttpClient Client = new HttpClient();
|
||||||
|
|
||||||
|
public class LegacyClass
|
||||||
|
{
|
||||||
|
[JsonPropertyName("legacy")]
|
||||||
|
public bool Legacy { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly MemoryFunctionVoid<nint, string, float> CAttributeListSetOrAddAttributeValueByName = new(GameData.GetSignature("CAttributeList_SetOrAddAttributeValueByName"));
|
||||||
|
|
||||||
|
private void Info(string message) => Console.WriteLine("\x1b[38;5;129m[AINDUSTRIES PRODUCTIONS] \x1b[38;5;82m[INFO] \x1b[38;5;255m{0}\x1b[0m", message);
|
||||||
|
private void Debug(string message) => Console.WriteLine("\x1b[38;5;129m[AINDUSTRIES PRODUCTIONS] \x1b[38;5;214m[DEBUG] \x1b[38;5;255m{0}\x1b[0m", message);
|
||||||
|
|
||||||
|
public override void Load(bool hotReload)
|
||||||
|
{
|
||||||
|
RegisterListener<Listeners.OnEntitySpawned>(OnEntityCreated);
|
||||||
|
RegisterListener<Listeners.OnEntityParentChanged>((entity, parent) =>
|
||||||
|
{
|
||||||
|
var designerName = entity.DesignerName;
|
||||||
|
|
||||||
|
if (!designerName.Contains("weapon_"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug("Parent changed for weapon");
|
||||||
|
|
||||||
|
var weapon = new CBasePlayerWeapon(entity.Handle);
|
||||||
|
if (weapon.AttributeManager.Item.ItemID != WeaponId)
|
||||||
|
{
|
||||||
|
Debug("Weapon is not a spawned weapon");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugWeapon(weapon);
|
||||||
|
|
||||||
|
bool legacy = IsWeaponLegacy(weapon);
|
||||||
|
|
||||||
|
//TODO: Check if this is necessary
|
||||||
|
// Seems not necessary, will keep it for now.
|
||||||
|
|
||||||
|
//CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);
|
||||||
|
//CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture seed", weapon.FallbackSeed);
|
||||||
|
//CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "set item texture prefab", weapon.FallbackPaintKit);
|
||||||
|
//CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "set item texture seed", weapon.FallbackSeed);
|
||||||
|
|
||||||
|
UpdateWeaponMeshGroupMask(weapon, legacy);
|
||||||
|
});
|
||||||
|
Info("Plugin Loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConsoleCommand("css_give", "Give an item to yourself")]
|
||||||
|
[CommandHelper(minArgs: 1, usage: "[name] [paint] [seed]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||||
|
public void Give(CCSPlayerController? player, CommandInfo commandInfo)
|
||||||
|
{
|
||||||
|
string weaponName = commandInfo.GetArg(1);
|
||||||
|
string paint = commandInfo.GetArg(2);
|
||||||
|
int paintId = 0;
|
||||||
|
if (paint != "")
|
||||||
|
{
|
||||||
|
paintId = Int32.Parse(paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
string pattern = commandInfo.GetArg(3);
|
||||||
|
int patternId = 1;
|
||||||
|
if (pattern != "")
|
||||||
|
{
|
||||||
|
patternId = Int32.Parse(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player == null) return;
|
||||||
|
|
||||||
|
var entity = player.GiveNamedItem(weaponName);
|
||||||
|
|
||||||
|
var weaponEntity = new CCSWeaponBase(entity);
|
||||||
|
var baseWeapon = new CBasePlayerWeapon(weaponEntity.Handle);
|
||||||
|
|
||||||
|
commandInfo.ReplyToCommand("Weapon given");
|
||||||
|
Server.NextFrame(() =>
|
||||||
|
{
|
||||||
|
GivePlayerWeaponSkin(player, baseWeapon, paintId, patternId);
|
||||||
|
Info("Weapon given and skin applied.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateWeaponMeshGroupMask(CBaseEntity weapon, bool isLegacy = false)
|
||||||
|
{
|
||||||
|
if (weapon.CBodyComponent?.SceneNode == null) return;
|
||||||
|
var skeleton = weapon.CBodyComponent.SceneNode.GetSkeletonInstance();
|
||||||
|
var value = (ulong)(isLegacy ? 2 : 1);
|
||||||
|
|
||||||
|
if (skeleton.ModelState.MeshGroupMask != value)
|
||||||
|
{
|
||||||
|
skeleton.ModelState.MeshGroupMask = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdatePlayerWeaponMeshGroupMask(CCSPlayerController player, CBasePlayerWeapon weapon, bool isLegacy)
|
||||||
|
{
|
||||||
|
UpdateWeaponMeshGroupMask(weapon, isLegacy);
|
||||||
|
|
||||||
|
var viewModel = GetPlayerViewModel(player);
|
||||||
|
if (viewModel == null || viewModel.Weapon.Value == null ||
|
||||||
|
viewModel.Weapon.Value.Index != weapon.Index) return;
|
||||||
|
|
||||||
|
UpdateWeaponMeshGroupMask(viewModel, isLegacy);
|
||||||
|
Utilities.SetStateChanged(viewModel, "CBaseEntity", "m_CBodyComponent");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CBaseViewModel? GetPlayerViewModel(CCSPlayerController player)
|
||||||
|
{
|
||||||
|
if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.ViewModelServices == null) return null;
|
||||||
|
CCSPlayer_ViewModelServices viewModelServices = new(player.PlayerPawn.Value.ViewModelServices!.Handle);
|
||||||
|
var ptr = viewModelServices.Handle + Schema.GetSchemaOffset("CCSPlayer_ViewModelServices", "m_hViewModel");
|
||||||
|
var references = MemoryMarshal.CreateSpan(ref ptr, 3);
|
||||||
|
var viewModel = (CHandle<CBaseViewModel>)Activator.CreateInstance(typeof(CHandle<CBaseViewModel>), references[0])!;
|
||||||
|
return viewModel.Value == null ? null : viewModel.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivePlayerWeaponSkin(CCSPlayerController? player, CBasePlayerWeapon baseWeapon, int paint, int pattern)
|
||||||
|
{
|
||||||
|
var weapon = new CEconEntity(baseWeapon.Handle);
|
||||||
|
baseWeapon.AttributeManager.Item.AttributeList.Attributes.RemoveAll();
|
||||||
|
baseWeapon.AttributeManager.Item.NetworkedDynamicAttributes.Attributes.RemoveAll();
|
||||||
|
|
||||||
|
weapon.FallbackPaintKit = paint;
|
||||||
|
weapon.FallbackSeed = pattern;
|
||||||
|
weapon.FallbackWear = 0.01f;
|
||||||
|
weapon.AttributeManager.Item.AccountID = (uint)player.SteamID;
|
||||||
|
|
||||||
|
/*
|
||||||
|
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture prefab", weapon.FallbackPaintKit);
|
||||||
|
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.NetworkedDynamicAttributes.Handle, "set item texture seed", weapon.FallbackSeed);
|
||||||
|
|
||||||
|
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "set item texture prefab", weapon.FallbackPaintKit);
|
||||||
|
CAttributeListSetOrAddAttributeValueByName.Invoke(weapon.AttributeManager.Item.AttributeList.Handle, "set item texture seed", weapon.FallbackSeed);
|
||||||
|
*/
|
||||||
|
|
||||||
|
weapon.AttributeManager.Item.ItemID = WeaponId;
|
||||||
|
weapon.AttributeManager.Item.ItemIDLow = (uint)WeaponId & 0xFFFFFFFF;
|
||||||
|
weapon.AttributeManager.Item.ItemIDHigh = (uint)WeaponId >> 32;
|
||||||
|
|
||||||
|
bool legacy = IsWeaponLegacy(baseWeapon);
|
||||||
|
|
||||||
|
UpdatePlayerWeaponMeshGroupMask(player, baseWeapon, legacy);
|
||||||
|
Info($"Gave weapon to {player.PlayerName}");
|
||||||
|
DebugWeapon(baseWeapon);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEntityCreated(CEntityInstance entity)
|
||||||
|
{
|
||||||
|
// TODO: Check if user has a loadout set, if so change the skins.
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DebugWeapon(CBasePlayerWeapon weapon)
|
||||||
|
{
|
||||||
|
Debug("[WEAPON DEBUG]");
|
||||||
|
Console.WriteLine("[Entity ID]: {0}", weapon.AttributeManager.Item.ItemID);
|
||||||
|
Console.WriteLine("[Owner ID]: {0}", weapon.AttributeManager.Item.AccountID);
|
||||||
|
Console.WriteLine("[Owner ID Low]: {0}", weapon.AttributeManager.Item.ItemIDLow);
|
||||||
|
Console.WriteLine("[Owner ID High]: {0}", weapon.AttributeManager.Item.ItemIDHigh);
|
||||||
|
Console.WriteLine("[Paint]: {0}", weapon.FallbackPaintKit);
|
||||||
|
Console.WriteLine("[Pattern]: {0}", weapon.FallbackSeed);
|
||||||
|
Console.WriteLine("[DefIndex]: {0}", weapon.AttributeManager.Item.ItemDefinitionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsWeaponLegacy(CBasePlayerWeapon weapon)
|
||||||
|
{
|
||||||
|
var designerName = weapon.DesignerName;
|
||||||
|
var paint = weapon.FallbackPaintKit;
|
||||||
|
HttpResponseMessage response = Client.GetAsync($"http://127.0.0.1:8900/api/legacy/{designerName}/{paint}").GetAwaiter().GetResult();
|
||||||
|
LegacyClass? value = null;
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
value = response.Content.ReadFromJsonAsync<LegacyClass>().GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
return value?.Legacy ?? false;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
commands/admin.cs
Normal file
60
commands/admin.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Admin;
|
||||||
|
using CounterStrikeSharp.API.Modules.Commands;
|
||||||
|
using CounterStrikeSharp.API.Modules.Cvars;
|
||||||
|
|
||||||
|
namespace Porning;
|
||||||
|
|
||||||
|
class AdminCommands
|
||||||
|
{
|
||||||
|
private readonly BasePlugin plugin;
|
||||||
|
|
||||||
|
public AdminCommands(BasePlugin pluginInstance)
|
||||||
|
{
|
||||||
|
plugin = pluginInstance;
|
||||||
|
}
|
||||||
|
private ConVar autoBhopCvar = ConVar.Find("sv_autobunnyhopping")!;
|
||||||
|
|
||||||
|
[CommandHelper(minArgs: 1, usage: "[map_name]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||||
|
[RequiresPermissions("@porning/admin")]
|
||||||
|
public void onMap(CCSPlayerController? player, CommandInfo commandInfo)
|
||||||
|
{
|
||||||
|
string map = commandInfo.GetArg(1);
|
||||||
|
if (!Server.IsMapValid(map))
|
||||||
|
{
|
||||||
|
Info info = new Info(plugin, "Map not recognised.");
|
||||||
|
info.Show(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Server.ExecuteCommand($"map {map}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHelper(minArgs: 0, usage: "[0/1]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||||
|
[RequiresPermissions("@porning/admin")]
|
||||||
|
public void onBhop(CCSPlayerController? player, CommandInfo commandInfo)
|
||||||
|
{
|
||||||
|
Info info;
|
||||||
|
if (commandInfo.ArgCount == 1)
|
||||||
|
{
|
||||||
|
bool autoBhop = autoBhopCvar.GetPrimitiveValue<bool>();
|
||||||
|
Server.ExecuteCommand($"sv_autobunnyhopping {!autoBhop}");
|
||||||
|
info = new Info(plugin, $"Toggled bhop: {!autoBhop}");
|
||||||
|
info.Show(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string bhop = commandInfo.GetArg(1);
|
||||||
|
Server.ExecuteCommand($"sv_autobunnyhopping {bhop}");
|
||||||
|
info = new Info(plugin, $"Toggled bhop: {bhop}");
|
||||||
|
info.Show(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHelper(minArgs: 1, usage: "[message]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||||
|
[RequiresPermissions("@porning/admin")]
|
||||||
|
public void onInfo(CCSPlayerController? player, CommandInfo commandInfo)
|
||||||
|
{
|
||||||
|
string message = commandInfo.GetCommandString.Substring(9);
|
||||||
|
Info info = new Info(plugin, message);
|
||||||
|
info.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
54
commands/player.cs
Normal file
54
commands/player.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Commands;
|
||||||
|
|
||||||
|
namespace Porning;
|
||||||
|
|
||||||
|
class PlayerCommands
|
||||||
|
{
|
||||||
|
private readonly BasePlugin plugin;
|
||||||
|
|
||||||
|
public PlayerCommands(BasePlugin pluginInstance)
|
||||||
|
{
|
||||||
|
plugin = pluginInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHelper(minArgs: 0, usage: "", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||||
|
public void onHelp(CCSPlayerController? player, CommandInfo commandInfo)
|
||||||
|
{
|
||||||
|
commandInfo.ReplyToCommand("/help: Show help");
|
||||||
|
commandInfo.ReplyToCommand("/map: Change map");
|
||||||
|
commandInfo.ReplyToCommand("/bhop: Toggle bhop");
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHelper(minArgs:0, usage: "[map]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||||
|
public void onMapVote(CCSPlayerController? player, CommandInfo commandInfo)
|
||||||
|
{
|
||||||
|
string map = commandInfo.GetArg(1);
|
||||||
|
if (!Server.IsMapValid(map))
|
||||||
|
{
|
||||||
|
Info info = new Info(plugin, "Map not recognised.");
|
||||||
|
info.Show(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vote vote = new Vote(plugin, $"Map vote: {map}", ["Yes", "No"]);
|
||||||
|
vote.BeginVote();
|
||||||
|
vote.OnEnd((best) =>
|
||||||
|
{
|
||||||
|
if (best == 0)
|
||||||
|
{
|
||||||
|
Info info = new Info(plugin, "Changing map!");
|
||||||
|
info.Show();
|
||||||
|
info.OnClose(() =>
|
||||||
|
{
|
||||||
|
Server.ExecuteCommand($"map {map}");
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Info info = new Info(plugin, "Not changing map!");
|
||||||
|
info.Show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
38
plugin.cs
Normal file
38
plugin.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
|
||||||
|
namespace Porning;
|
||||||
|
|
||||||
|
public class Porning : BasePlugin
|
||||||
|
{
|
||||||
|
public override string ModuleName => "p0rning";
|
||||||
|
public override string ModuleVersion => "0.0.1";
|
||||||
|
private static readonly ulong SpawnedWeaponId = 16384; // Randomly chosen
|
||||||
|
private readonly AdminCommands adminCommands;
|
||||||
|
private readonly PlayerCommands playerCommands;
|
||||||
|
|
||||||
|
public Porning()
|
||||||
|
{
|
||||||
|
adminCommands = new AdminCommands(this);
|
||||||
|
playerCommands = new PlayerCommands(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Load(bool hotReload)
|
||||||
|
{
|
||||||
|
new Logger().Info("Loaded!");
|
||||||
|
registerAdminCommands();
|
||||||
|
registerPlayerCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerAdminCommands()
|
||||||
|
{
|
||||||
|
AddCommand("css_amap", "Change map", adminCommands.onMap);
|
||||||
|
AddCommand("css_abhop", "Toggle bhop", adminCommands.onBhop);
|
||||||
|
AddCommand("css_ainfo", "Broadcast message", adminCommands.onInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerPlayerCommands()
|
||||||
|
{
|
||||||
|
AddCommand("css_help", "Help", playerCommands.onHelp);
|
||||||
|
AddCommand("css_map", "Vote Map", playerCommands.onMapVote);
|
||||||
|
}
|
||||||
|
}
|
||||||
30
plugin.csproj
Normal file
30
plugin.csproj
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="CounterStrikeSharp.API">
|
||||||
|
<HintPath>/games/cs2-server/game/csgo/addons/counterstrikesharp/api/CounterStrikeSharp.API.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="_old_plugin.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="_old_plugin.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="CopyAllOutputAfterBuild" AfterTargets="AfterBuild">
|
||||||
|
<ItemGroup>
|
||||||
|
<MyOutputFiles Include="$(TargetDir)**\*.*" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Copy SourceFiles="@(MyOutputFiles)" DestinationFolder="/games/cs2-server//game/csgo/addons/counterstrikesharp/plugins/plugin/%(RecursiveDir)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
53
utils/info.cs
Normal file
53
utils/info.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Menu;
|
||||||
|
|
||||||
|
namespace Porning;
|
||||||
|
|
||||||
|
class Info
|
||||||
|
{
|
||||||
|
private string message = "";
|
||||||
|
private BasePlugin plugin = null!;
|
||||||
|
private CenterHtmlMenu? menu = null;
|
||||||
|
private Action? callback = null;
|
||||||
|
|
||||||
|
public Info(BasePlugin plugin, string message)
|
||||||
|
{
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.message = $"<font color=\"red\">Porning</font><br>{message}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Show(CCSPlayerController? player=null)
|
||||||
|
{
|
||||||
|
menu = new CenterHtmlMenu(message, plugin)
|
||||||
|
{
|
||||||
|
ExitButton = false
|
||||||
|
};
|
||||||
|
|
||||||
|
if (player !=null)
|
||||||
|
{
|
||||||
|
MenuManager.OpenCenterHtmlMenu(plugin, player, menu);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
foreach (CCSPlayerController p in Utilities.GetPlayers())
|
||||||
|
{
|
||||||
|
MenuManager.OpenCenterHtmlMenu(plugin, p, menu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plugin.AddTimer(5.0f, Close);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
foreach (CCSPlayerController player in Utilities.GetPlayers())
|
||||||
|
{
|
||||||
|
MenuManager.CloseActiveMenu(player);
|
||||||
|
}
|
||||||
|
callback?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClose(Action callback)
|
||||||
|
{
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
utils/logger.cs
Normal file
14
utils/logger.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace Porning;
|
||||||
|
|
||||||
|
public class Logger
|
||||||
|
{
|
||||||
|
public void Info(string message)
|
||||||
|
{
|
||||||
|
Console.WriteLine("\x1b[38;5;129m[p0rning] \x1b[38;5;82m[INFO] \x1b[38;5;255m{0}\x1b[0m", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Debug(string message)
|
||||||
|
{
|
||||||
|
Console.WriteLine("\x1b[38;5;129m[p0rning] \x1b[38;5;214m[DEBUG] \x1b[38;5;255m{0}\x1b[0m", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
95
utils/vote.cs
Normal file
95
utils/vote.cs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Menu;
|
||||||
|
|
||||||
|
namespace Porning;
|
||||||
|
|
||||||
|
public class Vote
|
||||||
|
{
|
||||||
|
private List<int> counters = new List<int>();
|
||||||
|
private int best = -1;
|
||||||
|
private Action<int>? callback = null;
|
||||||
|
private int time = 0;
|
||||||
|
private string title = "";
|
||||||
|
private BasePlugin plugin = null!;
|
||||||
|
private CenterHtmlMenu menu = null!;
|
||||||
|
private List<string> options = null!;
|
||||||
|
|
||||||
|
public Vote(BasePlugin plugin, string message, List<string> options)
|
||||||
|
{
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.options = options;
|
||||||
|
title = $"<font color=\"red\">Porning</font><br>{message}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BeginVote()
|
||||||
|
{
|
||||||
|
menu = new CenterHtmlMenu($"{title} (10 sec)", plugin){
|
||||||
|
ExitButton = false
|
||||||
|
};
|
||||||
|
for (int i = 0; i < options.Count; i++)
|
||||||
|
{
|
||||||
|
counters.Add(0);
|
||||||
|
int current = i;
|
||||||
|
menu.AddMenuOption($"-> {options[i]} [0]", (player, action) => {counters[current]++;});
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (CCSPlayerController player in Utilities.GetPlayers())
|
||||||
|
{
|
||||||
|
MenuManager.OpenCenterHtmlMenu(plugin, player, menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.AddTimer(1.0f, Tick);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
new Logger().Info($"TICK: {time}");
|
||||||
|
if (time >= 10)
|
||||||
|
{
|
||||||
|
EndVote();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
time++;
|
||||||
|
|
||||||
|
menu.Title = $"{title} ({10-time} sec)";
|
||||||
|
|
||||||
|
for (int i = 0; i < options.Count; i++)
|
||||||
|
{
|
||||||
|
menu.MenuOptions[i].Text = $"-> {options[i]} [{counters[i]}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(CCSPlayerController player in Utilities.GetPlayers())
|
||||||
|
{
|
||||||
|
MenuManager.OpenCenterHtmlMenu(plugin, player, menu);
|
||||||
|
}
|
||||||
|
plugin.AddTimer(1.0f, Tick);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndVote()
|
||||||
|
{
|
||||||
|
foreach (CCSPlayerController player in Utilities.GetPlayers())
|
||||||
|
{
|
||||||
|
MenuManager.CloseActiveMenu(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxVotes = 0;
|
||||||
|
for (int i = 0; i < counters.Count; i++)
|
||||||
|
{
|
||||||
|
new Logger().Info($"Counter: {counters[i]}");
|
||||||
|
if (counters[i] > maxVotes)
|
||||||
|
{
|
||||||
|
maxVotes = counters[i];
|
||||||
|
best = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback?.Invoke(best);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnEnd(Action<int> function)
|
||||||
|
{
|
||||||
|
callback = function;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user