Implement field-deltas for melee (#33977)
* Implement field-deltas for melee * Review
This commit is contained in:
@@ -132,6 +132,16 @@ public sealed partial class ZombieSystem
|
|||||||
melee.Angle = 0.0f;
|
melee.Angle = 0.0f;
|
||||||
melee.HitSound = zombiecomp.BiteSound;
|
melee.HitSound = zombiecomp.BiteSound;
|
||||||
|
|
||||||
|
DirtyFields(target, melee, null, fields:
|
||||||
|
[
|
||||||
|
nameof(MeleeWeaponComponent.Animation),
|
||||||
|
nameof(MeleeWeaponComponent.WideAnimation),
|
||||||
|
nameof(MeleeWeaponComponent.AltDisarm),
|
||||||
|
nameof(MeleeWeaponComponent.Range),
|
||||||
|
nameof(MeleeWeaponComponent.Angle),
|
||||||
|
nameof(MeleeWeaponComponent.HitSound),
|
||||||
|
]);
|
||||||
|
|
||||||
if (mobState.CurrentState == MobState.Alive)
|
if (mobState.CurrentState == MobState.Alive)
|
||||||
{
|
{
|
||||||
// Groaning when damaged
|
// Groaning when damaged
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace Content.Shared.Weapons.Melee;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// When given to a mob lets them do unarmed attacks, or when given to an item lets someone wield it to do attacks.
|
/// When given to a mob lets them do unarmed attacks, or when given to an item lets someone wield it to do attacks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(fieldDeltas: true), AutoGenerateComponentPause]
|
||||||
public sealed partial class MeleeWeaponComponent : Component
|
public sealed partial class MeleeWeaponComponent : Component
|
||||||
{
|
{
|
||||||
// TODO: This is becoming bloated as shit.
|
// TODO: This is becoming bloated as shit.
|
||||||
@@ -18,28 +18,26 @@ public sealed partial class MeleeWeaponComponent : Component
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Does this entity do a disarm on alt attack.
|
/// Does this entity do a disarm on alt attack.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool AltDisarm = true;
|
public bool AltDisarm = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should the melee weapon's damage stats be examinable.
|
/// Should the melee weapon's damage stats be examinable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[DataField, AutoNetworkedField]
|
||||||
[DataField]
|
|
||||||
public bool Hidden;
|
public bool Hidden;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Next time this component is allowed to light attack. Heavy attacks are wound up and never have a cooldown.
|
/// Next time this component is allowed to light attack. Heavy attacks are wound up and never have a cooldown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField]
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField]
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
[AutoPausedField]
|
[AutoPausedField]
|
||||||
public TimeSpan NextAttack;
|
public TimeSpan NextAttack;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts attack cooldown when equipped if true.
|
/// Starts attack cooldown when equipped if true.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool ResetOnHandSelected = true;
|
public bool ResetOnHandSelected = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -51,72 +49,70 @@ public sealed partial class MeleeWeaponComponent : Component
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// How many times we can attack per second.
|
/// How many times we can attack per second.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public float AttackRate = 1f;
|
public float AttackRate = 1f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Are we currently holding down the mouse for an attack.
|
/// Are we currently holding down the mouse for an attack.
|
||||||
/// Used so we can't just hold the mouse button and attack constantly.
|
/// Used so we can't just hold the mouse button and attack constantly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
[AutoNetworkedField]
|
||||||
public bool Attacking = false;
|
public bool Attacking = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, attacks will be repeated automatically without requiring the mouse button to be lifted.
|
/// If true, attacks will be repeated automatically without requiring the mouse button to be lifted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool AutoAttack;
|
public bool AutoAttack;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, attacks will bypass armor resistances.
|
/// If true, attacks will bypass armor resistances.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool ResistanceBypass = false;
|
public bool ResistanceBypass = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base damage for this weapon. Can be modified via heavy damage or other means.
|
/// Base damage for this weapon. Can be modified via heavy damage or other means.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField(required: true)]
|
[DataField(required: true), AutoNetworkedField]
|
||||||
[ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
|
||||||
public DamageSpecifier Damage = default!;
|
public DamageSpecifier Damage = default!;
|
||||||
|
|
||||||
[DataField]
|
[DataField, AutoNetworkedField]
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public FixedPoint2 BluntStaminaDamageFactor = FixedPoint2.New(0.5f);
|
public FixedPoint2 BluntStaminaDamageFactor = FixedPoint2.New(0.5f);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiplies damage by this amount for single-target attacks.
|
/// Multiplies damage by this amount for single-target attacks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public FixedPoint2 ClickDamageModifier = FixedPoint2.New(1);
|
public FixedPoint2 ClickDamageModifier = FixedPoint2.New(1);
|
||||||
|
|
||||||
// TODO: Temporarily 1.5 until interactionoutline is adjusted to use melee, then probably drop to 1.2
|
// TODO: Temporarily 1.5 until interactionoutline is adjusted to use melee, then probably drop to 1.2
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Nearest edge range to hit an entity.
|
/// Nearest edge range to hit an entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public float Range = 1.5f;
|
public float Range = 1.5f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Total width of the angle for wide attacks.
|
/// Total width of the angle for wide attacks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public Angle Angle = Angle.FromDegrees(60);
|
public Angle Angle = Angle.FromDegrees(60);
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public EntProtoId Animation = "WeaponArcPunch";
|
public EntProtoId Animation = "WeaponArcPunch";
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public EntProtoId WideAnimation = "WeaponArcSlash";
|
public EntProtoId WideAnimation = "WeaponArcSlash";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rotation of the animation.
|
/// Rotation of the animation.
|
||||||
/// 0 degrees means the top faces the attacker.
|
/// 0 degrees means the top faces the attacker.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public Angle WideAnimationRotation = Angle.Zero;
|
public Angle WideAnimationRotation = Angle.Zero;
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
[DataField, AutoNetworkedField]
|
||||||
public bool SwingLeft;
|
public bool SwingLeft;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
if (gun.NextFire > component.NextAttack)
|
if (gun.NextFire > component.NextAttack)
|
||||||
{
|
{
|
||||||
component.NextAttack = gun.NextFire;
|
component.NextAttack = gun.NextFire;
|
||||||
Dirty(uid, component);
|
DirtyField(uid, component, nameof(MeleeWeaponComponent.NextAttack));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
component.NextAttack = minimum;
|
component.NextAttack = minimum;
|
||||||
Dirty(uid, component);
|
DirtyField(uid, component, nameof(MeleeWeaponComponent.NextAttack));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGetBonusMeleeDamage(EntityUid uid, BonusMeleeDamageComponent component, ref GetMeleeDamageEvent args)
|
private void OnGetBonusMeleeDamage(EntityUid uid, BonusMeleeDamageComponent component, ref GetMeleeDamageEvent args)
|
||||||
@@ -168,7 +168,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
weapon.Attacking = false;
|
weapon.Attacking = false;
|
||||||
Dirty(weaponUid, weapon);
|
DirtyField(weaponUid, weapon, nameof(MeleeWeaponComponent.Attacking));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLightAttack(LightAttackEvent msg, EntitySessionEventArgs args)
|
private void OnLightAttack(LightAttackEvent msg, EntitySessionEventArgs args)
|
||||||
@@ -392,7 +392,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
swings++;
|
swings++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dirty(weaponUid, weapon);
|
DirtyField(weaponUid, weapon, nameof(MeleeWeaponComponent.NextAttack));
|
||||||
|
|
||||||
// Do this AFTER attack so it doesn't spam every tick
|
// Do this AFTER attack so it doesn't spam every tick
|
||||||
var ev = new AttemptMeleeEvent();
|
var ev = new AttemptMeleeEvent();
|
||||||
@@ -442,6 +442,7 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
RaiseLocalEvent(user, ref attackEv);
|
RaiseLocalEvent(user, ref attackEv);
|
||||||
|
|
||||||
weapon.Attacking = true;
|
weapon.Attacking = true;
|
||||||
|
DirtyField(weaponUid, weapon, nameof(MeleeWeaponComponent.Attacking));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -838,15 +839,21 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
//Setting deactivated damage to the weapon's regular value before changing it.
|
//Setting deactivated damage to the weapon's regular value before changing it.
|
||||||
itemToggleMelee.DeactivatedDamage ??= meleeWeapon.Damage;
|
itemToggleMelee.DeactivatedDamage ??= meleeWeapon.Damage;
|
||||||
meleeWeapon.Damage = itemToggleMelee.ActivatedDamage;
|
meleeWeapon.Damage = itemToggleMelee.ActivatedDamage;
|
||||||
|
DirtyField(uid, meleeWeapon, nameof(MeleeWeaponComponent.Damage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (meleeWeapon.HitSound?.Equals(itemToggleMelee.ActivatedSoundOnHit) != true)
|
||||||
|
{
|
||||||
meleeWeapon.HitSound = itemToggleMelee.ActivatedSoundOnHit;
|
meleeWeapon.HitSound = itemToggleMelee.ActivatedSoundOnHit;
|
||||||
|
DirtyField(uid, meleeWeapon, nameof(MeleeWeaponComponent.HitSound));
|
||||||
|
}
|
||||||
|
|
||||||
if (itemToggleMelee.ActivatedSoundOnHitNoDamage != null)
|
if (itemToggleMelee.ActivatedSoundOnHitNoDamage != null)
|
||||||
{
|
{
|
||||||
//Setting the deactivated sound on no damage hit to the weapon's regular value before changing it.
|
//Setting the deactivated sound on no damage hit to the weapon's regular value before changing it.
|
||||||
itemToggleMelee.DeactivatedSoundOnHitNoDamage ??= meleeWeapon.NoDamageSound;
|
itemToggleMelee.DeactivatedSoundOnHitNoDamage ??= meleeWeapon.NoDamageSound;
|
||||||
meleeWeapon.NoDamageSound = itemToggleMelee.ActivatedSoundOnHitNoDamage;
|
meleeWeapon.NoDamageSound = itemToggleMelee.ActivatedSoundOnHitNoDamage;
|
||||||
|
DirtyField(uid, meleeWeapon, nameof(MeleeWeaponComponent.NoDamageSound));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemToggleMelee.ActivatedSoundOnSwing != null)
|
if (itemToggleMelee.ActivatedSoundOnSwing != null)
|
||||||
@@ -854,28 +861,41 @@ public abstract class SharedMeleeWeaponSystem : EntitySystem
|
|||||||
//Setting the deactivated sound on no damage hit to the weapon's regular value before changing it.
|
//Setting the deactivated sound on no damage hit to the weapon's regular value before changing it.
|
||||||
itemToggleMelee.DeactivatedSoundOnSwing ??= meleeWeapon.SwingSound;
|
itemToggleMelee.DeactivatedSoundOnSwing ??= meleeWeapon.SwingSound;
|
||||||
meleeWeapon.SwingSound = itemToggleMelee.ActivatedSoundOnSwing;
|
meleeWeapon.SwingSound = itemToggleMelee.ActivatedSoundOnSwing;
|
||||||
|
DirtyField(uid, meleeWeapon, nameof(MeleeWeaponComponent.SwingSound));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemToggleMelee.DeactivatedSecret)
|
if (itemToggleMelee.DeactivatedSecret)
|
||||||
|
{
|
||||||
meleeWeapon.Hidden = false;
|
meleeWeapon.Hidden = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (itemToggleMelee.DeactivatedDamage != null)
|
if (itemToggleMelee.DeactivatedDamage != null)
|
||||||
|
{
|
||||||
meleeWeapon.Damage = itemToggleMelee.DeactivatedDamage;
|
meleeWeapon.Damage = itemToggleMelee.DeactivatedDamage;
|
||||||
|
DirtyField(uid, meleeWeapon, nameof(MeleeWeaponComponent.Damage));
|
||||||
|
}
|
||||||
|
|
||||||
meleeWeapon.HitSound = itemToggleMelee.DeactivatedSoundOnHit;
|
meleeWeapon.HitSound = itemToggleMelee.DeactivatedSoundOnHit;
|
||||||
|
DirtyField(uid, meleeWeapon, nameof(MeleeWeaponComponent.HitSound));
|
||||||
|
|
||||||
if (itemToggleMelee.DeactivatedSoundOnHitNoDamage != null)
|
if (itemToggleMelee.DeactivatedSoundOnHitNoDamage != null)
|
||||||
|
{
|
||||||
meleeWeapon.NoDamageSound = itemToggleMelee.DeactivatedSoundOnHitNoDamage;
|
meleeWeapon.NoDamageSound = itemToggleMelee.DeactivatedSoundOnHitNoDamage;
|
||||||
|
DirtyField(uid, meleeWeapon, nameof(MeleeWeaponComponent.NoDamageSound));
|
||||||
|
}
|
||||||
|
|
||||||
if (itemToggleMelee.DeactivatedSoundOnSwing != null)
|
if (itemToggleMelee.DeactivatedSoundOnSwing != null)
|
||||||
|
{
|
||||||
meleeWeapon.SwingSound = itemToggleMelee.DeactivatedSoundOnSwing;
|
meleeWeapon.SwingSound = itemToggleMelee.DeactivatedSoundOnSwing;
|
||||||
|
DirtyField(uid, meleeWeapon, nameof(MeleeWeaponComponent.SwingSound));
|
||||||
|
}
|
||||||
|
|
||||||
if (itemToggleMelee.DeactivatedSecret)
|
if (itemToggleMelee.DeactivatedSecret)
|
||||||
|
{
|
||||||
meleeWeapon.Hidden = true;
|
meleeWeapon.Hidden = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Dirty(uid, meleeWeapon);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user