Skip to content

Commit

Permalink
Merge pull request #147 from Evgencheg/master
Browse files Browse the repository at this point in the history
фиксы и апстрим
  • Loading branch information
Evgencheg authored Sep 16, 2024
2 parents b7af1fc + 9a22fd0 commit 0ff10b2
Show file tree
Hide file tree
Showing 43 changed files with 883 additions and 36 deletions.
40 changes: 40 additions & 0 deletions Content.Client/Flight/Components/FlightVisualsComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Robust.Client.Graphics;
using Robust.Shared.GameStates;

namespace Content.Client.Flight.Components;

[RegisterComponent]
public sealed partial class FlightVisualsComponent : Component
{
/// <summary>
/// How long does the animation last
/// </summary>
[DataField]
public float Speed;

/// <summary>
/// How far it goes in any direction.
/// </summary>
[DataField]
public float Multiplier;

/// <summary>
/// How much the limbs (if there are any) rotate.
/// </summary>
[DataField]
public float Offset;

/// <summary>
/// Are we animating layers or the entire sprite?
/// </summary>
public bool AnimateLayer = false;
public int? TargetLayer;

[DataField]
public string AnimationKey = "default";

[ViewVariables(VVAccess.ReadWrite)]
public ShaderInstance Shader = default!;


}
67 changes: 67 additions & 0 deletions Content.Client/Flight/FlightSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Robust.Client.GameObjects;
using Content.Shared.Flight;
using Content.Shared.Flight.Events;
using Content.Client.Flight.Components;

namespace Content.Client.Flight;
public sealed class FlightSystem : SharedFlightSystem
{
[Dependency] private readonly IEntityManager _entityManager = default!;
public override void Initialize()
{
base.Initialize();

SubscribeNetworkEvent<FlightEvent>(OnFlight);

}

private void OnFlight(FlightEvent args)
{
var uid = GetEntity(args.Uid);
if (!_entityManager.TryGetComponent(uid, out SpriteComponent? sprite)
|| !args.IsAnimated
|| !_entityManager.TryGetComponent(uid, out FlightComponent? flight))
return;


int? targetLayer = null;
if (flight.IsLayerAnimated && flight.Layer is not null)
{
targetLayer = GetAnimatedLayer(uid, flight.Layer, sprite);
if (targetLayer == null)
return;
}

if (args.IsFlying && args.IsAnimated && flight.AnimationKey != "default")
{
var comp = new FlightVisualsComponent
{
AnimateLayer = flight.IsLayerAnimated,
AnimationKey = flight.AnimationKey,
Multiplier = flight.ShaderMultiplier,
Offset = flight.ShaderOffset,
Speed = flight.ShaderSpeed,
TargetLayer = targetLayer,
};
AddComp(uid, comp);
}
if (!args.IsFlying)
RemComp<FlightVisualsComponent>(uid);
}

public int? GetAnimatedLayer(EntityUid uid, string targetLayer, SpriteComponent? sprite = null)
{
if (!Resolve(uid, ref sprite))
return null;

int index = 0;
foreach (var layer in sprite.AllLayers)
{
// This feels like absolute shitcode, isn't there a better way to check for it?
if (layer.Rsi?.Path.ToString() == targetLayer)
return index;
index++;
}
return null;
}
}
64 changes: 64 additions & 0 deletions Content.Client/Flight/FlyingVisualizerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Content.Client.Flight.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Prototypes;

namespace Content.Client.Flight;

/// <summary>
/// Handles offsetting an entity while flying
/// </summary>
public sealed class FlyingVisualizerSystem : EntitySystem
{
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly SpriteSystem _spriteSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<FlightVisualsComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<FlightVisualsComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<FlightVisualsComponent, BeforePostShaderRenderEvent>(OnBeforeShaderPost);
}

private void OnStartup(EntityUid uid, FlightVisualsComponent comp, ComponentStartup args)
{
comp.Shader = _protoMan.Index<ShaderPrototype>(comp.AnimationKey).InstanceUnique();
AddShader(uid, comp.Shader, comp.AnimateLayer, comp.TargetLayer);
SetValues(comp, comp.Speed, comp.Offset, comp.Multiplier);
}

private void OnShutdown(EntityUid uid, FlightVisualsComponent comp, ComponentShutdown args)
{
AddShader(uid, null, comp.AnimateLayer, comp.TargetLayer);
}

private void AddShader(Entity<SpriteComponent?> entity, ShaderInstance? shader, bool animateLayer, int? layer)
{
if (!Resolve(entity, ref entity.Comp, false))
return;

if (!animateLayer)
entity.Comp.PostShader = shader;

if (animateLayer && layer is not null)
entity.Comp.LayerSetShader(layer.Value, shader);

entity.Comp.GetScreenTexture = shader is not null;
entity.Comp.RaiseShaderEvent = shader is not null;
}

/// <summary>
/// This function can be used to modify the shader's values while its running.
/// </summary>
private void OnBeforeShaderPost(EntityUid uid, FlightVisualsComponent comp, ref BeforePostShaderRenderEvent args)
{
SetValues(comp, comp.Speed, comp.Offset, comp.Multiplier);
}

private void SetValues(FlightVisualsComponent comp, float speed, float offset, float multiplier)
{
comp.Shader.SetParameter("Speed", speed);
comp.Shader.SetParameter("Offset", offset);
comp.Shader.SetParameter("Multiplier", multiplier);
}
}
158 changes: 158 additions & 0 deletions Content.Server/Flight/FlightSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@

using Content.Shared.Cuffs.Components;
using Content.Shared.Damage.Components;
using Content.Shared.DoAfter;
using Content.Shared.Flight;
using Content.Shared.Flight.Events;
using Content.Shared.Mobs;
using Content.Shared.Popups;
using Content.Shared.Stunnable;
using Content.Shared.Zombies;
using Robust.Shared.Audio.Systems;

namespace Content.Server.Flight;
public sealed class FlightSystem : SharedFlightSystem
{
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<FlightComponent, ToggleFlightEvent>(OnToggleFlight);
SubscribeLocalEvent<FlightComponent, FlightDoAfterEvent>(OnFlightDoAfter);
SubscribeLocalEvent<FlightComponent, MobStateChangedEvent>(OnMobStateChangedEvent);
SubscribeLocalEvent<FlightComponent, EntityZombifiedEvent>(OnZombified);
SubscribeLocalEvent<FlightComponent, KnockedDownEvent>(OnKnockedDown);
SubscribeLocalEvent<FlightComponent, StunnedEvent>(OnStunned);
SubscribeLocalEvent<FlightComponent, SleepStateChangedEvent>(OnSleep);
}
public override void Update(float frameTime)
{
base.Update(frameTime);

var query = EntityQueryEnumerator<FlightComponent>();
while (query.MoveNext(out var uid, out var component))
{
if (!component.On)
continue;

component.TimeUntilFlap -= frameTime;

if (component.TimeUntilFlap > 0f)
continue;

_audio.PlayPvs(component.FlapSound, uid);
component.TimeUntilFlap = component.FlapInterval;

}
}

#region Core Functions
private void OnToggleFlight(EntityUid uid, FlightComponent component, ToggleFlightEvent args)
{
// If the user isnt flying, we check for conditionals and initiate a doafter.
if (!component.On)
{
if (!CanFly(uid, component))
return;

var doAfterArgs = new DoAfterArgs(EntityManager,
uid, component.ActivationDelay,
new FlightDoAfterEvent(), uid, target: uid)
{
BlockDuplicate = true,
BreakOnTargetMove = true,
BreakOnUserMove = true,
BreakOnDamage = true,
NeedHand = true
};

if (!_doAfter.TryStartDoAfter(doAfterArgs))
return;
}
else
ToggleActive(uid, false, component);
}

private void OnFlightDoAfter(EntityUid uid, FlightComponent component, FlightDoAfterEvent args)
{
if (args.Handled || args.Cancelled)
return;

ToggleActive(uid, true, component);
args.Handled = true;
}

#endregion

#region Conditionals

private bool CanFly(EntityUid uid, FlightComponent component)
{
if (TryComp<CuffableComponent>(uid, out var cuffableComp) && !cuffableComp.CanStillInteract)
{
_popupSystem.PopupEntity(Loc.GetString("no-flight-while-restrained"), uid, uid, PopupType.Medium);
return false;
}

if (HasComp<ZombieComponent>(uid))
{
_popupSystem.PopupEntity(Loc.GetString("no-flight-while-zombified"), uid, uid, PopupType.Medium);
return false;
}
return true;
}

private void OnMobStateChangedEvent(EntityUid uid, FlightComponent component, MobStateChangedEvent args)
{
if (!component.On
|| args.NewMobState is MobState.Critical or MobState.Dead)
return;

ToggleActive(args.Target, false, component);
}

private void OnZombified(EntityUid uid, FlightComponent component, ref EntityZombifiedEvent args)
{
if (!component.On)
return;

ToggleActive(args.Target, false, component);
if (!TryComp<StaminaComponent>(uid, out var stamina))
return;
Dirty(uid, stamina);
}

private void OnKnockedDown(EntityUid uid, FlightComponent component, ref KnockedDownEvent args)
{
if (!component.On)
return;

ToggleActive(uid, false, component);
}

private void OnStunned(EntityUid uid, FlightComponent component, ref StunnedEvent args)
{
if (!component.On)
return;

ToggleActive(uid, false, component);
}

private void OnSleep(EntityUid uid, FlightComponent component, ref SleepStateChangedEvent args)
{
if (!component.On
|| !args.FellAsleep)
return;

ToggleActive(uid, false, component);
if (!TryComp<StaminaComponent>(uid, out var stamina))
return;

Dirty(uid, stamina);
}
#endregion
}
10 changes: 9 additions & 1 deletion Content.Shared/Cuffs/SharedCuffableSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Content.Shared.Contests;
using Content.Shared.Cuffs.Components;
using Content.Shared.Database;
using Content.Shared.Flight;
using Content.Shared.DoAfter;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
Expand Down Expand Up @@ -479,6 +480,13 @@ public bool TryCuffing(EntityUid user, EntityUid target, EntityUid handcuff, Han
return true;
}

if (TryComp<FlightComponent>(target, out var flight) && flight.On)
{
_popup.PopupClient(Loc.GetString("handcuff-component-target-flying-error",
("targetName", Identity.Name(target, EntityManager, user))), user, user);
return true;
}

var cuffTime = handcuffComponent.CuffTime;

if (HasComp<StunnedComponent>(target))
Expand Down Expand Up @@ -731,4 +739,4 @@ private sealed partial class AddCuffDoAfterEvent : SimpleDoAfterEvent
{
}
}
}
}
9 changes: 8 additions & 1 deletion Content.Shared/Damage/Components/StaminaComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ public sealed partial class StaminaComponent : Component
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public float CritThreshold = 100f;

/// <summary>
/// A dictionary of active stamina drains, with the key being the source of the drain,
/// DrainRate how much it changes per tick, and ModifiesSpeed if it should slow down the user.
/// </summary>
[DataField, AutoNetworkedField]
public Dictionary<EntityUid, (float DrainRate, bool ModifiesSpeed)> ActiveDrains = new();

/// <summary>
/// How long will this mob be stunned for?
/// </summary>
Expand All @@ -63,4 +70,4 @@ public sealed partial class StaminaComponent : Component
/// </summary>
[DataField, AutoNetworkedField]
public float SlowdownMultiplier = 0.75f;
}
}
Loading

0 comments on commit 0ff10b2

Please sign in to comment.