Files
crystall-punk-14/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs
Ed 109edeb4b5 Modular weapon crafting WIP (#611)
* data initalizing

* modular assembling

* grips and blades sprites

* first prototypes

* jewerly decoration

* disassemble modular weapon

* grip start stats

* blade modifiers

* inhand sprites generation

* resprites inhand, add sickle, add attempt modify size

* auto inhand sprite parsing

* icon default parsing

* spear blade

* mace ball

* sword blade

* sharedization + autonetwork hotswipe

* wielding sprite support!

* iron long grip

* wielded sickle, fix ERROR sprite if state not added

* Update grips.yml

* wielded spear + ruby rework

* wielding damage bonus modifier

* modular size fix

* fix storedOffset rotation

* parts offset

* fix inheriting modifiers

* some bugfix and balance tweaks

* DPS Meter

* fix dividing by zero

* rebalance

* replace baseknife to modular knife. Delete ice knife spell

* sickle and mace modular replace

* modular spear & sword replacement. add wielded icons

* Update CP14DPSMeterSystem.cs

* back to serverization

* grip disassemble drop again

* clothing sprite generation code

* back slot long grips and mace

* remove jewerly slot, add more clothing states

* finish clothing states

* shovel modular

* YEEEEE

* anvil modular craft

* bugfixes

* more integration check fixes
2024-11-29 01:31:42 +03:00

184 lines
6.5 KiB
C#

using Content.Shared.Damage;
using Content.Shared.FixedPoint;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Weapons.Melee;
/// <summary>
/// When given to a mob lets them do unarmed attacks, or when given to an item lets someone wield it to do attacks.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
public sealed partial class MeleeWeaponComponent : Component
{
// TODO: This is becoming bloated as shit.
// This should just be its own component for alt attacks.
/// <summary>
/// Does this entity do a disarm on alt attack.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public bool AltDisarm = true;
/// <summary>
/// Should the melee weapon's damage stats be examinable.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public bool Hidden;
/// <summary>
/// Next time this component is allowed to light attack. Heavy attacks are wound up and never have a cooldown.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField]
[ViewVariables(VVAccess.ReadWrite)]
[AutoPausedField]
public TimeSpan NextAttack;
/// <summary>
/// Starts attack cooldown when equipped if true.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] //CP14 AutoNetworked
public bool ResetOnHandSelected = true;
/*
* Melee combat works based around 2 types of attacks:
* 1. Click attacks with left-click. This attacks whatever is under your mnouse
* 2. Wide attacks with right-click + left-click. This attacks whatever is in the direction of your mouse.
*/
/// <summary>
/// How many times we can attack per second.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public float AttackRate = 1f;
/// <summary>
/// Are we currently holding down the mouse for an attack.
/// Used so we can't just hold the mouse button and attack constantly.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public bool Attacking = false;
/// <summary>
/// If true, attacks will be repeated automatically without requiring the mouse button to be lifted.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public bool AutoAttack;
/// <summary>
/// If true, attacks will bypass armor resistances.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public bool ResistanceBypass = false;
/// <summary>
/// Base damage for this weapon. Can be modified via heavy damage or other means.
/// </summary>
[DataField(required: true)]
[ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public DamageSpecifier Damage = default!;
[DataField]
[ViewVariables(VVAccess.ReadWrite)]
public FixedPoint2 BluntStaminaDamageFactor = FixedPoint2.New(0.5f);
/// <summary>
/// Multiplies damage by this amount for single-target attacks.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField]
public FixedPoint2 ClickDamageModifier = FixedPoint2.New(1);
// TODO: Temporarily 1.5 until interactionoutline is adjusted to use melee, then probably drop to 1.2
/// <summary>
/// Nearest edge range to hit an entity.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public float Range = 1.5f;
/// <summary>
/// Total width of the angle for wide attacks.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField]
public Angle Angle = Angle.FromDegrees(60);
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public EntProtoId Animation = "WeaponArcPunch";
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public EntProtoId WideAnimation = "WeaponArcSlash";
/// <summary>
/// Rotation of the animation.
/// 0 degrees means the top faces the attacker.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField]
public Angle WideAnimationRotation = Angle.Zero;
[ViewVariables(VVAccess.ReadWrite), DataField]
public bool SwingLeft;
/// <summary>
/// CrystallEdge Melee upgrade. Allows each attack to take turns being either left or right
/// </summary>
[DataField]
public bool CPSwingBeverage = true;
/// <summary>
/// CrystallEdge Melee upgrade. Modifier of wide attack animation speed
/// </summary>
[DataField]
public float CPAnimationLength = 0.5f;
/// <summary>
/// CrystallEdge Melee upgrade. how far away from the player the animation should be played.
/// </summary>
[DataField]
public float CPAnimationOffset = -1f;
// Sounds
/// <summary>
/// This gets played whenever a melee attack is done. This is predicted by the client.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("soundSwing"), AutoNetworkedField]
public SoundSpecifier SwingSound { get; set; } = new SoundPathSpecifier("/Audio/Weapons/punchmiss.ogg")
{
Params = AudioParams.Default.WithVolume(-3f).WithVariation(0.025f),
};
// We do not predict the below sounds in case the client thinks but the server disagrees. If this were the case
// then a player may doubt if the target actually took damage or not.
// If overwatch and apex do this then we probably should too.
[ViewVariables(VVAccess.ReadWrite)]
[DataField("soundHit"), AutoNetworkedField]
public SoundSpecifier? HitSound;
/// <summary>
/// Plays if no damage is done to the target entity.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("soundNoDamage"), AutoNetworkedField]
public SoundSpecifier NoDamageSound { get; set; } = new SoundCollectionSpecifier("WeakHit");
/// <summary>
/// If true, the weapon must be equipped for it to be used.
/// E.g boxing gloves must be equipped to your gloves,
/// not just held in your hand to be used.
/// </summary>
[DataField, AutoNetworkedField]
public bool MustBeEquippedToUse = false;
}
/// <summary>
/// Event raised on entity in GetWeapon function to allow systems to manually
/// specify what the weapon should be.
/// </summary>
public sealed class GetMeleeWeaponEvent : HandledEntityEventArgs
{
public EntityUid? Weapon;
}