mirror of
https://github.com/space-wizards/space-station-14.git
synced 2026-06-09 10:06:43 +02:00
Changeling reagent stings (#43805)
* Changeling-Stings * update yml * attempt failed dead * sprite and ChangelingNeurodepressantSting * Update changeling_catalog.yml * merge * update * review * review 2 * clean up, remove non-blind stings * fix stuff * lethal, cryogenic, hallucination + armblade nerf * validate deez * a * review --------- Co-authored-by: ScarKy0 <scarky0@onet.eu> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
using Content.Shared.EntityEffects;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Actions.Components;
|
||||
|
||||
/// <summary>
|
||||
/// An action component that applies a list of entity effects to the target when performed.
|
||||
/// Requires <see cref="EntityTargetActionComponent"/> and <see cref="ActionComponent"/>.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(EntityEffectActionSystem))]
|
||||
public sealed partial class EntityEffectActionComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// List of entity effects to apply to the target when this action is performed.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public List<EntityEffect> Effects = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when an entity effect action is performed.
|
||||
/// </summary>
|
||||
public sealed partial class EntityEffectActionEvent : EntityTargetActionEvent;
|
||||
@@ -0,0 +1,35 @@
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Actions.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Displays a popup message when the action is successfully performed.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(PopupOnActionSystem))]
|
||||
public sealed partial class PopupOnActionComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The locale ID of the message to the performer of the action.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? SelfMessage;
|
||||
|
||||
/// <summary>
|
||||
/// The message to show to those around the performer of the action.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? OthersMessage;
|
||||
|
||||
/// <summary>
|
||||
/// The message to show to the action target.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId? TargetMessage;
|
||||
|
||||
/// <summary>
|
||||
/// The visual style of the popup.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public PopupType PopupType = PopupType.Small;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Content.Shared.Actions.Components;
|
||||
using Content.Shared.EntityEffects;
|
||||
|
||||
namespace Content.Shared.Actions;
|
||||
|
||||
/// <summary>
|
||||
/// Handles applying entity effects when an entity effect action is performed.
|
||||
/// </summary>
|
||||
public sealed partial class EntityEffectActionSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private SharedEntityEffectsSystem _effects = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<EntityEffectActionComponent, EntityEffectActionEvent>(OnEntityEffectAction);
|
||||
}
|
||||
|
||||
private void OnEntityEffectAction(Entity<EntityEffectActionComponent> ent, ref EntityEffectActionEvent args)
|
||||
{
|
||||
foreach (var effect in ent.Comp.Effects)
|
||||
{
|
||||
if (_effects.TryApplyEffect(args.Target, effect, user: args.Performer))
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Content.Shared.Actions.Components;
|
||||
using Content.Shared.Actions.Events;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Shared.Actions;
|
||||
|
||||
/// <summary>
|
||||
/// Handles displaying popup messages when actions are successfully performed.
|
||||
/// </summary>
|
||||
public sealed partial class PopupOnActionSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private SharedPopupSystem _popup = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PopupOnActionComponent, ActionPerformedEvent>(OnActionPerformed);
|
||||
}
|
||||
|
||||
private void OnActionPerformed(Entity<PopupOnActionComponent> ent, ref ActionPerformedEvent args)
|
||||
{
|
||||
EntityUid? target = null;
|
||||
|
||||
if (TryComp<EntityTargetActionComponent>(ent, out var entityTarget) && entityTarget.Event is { } ev)
|
||||
target = ev.Target;
|
||||
|
||||
var userName = Identity.Name(args.Performer, EntityManager);
|
||||
var targetName = target != null ? Identity.Name(target.Value, EntityManager) : string.Empty;
|
||||
|
||||
var selfMessage = ent.Comp.SelfMessage != null
|
||||
? Loc.GetString(ent.Comp.SelfMessage, ("target", targetName), ("user", userName))
|
||||
: null;
|
||||
|
||||
var othersMessage = ent.Comp.OthersMessage != null
|
||||
? Loc.GetString(ent.Comp.OthersMessage, ("target", targetName), ("user", userName))
|
||||
: null;
|
||||
|
||||
var targetMessage = ent.Comp.TargetMessage != null
|
||||
? Loc.GetString(ent.Comp.TargetMessage, ("target", targetName), ("user", userName))
|
||||
: null;
|
||||
|
||||
// Popup to show to the performer.
|
||||
// If there is a target the popup is located on the target, if there is no target it is located on the user.
|
||||
_popup.PopupClient(selfMessage, target ?? args.Performer, args.Performer, ent.Comp.PopupType);
|
||||
|
||||
// Popup to show to the target.
|
||||
// Located on the target.
|
||||
if (target != null)
|
||||
_popup.PopupEntity(targetMessage, target.Value, target.Value, ent.Comp.PopupType);
|
||||
|
||||
// Popup for everyone else.
|
||||
// Located on the performer.
|
||||
var filter = Filter.PvsExcept(args.Performer, entityManager: EntityManager);
|
||||
if (target != null)
|
||||
filter = filter.RemovePlayerByAttachedEntity(target.Value);
|
||||
|
||||
_popup.PopupEntity(othersMessage, args.Performer, filter, true, ent.Comp.PopupType);
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,6 @@ public sealed partial class ChangelingAbilitySystem : EntitySystem
|
||||
if (!_changelingDevour.CanDevour(ent.Owner, args.Target, checkDead: false, checkProtected: false))
|
||||
return;
|
||||
|
||||
_popup.PopupClient(Loc.GetString("changeling-sting-success", ("target", Identity.Entity(args.Target, EntityManager))), args.Target, ent.Owner, PopupType.Medium);
|
||||
_changelingIdentity.GrantIdentity(ent, args.Target);
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
@@ -11,6 +11,7 @@ public sealed partial class ReactiveSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private IPrototypeManager _proto = default!;
|
||||
|
||||
// TODO: Someone add documentation, I beg you
|
||||
public void DoEntityReaction(EntityUid uid, Solution solution, ReactionMethod method)
|
||||
{
|
||||
foreach (var reagent in solution.Contents.ToArray())
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Systems;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.EntityEffects.Effects.Body;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a reagent directly to the target's bloodstream.
|
||||
/// Quantity is modified by scale.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
|
||||
public sealed partial class AddReagentToBloodstreamEntityEffectSystem : EntityEffectSystem<BloodstreamComponent, AddReagentToBloodstream>
|
||||
{
|
||||
[Dependency] private SharedBloodstreamSystem _bloodstream = default!;
|
||||
[Dependency] private ReactiveSystem _reactive = default!;
|
||||
|
||||
protected override void Effect(Entity<BloodstreamComponent> entity, ref EntityEffectEvent<AddReagentToBloodstream> args)
|
||||
{
|
||||
var solution = new Content.Shared.Chemistry.Components.Solution();
|
||||
solution.AddReagent(args.Effect.Reagent, args.Effect.Quantity * args.Scale);
|
||||
|
||||
_bloodstream.TryAddToBloodstream(entity.AsNullable(), solution);
|
||||
_reactive.DoEntityReaction(entity, solution, ReactionMethod.Injection); // TODO: This should be part of TryAddToBloodstream
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityEffect"/>
|
||||
public sealed partial class AddReagentToBloodstream : EntityEffectBase<AddReagentToBloodstream>
|
||||
{
|
||||
/// <summary>
|
||||
/// Prototype of the reagent we're adding.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public ProtoId<ReagentPrototype> Reagent;
|
||||
|
||||
/// <summary>
|
||||
/// Amount of reagent to add to the bloodstream.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public FixedPoint2 Quantity = 1.0;
|
||||
|
||||
public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
return prototype.Resolve(Reagent, out var proto)
|
||||
? Loc.GetString("entity-effect-guidebook-add-reagent-to-bloodstream", ("chance", Probability), ("reagent", proto.LocalizedName), ("quantity", Quantity))
|
||||
: null;
|
||||
}
|
||||
}
|
||||
@@ -530,3 +530,9 @@ entity-effect-guidebook-plant-mutate-chemicals =
|
||||
[1] Mutates
|
||||
*[other] mutate
|
||||
} a plant to produce {$name}
|
||||
|
||||
entity-effect-guidebook-add-reagent-to-bloodstream =
|
||||
{ $chance ->
|
||||
[1] Injects
|
||||
*[other] inject
|
||||
} {$quantity} of {$reagent} directly into the bloodstream
|
||||
|
||||
@@ -12,3 +12,15 @@ changeling-catalog-biodegrade-desc = You learn to utilize acid glands within you
|
||||
|
||||
changeling-catalog-sting-dna-name = Extract DNA
|
||||
changeling-catalog-sting-dna-desc = Learn to utilize your stinger to absorb the identity of unsuspecting victims. Does not grant DNA to your store or objective progress.
|
||||
|
||||
changeling-catalog-blind-sting-name = Blind Sting
|
||||
changeling-catalog-blind-sting-desc = Causes temporary blindness in the target. Good to escape or initiate a fight. Can be used on self.
|
||||
|
||||
changeling-catalog-cryogenic-sting-name = Cryogenic Sting
|
||||
changeling-catalog-cryogenic-sting-desc = Causes movement slowdown in the target. Perfect for keeping prey from running away. Can be used on self.
|
||||
|
||||
changeling-catalog-lethal-sting-name = Lethal Sting
|
||||
changeling-catalog-lethal-sting-desc = Causes very slow damage to the target. Useless in combat, but ensures they will require medical attention. Can be used on self.
|
||||
|
||||
changeling-catalog-hallucinogenic-sting-name = Hallucinogenic Sting
|
||||
changeling-catalog-hallucinogenic-sting-desc = Causes the target to get high and have difficulty speaking. Causes confusion among the crew. Can be used on self.
|
||||
|
||||
@@ -102,6 +102,103 @@
|
||||
canTargetSelf: false
|
||||
whitelist:
|
||||
components:
|
||||
- MobState
|
||||
- HumanoidProfile
|
||||
event: !type:ChangelingStingDnaEvent
|
||||
- type: PopupOnAction
|
||||
popupType: Medium
|
||||
selfMessage: changeling-sting-success
|
||||
|
||||
- type: entity
|
||||
abstract: true
|
||||
parent: BaseAction
|
||||
id: BaseActionChangelingSting
|
||||
components:
|
||||
- type: TargetAction
|
||||
interactOnMiss: false
|
||||
- type: EntityTargetAction
|
||||
whitelist:
|
||||
components:
|
||||
- Bloodstream
|
||||
event: !type:EntityEffectActionEvent
|
||||
- type: PopupOnAction
|
||||
popupType: Medium
|
||||
selfMessage: changeling-sting-success
|
||||
|
||||
- type: entity
|
||||
parent: BaseActionChangelingSting
|
||||
id: ActionChangelingStingBlind
|
||||
name: Blind Sting
|
||||
description: Silently sting a target and worsen their sight for a short duration.
|
||||
components:
|
||||
- type: Action
|
||||
useDelay: 60 # TODO: Chemical cost
|
||||
raiseOnAction: true
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: Interface/Actions/changeling2.rsi
|
||||
state: blind_sting
|
||||
- type: EntityEffectAction
|
||||
effects:
|
||||
- !type:AddReagentToBloodstream
|
||||
reagent: NorepinephricAcid
|
||||
quantity: 23
|
||||
|
||||
- type: entity
|
||||
parent: BaseActionChangelingSting
|
||||
id: ActionChangelingStingCryogenic
|
||||
name: Cryogenic Sting
|
||||
description: Silently sting a target and slow down their movement drastically.
|
||||
components:
|
||||
- type: Action
|
||||
useDelay: 60 # TODO: Chemical cost
|
||||
raiseOnAction: true
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: Interface/Actions/changeling2.rsi
|
||||
state: cryogenic_sting
|
||||
- type: EntityEffectAction
|
||||
effects:
|
||||
- !type:AddReagentToBloodstream
|
||||
reagent: Fresium
|
||||
quantity: 10 # About 20 seconds of slowdown.
|
||||
|
||||
- type: entity
|
||||
parent: BaseActionChangelingSting
|
||||
id: ActionChangelingStingLead
|
||||
name: Lethal Sting
|
||||
description: Silently sting a target and inject them with a lethal dose of a slow acting poison.
|
||||
components:
|
||||
- type: Action
|
||||
useDelay: 180 # TODO: Chemical cost
|
||||
raiseOnAction: true
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: Interface/Actions/changeling2.rsi
|
||||
state: lethal_sting
|
||||
- type: EntityEffectAction
|
||||
effects:
|
||||
- !type:AddReagentToBloodstream
|
||||
reagent: Lead
|
||||
quantity: 5 # Exactly 100 poison damage over 3 minutes.
|
||||
|
||||
- type: entity
|
||||
parent: BaseActionChangelingSting
|
||||
id: ActionChangelingStingHallucinogenic
|
||||
name: Hallucinogenic Sting
|
||||
description: Silently sting a target and inject them with chemicals that slow down their higher brain functions.
|
||||
components:
|
||||
- type: Action
|
||||
useDelay: 90 # TODO: Chemical cost
|
||||
raiseOnAction: true
|
||||
itemIconStyle: BigAction
|
||||
icon:
|
||||
sprite: Interface/Actions/changeling2.rsi
|
||||
state: hallucination_sting
|
||||
- type: EntityEffectAction
|
||||
effects:
|
||||
- !type:AddReagentToBloodstream
|
||||
reagent: SpaceDrugs
|
||||
quantity: 10 # About 100s of being high
|
||||
- !type:AddReagentToBloodstream
|
||||
reagent: Cryptobiolin
|
||||
quantity: 10 # About 20s of your speech being scrambled
|
||||
|
||||
@@ -70,3 +70,63 @@
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
productAction: ActionChangelingStingDna
|
||||
|
||||
- type: listing
|
||||
id: ChangelingStingBlind
|
||||
name: changeling-catalog-blind-sting-name
|
||||
description: changeling-catalog-blind-sting-desc
|
||||
icon: { sprite: /Textures/Interface/Actions/changeling2.rsi, state: blind_sting }
|
||||
applyToMob: true
|
||||
cost:
|
||||
ChangelingDNA: 15
|
||||
categories:
|
||||
- ChangelingStoreCombat
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
productAction: ActionChangelingStingBlind
|
||||
|
||||
- type: listing
|
||||
id: ChangelingStingCryogenic
|
||||
name: changeling-catalog-cryogenic-sting-name
|
||||
description: changeling-catalog-cryogenic-sting-desc
|
||||
icon: { sprite: /Textures/Interface/Actions/changeling2.rsi, state: cryogenic_sting }
|
||||
applyToMob: true
|
||||
cost:
|
||||
ChangelingDNA: 15
|
||||
categories:
|
||||
- ChangelingStoreCombat
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
productAction: ActionChangelingStingCryogenic
|
||||
|
||||
- type: listing
|
||||
id: ChangelingStingLead
|
||||
name: changeling-catalog-lethal-sting-name
|
||||
description: changeling-catalog-lethal-sting-desc
|
||||
icon: { sprite: /Textures/Interface/Actions/changeling2.rsi, state: lethal_sting }
|
||||
applyToMob: true
|
||||
cost:
|
||||
ChangelingDNA: 10
|
||||
categories:
|
||||
- ChangelingStoreUtility
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
productAction: ActionChangelingStingLead
|
||||
|
||||
- type: listing
|
||||
id: ChangelingStingHallucinogenic
|
||||
name: changeling-catalog-hallucinogenic-sting-name
|
||||
description: changeling-catalog-hallucinogenic-sting-desc
|
||||
icon: { sprite: /Textures/Interface/Actions/changeling2.rsi, state: hallucination_sting }
|
||||
applyToMob: true
|
||||
cost:
|
||||
ChangelingDNA: 10
|
||||
categories:
|
||||
- ChangelingStoreUtility
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
productAction: ActionChangelingStingHallucinogenic
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
wideAnimationRotation: 90
|
||||
attackRate: 1
|
||||
damage:
|
||||
types: # Same as energy sword, but slash/pierce instead of slash/heat
|
||||
Slash: 15
|
||||
Piercing: 15
|
||||
types:
|
||||
Slash: 11
|
||||
Piercing: 11
|
||||
Structural: 20
|
||||
- type: Item
|
||||
size: Normal
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Made by ketufaispikinut from a sprite taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039 (scientist suit), a sprite taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039 (hydro suit) and the changeling ability border/background sprites created by TiniestShark. Biodegrade, Mimicry and Extract Dna On/Off by ketufaispikinut, based on TiniestShark's textures. Shop icon by ketufaispikinut, based on TiniestShark's textures.",
|
||||
"copyright": "Made by ketufaispikinut from a sprite taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039 (scientist suit), a sprite taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039 (hydro suit) and the changeling ability border/background sprites created by TiniestShark. Biodegrade, Mimicry and Extract Dna On/Off, Blind, Mute, Neurodepressant, Cryogenic, Lethal and Hallucination sting by ketufaispikinut, based on TiniestShark's textures. Shop icon by ketufaispikinut, based on TiniestShark's textures.",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
@@ -18,12 +18,28 @@
|
||||
},
|
||||
{
|
||||
"name": "biodegrade"
|
||||
}
|
||||
,
|
||||
},
|
||||
{
|
||||
"name": "blind_sting"
|
||||
},
|
||||
{
|
||||
"name": "mute_sting"
|
||||
},
|
||||
{
|
||||
"name": "hallucination_sting"
|
||||
},
|
||||
{
|
||||
"name": "neurodepressant_sting"
|
||||
},
|
||||
{
|
||||
"name": "cryogenic_sting"
|
||||
},
|
||||
{
|
||||
"name": "lethal_sting"
|
||||
},
|
||||
{
|
||||
"name": "extract_dna_on"
|
||||
}
|
||||
,
|
||||
},
|
||||
{
|
||||
"name": "extract_dna_off"
|
||||
},
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Reference in New Issue
Block a user