[Feature] Экспериментальный телепортер синдиката (#250)

* add: experimental syndicate teleporter

* randomvector method

* fix

* check mob attempt 1

* revert

* add check for pull

* new charge system

* changes

* changes

* small fix
This commit is contained in:
CaypenNow
2024-04-01 13:51:50 +05:00
committed by GitHub
parent 2d7b061365
commit 35a354b55a
12 changed files with 407 additions and 0 deletions

View File

@@ -0,0 +1,169 @@
using System.Linq;
using System.Numerics;
using Content.Server._White.Other;
using Content.Server.Body.Systems;
using Content.Server.Popups;
using Content.Server.Pulling;
using Content.Shared.Coordinates.Helpers;
using Content.Shared.Examine;
using Content.Shared.Interaction.Events;
using Content.Shared.Maps;
using Content.Shared.Popups;
using Content.Shared.Pulling.Components;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server._White.ExperimentalSyndicateTeleporter;
public sealed class ExperimentalSyndicateTeleporter : EntitySystem
{
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly BodySystem _bodySystem = default!;
[Dependency] private readonly MapSystem _mapSystem = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly PullingSystem _pullingSystem = default!;
[Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ExperimentalSyndicateTeleporterComponent, UseInHandEvent>(OnUse);
SubscribeLocalEvent<ExperimentalSyndicateTeleporterComponent, ExaminedEvent>(OnExamine);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<ExperimentalSyndicateTeleporterComponent>();
while (query.MoveNext(out var component))
{
if (component.Uses >= 4)
continue;
component.ChargeCooldown += _timing.FrameTime;
if (component.ChargeCooldown <= component.NextRechargeAttempt)
continue;
if (_random.Next(0, 10) != 0)
{
component.ChargeCooldown = TimeSpan.Zero;
continue;
}
component.Uses++;
}
}
private void OnUse(EntityUid uid, ExperimentalSyndicateTeleporterComponent component, UseInHandEvent args)
{
if (component.Uses <= 0)
{
_popupSystem.PopupEntity(Loc.GetString("experimental-syndicate-teleporter-end-uses"), args.User, args.User, PopupType.Medium);
return;
}
if (component.NextUse > _timing.CurTime)
{
_popupSystem.PopupEntity(Loc.GetString("experimental-syndicate-teleporter-cooldown"), args.User, args.User, PopupType.Medium);
return;
}
if (!TryComp<TransformComponent>(args.User, out var xform))
return;
if (TryComp<SharedPullableComponent>(args.User, out var pullable) && pullable.BeingPulled)
{
_pullingSystem.TryStopPull(pullable);
}
if (TryComp<SharedPullerComponent>(args.User, out var pulling)
&& pulling.Pulling != null &&
TryComp<SharedPullableComponent>(pulling.Pulling.Value, out var subjectPulling))
{
_pullingSystem.TryStopPull(subjectPulling);
}
var oldCoords = xform.Coordinates;
var random = _random.Next(component.MinTeleportRange, component.MaxTeleportRange);
var offset = xform.LocalRotation.ToWorldVec().Normalized();
var direction = xform.LocalRotation.GetDir().ToVec();
var newOffset = offset + direction * random;
var coords = xform.Coordinates.Offset(newOffset).SnapToGrid(EntityManager);
if (TryCheckWall(coords))
{
EmergencyTeleportation(args.User, xform, component, oldCoords);
return;
}
SoundAndEffects(component, coords, oldCoords);
_transform.SetCoordinates(args.User, coords);
component.Uses--;
component.NextUse = _timing.CurTime + component.Cooldown;
}
private void OnExamine(EntityUid uid, ExperimentalSyndicateTeleporterComponent component, ExaminedEvent args)
{
args.PushMarkup(Loc.GetString("experimental-syndicate-teleporter-examine", ("uses", component.Uses)));
}
private void EmergencyTeleportation(EntityUid uid, TransformComponent xform, ExperimentalSyndicateTeleporterComponent component, EntityCoordinates oldCoords)
{
var offset = xform.LocalRotation.ToWorldVec().Normalized();
var newOffset = offset + VectorRandomDirection(component, offset, component.EmergencyLength);
var coords = xform.Coordinates.Offset(newOffset).SnapToGrid(EntityManager);
SoundAndEffects(component, coords, oldCoords);
_transform.SetCoordinates(uid, coords);
component.Uses--;
component.NextUse = _timing.CurTime + component.Cooldown;
if (TryCheckWall(coords))
{
_bodySystem.GibBody(uid, true, splatModifier: 3F);
}
}
private void SoundAndEffects(ExperimentalSyndicateTeleporterComponent component, EntityCoordinates coords, EntityCoordinates oldCoords)
{
_audio.PlayPvs(component.TeleportSound, coords);
_audio.PlayPvs(component.TeleportSound, oldCoords);
_entManager.SpawnEntity(component.ExpSyndicateTeleportInEffect, coords);
_entManager.SpawnEntity(component.ExpSyndicateTeleportOutEffect, oldCoords);
}
private bool TryCheckWall(EntityCoordinates coords)
{
if (!coords.TryGetTileRef(out var tile))
return false;
if (!TryComp<MapGridComponent>(tile.Value.GridUid, out var mapGridComponent))
return false;
var anchoredEntities = _mapSystem.GetAnchoredEntities(tile.Value.GridUid, mapGridComponent, coords);
return anchoredEntities.Any(HasComp<WallMarkComponent>);
}
private Vector2 VectorRandomDirection(ExperimentalSyndicateTeleporterComponent component, Vector2 offset, int length)
{
var randomRotation = _random.Next(0, component.RandomRotations.Count);
return Angle.FromDegrees(component.RandomRotations[randomRotation]).RotateVec(offset.Normalized() * length);
}
}

View File

@@ -0,0 +1,45 @@
using System.Numerics;
using System.Threading;
using Robust.Shared.Audio;
namespace Content.Server._White.ExperimentalSyndicateTeleporter;
[RegisterComponent]
public sealed partial class ExperimentalSyndicateTeleporterComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public int Uses = 4;
[ViewVariables(VVAccess.ReadWrite)]
public int MinTeleportRange = 3;
[ViewVariables(VVAccess.ReadWrite)]
public int MaxTeleportRange = 8;
[ViewVariables(VVAccess.ReadWrite)]
public int EmergencyLength = 3;
[ViewVariables(VVAccess.ReadWrite)]
public List<int> RandomRotations = new() {90, -90};
[ViewVariables(VVAccess.ReadOnly)]
public string? ExpSyndicateTeleportInEffect = "ExpSyndicateTeleporterInEffect";
[ViewVariables(VVAccess.ReadOnly)]
public string? ExpSyndicateTeleportOutEffect = "ExpSyndicateTeleporterOutEffect";
[ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier TeleportSound = new SoundPathSpecifier("/Audio/White/Devices/expsyndicateteleport.ogg");
[ViewVariables(VVAccess.ReadWrite)]
public TimeSpan Cooldown = TimeSpan.FromSeconds(5);
[ViewVariables(VVAccess.ReadOnly)]
public TimeSpan NextUse = TimeSpan.Zero;
[ViewVariables(VVAccess.ReadOnly)]
public TimeSpan NextRechargeAttempt = TimeSpan.FromSeconds(1);
[ViewVariables(VVAccess.ReadOnly)]
public TimeSpan ChargeCooldown = TimeSpan.Zero;
}