-
Notifications
You must be signed in to change notification settings - Fork 399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add space ferrets as a midround event #1045
Changes from 20 commits
f341a4a
07c6750
524b1bc
2588150
ddd1218
c039441
95d664d
d56e2df
d11b4d7
9b6c8c2
4219094
f8779fc
ab0245f
be49ffc
04d6d28
f38f97b
b196164
4ddea05
a0a494e
2305f30
28025c9
8457d90
2f4ee71
7bf955e
353057c
1904830
0865d08
993ddf7
36000ff
56b4138
2345cd6
c176c31
577b6cd
eda1502
32d8f2b
18215a2
7bb068b
301fca8
f104fef
6ac2aec
48d02ce
7b50156
6a9ea44
3a0722a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
using Content.Shared.DeltaV.SpaceFerret; | ||
using Robust.Client.Animations; | ||
using Robust.Client.Audio; | ||
using Robust.Client.GameObjects; | ||
using Robust.Shared.Animations; | ||
using Robust.Shared.Audio; | ||
using Robust.Shared.Player; | ||
|
||
namespace Content.Client.DeltaV.SpaceFerret; | ||
|
||
public sealed class CanBackflipSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly AnimationPlayerSystem _animation = default!; | ||
[Dependency] private readonly AudioSystem _audio = default!; | ||
|
||
public const string BackflipKey = "backflip"; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeNetworkEvent<DoABackFlipEvent>(OnBackflipEvent); | ||
} | ||
|
||
public void OnBackflipEvent(DoABackFlipEvent args) | ||
{ | ||
if (!TryGetEntity(args.Actioner, out var uid)) | ||
{ | ||
return; | ||
} | ||
|
||
_animation.Play(uid.Value, new Animation | ||
{ | ||
Length = TimeSpan.FromSeconds(0.66), | ||
AnimationTracks = | ||
{ | ||
new AnimationTrackComponentProperty() | ||
{ | ||
ComponentType = typeof(SpriteComponent), | ||
Property = nameof(SpriteComponent.Rotation), | ||
InterpolationMode = AnimationInterpolationMode.Linear, | ||
KeyFrames = | ||
{ | ||
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(0), 0f), | ||
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(180), 0.33f), | ||
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(360), 0.33f), | ||
} | ||
} | ||
} | ||
}, BackflipKey); | ||
|
||
_audio.PlayEntity(new SoundPathSpecifier(args.SfxSource), Filter.Local(), uid.Value, false); | ||
NullWanderer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using Content.Shared.DeltaV.SpaceFerret; | ||
using Robust.Client.GameObjects; | ||
|
||
namespace Content.Client.DeltaV.SpaceFerret; | ||
|
||
public sealed class CanHibernateSystem : EntitySystem | ||
{ | ||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeNetworkEvent<EntityHasHibernated>(OnHibernateEvent); | ||
} | ||
|
||
public void OnHibernateEvent(EntityHasHibernated args) | ||
{ | ||
if (!TryGetEntity(args.Hibernator, out var uid)) | ||
{ | ||
return; | ||
} | ||
|
||
if (!TryComp<SpriteComponent>(uid, out var comp)) | ||
{ | ||
return; | ||
} | ||
|
||
comp.LayerSetState(0, args.SpriteStateId); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ideally use appearance for this otherwise remove from the event and just use the component directly along with actual validation |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
using Content.Server.DeltaV.SpaceFerret.Systems; | ||
using Content.Shared.Roles; | ||
|
||
namespace Content.Server.DeltaV.SpaceFerret.Components; | ||
|
||
[RegisterComponent, Access(typeof(SpaceFerretSystem)), ExclusiveAntagonist] | ||
public sealed partial class SpaceFerretRoleComponent : AntagonistRoleComponent; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using Content.Server.Actions; | ||
using Content.Shared.DeltaV.SpaceFerret; | ||
|
||
namespace Content.Server.DeltaV.SpaceFerret.Systems; | ||
|
||
public sealed class CanBackflipSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly ActionsSystem _actions = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<CanBackflipComponent, MapInitEvent>(OnInit); | ||
SubscribeLocalEvent<CanBackflipComponent, BackflipActionEvent>(OnBackflipAction); | ||
} | ||
|
||
private void OnInit(EntityUid uid, CanBackflipComponent component, MapInitEvent args) | ||
{ | ||
_actions.AddAction(uid, ref component.BackflipActionEntity, component.BackflipAction, uid); | ||
} | ||
|
||
public void OnBackflipAction(EntityUid uid, CanBackflipComponent comp, BackflipActionEvent args) | ||
{ | ||
RaiseNetworkEvent(new DoABackFlipEvent(GetNetEntity(uid), comp.ClappaSfx)); | ||
NullWanderer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
args.Handled = true; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
using Content.Server.Actions; | ||
using Content.Server.Atmos.Piping.Unary.Components; | ||
using Content.Server.GameTicking; | ||
using Content.Server.Ghost.Roles.Components; | ||
using Content.Server.Popups; | ||
using Content.Shared.DeltaV.SpaceFerret; | ||
using Content.Shared.Interaction.Components; | ||
using Content.Shared.Mind; | ||
using Content.Shared.NPC; | ||
using Content.Shared.Popups; | ||
using Robust.Server.Audio; | ||
using Robust.Shared.Audio; | ||
|
||
namespace Content.Server.DeltaV.SpaceFerret.Systems; | ||
|
||
public sealed class CanHibernateSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly ActionsSystem _actions = default!; | ||
[Dependency] private readonly EntityLookupSystem _lookup = default!; | ||
[Dependency] private readonly PopupSystem _popup = default!; | ||
[Dependency] private readonly SharedMindSystem _mind = default!; | ||
[Dependency] private readonly GameTicker _ticker = default!; | ||
[Dependency] private readonly AudioSystem _audio = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<CanHibernateComponent, MapInitEvent>(OnInit); | ||
SubscribeLocalEvent<CanHibernateComponent, EepyActionEvent>(OnEepyAction); | ||
} | ||
|
||
private void OnInit(EntityUid uid, CanHibernateComponent component, MapInitEvent args) | ||
{ | ||
_actions.AddAction(uid, ref component.EepyActionEntity, component.EepyAction, uid); | ||
} | ||
|
||
public void OnEepyAction(EntityUid uid, CanHibernateComponent comp, EepyActionEvent args) | ||
{ | ||
// If you require food before hibernating, assert that this condition has been fulfilled. | ||
if (_mind.TryGetObjectiveComp<ConsumeNutrientsConditionComponent>(uid, out var nutrientsCondition) && nutrientsCondition.NutrientsConsumed / nutrientsCondition.NutrientsRequired < 1.0) | ||
{ | ||
_popup.PopupEntity(Loc.GetString(comp.NotEnoughNutrientsMessage), uid, PopupType.SmallCaution); | ||
|
||
return; | ||
} | ||
|
||
// Assert that you're near a hibernation point (scrubbers) | ||
var scrubbers = _lookup.GetEntitiesInRange<GasVentScrubberComponent>(Transform(uid).Coordinates, 2f); | ||
if (scrubbers.Count <= 0) | ||
{ | ||
_popup.PopupEntity(Loc.GetString(comp.TooFarFromHibernationSpot), uid, PopupType.SmallCaution); | ||
|
||
return; | ||
} | ||
|
||
if (_mind.TryGetObjectiveComp<HibernateConditionComponent>(uid, out var hibernateCondition)) | ||
{ | ||
_audio.PlayPvs(new SoundPathSpecifier(hibernateCondition.SuccessSfx), uid); | ||
_popup.PopupEntity(Loc.GetString(hibernateCondition.SuccessMessage), uid, PopupType.Large); | ||
hibernateCondition.Hibernated = true; | ||
} | ||
|
||
// Kick player out | ||
var mind = _mind.GetMind(uid); | ||
if (mind != null) | ||
{ | ||
_ticker.OnGhostAttempt(mind.Value, false); | ||
} | ||
|
||
// End ghost-role | ||
AddComp<BlockMovementComponent>(uid); | ||
RemComp<ActiveNPCComponent>(uid); | ||
RemComp<GhostTakeoverAvailableComponent>(uid); | ||
|
||
// Notify | ||
RaiseNetworkEvent(new EntityHasHibernated(GetNetEntity(uid), comp.SpriteStateId)); | ||
NullWanderer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
args.Handled = true; | ||
} | ||
} | ||
|
||
public struct EntityHibernateAttemptSuccessEvent(EntityUid entity) | ||
{ | ||
public EntityUid Entity = entity; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using Content.Shared.DeltaV.SpaceFerret; | ||
using Content.Shared.Objectives.Components; | ||
|
||
namespace Content.Server.DeltaV.SpaceFerret.Systems; | ||
|
||
public sealed class ConsumeNutrientsObjectiveSystem : EntitySystem | ||
{ | ||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<ConsumeNutrientsConditionComponent, ObjectiveGetProgressEvent>(OnConsumeNutrientsGetProgress); | ||
} | ||
|
||
private static void OnConsumeNutrientsGetProgress(EntityUid uid, ConsumeNutrientsConditionComponent comp, ref ObjectiveGetProgressEvent args) | ||
{ | ||
args.Progress = comp.NutrientsConsumed / comp.NutrientsRequired; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using Content.Shared.DeltaV.SpaceFerret; | ||
using Content.Shared.Objectives.Components; | ||
|
||
namespace Content.Server.DeltaV.SpaceFerret.Systems; | ||
|
||
public sealed class HibernateObjectiveSystem : EntitySystem | ||
{ | ||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<HibernateConditionComponent, ObjectiveGetProgressEvent>(OnHibernateGetProgress); | ||
} | ||
|
||
private static void OnHibernateGetProgress(EntityUid uid, HibernateConditionComponent comp, ref ObjectiveGetProgressEvent args) | ||
{ | ||
args.Progress = comp.Hibernated ? 1.0f : 0.0f; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using Content.Server.Chat.Managers; | ||
using Content.Server.DeltaV.SpaceFerret.Components; | ||
using Content.Server.GenericAntag; | ||
using Content.Server.Roles; | ||
using Content.Shared.DeltaV.SpaceFerret; | ||
using Content.Shared.Interaction.Events; | ||
using Content.Shared.Mind; | ||
using Content.Shared.Nutrition; | ||
using Robust.Shared.Audio; | ||
|
||
namespace Content.Server.DeltaV.SpaceFerret.Systems; | ||
|
||
public sealed class SpaceFerretSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly RoleSystem _role = default!; | ||
[Dependency] private readonly IChatManager _chatMan = default!; | ||
[Dependency] private readonly SharedMindSystem _mind = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<SpaceFerretComponent, GenericAntagCreatedEvent>(OnInit); | ||
SubscribeLocalEvent<SpaceFerretComponent, InteractionAttemptFailed>(OnInteractFailed); | ||
SubscribeLocalEvent<SpaceFerretComponent, HungerModifiedEvent>(OnHungerModified); | ||
} | ||
|
||
private void OnInit(EntityUid uid, SpaceFerretComponent component, GenericAntagCreatedEvent args) | ||
{ | ||
var mind = args.Mind; | ||
|
||
if (mind.Session == null) | ||
return; | ||
|
||
var session = mind.Session; | ||
_role.MindAddRole(args.MindId, new RoleBriefingComponent | ||
{ | ||
Briefing = Loc.GetString(component.RoleBriefing) | ||
}, mind); | ||
_role.MindAddRole(args.MindId, new SpaceFerretRoleComponent() | ||
{ | ||
PrototypeId = component.AntagProtoId | ||
}, mind); | ||
_role.MindPlaySound(args.MindId, new SoundPathSpecifier(component.RoleIntroSfx), mind); | ||
_chatMan.DispatchServerMessage(session, Loc.GetString(component.RoleGreeting)); | ||
} | ||
|
||
public void OnInteractFailed(EntityUid uid, SpaceFerretComponent _, InteractionAttemptFailed args) | ||
{ | ||
RaiseLocalEvent(uid, new BackflipActionEvent()); | ||
} | ||
|
||
private void OnHungerModified(EntityUid uid, SpaceFerretComponent comp, HungerModifiedEvent args) | ||
{ | ||
if (_mind.TryGetObjectiveComp<ConsumeNutrientsConditionComponent>(uid, out var nutrientsCondition) && args.Amount > 0) | ||
{ | ||
nutrientsCondition.NutrientsConsumed += args.Amount; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace Content.Shared.Interaction.Events; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. deltav namespace + record struct instead of class |
||
|
||
public sealed class InteractionAttemptFailed(EntityUid target) | ||
{ | ||
public EntityUid Target = target; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace Content.Shared.Nutrition; | ||
|
||
public sealed class HungerModifiedEvent(float amount) : EntityEventArgs | ||
NullWanderer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
public float Amount = amount; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using Content.Shared.Actions; | ||
using Robust.Shared.Prototypes; | ||
using Robust.Shared.Serialization; | ||
|
||
namespace Content.Shared.DeltaV.SpaceFerret; | ||
|
||
[RegisterComponent] | ||
public sealed partial class CanBackflipComponent : Component | ||
{ | ||
[DataField] | ||
public EntProtoId BackflipAction = "ActionBackflip"; | ||
|
||
[DataField] | ||
public EntityUid? BackflipActionEntity; | ||
|
||
[DataField] | ||
NullWanderer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public string ClappaSfx = ""; | ||
} | ||
|
||
public sealed partial class BackflipActionEvent : InstantActionEvent | ||
{ | ||
} | ||
|
||
[Serializable] [NetSerializable] | ||
public sealed class DoABackFlipEvent(NetEntity actioner, string sfxSource) : EntityEventArgs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. from before remove sfxsource There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aren't these supposed to be sealed classes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh you right RaiseNetworkEvent requires it to be a class either way have these events just take NetEntity nothing else |
||
{ | ||
public NetEntity Actioner = actioner; | ||
public string SfxSource = sfxSource; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no validation of any kind here either...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it used to let malf clients play any sound which is Not Good
now it cant do that, also can probably get mob from message session so player cant even spoof the entity of an actual ferret