-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #272 from Schrodinger71/update-felinid
Новые компоненты для фелинидов.
- Loading branch information
Showing
17 changed files
with
510 additions
and
1 deletion.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
Content.Server/ADT/Abilities/Felinid/CoughingUpHairballComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
namespace Content.Server.ADT.Abilities.Felinid; | ||
|
||
[RegisterComponent] | ||
public sealed partial class CoughingUpHairballComponent : Component | ||
{ | ||
[DataField("accumulator")] | ||
public float Accumulator = 0f; | ||
|
||
[DataField("coughUpTime")] | ||
public TimeSpan CoughUpTime = TimeSpan.FromSeconds(2.15); // length of hairball.ogg | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Server.ADT.Abilities.Felinid; | ||
|
||
[RegisterComponent] | ||
public sealed partial class FelinidComponent : Component | ||
{ | ||
/// <summary> | ||
/// The hairball prototype to use. | ||
/// </summary> | ||
[DataField("hairballPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))] | ||
public string HairballPrototype = "Hairball"; | ||
|
||
public EntityUid? HairballAction = null; | ||
|
||
public EntityUid? EatMouse = null; | ||
|
||
public EntityUid? PotentialTarget = null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace Content.Server.ADT.Abilities.Felinid; | ||
|
||
[RegisterComponent] | ||
public sealed partial class FelinidFoodComponent : Component | ||
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
using Content.Server.Actions; | ||
using Content.Shared.Actions; | ||
using Content.Shared.StatusEffect; | ||
using Content.Shared.Throwing; | ||
using Content.Shared.Item; | ||
using Content.Shared.Inventory; | ||
using Content.Shared.Hands; | ||
using Content.Shared.IdentityManagement; | ||
using Content.Shared.Nutrition.Components; | ||
using Content.Shared.Nutrition.EntitySystems; | ||
using Content.Server.Body.Components; | ||
using Content.Server.Medical; | ||
using Content.Server.Nutrition.EntitySystems; | ||
using Content.Server.Popups; | ||
using Content.Shared.ADT.Psionics.Events; | ||
using Content.Shared.Chemistry.EntitySystems; | ||
using Robust.Shared.Audio; | ||
using Robust.Shared.Audio.Systems; | ||
using Robust.Shared.Random; | ||
using Robust.Shared.Prototypes; | ||
using Robust.Shared.Timing; | ||
using Content.Server.Clothing; | ||
|
||
namespace Content.Server.ADT.Abilities.Felinid; | ||
|
||
public sealed class FelinidSystem : EntitySystem | ||
{ | ||
|
||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!; | ||
[Dependency] private readonly HungerSystem _hungerSystem = default!; | ||
[Dependency] private readonly VomitSystem _vomitSystem = default!; | ||
[Dependency] private readonly SolutionContainerSystem _solutionSystem = default!; | ||
[Dependency] private readonly IRobustRandom _robustRandom = default!; | ||
[Dependency] private readonly PopupSystem _popupSystem = default!; | ||
[Dependency] private readonly InventorySystem _inventorySystem = default!; | ||
[Dependency] private readonly ActionsSystem _actions = default!; | ||
[Dependency] private readonly IGameTiming _gameTiming = default!; | ||
[Dependency] private readonly SharedAudioSystem _audio = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
SubscribeLocalEvent<FelinidComponent, ComponentInit>(OnInit); | ||
SubscribeLocalEvent<FelinidComponent, HairballActionEvent>(OnHairball); | ||
SubscribeLocalEvent<FelinidComponent, EatMouseActionEvent>(OnEatMouse); | ||
SubscribeLocalEvent<FelinidComponent, DidEquipHandEvent>(OnEquipped); | ||
SubscribeLocalEvent<FelinidComponent,DidUnequipHandEvent>(OnUnequipped); | ||
SubscribeLocalEvent<HairballComponent, ThrowDoHitEvent>(OnHairballHit); | ||
SubscribeLocalEvent<HairballComponent, GettingPickedUpAttemptEvent>(OnHairballPickupAttempt); | ||
} | ||
|
||
public override void Update(float frameTime) | ||
{ | ||
base.Update(frameTime); | ||
|
||
var query = EntityQueryEnumerator<CoughingUpHairballComponent, FelinidComponent>(); | ||
while (query.MoveNext(out var entityUid, out var hairballComp, out var catComp)) | ||
{ | ||
hairballComp.Accumulator += frameTime; | ||
if (hairballComp.Accumulator < hairballComp.CoughUpTime.TotalSeconds) | ||
continue; | ||
|
||
hairballComp.Accumulator = 0; | ||
SpawnHairball(entityUid, catComp); | ||
RemCompDeferred<CoughingUpHairballComponent>(entityUid); | ||
} | ||
} | ||
|
||
[ValidatePrototypeId<EntityPrototype>] private const string ActionHairball = "ActionHairball"; | ||
[ValidatePrototypeId<EntityPrototype>] private const string ActionEatMouse = "ActionEatMouse"; | ||
|
||
private void OnInit(EntityUid uid, FelinidComponent component, ComponentInit args) | ||
{ | ||
_actions.AddAction(uid, ref component.HairballAction, ActionHairball); | ||
|
||
if (_actions.TryGetActionData(component.HairballAction, out var action) && action?.UseDelay != null) | ||
{ | ||
_actions.SetCooldown(component.HairballAction, | ||
_gameTiming.CurTime, _gameTiming.CurTime + (TimeSpan) action?.UseDelay!); | ||
} | ||
} | ||
|
||
private void OnEquipped(EntityUid uid, FelinidComponent component, DidEquipHandEvent args) | ||
{ | ||
if (!HasComp<FelinidFoodComponent>(args.Equipped)) | ||
return; | ||
|
||
component.PotentialTarget = args.Equipped; | ||
|
||
_actions.AddAction(uid, ref component.EatMouse, ActionEatMouse); | ||
} | ||
|
||
private void OnUnequipped(EntityUid uid, FelinidComponent component, DidUnequipHandEvent args) | ||
{ | ||
if (args.Unequipped == component.PotentialTarget) | ||
{ | ||
component.PotentialTarget = null; | ||
|
||
_actions.RemoveAction(uid, component.EatMouse); | ||
} | ||
} | ||
|
||
private static readonly SoundSpecifier HairballPlay = new SoundPathSpecifier("/Audio/ADT/Felinid/hairball.ogg", | ||
AudioParams.Default.WithVariation(0.15f)); | ||
|
||
private void OnHairball(EntityUid uid, FelinidComponent component, HairballActionEvent args) | ||
{ | ||
//if (_inventorySystem.TryGetSlotEntity(uid, "mask", out var maskUid) && | ||
// EntityManager.TryGetComponent<IngestionBlockerComponent>(maskUid, out var blocker) && | ||
// blocker.Enabled) | ||
//{ | ||
// _popupSystem.PopupEntity(Loc.GetString("hairball-mask", ("mask", maskUid)), uid, uid); | ||
// return; | ||
//} | ||
|
||
_popupSystem.PopupEntity(Loc.GetString("hairball-cough", ("name", Identity.Entity(uid, EntityManager))), uid); | ||
_audio.PlayPredicted(HairballPlay, uid, null); | ||
|
||
EnsureComp<CoughingUpHairballComponent>(uid); | ||
args.Handled = true; | ||
} | ||
|
||
private static readonly SoundSpecifier EatMousePlay = new SoundPathSpecifier("/Audio/Items/eatfood.ogg", | ||
AudioParams.Default.WithVariation(0.15f)); | ||
|
||
private void OnEatMouse(EntityUid uid, FelinidComponent component, EatMouseActionEvent args) | ||
{ | ||
if (component.PotentialTarget == null) | ||
return; | ||
|
||
if (!TryComp<HungerComponent>(uid, out var hunger)) | ||
return; | ||
|
||
if (hunger.CurrentThreshold == Shared.Nutrition.Components.HungerThreshold.Overfed) | ||
{ | ||
_popupSystem.PopupEntity(Loc.GetString("food-system-you-cannot-eat-any-more"), uid, uid, Shared.Popups.PopupType.SmallCaution); | ||
return; | ||
} | ||
|
||
//if (_inventorySystem.TryGetSlotEntity(uid, "mask", out var maskUid) && | ||
// EntityManager.TryGetComponent<IngestionBlockerComponent>(maskUid, out var blocker) && | ||
// blocker.Enabled) | ||
//{ | ||
// _popupSystem.PopupEntity(Loc.GetString("hairball-mask", ("mask", maskUid)), uid, uid, Shared.Popups.PopupType.SmallCaution); | ||
// return; | ||
//} | ||
|
||
if (component.HairballAction != null && _actions.TryGetActionData(component.HairballAction, out var skill)) | ||
{ | ||
_actionsSystem.SetCharges(component.HairballAction, skill?.Charges + 1); | ||
_actionsSystem.SetEnabled(component.HairballAction, true); | ||
} | ||
Del(component.PotentialTarget.Value); | ||
component.PotentialTarget = null; | ||
|
||
_audio.PlayPredicted(EatMousePlay, uid, null); | ||
|
||
_hungerSystem.ModifyHunger(uid, 70f, hunger); | ||
|
||
_actions.RemoveAction(uid, component.EatMouse); | ||
} | ||
|
||
private void SpawnHairball(EntityUid uid, FelinidComponent component) | ||
{ | ||
var hairball = EntityManager.SpawnEntity(component.HairballPrototype, Transform(uid).Coordinates); | ||
var hairballComp = Comp<HairballComponent>(hairball); | ||
|
||
if (TryComp<BloodstreamComponent>(uid, out var bloodstream)) | ||
{ | ||
var temp = bloodstream.ChemicalSolution.SplitSolution(20); | ||
|
||
if (_solutionSystem.TryGetSolution(hairball, hairballComp.SolutionName, out var hairballSolution)) | ||
{ | ||
_solutionSystem.TryAddSolution(hairball, hairballSolution, temp); | ||
} | ||
} | ||
} | ||
private void OnHairballHit(EntityUid uid, HairballComponent component, ThrowDoHitEvent args) | ||
{ | ||
if (HasComp<FelinidComponent>(args.Target) || !HasComp<StatusEffectsComponent>(args.Target)) | ||
return; | ||
if (_robustRandom.Prob(0.2f)) | ||
_vomitSystem.Vomit(args.Target); | ||
} | ||
|
||
private void OnHairballPickupAttempt(EntityUid uid, HairballComponent component, GettingPickedUpAttemptEvent args) | ||
{ | ||
if (HasComp<FelinidComponent>(args.User) || !HasComp<StatusEffectsComponent>(args.User)) | ||
return; | ||
|
||
if (_robustRandom.Prob(0.2f)) | ||
{ | ||
_vomitSystem.Vomit(args.User); | ||
args.Cancel(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Content.Server.ADT.Abilities.Felinid; | ||
|
||
[RegisterComponent] | ||
public sealed partial class HairballComponent : Component | ||
{ | ||
public string SolutionName = "hairball"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
//using Content.Server.Actions; | ||
//using Content.Server.Atmos.Components; | ||
//using Content.Server.Atmos.EntitySystems; | ||
//using Content.Server.Body.Components; | ||
//using Content.Server.Body.Systems; | ||
//using Content.Server.Clothing.Components; | ||
//using Content.Server.IdentityManagement; | ||
//using Content.Server.Nutrition.EntitySystems; | ||
//using Content.Server.Popups; | ||
//using Content.Server.VoiceMask; | ||
//using Content.Shared.Actions; | ||
//using Content.Shared.Clothing; | ||
//using Content.Shared.Clothing.Components; | ||
//using Content.Shared.Clothing.EntitySystems; | ||
//using Content.Shared.IdentityManagement.Components; | ||
//using Content.Shared.Inventory; | ||
//using Content.Shared.Inventory.Events; | ||
|
||
//namespace Content.Server.Clothing | ||
//{ | ||
// public sealed class MaskSystem : EntitySystem | ||
// { | ||
// [Dependency] private readonly ActionsSystem _actionSystem = default!; | ||
// [Dependency] private readonly AtmosphereSystem _atmos = default!; | ||
// [Dependency] private readonly InternalsSystem _internals = default!; | ||
// [Dependency] private readonly InventorySystem _inventorySystem = default!; | ||
// [Dependency] private readonly PopupSystem _popupSystem = default!; | ||
// [Dependency] private readonly IdentitySystem _identity = default!; | ||
// [Dependency] private readonly ClothingSystem _clothing = default!; | ||
|
||
// public override void Initialize() | ||
// { | ||
// base.Initialize(); | ||
|
||
// SubscribeLocalEvent<MaskComponent, ToggleMaskEvent>(OnToggleMask); | ||
// SubscribeLocalEvent<MaskComponent, GetItemActionsEvent>(OnGetActions); | ||
// SubscribeLocalEvent<MaskComponent, GotUnequippedEvent>(OnGotUnequipped); | ||
// } | ||
|
||
// private void OnGetActions(EntityUid uid, MaskComponent component, GetItemActionsEvent args) | ||
// { | ||
// if (!args.InHands) | ||
// args.AddAction(ref component.ToggleActionEntity, component.ToggleAction); | ||
// } | ||
|
||
// private void OnToggleMask(Entity<MaskComponent> ent, ref ToggleMaskEvent args) | ||
// { | ||
// var (uid, mask) = ent; | ||
// if (mask.ToggleActionEntity == null) | ||
// return; | ||
|
||
// if (!_inventorySystem.TryGetSlotEntity(args.Performer, "mask", out var existing) || !uid.Equals(existing)) | ||
// return; | ||
|
||
// //mask.IsToggled ^= true; | ||
// //_actionSystem.SetToggled(mask.ToggleActionEntity, mask.IsToggled); | ||
|
||
// // Pulling mask down can change identity, so we want to update that | ||
// _identity.QueueIdentityUpdate(args.Performer); | ||
|
||
// if (mask.IsToggled) | ||
// _popupSystem.PopupEntity(Loc.GetString("action-mask-pull-down-popup-message", ("mask", uid)), args.Performer, args.Performer); | ||
// else | ||
// _popupSystem.PopupEntity(Loc.GetString("action-mask-pull-up-popup-message", ("mask", uid)), args.Performer, args.Performer); | ||
|
||
// ToggleMaskComponents(uid, mask, args.Performer); | ||
// } | ||
|
||
// // set to untoggled when unequipped, so it isn't left in a 'pulled down' state | ||
// private void OnGotUnequipped(EntityUid uid, MaskComponent mask, GotUnequippedEvent args) | ||
// { | ||
// if (mask.ToggleActionEntity == null) | ||
// return; | ||
|
||
// //mask.IsToggled = false; | ||
// //_actionSystem.SetToggled(mask.ToggleActionEntity, mask.IsToggled); | ||
|
||
// ToggleMaskComponents(uid, mask, args.Equipee, true); | ||
// } | ||
|
||
// private void ToggleMaskComponents(EntityUid uid, MaskComponent mask, EntityUid wearer, bool isEquip = false) | ||
// { | ||
// // toggle visuals | ||
// if (TryComp<ClothingComponent>(uid, out var clothing)) | ||
// { | ||
// //TODO: sprites for 'pulled down' state. defaults to invisible due to no sprite with this prefix | ||
// _clothing.SetEquippedPrefix(uid, mask.IsToggled ? "toggled" : null, clothing); | ||
// } | ||
|
||
// // shouldn't this be an event? | ||
|
||
// // toggle ingestion blocking | ||
// if (TryComp<IngestionBlockerComponent>(uid, out var blocker)) | ||
// blocker.Enabled = !mask.IsToggled; | ||
|
||
// // toggle identity | ||
// if (TryComp<IdentityBlockerComponent>(uid, out var identity)) | ||
// identity.Enabled = !mask.IsToggled; | ||
|
||
// // toggle voice masking | ||
// if (TryComp<VoiceMaskComponent>(wearer, out var voiceMask)) | ||
// voiceMask.Enabled = !mask.IsToggled; | ||
|
||
// // toggle breath tool connection (skip during equip since that is handled in LungSystem) | ||
// if (isEquip || !TryComp<BreathToolComponent>(uid, out var breathTool)) | ||
// return; | ||
|
||
// if (mask.IsToggled) | ||
// { | ||
// _atmos.DisconnectInternals(breathTool); | ||
// } | ||
// else | ||
// { | ||
// breathTool.IsFunctional = true; | ||
|
||
// if (TryComp(wearer, out InternalsComponent? internals)) | ||
// { | ||
// breathTool.ConnectedInternalsEntity = wearer; | ||
// _internals.ConnectBreathTool((wearer, internals), uid); | ||
// } | ||
// } | ||
// } | ||
// } | ||
//} |
Oops, something went wrong.