mirror of
https://github.com/MSWS/TTT.git
synced 2025-12-08 15:27:32 -08:00
Compare commits
3 Commits
1.2.0-dev.
...
1.2.0-dev.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb79552ba3 | ||
|
|
e2011b8d24 | ||
|
|
ec41a6f367 |
@@ -1,5 +1,5 @@
|
||||
namespace SpecialRoundAPI.Configs;
|
||||
|
||||
public record BhopRoundConfig : SpecialRoundConfig {
|
||||
public override float Weight { get; init; } = 0.2f;
|
||||
public override float Weight { get; init; } = 0.25f;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace SpecialRoundAPI.Configs;
|
||||
|
||||
public record PistolRoundConfig : SpecialRoundConfig {
|
||||
public override float Weight { get; init; } = 0.75f;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace SpecialRoundAPI.Configs;
|
||||
|
||||
public record SilentRoundConfig : SpecialRoundConfig {
|
||||
public override float Weight { get; init; } = 0.1f;
|
||||
public override float Weight { get; init; } = 0.5f;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
namespace SpecialRoundAPI.Configs;
|
||||
|
||||
public record SpeedRoundConfig : SpecialRoundConfig {
|
||||
public override float Weight { get; init; } = 0.6f;
|
||||
public override float Weight { get; init; } = 1;
|
||||
|
||||
public TimeSpan InitialSeconds { get; init; } = TimeSpan.FromSeconds(40);
|
||||
public TimeSpan SecondsPerKill { get; init; } = TimeSpan.FromSeconds(10);
|
||||
public TimeSpan SecondsPerKill { get; init; } = TimeSpan.FromSeconds(8);
|
||||
public TimeSpan MaxTimeEver { get; init; } = TimeSpan.FromSeconds(90);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace SpecialRoundAPI.Configs;
|
||||
|
||||
public record SuppressedRoundConfig : SpecialRoundConfig {
|
||||
public override float Weight { get; init; } = 0.3f;
|
||||
public override float Weight { get; init; } = 0.75f;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace SpecialRoundAPI.Configs;
|
||||
|
||||
public record VanillaRoundConfig : SpecialRoundConfig {
|
||||
public override float Weight { get; init; } = 0.2f;
|
||||
public override float Weight { get; init; } = 0.5f;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using System.Drawing;
|
||||
using System.Reactive.Concurrency;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -19,6 +21,7 @@ namespace TTT.CS2.Items.Tripwire;
|
||||
public static class TripwireServiceCollection {
|
||||
public static void AddTripwireServices(this IServiceCollection services) {
|
||||
services.AddModBehavior<TripwireItem>();
|
||||
services.AddModBehavior<TripwireMovementListener>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +29,15 @@ public class TripwireItem(IServiceProvider provider)
|
||||
: RoleRestrictedItem<TraitorRole>(provider), IPluginModule {
|
||||
public override string Name => Locale[TripwireMsgs.SHOP_ITEM_TRIPWIRE];
|
||||
|
||||
private readonly IScheduler scheduler =
|
||||
provider.GetRequiredService<IScheduler>();
|
||||
|
||||
protected readonly IPlayerConverter<CCSPlayerController> converter =
|
||||
provider.GetRequiredService<IPlayerConverter<CCSPlayerController>>();
|
||||
|
||||
public record TripwireInstance(IOnlinePlayer owner, CEnvBeam Beam,
|
||||
CDynamicProp TripwireProp, Vector StartPos, Vector EndPos);
|
||||
|
||||
private TripwireConfig config = provider
|
||||
.GetService<IStorage<TripwireConfig>>()
|
||||
?.Load()
|
||||
@@ -40,6 +49,8 @@ public class TripwireItem(IServiceProvider provider)
|
||||
|
||||
public override ShopItemConfig Config => config;
|
||||
|
||||
public List<TripwireInstance> ActiveTripwires = new();
|
||||
|
||||
public void Start(BasePlugin? plugin) {
|
||||
Start();
|
||||
plugin
|
||||
@@ -87,20 +98,67 @@ public class TripwireItem(IServiceProvider provider)
|
||||
public override void OnPurchase(IOnlinePlayer player) {
|
||||
Server.NextWorldUpdate(() => {
|
||||
var gamePlayer = converter.GetPlayer(player);
|
||||
if (gamePlayer == null) return;
|
||||
var trace = gamePlayer.GetGameTraceByEyePosition(TraceMask.MaskSolid,
|
||||
var playerPawn = gamePlayer?.PlayerPawn.Value;
|
||||
if (gamePlayer == null || playerPawn == null) return;
|
||||
var originTrace =
|
||||
gamePlayer.GetGameTraceByEyePosition(TraceMask.MaskSolid,
|
||||
Contents.NoDraw, gamePlayer);
|
||||
var origin = gamePlayer.GetEyePosition();
|
||||
if (origin == null || originTrace == null) return;
|
||||
|
||||
var angles = vectorToAngle(originTrace.Value.Normal.toVector());
|
||||
|
||||
var endTrace = TraceRay.TraceShape(origin, angles, TraceMask.MaskSolid,
|
||||
Contents.NoDraw, gamePlayer);
|
||||
if (trace == null) return;
|
||||
|
||||
var tripwire = Utilities.CreateEntityByName<CPhysicsProp>("prop_physics");
|
||||
|
||||
var tripwire = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic");
|
||||
if (tripwire == null) return;
|
||||
|
||||
tripwire.SetModel(
|
||||
"models/generic/conveyor_control_panel_01/conveyor_button_02.vmdl");
|
||||
tripwire.DispatchSpawn();
|
||||
|
||||
tripwire.Teleport(trace.Value.EndPos.toVector());
|
||||
tripwire.Teleport(originTrace.Value.EndPos.toVector(),
|
||||
vectorToAngle(originTrace.Value.Normal.toVector()));
|
||||
tripwire.EmitSound("Weapon_ELITE.Clipout");
|
||||
|
||||
scheduler.Schedule(TimeSpan.FromSeconds(2), () => {
|
||||
Server.NextWorldUpdate(() => {
|
||||
if (!gamePlayer.IsValid) return;
|
||||
createBeam(player, tripwire, originTrace.Value.EndPos.toVector(),
|
||||
endTrace.EndPos.toVector());
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void createBeam(IOnlinePlayer owner, CDynamicProp prop, Vector start,
|
||||
Vector end) {
|
||||
prop.EmitSound("C4.ExplodeTriggerTrip");
|
||||
var beam = createBeamEnt(start, end);
|
||||
if (beam == null) return;
|
||||
|
||||
var instance = new TripwireInstance(owner, beam, prop, start, end);
|
||||
ActiveTripwires.Add(instance);
|
||||
}
|
||||
|
||||
private QAngle vectorToAngle(Vector vec) {
|
||||
var pitch = (float)(Math.Atan2(-vec.Z,
|
||||
Math.Sqrt(vec.X * vec.X + vec.Y * vec.Y)) * (180.0 / Math.PI));
|
||||
var yaw = (float)(Math.Atan2(vec.Y, vec.X) * (180.0 / Math.PI));
|
||||
return new QAngle(pitch, yaw, 0);
|
||||
}
|
||||
|
||||
private CEnvBeam? createBeamEnt(Vector start, Vector end) {
|
||||
var beam = Utilities.CreateEntityByName<CEnvBeam>("env_beam");
|
||||
if (beam == null) return null;
|
||||
beam.RenderMode = RenderMode_t.kRenderTransAlpha;
|
||||
beam.Width = 0.5f;
|
||||
beam.Render = Color.FromArgb(128, Color.Red);
|
||||
beam.EndPos.X = end.X;
|
||||
beam.EndPos.Y = end.Y;
|
||||
beam.EndPos.Z = end.Z;
|
||||
beam.Teleport(start);
|
||||
return beam;
|
||||
}
|
||||
}
|
||||
117
TTT/CS2/Items/Tripwire/TripwireMovementListener.cs
Normal file
117
TTT/CS2/Items/Tripwire/TripwireMovementListener.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Timers;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TTT.API;
|
||||
using TTT.API.Events;
|
||||
using TTT.API.Game;
|
||||
using TTT.API.Player;
|
||||
using TTT.CS2.Extensions;
|
||||
using TTT.CS2.RayTrace.Class;
|
||||
using TTT.CS2.RayTrace.Enum;
|
||||
using TTT.CS2.Utils;
|
||||
using TTT.Game.Events.Body;
|
||||
using TTT.Game.Events.Game;
|
||||
using TTT.Game.Events.Player;
|
||||
|
||||
namespace TTT.CS2.Items.Tripwire;
|
||||
|
||||
public class TripwireMovementListener(IServiceProvider provider)
|
||||
: IPluginModule, IListener {
|
||||
private readonly TripwireItem? item = provider.GetService<TripwireItem>();
|
||||
|
||||
private readonly IPlayerFinder finder =
|
||||
provider.GetRequiredService<IPlayerFinder>();
|
||||
|
||||
private readonly IPlayerConverter<CCSPlayerController> converter =
|
||||
provider.GetRequiredService<IPlayerConverter<CCSPlayerController>>();
|
||||
|
||||
private readonly IEventBus bus = provider.GetRequiredService<IEventBus>();
|
||||
|
||||
public void Dispose() { }
|
||||
public void Start() { }
|
||||
|
||||
public void Start(BasePlugin? plugin) {
|
||||
if (item == null) return;
|
||||
plugin?.AddTimer(0.1f, checkTripwires, TimerFlags.REPEAT);
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, TripwireItem.TripwireInstance>
|
||||
killedWithTripwire = new();
|
||||
|
||||
private void checkTripwires() {
|
||||
if (item == null) return;
|
||||
var toRemove = new List<TripwireItem.TripwireInstance>();
|
||||
foreach (var wire in item.ActiveTripwires) {
|
||||
var ray = TraceRay.TraceShape(wire.StartPos, wire.EndPos, Contents.Player,
|
||||
wire.TripwireProp.Handle);
|
||||
if (!ray.DidHit() || !ray.HitPlayer(out _)) continue;
|
||||
|
||||
toRemove.Add(wire);
|
||||
|
||||
wire.TripwireProp.EmitSound("Flashbang.ExplodeDistant");
|
||||
doExplosion(wire);
|
||||
}
|
||||
|
||||
foreach (var wire in toRemove) {
|
||||
item.ActiveTripwires.Remove(wire);
|
||||
wire.Beam.Remove();
|
||||
wire.TripwireProp.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
private void doExplosion(TripwireItem.TripwireInstance instance) {
|
||||
foreach (var player in finder.GetOnline()) {
|
||||
if (!player.IsAlive) continue;
|
||||
var gamePlayer = converter.GetPlayer(player);
|
||||
if (gamePlayer == null || gamePlayer.Pawn.Value == null) continue;
|
||||
if (gamePlayer.Pawn.Value.AbsOrigin == null) continue;
|
||||
|
||||
var distance =
|
||||
instance.StartPos.Distance(gamePlayer.Pawn.Value.AbsOrigin);
|
||||
var damage = (int)Math.Round(getDamage(distance));
|
||||
if (damage < 1) continue;
|
||||
|
||||
if (player.Health - damage <= 0) {
|
||||
killedWithTripwire[player.Id] = instance;
|
||||
var death = new PlayerDeathEvent(player).WithKiller(instance.owner)
|
||||
.WithWeapon("[Tripwire]");
|
||||
bus.Dispatch(death);
|
||||
} else {
|
||||
var damaged =
|
||||
new PlayerDamagedEvent(player, instance.owner, damage) {
|
||||
Weapon = "[Tripwire]"
|
||||
};
|
||||
bus.Dispatch(damaged);
|
||||
}
|
||||
|
||||
player.Health -= damage;
|
||||
gamePlayer.EmitSound("Player.BurnDamage");
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly float fallofDelay = 0.01f;
|
||||
|
||||
private float getDamage(float distance) {
|
||||
return 1000.0f * MathF.Pow(MathF.E, -distance * fallofDelay);
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
[EventHandler]
|
||||
public void OnGameEnd(GameStateUpdateEvent ev) {
|
||||
if (ev.NewState != State.FINISHED) return;
|
||||
|
||||
killedWithTripwire.Clear();
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
[EventHandler]
|
||||
public void OnRagdollSpawn(BodyCreateEvent ev) {
|
||||
if (!killedWithTripwire.TryGetValue(ev.Body.Id, out var info)) return;
|
||||
if (ev.Body.Killer != null && ev.Body.Killer.Id != ev.Body.OfPlayer.Id)
|
||||
return;
|
||||
ev.Body.Killer = info.owner;
|
||||
}
|
||||
}
|
||||
66
TTT/SpecialRound/Rounds/PistolRound.cs
Normal file
66
TTT/SpecialRound/Rounds/PistolRound.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using SpecialRound.lang;
|
||||
using SpecialRoundAPI;
|
||||
using SpecialRoundAPI.Configs;
|
||||
using TTT.API;
|
||||
using TTT.API.Game;
|
||||
using TTT.API.Player;
|
||||
using TTT.API.Storage;
|
||||
using TTT.Game.Events.Game;
|
||||
using TTT.Locale;
|
||||
|
||||
namespace SpecialRound.Rounds;
|
||||
|
||||
public class PistolRound(IServiceProvider provider)
|
||||
: AbstractSpecialRound(provider), IPluginModule {
|
||||
public override string Name => "Pistol";
|
||||
public override IMsg Description => RoundMsgs.SPECIAL_ROUND_PISTOL;
|
||||
private BasePlugin? plugin;
|
||||
|
||||
private PistolRoundConfig config
|
||||
=> Provider.GetService<IStorage<PistolRoundConfig>>()
|
||||
?.Load()
|
||||
.GetAwaiter()
|
||||
.GetResult() ?? new PistolRoundConfig();
|
||||
|
||||
private readonly IInventoryManager inventory = provider
|
||||
.GetRequiredService<IInventoryManager>();
|
||||
|
||||
public override SpecialRoundConfig Config => config;
|
||||
|
||||
public void Start(BasePlugin? newPluing) { plugin = newPluing; }
|
||||
|
||||
public override void ApplyRoundEffects() {
|
||||
VirtualFunctions.CCSPlayer_ItemServices_CanAcquireFunc.Hook(canAcquire,
|
||||
HookMode.Pre);
|
||||
foreach (var player in Finder.GetOnline())
|
||||
inventory.RemoveWeaponInSlot(player, 0);
|
||||
}
|
||||
|
||||
private HookResult canAcquire(DynamicHook hook) {
|
||||
var player = hook.GetParam<CCSPlayer_ItemServices>(0)
|
||||
.Pawn.Value.Controller.Value?.As<CCSPlayerController>();
|
||||
var data = VirtualFunctions.GetCSWeaponDataFromKey.Invoke(-1,
|
||||
hook.GetParam<CEconItemView>(1).ItemDefinitionIndex.ToString());
|
||||
|
||||
if (player == null || !player.IsValid) return HookResult.Continue;
|
||||
|
||||
if (Tag.RIFLES.Contains(data.Name)) {
|
||||
hook.SetReturn(AcquireResult.NotAllowedByMode);
|
||||
return HookResult.Handled;
|
||||
}
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
public override void OnGameState(GameStateUpdateEvent ev) {
|
||||
if (ev.NewState != State.FINISHED) return;
|
||||
|
||||
VirtualFunctions.CCSPlayer_ItemServices_CanAcquireFunc.Unhook(canAcquire,
|
||||
HookMode.Pre);
|
||||
}
|
||||
}
|
||||
@@ -15,5 +15,6 @@ public static class SpecialRoundCollection {
|
||||
services.AddModBehavior<VanillaRound>();
|
||||
services.AddModBehavior<SuppressedRound>();
|
||||
services.AddModBehavior<SilentRound>();
|
||||
services.AddModBehavior<PistolRound>();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,9 @@ public class RoundMsgs {
|
||||
public static IMsg SPECIAL_ROUND_SILENT
|
||||
=> MsgFactory.Create(nameof(SPECIAL_ROUND_SILENT));
|
||||
|
||||
public static IMsg SPECIAL_ROUND_PISTOL
|
||||
=> MsgFactory.Create(nameof(SPECIAL_ROUND_PISTOL));
|
||||
|
||||
public static IMsg SPECIAL_ROUND_STARTED(AbstractSpecialRound round) {
|
||||
return MsgFactory.Create(nameof(SPECIAL_ROUND_STARTED), round.Name);
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@ SPECIAL_ROUND_BHOP: " {Yellow}BHOP{grey}: Bunny hopping is enabled! Hold jump to
|
||||
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!"
|
||||
SPECIAL_ROUND_PISTOL: " {blue}PISTOL{grey}: You can only use pistols this round!"
|
||||
VANILLA_ROUND_REMINDER: "%SHOP_PREFIX%This is a {purple}Vanilla{grey} round. The shop is disabled."
|
||||
Reference in New Issue
Block a user