mirror of
https://github.com/MSWS/TTT.git
synced 2025-12-07 23:06:33 -08:00
Compare commits
24 Commits
0.22.3-dev
...
1.1.1-dev.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
642155b1bc | ||
|
|
bacd288fe7 | ||
|
|
29e28038b8 | ||
|
|
b253d8ee12 | ||
|
|
02575b51e2 | ||
|
|
d8d365b497 | ||
|
|
1ac38dc0ad | ||
|
|
62e57ffa97 | ||
|
|
81e6b2e695 | ||
|
|
2ce0457346 | ||
|
|
ed90c54e53 | ||
|
|
06d2d71f76 | ||
|
|
c6ba041a6b | ||
|
|
f283d7407e | ||
|
|
51ff4df545 | ||
|
|
e0ee4bf325 | ||
|
|
4a4c7e0782 | ||
|
|
d4f67ced0c | ||
|
|
33ca0c8385 | ||
|
|
ff2e97a3ce | ||
|
|
a56cdc1285 | ||
|
|
ceda5cba64 | ||
|
|
7c203bcd91 | ||
|
|
f91fc54897 |
@@ -1,16 +1,16 @@
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using SpecialRoundAPI.Configs;
|
||||||
using TTT.API;
|
using TTT.API;
|
||||||
using TTT.API.Events;
|
using TTT.API.Events;
|
||||||
using TTT.Game.Events.Game;
|
using TTT.Game.Events.Game;
|
||||||
|
using TTT.Game.Listeners;
|
||||||
using TTT.Locale;
|
using TTT.Locale;
|
||||||
|
|
||||||
namespace SpecialRoundAPI;
|
namespace SpecialRoundAPI;
|
||||||
|
|
||||||
public abstract class AbstractSpecialRound(IServiceProvider provider)
|
public abstract class AbstractSpecialRound(IServiceProvider provider)
|
||||||
: ITerrorModule, IListener {
|
: BaseListener(provider) {
|
||||||
protected readonly IServiceProvider Provider = provider;
|
|
||||||
|
|
||||||
protected readonly ISpecialRoundTracker Tracker =
|
protected readonly ISpecialRoundTracker Tracker =
|
||||||
provider.GetRequiredService<ISpecialRoundTracker>();
|
provider.GetRequiredService<ISpecialRoundTracker>();
|
||||||
|
|
||||||
@@ -18,9 +18,6 @@ public abstract class AbstractSpecialRound(IServiceProvider provider)
|
|||||||
public abstract IMsg Description { get; }
|
public abstract IMsg Description { get; }
|
||||||
public abstract SpecialRoundConfig Config { get; }
|
public abstract SpecialRoundConfig Config { get; }
|
||||||
|
|
||||||
public void Dispose() { }
|
|
||||||
public void Start() { }
|
|
||||||
|
|
||||||
public abstract void ApplyRoundEffects();
|
public abstract void ApplyRoundEffects();
|
||||||
|
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace SpecialRoundAPI;
|
namespace SpecialRoundAPI.Configs;
|
||||||
|
|
||||||
public record BhopRoundConfig : SpecialRoundConfig {
|
public record BhopRoundConfig : SpecialRoundConfig {
|
||||||
public override float Weight { get; init; } = 0.2f;
|
public override float Weight { get; init; } = 0.2f;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace SpecialRoundAPI.Configs;
|
||||||
|
|
||||||
|
public record SilentRoundConfig : SpecialRoundConfig {
|
||||||
|
public override float Weight { get; init; } = 0.1f;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace SpecialRoundAPI;
|
namespace SpecialRoundAPI.Configs;
|
||||||
|
|
||||||
public abstract record SpecialRoundConfig {
|
public abstract record SpecialRoundConfig {
|
||||||
public abstract float Weight { get; init; }
|
public abstract float Weight { get; init; }
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
namespace SpecialRoundAPI;
|
namespace SpecialRoundAPI.Configs;
|
||||||
|
|
||||||
public record SpeedRoundConfig : SpecialRoundConfig {
|
public record SpeedRoundConfig : SpecialRoundConfig {
|
||||||
public override float Weight { get; init; } = 0.5f;
|
public override float Weight { get; init; } = 0.6f;
|
||||||
|
|
||||||
public TimeSpan InitialSeconds { get; init; } = TimeSpan.FromSeconds(40);
|
public TimeSpan InitialSeconds { get; init; } = TimeSpan.FromSeconds(40);
|
||||||
public TimeSpan SecondsPerKill { get; init; } = TimeSpan.FromSeconds(10);
|
public TimeSpan SecondsPerKill { get; init; } = TimeSpan.FromSeconds(10);
|
||||||
|
public TimeSpan MaxTimeEver { get; init; } = TimeSpan.FromSeconds(90);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace SpecialRoundAPI.Configs;
|
||||||
|
|
||||||
|
public record SuppressedRoundConfig : SpecialRoundConfig {
|
||||||
|
public override float Weight { get; init; } = 0.3f;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace SpecialRoundAPI.Configs;
|
||||||
|
|
||||||
|
public record VanillaRoundConfig : SpecialRoundConfig {
|
||||||
|
public override float Weight { get; init; } = 0.2f;
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
namespace SpecialRoundAPI;
|
|
||||||
|
|
||||||
public record VanillaRoundConfig : SpecialRoundConfig {
|
|
||||||
public override float Weight { get; init; } = 0.3f;
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using CounterStrikeSharp.API.Core;
|
using CounterStrikeSharp.API.Core;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using ShopAPI;
|
||||||
using ShopAPI.Configs;
|
using ShopAPI.Configs;
|
||||||
using ShopAPI.Configs.Detective;
|
using ShopAPI.Configs.Detective;
|
||||||
using ShopAPI.Configs.Traitor;
|
using ShopAPI.Configs.Traitor;
|
||||||
@@ -63,6 +64,8 @@ public static class CS2ServiceCollection {
|
|||||||
collection
|
collection
|
||||||
.AddModBehavior<IStorage<OneHitKnifeConfig>, CS2OneHitKnifeConfig>();
|
.AddModBehavior<IStorage<OneHitKnifeConfig>, CS2OneHitKnifeConfig>();
|
||||||
collection.AddModBehavior<IStorage<SilentAWPConfig>, CS2SilentAWPConfig>();
|
collection.AddModBehavior<IStorage<SilentAWPConfig>, CS2SilentAWPConfig>();
|
||||||
|
collection
|
||||||
|
.AddModBehavior<IStorage<HealthshotConfig>, CS2HealthshotConfig>();
|
||||||
|
|
||||||
// TTT - CS2 Specific optionals
|
// TTT - CS2 Specific optionals
|
||||||
collection.AddScoped<ITextSpawner, TextSpawner>();
|
collection.AddScoped<ITextSpawner, TextSpawner>();
|
||||||
|
|||||||
@@ -41,15 +41,15 @@ public class PlayerPingShopAlias(IServiceProvider provider) : IPluginModule {
|
|||||||
|
|
||||||
private void onButton(CCSPlayerController? player, int index) {
|
private void onButton(CCSPlayerController? player, int index) {
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (converter.GetPlayer(player) is not IOnlinePlayer gamePlayer) return;
|
if (converter.GetPlayer(player) is not IOnlinePlayer apiPlayer) return;
|
||||||
|
|
||||||
var lastUpdated = itemSorter.GetLastUpdate(gamePlayer);
|
var lastUpdated = itemSorter.GetLastUpdate(apiPlayer);
|
||||||
if (lastUpdated == null
|
if (lastUpdated == null
|
||||||
|| DateTime.Now - lastUpdated > TimeSpan.FromSeconds(20))
|
|| DateTime.Now - lastUpdated > TimeSpan.FromSeconds(20))
|
||||||
return;
|
return;
|
||||||
var cmdInfo = new CS2CommandInfo(provider, gamePlayer, 0, "css_shop", "buy",
|
var cmdInfo = new CS2CommandInfo(provider, apiPlayer, 0, "css_shop", "buy",
|
||||||
(index - 1).ToString());
|
(index - 1).ToString()) { CallingContext = CommandCallingContext.Chat };
|
||||||
cmdInfo.CallingContext = CommandCallingContext.Chat;
|
|
||||||
provider.GetRequiredService<ICommandManager>().ProcessCommand(cmdInfo);
|
provider.GetRequiredService<ICommandManager>().ProcessCommand(cmdInfo);
|
||||||
|
itemSorter.InvalidateOrder(apiPlayer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,8 @@ public class SpecCommand(IServiceProvider provider) : ICommand {
|
|||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
public void Start() { }
|
public void Start() { }
|
||||||
|
|
||||||
|
public string Id => "spec";
|
||||||
|
|
||||||
public Task<CommandResult>
|
public Task<CommandResult>
|
||||||
Execute(IOnlinePlayer? executor, ICommandInfo info) {
|
Execute(IOnlinePlayer? executor, ICommandInfo info) {
|
||||||
var target = executor;
|
var target = executor;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using CounterStrikeSharp.API;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using SpecialRoundAPI;
|
using SpecialRoundAPI;
|
||||||
using TTT.API;
|
using TTT.API;
|
||||||
using TTT.API.Command;
|
using TTT.API.Command;
|
||||||
@@ -25,7 +26,7 @@ public class SpecialRoundCommand(IServiceProvider provider) : ICommand {
|
|||||||
|
|
||||||
var rounds = provider.GetServices<ITerrorModule>()
|
var rounds = provider.GetServices<ITerrorModule>()
|
||||||
.OfType<AbstractSpecialRound>()
|
.OfType<AbstractSpecialRound>()
|
||||||
.ToDictionary(r => r.GetType().Name.ToLower(), r => r);
|
.ToDictionary(r => r.Name.ToLower(), r => r);
|
||||||
|
|
||||||
var roundName = info.Args[1].ToLower();
|
var roundName = info.Args[1].ToLower();
|
||||||
if (!rounds.TryGetValue(roundName, out var round)) {
|
if (!rounds.TryGetValue(roundName, out var round)) {
|
||||||
@@ -34,8 +35,10 @@ public class SpecialRoundCommand(IServiceProvider provider) : ICommand {
|
|||||||
return Task.FromResult(CommandResult.INVALID_ARGS);
|
return Task.FromResult(CommandResult.INVALID_ARGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
tracker.TryStartSpecialRound(round);
|
Server.NextWorldUpdate(() => {
|
||||||
info.ReplySync($"Started special round '{roundName}'.");
|
tracker.TryStartSpecialRound(round);
|
||||||
|
info.ReplySync($"Started special round '{roundName}'.");
|
||||||
|
});
|
||||||
return Task.FromResult(CommandResult.SUCCESS);
|
return Task.FromResult(CommandResult.SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,21 +63,19 @@ public class CS2GameConfig : IStorage<TTTConfig>, IPluginModule {
|
|||||||
|
|
||||||
public static readonly FakeConVar<string> CV_TRAITOR_WEAPONS = new(
|
public static readonly FakeConVar<string> CV_TRAITOR_WEAPONS = new(
|
||||||
"css_ttt_roleweapons_traitor",
|
"css_ttt_roleweapons_traitor",
|
||||||
"Weapons available to traitors at start of round",
|
"Weapons available to traitors at start of round", "",
|
||||||
"weapon_knife,weapon_glock", ConVarFlags.FCVAR_NONE,
|
ConVarFlags.FCVAR_NONE, new ItemValidator(allowMultiple: true));
|
||||||
new ItemValidator(allowMultiple: true));
|
|
||||||
|
|
||||||
public static readonly FakeConVar<string> CV_DETECTIVE_WEAPONS = new(
|
public static readonly FakeConVar<string> CV_DETECTIVE_WEAPONS = new(
|
||||||
"css_ttt_roleweapons_detective",
|
"css_ttt_roleweapons_detective",
|
||||||
"Weapons available to detectives at start of round",
|
"Weapons available to detectives at start of round",
|
||||||
"weapon_knife,weapon_taser,weapon_m4a1,weapon_revolver",
|
"weapon_taser,weapon_m4a1_silencer,weapon_revolver", ConVarFlags.FCVAR_NONE,
|
||||||
ConVarFlags.FCVAR_NONE, new ItemValidator(allowMultiple: true));
|
new ItemValidator(allowMultiple: true));
|
||||||
|
|
||||||
public static readonly FakeConVar<string> CV_INNOCENT_WEAPONS = new(
|
public static readonly FakeConVar<string> CV_INNOCENT_WEAPONS = new(
|
||||||
"css_ttt_roleweapons_innocent",
|
"css_ttt_roleweapons_innocent",
|
||||||
"Weapons available to innocents at start of round",
|
"Weapons available to innocents at start of round", "",
|
||||||
"weapon_knife,weapon_glock", ConVarFlags.FCVAR_NONE,
|
ConVarFlags.FCVAR_NONE, new ItemValidator(allowMultiple: true));
|
||||||
new ItemValidator(allowMultiple: true));
|
|
||||||
|
|
||||||
public static readonly FakeConVar<int> CV_TIME_BETWEEN_ROUNDS = new(
|
public static readonly FakeConVar<int> CV_TIME_BETWEEN_ROUNDS = new(
|
||||||
"css_ttt_time_between_rounds", "Time to wait between rounds in seconds", 1,
|
"css_ttt_time_between_rounds", "Time to wait between rounds in seconds", 1,
|
||||||
|
|||||||
@@ -74,13 +74,13 @@ public class CS2KarmaConfig : IStorage<KarmaConfig>, IPluginModule {
|
|||||||
|
|
||||||
public static readonly FakeConVar<int> CV_KARMA_PER_ROUND = new(
|
public static readonly FakeConVar<int> CV_KARMA_PER_ROUND = new(
|
||||||
"css_ttt_karma_per_round",
|
"css_ttt_karma_per_round",
|
||||||
"Amount of karma a player will gain at the end of each round", 2,
|
"Amount of karma a player will gain at the end of each round", 1,
|
||||||
ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 50));
|
ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 50));
|
||||||
|
|
||||||
public static readonly FakeConVar<int> CV_KARMA_PER_ROUND_WIN = new(
|
public static readonly FakeConVar<int> CV_KARMA_PER_ROUND_WIN = new(
|
||||||
"css_ttt_karma_per_round_win",
|
"css_ttt_karma_per_round_win",
|
||||||
"Amount of karma a player will gain at the end of each round if their team won",
|
"Amount of karma a player will gain at the end of each round if their team won",
|
||||||
4, ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 50));
|
1, ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 50));
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace TTT.CS2.Configs.ShopItems;
|
|||||||
|
|
||||||
public class CS2BodyPaintConfig : IStorage<BodyPaintConfig>, IPluginModule {
|
public class CS2BodyPaintConfig : IStorage<BodyPaintConfig>, IPluginModule {
|
||||||
public static readonly FakeConVar<int> CV_PRICE = new(
|
public static readonly FakeConVar<int> CV_PRICE = new(
|
||||||
"css_ttt_shop_bodypaint_price", "Price of the Body Paint item", 40,
|
"css_ttt_shop_bodypaint_price", "Price of the Body Paint item", 30,
|
||||||
ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 10000));
|
ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 10000));
|
||||||
|
|
||||||
public static readonly FakeConVar<int> CV_MAX_USES = new(
|
public static readonly FakeConVar<int> CV_MAX_USES = new(
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class CS2CamoConfig : IStorage<CamoConfig>, IPluginModule {
|
|||||||
public static readonly FakeConVar<float> CV_CAMO_VISIBILITY = new(
|
public static readonly FakeConVar<float> CV_CAMO_VISIBILITY = new(
|
||||||
"css_ttt_shop_camo_visibility",
|
"css_ttt_shop_camo_visibility",
|
||||||
"Player visibility multiplier while camouflaged (0 = invisible, 1 = fully visible)",
|
"Player visibility multiplier while camouflaged (0 = invisible, 1 = fully visible)",
|
||||||
0.6f, ConVarFlags.FCVAR_NONE, new RangeValidator<float>(0f, 1f));
|
0.5f, ConVarFlags.FCVAR_NONE, new RangeValidator<float>(0f, 1f));
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
|
|
||||||
|
|||||||
43
TTT/CS2/Configs/ShopItems/CS2HealthshotConfig.cs
Normal file
43
TTT/CS2/Configs/ShopItems/CS2HealthshotConfig.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Cvars;
|
||||||
|
using CounterStrikeSharp.API.Modules.Cvars.Validators;
|
||||||
|
using ShopAPI;
|
||||||
|
using TTT.API;
|
||||||
|
using TTT.API.Storage;
|
||||||
|
|
||||||
|
namespace TTT.CS2.Configs.ShopItems;
|
||||||
|
|
||||||
|
public class CS2HealthshotConfig : IStorage<HealthshotConfig>, IPluginModule {
|
||||||
|
public static readonly FakeConVar<int> CV_PRICE = new(
|
||||||
|
"css_ttt_shop_healthshot_price", "Price of the Healthshot item", 40,
|
||||||
|
ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 10000));
|
||||||
|
|
||||||
|
public static readonly FakeConVar<int> CV_MAX_PURCHASES = new(
|
||||||
|
"css_ttt_shop_healthshot_max_purchases",
|
||||||
|
"Maximum number of times a player can purchase the Healthshot per round", 2,
|
||||||
|
ConVarFlags.FCVAR_NONE, new RangeValidator<int>(1, 100));
|
||||||
|
|
||||||
|
public static readonly FakeConVar<string> CV_WEAPON = new(
|
||||||
|
"css_ttt_shop_healthshot_weapon", "Weapon entity name for the Healthshot",
|
||||||
|
"weapon_healthshot");
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
|
|
||||||
|
public void Start() { }
|
||||||
|
|
||||||
|
public void Start(BasePlugin? plugin) {
|
||||||
|
ArgumentNullException.ThrowIfNull(plugin, nameof(plugin));
|
||||||
|
plugin.RegisterFakeConVars(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<HealthshotConfig?> Load() {
|
||||||
|
var cfg = new HealthshotConfig {
|
||||||
|
Price = CV_PRICE.Value,
|
||||||
|
MaxPurchases = CV_MAX_PURCHASES.Value,
|
||||||
|
Weapon = CV_WEAPON.Value
|
||||||
|
};
|
||||||
|
|
||||||
|
return Task.FromResult<HealthshotConfig?>(cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ namespace TTT.CS2.Configs.ShopItems;
|
|||||||
|
|
||||||
public class CS2StickersConfig : IStorage<StickersConfig>, IPluginModule {
|
public class CS2StickersConfig : IStorage<StickersConfig>, IPluginModule {
|
||||||
public static readonly FakeConVar<int> CV_PRICE = new(
|
public static readonly FakeConVar<int> CV_PRICE = new(
|
||||||
"css_ttt_shop_stickers_price", "Price of the Stickers item (Detective)", 35,
|
"css_ttt_shop_stickers_price", "Price of the Stickers item (Detective)", 45,
|
||||||
ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 10000));
|
ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 10000));
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
|
|||||||
@@ -51,7 +51,9 @@ public class PropMover(IServiceProvider provider) : IPluginModule {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pressed.HasFlag(PlayerButtons.Use)) return;
|
if (!pressed.HasFlag(PlayerButtons.Use)
|
||||||
|
&& !pressed.HasFlag(PlayerButtons.Inspect))
|
||||||
|
return;
|
||||||
|
|
||||||
onStartUse(player);
|
onStartUse(player);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using CounterStrikeSharp.API.Core;
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.Utils;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using ShopAPI.Configs.Traitor;
|
using ShopAPI.Configs.Traitor;
|
||||||
@@ -45,6 +47,13 @@ public class DamageStation(IServiceProvider provider)
|
|||||||
override protected void onInterval() {
|
override protected void onInterval() {
|
||||||
var players = finder.GetOnline();
|
var players = finder.GetOnline();
|
||||||
var toRemove = new List<CPhysicsPropMultiplayer>();
|
var toRemove = new List<CPhysicsPropMultiplayer>();
|
||||||
|
var playerMapping = players
|
||||||
|
.Select(p => (ApiPlayer: p, GamePlayer: converter.GetPlayer(p)))
|
||||||
|
.Where(m
|
||||||
|
=> m.GamePlayer != null
|
||||||
|
&& !Roles.GetRoles(m.ApiPlayer).Any(r => r is TraitorRole))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
foreach (var (prop, info) in props) {
|
foreach (var (prop, info) in props) {
|
||||||
if (_Config.TotalHealthGiven != 0 && Math.Abs(info.HealthGiven)
|
if (_Config.TotalHealthGiven != 0 && Math.Abs(info.HealthGiven)
|
||||||
> Math.Abs(_Config.TotalHealthGiven)) {
|
> Math.Abs(_Config.TotalHealthGiven)) {
|
||||||
@@ -59,10 +68,6 @@ public class DamageStation(IServiceProvider provider)
|
|||||||
|
|
||||||
var propPos = prop.AbsOrigin;
|
var propPos = prop.AbsOrigin;
|
||||||
|
|
||||||
var playerMapping = players.Select(p
|
|
||||||
=> (ApiPlayer: p, GamePlayer: converter.GetPlayer(p)))
|
|
||||||
.Where(m => m.GamePlayer != null);
|
|
||||||
|
|
||||||
var playerDists = playerMapping
|
var playerDists = playerMapping
|
||||||
.Select(t => (t.ApiPlayer, Origin: t.GamePlayer!.Pawn.Value?.AbsOrigin,
|
.Select(t => (t.ApiPlayer, Origin: t.GamePlayer!.Pawn.Value?.AbsOrigin,
|
||||||
t.GamePlayer))
|
t.GamePlayer))
|
||||||
@@ -73,9 +78,6 @@ public class DamageStation(IServiceProvider provider)
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
foreach (var (player, dist, gamePlayer) in playerDists) {
|
foreach (var (player, dist, gamePlayer) in playerDists) {
|
||||||
gamePlayer.EmitSound("Player.DamageFall", null, 0.2f);
|
|
||||||
if (Roles.GetRoles(player).Any(r => r is TraitorRole)) continue;
|
|
||||||
|
|
||||||
var healthScale = 1.0 - dist / _Config.MaxRange;
|
var healthScale = 1.0 - dist / _Config.MaxRange;
|
||||||
var damageAmount =
|
var damageAmount =
|
||||||
(int)Math.Floor(_Config.HealthIncrements * healthScale);
|
(int)Math.Floor(_Config.HealthIncrements * healthScale);
|
||||||
@@ -95,6 +97,7 @@ public class DamageStation(IServiceProvider provider)
|
|||||||
bus.Dispatch(playerDeath);
|
bus.Dispatch(playerDeath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gamePlayer.EmitSound("Player.DamageFall", SELF(gamePlayer.Slot), 0.2f);
|
||||||
player.Health += damageAmount;
|
player.Health += damageAmount;
|
||||||
info.HealthGiven += damageAmount;
|
info.HealthGiven += damageAmount;
|
||||||
}
|
}
|
||||||
@@ -103,6 +106,10 @@ public class DamageStation(IServiceProvider provider)
|
|||||||
foreach (var prop in toRemove) props.Remove(prop);
|
foreach (var prop in toRemove) props.Remove(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static RecipientFilter SELF(int slot) {
|
||||||
|
return new RecipientFilter(slot);
|
||||||
|
}
|
||||||
|
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
[EventHandler]
|
[EventHandler]
|
||||||
public void OnGameEnd(GameStateUpdateEvent ev) {
|
public void OnGameEnd(GameStateUpdateEvent ev) {
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public class BodyPickupListener(IServiceProvider provider)
|
|||||||
if (ev.Player is not IOnlinePlayer online)
|
if (ev.Player is not IOnlinePlayer online)
|
||||||
throw new InvalidOperationException("Player is not an online player.");
|
throw new InvalidOperationException("Player is not an online player.");
|
||||||
|
|
||||||
|
if (ev.Player.Id == body.OfPlayer.Id) return;
|
||||||
|
|
||||||
var identifyEvent = new BodyIdentifyEvent(body, online);
|
var identifyEvent = new BodyIdentifyEvent(body, online);
|
||||||
|
|
||||||
Bus.Dispatch(identifyEvent);
|
Bus.Dispatch(identifyEvent);
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ public record TTTConfig {
|
|||||||
public Func<int, int> TraitorCount { get; init; } =
|
public Func<int, int> TraitorCount { get; init; } =
|
||||||
p => (int)Math.Ceiling((p - 1) / 5f);
|
p => (int)Math.Ceiling((p - 1) / 5f);
|
||||||
|
|
||||||
public Func<int, int> DetectiveCount { get; init; } =
|
public Func<int, int> DetectiveCount { get; init; } = p
|
||||||
p => (int)Math.Floor(p / 8f);
|
=> (int)Math.Ceiling(Math.Floor(p / 8f) / 1.5f);
|
||||||
|
|
||||||
public Func<int, int> InnocentCount { get; init; } = p
|
public Func<int, int> InnocentCount { get; init; } = p
|
||||||
=> p - (int)Math.Ceiling((p - 1) / 5f) - (int)Math.Floor(p / 8f);
|
=> p - (int)Math.Ceiling((p - 1) / 5f)
|
||||||
|
- (int)Math.Ceiling(Math.Floor(p / 8f) / 1.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public record RoleConfig {
|
public record RoleConfig {
|
||||||
|
|||||||
@@ -74,6 +74,12 @@ public class ListCommand(IServiceProvider provider) : ICommand, IItemSorter {
|
|||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void InvalidateOrder(IOnlinePlayer? player) {
|
||||||
|
if (player == null) return;
|
||||||
|
cache.Remove(player.Id);
|
||||||
|
lastUpdate.Remove(player.Id);
|
||||||
|
}
|
||||||
|
|
||||||
private List<IShopItem> calculateSortedItems(IOnlinePlayer? player) {
|
private List<IShopItem> calculateSortedItems(IOnlinePlayer? player) {
|
||||||
var items = new List<IShopItem>(shop.Items).Where(item
|
var items = new List<IShopItem>(shop.Items).Where(item
|
||||||
=> player == null
|
=> player == null
|
||||||
|
|||||||
@@ -72,4 +72,8 @@ public class ShopCommand(IServiceProvider provider) : ICommand, IItemSorter {
|
|||||||
public DateTime? GetLastUpdate(IOnlinePlayer? player) {
|
public DateTime? GetLastUpdate(IOnlinePlayer? player) {
|
||||||
return listCmd.GetLastUpdate(player);
|
return listCmd.GetLastUpdate(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void InvalidateOrder(IOnlinePlayer? player) {
|
||||||
|
listCmd.InvalidateOrder(player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ using System.Drawing;
|
|||||||
namespace ShopAPI.Configs;
|
namespace ShopAPI.Configs;
|
||||||
|
|
||||||
public record BodyPaintConfig : ShopItemConfig {
|
public record BodyPaintConfig : ShopItemConfig {
|
||||||
public override int Price { get; init; } = 40;
|
public override int Price { get; init; } = 30;
|
||||||
public int MaxUses { get; init; } = 4;
|
public int MaxUses { get; init; } = 4;
|
||||||
public Color ColorToApply { get; init; } = Color.GreenYellow;
|
public Color ColorToApply { get; init; } = Color.GreenYellow;
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
namespace ShopAPI.Configs.Traitor;
|
namespace ShopAPI.Configs.Traitor;
|
||||||
|
|
||||||
public record CompassConfig : ShopItemConfig {
|
public record CompassConfig : ShopItemConfig {
|
||||||
public override int Price { get; init; } = 70;
|
public override int Price { get; init; } = 60;
|
||||||
public float MaxRange { get; init; } = 10000;
|
public float MaxRange { get; init; } = 10000;
|
||||||
public float CompassFOV { get; init; } = 120;
|
public float CompassFOV { get; init; } = 120;
|
||||||
public int CompassLength { get; init; } = 64;
|
public int CompassLength { get; init; } = 64;
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ namespace ShopAPI;
|
|||||||
public interface IItemSorter {
|
public interface IItemSorter {
|
||||||
List<IShopItem> GetSortedItems(IOnlinePlayer? player, bool refresh = false);
|
List<IShopItem> GetSortedItems(IOnlinePlayer? player, bool refresh = false);
|
||||||
DateTime? GetLastUpdate(IOnlinePlayer? player);
|
DateTime? GetLastUpdate(IOnlinePlayer? player);
|
||||||
|
void InvalidateOrder(IOnlinePlayer? player);
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using SpecialRound.lang;
|
using SpecialRound.lang;
|
||||||
using SpecialRoundAPI;
|
using SpecialRoundAPI;
|
||||||
|
using SpecialRoundAPI.Configs;
|
||||||
using TTT.API.Game;
|
using TTT.API.Game;
|
||||||
using TTT.API.Storage;
|
using TTT.API.Storage;
|
||||||
using TTT.Game.Events.Game;
|
using TTT.Game.Events.Game;
|
||||||
|
|||||||
30
TTT/SpecialRound/Rounds/SilentRound.cs
Normal file
30
TTT/SpecialRound/Rounds/SilentRound.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using SpecialRound.lang;
|
||||||
|
using SpecialRoundAPI;
|
||||||
|
using SpecialRoundAPI.Configs;
|
||||||
|
using TTT.API.Storage;
|
||||||
|
using TTT.Game.Events.Game;
|
||||||
|
using TTT.Locale;
|
||||||
|
|
||||||
|
namespace SpecialRound.Rounds;
|
||||||
|
|
||||||
|
public class SilentRound(IServiceProvider provider)
|
||||||
|
: AbstractSpecialRound(provider) {
|
||||||
|
public override string Name => "Silent";
|
||||||
|
public override IMsg Description => RoundMsgs.SPECIAL_ROUND_SILENT;
|
||||||
|
public override SpecialRoundConfig Config => config;
|
||||||
|
|
||||||
|
private SilentRoundConfig config
|
||||||
|
=> Provider.GetService<IStorage<SilentRoundConfig>>()
|
||||||
|
?.Load()
|
||||||
|
.GetAwaiter()
|
||||||
|
.GetResult() ?? new SilentRoundConfig();
|
||||||
|
|
||||||
|
public override void ApplyRoundEffects() {
|
||||||
|
foreach (var player in Utilities.GetPlayers())
|
||||||
|
player.VoiceFlags |= VoiceFlags.Muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnGameState(GameStateUpdateEvent ev) { }
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ using JetBrains.Annotations;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using SpecialRound.lang;
|
using SpecialRound.lang;
|
||||||
using SpecialRoundAPI;
|
using SpecialRoundAPI;
|
||||||
|
using SpecialRoundAPI.Configs;
|
||||||
using TTT.API.Events;
|
using TTT.API.Events;
|
||||||
using TTT.API.Game;
|
using TTT.API.Game;
|
||||||
using TTT.API.Role;
|
using TTT.API.Role;
|
||||||
@@ -58,6 +59,8 @@ public class SpeedRound(IServiceProvider provider)
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setTime(TimeSpan span) {
|
private void setTime(TimeSpan span) {
|
||||||
|
span = TimeSpan.FromSeconds(Math.Min(span.TotalSeconds,
|
||||||
|
config.MaxTimeEver.TotalSeconds));
|
||||||
Server.NextWorldUpdate(() => {
|
Server.NextWorldUpdate(() => {
|
||||||
RoundUtil.SetTimeRemaining((int)span.TotalSeconds);
|
RoundUtil.SetTimeRemaining((int)span.TotalSeconds);
|
||||||
});
|
});
|
||||||
|
|||||||
61
TTT/SpecialRound/Rounds/SuppressedRound.cs
Normal file
61
TTT/SpecialRound/Rounds/SuppressedRound.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using CounterStrikeSharp.API;
|
||||||
|
using CounterStrikeSharp.API.Core;
|
||||||
|
using CounterStrikeSharp.API.Modules.UserMessages;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using SpecialRound.lang;
|
||||||
|
using SpecialRoundAPI;
|
||||||
|
using SpecialRoundAPI.Configs;
|
||||||
|
using TTT.API;
|
||||||
|
using TTT.API.Game;
|
||||||
|
using TTT.API.Storage;
|
||||||
|
using TTT.Game.Events.Game;
|
||||||
|
using TTT.Locale;
|
||||||
|
|
||||||
|
namespace SpecialRound.Rounds;
|
||||||
|
|
||||||
|
public class SuppressedRound(IServiceProvider provider)
|
||||||
|
: AbstractSpecialRound(provider), IPluginModule {
|
||||||
|
public override string Name => "Suppressed";
|
||||||
|
public override IMsg Description => RoundMsgs.SPECIAL_ROUND_SUPPRESSED;
|
||||||
|
public override SpecialRoundConfig Config => config;
|
||||||
|
private BasePlugin? plugin;
|
||||||
|
|
||||||
|
private SuppressedRoundConfig config
|
||||||
|
=> Provider.GetService<IStorage<SuppressedRoundConfig>>()
|
||||||
|
?.Load()
|
||||||
|
.GetAwaiter()
|
||||||
|
.GetResult() ?? new SuppressedRoundConfig();
|
||||||
|
|
||||||
|
public void Start(BasePlugin? newPlugin) { plugin ??= newPlugin; }
|
||||||
|
|
||||||
|
public override void ApplyRoundEffects() {
|
||||||
|
plugin?.HookUserMessage(452, onWeaponSound);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly HashSet<uint> silencedWeapons = new() {
|
||||||
|
1, // deagle
|
||||||
|
2, // dual berettas
|
||||||
|
3, // five seven
|
||||||
|
30, // tec9
|
||||||
|
32, // p2000
|
||||||
|
36, // p250
|
||||||
|
4, // glock
|
||||||
|
61, // usp-s
|
||||||
|
63, // cz75 auto
|
||||||
|
64 // r8 revolver
|
||||||
|
};
|
||||||
|
|
||||||
|
private HookResult onWeaponSound(UserMessage msg) {
|
||||||
|
var defIndex = msg.ReadUInt("item_def_index");
|
||||||
|
|
||||||
|
if (!silencedWeapons.Contains(defIndex)) return HookResult.Continue;
|
||||||
|
|
||||||
|
msg.Recipients.Clear();
|
||||||
|
return HookResult.Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnGameState(GameStateUpdateEvent ev) {
|
||||||
|
if (ev.NewState != State.FINISHED) return;
|
||||||
|
plugin?.UnhookUserMessage(452, onWeaponSound);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using ShopAPI.Events;
|
using ShopAPI.Events;
|
||||||
using SpecialRound.lang;
|
using SpecialRound.lang;
|
||||||
using SpecialRoundAPI;
|
using SpecialRoundAPI;
|
||||||
|
using SpecialRoundAPI.Configs;
|
||||||
using TTT.API.Events;
|
using TTT.API.Events;
|
||||||
using TTT.API.Messages;
|
using TTT.API.Messages;
|
||||||
using TTT.API.Storage;
|
using TTT.API.Storage;
|
||||||
|
|||||||
@@ -13,5 +13,7 @@ public static class SpecialRoundCollection {
|
|||||||
services.AddModBehavior<SpeedRound>();
|
services.AddModBehavior<SpeedRound>();
|
||||||
services.AddModBehavior<BhopRound>();
|
services.AddModBehavior<BhopRound>();
|
||||||
services.AddModBehavior<VanillaRound>();
|
services.AddModBehavior<VanillaRound>();
|
||||||
|
services.AddModBehavior<SuppressedRound>();
|
||||||
|
services.AddModBehavior<SilentRound>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
public record SpecialRoundsConfig {
|
public record SpecialRoundsConfig {
|
||||||
public int MinRoundsBetweenSpecial { get; init; } = 3;
|
public int MinRoundsBetweenSpecial { get; init; } = 3;
|
||||||
public int MinPlayersForSpecial { get; init; } = 8;
|
public int MinPlayersForSpecial { get; init; } = 5;
|
||||||
public int MinRoundsAfterMapChange { get; init; } = 2;
|
public int MinRoundsAfterMapChange { get; init; } = 2;
|
||||||
public float SpecialRoundChance { get; init; } = 0.2f;
|
public float SpecialRoundChance { get; init; } = 0.2f;
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,12 @@ public class RoundMsgs {
|
|||||||
public static IMsg VANILLA_ROUND_REMINDER
|
public static IMsg VANILLA_ROUND_REMINDER
|
||||||
=> MsgFactory.Create(nameof(VANILLA_ROUND_REMINDER));
|
=> MsgFactory.Create(nameof(VANILLA_ROUND_REMINDER));
|
||||||
|
|
||||||
|
public static IMsg SPECIAL_ROUND_SUPPRESSED
|
||||||
|
=> MsgFactory.Create(nameof(SPECIAL_ROUND_SUPPRESSED));
|
||||||
|
|
||||||
|
public static IMsg SPECIAL_ROUND_SILENT
|
||||||
|
=> MsgFactory.Create(nameof(SPECIAL_ROUND_SILENT));
|
||||||
|
|
||||||
public static IMsg SPECIAL_ROUND_STARTED(AbstractSpecialRound round) {
|
public static IMsg SPECIAL_ROUND_STARTED(AbstractSpecialRound round) {
|
||||||
return MsgFactory.Create(nameof(SPECIAL_ROUND_STARTED), round.Name);
|
return MsgFactory.Create(nameof(SPECIAL_ROUND_STARTED), round.Name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,6 @@
|
|||||||
SPECIAL_ROUND_SPEED: " {yellow}SPEED{grey}: The round is faster than usual! {red}Traitors{grey} must kill to gain more time."
|
SPECIAL_ROUND_SPEED: " {yellow}SPEED{grey}: The round is faster than usual! {red}Traitors{grey} must kill to gain more time."
|
||||||
SPECIAL_ROUND_BHOP: " {Yellow}BHOP{grey}: Bunny hopping is enabled! Hold jump to move faster!"
|
SPECIAL_ROUND_BHOP: " {Yellow}BHOP{grey}: Bunny hopping is enabled! Hold jump to move faster!"
|
||||||
SPECIAL_ROUND_VANILLA: " {green}VANILLA{grey}: The shop has been disabled!"
|
SPECIAL_ROUND_VANILLA: " {green}VANILLA{grey}: The shop has been disabled!"
|
||||||
|
SPECIAL_ROUND_SUPPRESSED: " {grey}SUPPRESSED{grey}: All pistols are silent!"
|
||||||
|
SPECIAL_ROUND_SILENT: " {grey}SILENT{grey}: All players are muted!"
|
||||||
VANILLA_ROUND_REMINDER: "%SHOP_PREFIX%This is a {purple}Vanilla{grey} round. The shop is disabled."
|
VANILLA_ROUND_REMINDER: "%SHOP_PREFIX%This is a {purple}Vanilla{grey} round. The shop is disabled."
|
||||||
@@ -53,10 +53,10 @@ public class RoleAssignerTest(IServiceProvider provider) {
|
|||||||
[InlineData(9, 6, 2, 1)]
|
[InlineData(9, 6, 2, 1)]
|
||||||
[InlineData(10, 7, 2, 1)]
|
[InlineData(10, 7, 2, 1)]
|
||||||
[InlineData(20, 14, 4, 2)]
|
[InlineData(20, 14, 4, 2)]
|
||||||
[InlineData(30, 21, 6, 3)]
|
[InlineData(30, 22, 6, 2)]
|
||||||
[InlineData(32, 21, 7, 4)]
|
[InlineData(32, 22, 7, 3)]
|
||||||
[InlineData(60, 41, 12, 7)]
|
[InlineData(60, 43, 12, 5)]
|
||||||
[InlineData(64, 43, 13, 8)]
|
[InlineData(64, 45, 13, 6)]
|
||||||
public void AssignRole_AssignsBalanced_Roles(int players, int innos,
|
public void AssignRole_AssignsBalanced_Roles(int players, int innos,
|
||||||
int traitors, int detectives) {
|
int traitors, int detectives) {
|
||||||
var playerList = new HashSet<IOnlinePlayer>();
|
var playerList = new HashSet<IOnlinePlayer>();
|
||||||
|
|||||||
Reference in New Issue
Block a user