ninja 2 electric boogaloo (#15534)
Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
38
Content.Shared/Ninja/Components/BatteryDrainerComponent.cs
Normal file
38
Content.Shared/Ninja/Components/BatteryDrainerComponent.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Content.Shared.Ninja.Systems;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Shared.Ninja.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component for draining power from APCs/substations/SMESes, when ProviderUid is set to a battery cell.
|
||||
/// Does not rely on relay, simply being on the user and having BatteryUid set is enough.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedBatteryDrainerSystem))]
|
||||
public sealed partial class BatteryDrainerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The powercell entity to drain power into.
|
||||
/// Determines whether draining is possible.
|
||||
/// </summary>
|
||||
[DataField("batteryUid"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public EntityUid? BatteryUid;
|
||||
|
||||
/// <summary>
|
||||
/// Conversion rate between joules in a device and joules added to battery.
|
||||
/// Should be very low since powercells store nothing compared to even an APC.
|
||||
/// </summary>
|
||||
[DataField("drainEfficiency"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float DrainEfficiency = 0.001f;
|
||||
|
||||
/// <summary>
|
||||
/// Time that the do after takes to drain charge from a battery, in seconds
|
||||
/// </summary>
|
||||
[DataField("drainTime"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float DrainTime = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Sound played after the doafter ends.
|
||||
/// </summary>
|
||||
[DataField("sparkSound")]
|
||||
public SoundSpecifier SparkSound = new SoundCollectionSpecifier("sparks");
|
||||
}
|
||||
33
Content.Shared/Ninja/Components/DashAbilityComponent.cs
Normal file
33
Content.Shared/Ninja/Components/DashAbilityComponent.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Ninja.Systems;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
/// <summary>
|
||||
/// Adds an action to dash, teleport to clicked position, when this item is held.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(DashAbilitySystem))]
|
||||
public sealed partial class DashAbilityComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The action id for dashing.
|
||||
/// </summary>
|
||||
[DataField("dashAction", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>)), ViewVariables(VVAccess.ReadWrite)]
|
||||
public string DashAction = string.Empty;
|
||||
|
||||
[DataField("dashActionEntity")]
|
||||
public EntityUid? DashActionEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Sound played when using dash action.
|
||||
/// </summary>
|
||||
[DataField("blinkSound"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public SoundSpecifier BlinkSound = new SoundPathSpecifier("/Audio/Magic/blink.ogg")
|
||||
{
|
||||
Params = AudioParams.Default.WithVolume(5f)
|
||||
};
|
||||
}
|
||||
|
||||
public sealed partial class DashEvent : WorldTargetActionEvent { }
|
||||
28
Content.Shared/Ninja/Components/EmagProviderComponent.cs
Normal file
28
Content.Shared/Ninja/Components/EmagProviderComponent.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Content.Shared.Ninja.Systems;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Ninja.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component for emagging things on click.
|
||||
/// No charges but checks against a whitelist.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
[Access(typeof(EmagProviderSystem))]
|
||||
public sealed partial class EmagProviderComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The tag that marks an entity as immune to emagging.
|
||||
/// </summary>
|
||||
[DataField("emagImmuneTag", customTypeSerializer: typeof(PrototypeIdSerializer<TagPrototype>))]
|
||||
public string EmagImmuneTag = "EmagImmune";
|
||||
|
||||
/// <summary>
|
||||
/// Whitelist that entities must be on to work.
|
||||
/// </summary>
|
||||
[DataField("whitelist"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||
public EntityWhitelist? Whitelist = null;
|
||||
}
|
||||
12
Content.Shared/Ninja/Components/EnergyKatanaComponent.cs
Normal file
12
Content.Shared/Ninja/Components/EnergyKatanaComponent.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Ninja.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component for a Space Ninja's katana, controls ninja related dash logic.
|
||||
/// Requires a ninja with a suit for abilities to work.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class EnergyKatanaComponent : Component
|
||||
{
|
||||
}
|
||||
45
Content.Shared/Ninja/Components/NinjaGlovesComponent.cs
Normal file
45
Content.Shared/Ninja/Components/NinjaGlovesComponent.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Ninja.Systems;
|
||||
using Content.Shared.Toggleable;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Ninja.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component for toggling glove powers.
|
||||
/// Powers being enabled is controlled by User not being null.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
[Access(typeof(SharedNinjaGlovesSystem))]
|
||||
public sealed partial class NinjaGlovesComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity of the ninja using these gloves, usually means enabled
|
||||
/// </summary>
|
||||
[DataField("user"), AutoNetworkedField]
|
||||
public EntityUid? User;
|
||||
|
||||
/// <summary>
|
||||
/// The action id for toggling ninja gloves abilities
|
||||
/// </summary>
|
||||
[DataField("toggleAction", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ToggleAction = "ActionToggleNinjaGloves";
|
||||
|
||||
[DataField("toggleActionEntity")]
|
||||
public EntityUid? ToggleActionEntity;
|
||||
|
||||
/// <summary>
|
||||
/// The whitelist used for the emag provider to emag airlocks only (not regular doors).
|
||||
/// </summary>
|
||||
[DataField("doorjackWhitelist")]
|
||||
public EntityWhitelist DoorjackWhitelist = new()
|
||||
{
|
||||
Components = new[] {"Airlock"}
|
||||
};
|
||||
}
|
||||
125
Content.Shared/Ninja/Components/NinjaSuitComponent.cs
Normal file
125
Content.Shared/Ninja/Components/NinjaSuitComponent.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Ninja.Systems;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Ninja.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component for ninja suit abilities and power consumption.
|
||||
/// As an implementation detail, dashing with katana is a suit action which isn't ideal.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedNinjaSuitSystem))]
|
||||
public sealed partial class NinjaSuitComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Battery charge used passively, in watts. Will last 1000 seconds on a small-capacity power cell.
|
||||
/// </summary>
|
||||
[DataField("passiveWattage")]
|
||||
public float PassiveWattage = 0.36f;
|
||||
|
||||
/// <summary>
|
||||
/// Battery charge used while cloaked, stacks with passive. Will last 200 seconds while cloaked on a small-capacity power cell.
|
||||
/// </summary>
|
||||
[DataField("cloakWattage")]
|
||||
public float CloakWattage = 1.44f;
|
||||
|
||||
/// <summary>
|
||||
/// Sound played when a ninja is hit while cloaked.
|
||||
/// </summary>
|
||||
[DataField("revealSound")]
|
||||
public SoundSpecifier RevealSound = new SoundPathSpecifier("/Audio/Effects/chime.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// How long to disable all abilities for when revealed.
|
||||
/// This adds a UseDelay to the ninja so it should not be set by anything else.
|
||||
/// </summary>
|
||||
[DataField("disableTime")]
|
||||
public TimeSpan DisableTime = TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <summary>
|
||||
/// The action id for creating throwing stars.
|
||||
/// </summary>
|
||||
[DataField("createThrowingStarAction", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string CreateThrowingStarAction = "ActionCreateThrowingStar";
|
||||
|
||||
[DataField("createThrowingStarActionEntity")]
|
||||
public EntityUid? CreateThrowingStarActionEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Battery charge used to create a throwing star. Can do it 25 times on a small-capacity power cell.
|
||||
/// </summary>
|
||||
[DataField("throwingStarCharge")]
|
||||
public float ThrowingStarCharge = 14.4f;
|
||||
|
||||
/// <summary>
|
||||
/// Throwing star item to create with the action
|
||||
/// </summary>
|
||||
[DataField("throwingStarPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ThrowingStarPrototype = "ThrowingStarNinja";
|
||||
|
||||
/// <summary>
|
||||
/// The action id for recalling a bound energy katana
|
||||
/// </summary>
|
||||
[DataField("recallKatanaAction", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string RecallKatanaAction = "ActionRecallKatana";
|
||||
|
||||
[DataField("recallKatanaActionEntity")]
|
||||
public EntityUid? RecallKatanaActionEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Battery charge used per tile the katana teleported.
|
||||
/// Uses 1% of a default battery per tile.
|
||||
/// </summary>
|
||||
[DataField("recallCharge")]
|
||||
public float RecallCharge = 3.6f;
|
||||
|
||||
/// <summary>
|
||||
/// The action id for creating an EMP burst
|
||||
/// </summary>
|
||||
[DataField("empAction", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string EmpAction = "ActionNinjaEmp";
|
||||
|
||||
[DataField("empActionEntity")]
|
||||
public EntityUid? EmpActionEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Battery charge used to create an EMP burst. Can do it 2 times on a small-capacity power cell.
|
||||
/// </summary>
|
||||
[DataField("empCharge")]
|
||||
public float EmpCharge = 180f;
|
||||
|
||||
/// <summary>
|
||||
/// Range of the EMP in tiles.
|
||||
/// </summary>
|
||||
[DataField("empRange")]
|
||||
public float EmpRange = 6f;
|
||||
|
||||
/// <summary>
|
||||
/// Power consumed from batteries by the EMP
|
||||
/// </summary>
|
||||
[DataField("empConsumption")]
|
||||
public float EmpConsumption = 100000f;
|
||||
|
||||
/// <summary>
|
||||
/// How long the EMP effects last for, in seconds
|
||||
/// </summary>
|
||||
[DataField("empDuration")]
|
||||
public float EmpDuration = 60f;
|
||||
}
|
||||
|
||||
public sealed partial class CreateThrowingStarEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
|
||||
public sealed partial class RecallKatanaEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
|
||||
public sealed partial class NinjaEmpEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
38
Content.Shared/Ninja/Components/SpaceNinjaComponent.cs
Normal file
38
Content.Shared/Ninja/Components/SpaceNinjaComponent.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Content.Shared.Ninja.Systems;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Ninja.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component placed on a mob to make it a space ninja, able to use suit and glove powers.
|
||||
/// Contains ids of all ninja equipment and the game rule.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
[Access(typeof(SharedSpaceNinjaSystem))]
|
||||
public sealed partial class SpaceNinjaComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The ninja game rule that spawned this ninja.
|
||||
/// </summary>
|
||||
[DataField("rule")]
|
||||
public EntityUid? Rule;
|
||||
|
||||
/// <summary>
|
||||
/// Currently worn suit
|
||||
/// </summary>
|
||||
[DataField("suit"), AutoNetworkedField]
|
||||
public EntityUid? Suit;
|
||||
|
||||
/// <summary>
|
||||
/// Currently worn gloves
|
||||
/// </summary>
|
||||
[DataField("gloves"), AutoNetworkedField]
|
||||
public EntityUid? Gloves;
|
||||
|
||||
/// <summary>
|
||||
/// Bound katana, set once picked up and never removed
|
||||
/// </summary>
|
||||
[DataField("katana"), AutoNetworkedField]
|
||||
public EntityUid? Katana;
|
||||
}
|
||||
19
Content.Shared/Ninja/Components/SpiderChargeComponent.cs
Normal file
19
Content.Shared/Ninja/Components/SpiderChargeComponent.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Ninja.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component for the Space Ninja's unique Spider Charge.
|
||||
/// Only this component detonating can trigger the ninja's objective.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class SpiderChargeComponent : Component
|
||||
{
|
||||
/// Range for planting within the target area
|
||||
[DataField("range")]
|
||||
public float Range = 10f;
|
||||
|
||||
/// The ninja that planted this charge
|
||||
[DataField("planter")]
|
||||
public EntityUid? Planter = null;
|
||||
}
|
||||
67
Content.Shared/Ninja/Components/StunProviderComponent.cs
Normal file
67
Content.Shared/Ninja/Components/StunProviderComponent.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using Content.Shared.Ninja.Systems;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.Ninja.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Component for stunning mobs on click outside of harm mode.
|
||||
/// Knocks them down for a bit and deals shock damage.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedStunProviderSystem))]
|
||||
public sealed partial class StunProviderComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The powercell entity to take power from.
|
||||
/// Determines whether stunning is possible.
|
||||
/// </summary>
|
||||
[DataField("batteryUid"), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||
public EntityUid? BatteryUid;
|
||||
|
||||
/// <summary>
|
||||
/// Joules required in the battery to stun someone. Defaults to 10 uses on a small battery.
|
||||
/// </summary>
|
||||
[DataField("stunCharge"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float StunCharge = 36.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Shock damage dealt when stunning someone
|
||||
/// </summary>
|
||||
[DataField("stunDamage"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int StunDamage = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Time that someone is stunned for, stacks if done multiple times.
|
||||
/// </summary>
|
||||
[DataField("stunTime"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public TimeSpan StunTime = TimeSpan.FromSeconds(3);
|
||||
|
||||
/// <summary>
|
||||
/// How long stunning is disabled after stunning something.
|
||||
/// </summary>
|
||||
[DataField("cooldown"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public TimeSpan Cooldown = TimeSpan.FromSeconds(1);
|
||||
|
||||
/// <summary>
|
||||
/// Locale string to popup when there is no power
|
||||
/// </summary>
|
||||
[DataField("noPowerPopup", required: true), ViewVariables(VVAccess.ReadWrite)]
|
||||
public string NoPowerPopup = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Whitelist for what counts as a mob.
|
||||
/// </summary>
|
||||
[DataField("whitelist")]
|
||||
public EntityWhitelist Whitelist = new()
|
||||
{
|
||||
Components = new[] {"Stamina"}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// When someone can next be stunned.
|
||||
/// Essentially a UseDelay unique to this component.
|
||||
/// </summary>
|
||||
[DataField("nextStun", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)]
|
||||
public TimeSpan NextStun = TimeSpan.Zero;
|
||||
}
|
||||
Reference in New Issue
Block a user