More dynamic melee sounds (#8207)
This commit is contained in:
@@ -345,6 +345,7 @@ namespace Content.Client.Entry
|
|||||||
"Artifact",
|
"Artifact",
|
||||||
"RandomArtifactSprite",
|
"RandomArtifactSprite",
|
||||||
"EnergySword",
|
"EnergySword",
|
||||||
|
"MeleeSound",
|
||||||
"DoorRemote",
|
"DoorRemote",
|
||||||
"InteractionPopup",
|
"InteractionPopup",
|
||||||
"HealthAnalyzer",
|
"HealthAnalyzer",
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Content.Shared.Damage.Prototypes;
|
||||||
|
using Content.Shared.Sound;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||||
|
|
||||||
|
namespace Content.Server.Weapon.Melee.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Plays the specified sound upon receiving damage of the specified type.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class MeleeSoundComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specified sounds to apply when the entity takes damage with the specified group.
|
||||||
|
/// Will fallback to defaults if none specified.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("soundGroups",
|
||||||
|
customTypeSerializer: typeof(PrototypeIdDictionarySerializer<SoundSpecifier, DamageGroupPrototype>))]
|
||||||
|
public Dictionary<string, SoundSpecifier>? SoundGroups;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specified sounds to apply when the entity takes damage with the specified type.
|
||||||
|
/// Will fallback to defaults if none specified.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("soundTypes",
|
||||||
|
customTypeSerializer: typeof(PrototypeIdDictionarySerializer<SoundSpecifier, DamageTypePrototype>))]
|
||||||
|
public Dictionary<string, SoundSpecifier>? SoundTypes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sound that plays if no damage is done.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("noDamageSound")] public SoundSpecifier? NoDamageSound;
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ namespace Content.Server.Weapon.Melee.Components
|
|||||||
{
|
{
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[DataField("hitSound")]
|
[DataField("hitSound")]
|
||||||
public SoundSpecifier HitSound { get; set; } = new SoundCollectionSpecifier("GenericHit");
|
public SoundSpecifier? HitSound;
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[DataField("missSound")]
|
[DataField("missSound")]
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ using Content.Shared.Damage;
|
|||||||
using Content.Shared.Sound;
|
using Content.Shared.Sound;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Hands;
|
using Content.Shared.Hands;
|
||||||
using Content.Shared.Interaction;
|
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using Content.Shared.Weapons.Melee;
|
using Content.Shared.Weapons.Melee;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
@@ -19,18 +19,22 @@ using Robust.Shared.Containers;
|
|||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.Weapon.Melee
|
namespace Content.Server.Weapon.Melee
|
||||||
{
|
{
|
||||||
public sealed class MeleeWeaponSystem : EntitySystem
|
public sealed class MeleeWeaponSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||||
[Dependency] private SolutionContainerSystem _solutionsSystem = default!;
|
[Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!;
|
||||||
[Dependency] private readonly AdminLogSystem _logSystem = default!;
|
[Dependency] private readonly AdminLogSystem _logSystem = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||||
|
|
||||||
|
private const float DamagePitchVariation = 0.15f;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
@@ -73,7 +77,7 @@ namespace Content.Server.Weapon.Melee
|
|||||||
if (curTime < comp.CooldownEnd || args.Target == null)
|
if (curTime < comp.CooldownEnd || args.Target == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var location = EntityManager.GetComponent<TransformComponent>(args.User).Coordinates;
|
var location = Transform(args.User).Coordinates;
|
||||||
var diff = args.ClickLocation.ToMapPos(EntityManager) - location.ToMapPos(EntityManager);
|
var diff = args.ClickLocation.ToMapPos(EntityManager) - location.ToMapPos(EntityManager);
|
||||||
var angle = Angle.FromWorldVec(diff);
|
var angle = Angle.FromWorldVec(diff);
|
||||||
|
|
||||||
@@ -103,19 +107,12 @@ namespace Content.Server.Weapon.Melee
|
|||||||
$"{ToPrettyString(args.User):user} melee attacked {ToPrettyString(args.Target.Value):target} using {ToPrettyString(args.Used):used} and dealt {damageResult.Total:damage} damage");
|
$"{ToPrettyString(args.User):user} melee attacked {ToPrettyString(args.Target.Value):target} using {ToPrettyString(args.Used):used} and dealt {damageResult.Total:damage} damage");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hitEvent.HitSoundOverride != null)
|
PlayHitSound(target, GetHighestDamageSound(modifiedDamage), hitEvent.HitSoundOverride, comp.HitSound);
|
||||||
{
|
|
||||||
SoundSystem.Play(Filter.Pvs(owner), hitEvent.HitSoundOverride.GetSound(), target, AudioHelpers.WithVariation(0.25f));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SoundSystem.Play(Filter.Pvs(owner), comp.HitSound.GetSound(), target);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SoundSystem.Play(Filter.Pvs(owner), comp.MissSound.GetSound(), args.User);
|
SoundSystem.Play(Filter.Pvs(owner, entityManager: EntityManager), comp.MissSound.GetSound(), args.User);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,24 +158,20 @@ namespace Content.Server.Weapon.Melee
|
|||||||
|
|
||||||
if (!hitEvent.Handled)
|
if (!hitEvent.Handled)
|
||||||
{
|
{
|
||||||
|
var modifiedDamage = DamageSpecifier.ApplyModifierSets(comp.Damage + hitEvent.BonusDamage, hitEvent.ModifiersList);
|
||||||
|
|
||||||
if (entities.Count != 0)
|
if (entities.Count != 0)
|
||||||
{
|
{
|
||||||
if (hitEvent.HitSoundOverride != null)
|
var target = entities.First();
|
||||||
{
|
TryComp<MeleeWeaponComponent>(target, out var meleeWeapon);
|
||||||
SoundSystem.Play(Filter.Pvs(owner), hitEvent.HitSoundOverride.GetSound(), Transform(entities.First()).Coordinates);
|
|
||||||
}
|
PlayHitSound(target, GetHighestDamageSound(modifiedDamage), hitEvent.HitSoundOverride, meleeWeapon?.HitSound);
|
||||||
else
|
|
||||||
{
|
|
||||||
SoundSystem.Play(Filter.Pvs(owner), comp.HitSound.GetSound(), Transform(entities.First()).Coordinates);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SoundSystem.Play(Filter.Pvs(owner), comp.MissSound.GetSound(), Transform(args.User).Coordinates);
|
SoundSystem.Play(Filter.Pvs(owner), comp.MissSound.GetSound(), Transform(args.User).Coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
var modifiedDamage = DamageSpecifier.ApplyModifierSets(comp.Damage + hitEvent.BonusDamage, hitEvent.ModifiersList);
|
|
||||||
|
|
||||||
foreach (var entity in hitEntities)
|
foreach (var entity in hitEntities)
|
||||||
{
|
{
|
||||||
RaiseLocalEvent(entity, new AttackedEvent(args.Used, args.User, args.ClickLocation));
|
RaiseLocalEvent(entity, new AttackedEvent(args.Used, args.User, args.ClickLocation));
|
||||||
@@ -203,6 +196,89 @@ namespace Content.Server.Weapon.Melee
|
|||||||
RaiseLocalEvent(owner, new RefreshItemCooldownEvent(comp.LastAttackTime, comp.CooldownEnd), false);
|
RaiseLocalEvent(owner, new RefreshItemCooldownEvent(comp.LastAttackTime, comp.CooldownEnd), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string? GetHighestDamageSound(DamageSpecifier modifiedDamage)
|
||||||
|
{
|
||||||
|
var groups = modifiedDamage.GetDamagePerGroup(_protoManager);
|
||||||
|
|
||||||
|
// Use group if it's exclusive, otherwise fall back to type.
|
||||||
|
if (groups.Count == 1)
|
||||||
|
{
|
||||||
|
return groups.Keys.First();
|
||||||
|
}
|
||||||
|
|
||||||
|
var highestDamage = FixedPoint2.Zero;
|
||||||
|
string? highestDamageType = null;
|
||||||
|
|
||||||
|
foreach (var (type, damage) in modifiedDamage.DamageDict)
|
||||||
|
{
|
||||||
|
if (damage <= highestDamage) continue;
|
||||||
|
highestDamageType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return highestDamageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PlayHitSound(EntityUid target, string? type, SoundSpecifier? hitSoundOverride, SoundSpecifier? hitSound)
|
||||||
|
{
|
||||||
|
var playedSound = false;
|
||||||
|
|
||||||
|
// Play sound based off of highest damage type.
|
||||||
|
if (TryComp<MeleeSoundComponent>(target, out var damageSoundComp))
|
||||||
|
{
|
||||||
|
if (type == null && damageSoundComp.NoDamageSound != null)
|
||||||
|
{
|
||||||
|
SoundSystem.Play(Filter.Pvs(target, entityManager: EntityManager), damageSoundComp.NoDamageSound.GetSound(), target, AudioHelpers.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
else if (type != null && damageSoundComp.SoundTypes?.TryGetValue(type, out var damageSoundType) == true)
|
||||||
|
{
|
||||||
|
SoundSystem.Play(Filter.Pvs(target, entityManager: EntityManager), damageSoundType!.GetSound(), target, AudioHelpers.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
else if (type != null && damageSoundComp.SoundGroups?.TryGetValue(type, out var damageSoundGroup) == true)
|
||||||
|
{
|
||||||
|
SoundSystem.Play(Filter.Pvs(target, entityManager: EntityManager), damageSoundGroup!.GetSound(), target, AudioHelpers.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use weapon sounds if the thing being hit doesn't specify its own sounds.
|
||||||
|
if (!playedSound)
|
||||||
|
{
|
||||||
|
if (hitSoundOverride != null)
|
||||||
|
{
|
||||||
|
SoundSystem.Play(Filter.Pvs(target, entityManager: EntityManager), hitSoundOverride.GetSound(), target, AudioHelpers.WithVariation(DamagePitchVariation));
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
else if (hitSound != null)
|
||||||
|
{
|
||||||
|
SoundSystem.Play(Filter.Pvs(target, entityManager: EntityManager), hitSound.GetSound(), target);
|
||||||
|
playedSound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to generic sounds.
|
||||||
|
if (!playedSound)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
// Unfortunately heat returns caustic group so can't just use the damagegroup in that instance.
|
||||||
|
case "Burn":
|
||||||
|
case "Heat":
|
||||||
|
case "Cold":
|
||||||
|
SoundSystem.Play(Filter.Pvs(target, entityManager: EntityManager), "/Audio/Items/welder.ogg", target);
|
||||||
|
break;
|
||||||
|
// No damage, fallback to tappies
|
||||||
|
case null:
|
||||||
|
SoundSystem.Play(Filter.Pvs(target, entityManager: EntityManager), "/Audio/Weapons/tap.ogg", target);
|
||||||
|
break;
|
||||||
|
case "Brute":
|
||||||
|
SoundSystem.Play(Filter.Pvs(target, entityManager: EntityManager), "/Audio/Weapons/smash.ogg", target);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private HashSet<EntityUid> ArcRayCast(Vector2 position, Angle angle, float arcWidth, float range, MapId mapId, EntityUid ignore)
|
private HashSet<EntityUid> ArcRayCast(Vector2 position, Angle angle, float arcWidth, float range, MapId mapId, EntityUid ignore)
|
||||||
{
|
{
|
||||||
var widthRad = Angle.FromDegrees(arcWidth);
|
var widthRad = Angle.FromDegrees(arcWidth);
|
||||||
|
|||||||
BIN
Resources/Audio/Weapons/dodgeball.ogg
Normal file
BIN
Resources/Audio/Weapons/dodgeball.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/Weapons/grille_hit.ogg
Normal file
BIN
Resources/Audio/Weapons/grille_hit.ogg
Normal file
Binary file not shown.
7
Resources/Audio/Weapons/licenses.txt
Normal file
7
Resources/Audio/Weapons/licenses.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
dodgeball.ogg taken from https://github.com/tgstation/tgstation/blob/5d264fbea0124e5af511af3fed24203e196d108b/sound/items/dodgeball.ogg under CC BY-SA 3.0
|
||||||
|
|
||||||
|
grille_hit.ogg taken from https://github.com/tgstation/tgstation/blob/803ca4537df35cf252b056d8460d510be8a4f353/sound/effects/grillehit.ogg under CC BY-SA 3.0
|
||||||
|
|
||||||
|
slash.ogg taken from https://github.com/tgstation/tgstation/blob/5d264fbea0124e5af511af3fed24203e196d108b/sound/weapons/slash.ogg under CC BY-SA 3.0
|
||||||
|
|
||||||
|
tap.ogg taken from https://github.com/tgstation/tgstation/blob/803ca4537df35cf252b056d8460d510be8a4f353/sound/weapons/tap.ogg under CC BY-SA 3.0
|
||||||
BIN
Resources/Audio/Weapons/slash.ogg
Normal file
BIN
Resources/Audio/Weapons/slash.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/Weapons/tap.ogg
Normal file
BIN
Resources/Audio/Weapons/tap.ogg
Normal file
Binary file not shown.
@@ -7,6 +7,11 @@
|
|||||||
snap:
|
snap:
|
||||||
- Wall
|
- Wall
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Weapons/slash.ogg"
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Misc/kudzu.rsi
|
sprite: Objects/Misc/kudzu.rsi
|
||||||
state: kudzu_11
|
state: kudzu_11
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
id: BaseLightbulb
|
id: BaseLightbulb
|
||||||
abstract: true
|
abstract: true
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Effects/glass_hit.ogg"
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
netsync: false
|
netsync: false
|
||||||
sprite: Objects/Power/light_bulb.rsi
|
sprite: Objects/Power/light_bulb.rsi
|
||||||
|
|||||||
@@ -85,6 +85,11 @@
|
|||||||
parent: Airlock
|
parent: Airlock
|
||||||
name: glass airlock
|
name: glass airlock
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Effects/glass_hit.ogg"
|
||||||
- type: Door
|
- type: Door
|
||||||
occludes: false
|
occludes: false
|
||||||
- type: Occluder
|
- type: Occluder
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
name: airlock
|
name: airlock
|
||||||
description: It opens, it closes, and maybe crushes you.
|
description: It opens, it closes, and maybe crushes you.
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Weapons/smash.ogg"
|
||||||
- type: InteractionOutline
|
- type: InteractionOutline
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
netsync: false
|
netsync: false
|
||||||
|
|||||||
@@ -5,6 +5,11 @@
|
|||||||
placement:
|
placement:
|
||||||
mode: SnapgridCenter
|
mode: SnapgridCenter
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Effects/glass_hit.ogg"
|
||||||
- type: InteractionOutline
|
- type: InteractionOutline
|
||||||
- type: Physics
|
- type: Physics
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
|
|||||||
@@ -5,6 +5,11 @@
|
|||||||
parent: SeatBase
|
parent: SeatBase
|
||||||
description: The HT-451, a torque rotation-based, waste disposal unit for small matter. This one seems remarkably clean.
|
description: The HT-451, a torque rotation-based, waste disposal unit for small matter. This one seems remarkably clean.
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Weapons/slash.ogg"
|
||||||
- type: Anchorable
|
- type: Anchorable
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Furniture/toilet.rsi
|
sprite: Structures/Furniture/toilet.rsi
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
placement:
|
placement:
|
||||||
mode: SnapgridCenter
|
mode: SnapgridCenter
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Effects/glass_hit.ogg"
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: Computer
|
graph: Computer
|
||||||
node: computer
|
node: computer
|
||||||
|
|||||||
@@ -5,6 +5,11 @@
|
|||||||
placement:
|
placement:
|
||||||
mode: SnapgridCenter
|
mode: SnapgridCenter
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Effects/glass_hit.ogg"
|
||||||
- type: Clickable
|
- type: Clickable
|
||||||
- type: InteractionOutline
|
- type: InteractionOutline
|
||||||
- type: Transform
|
- type: Transform
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
name: rack
|
name: rack
|
||||||
description: A rack for storing things on.
|
description: A rack for storing things on.
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Weapons/dodgeball.ogg"
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: Rack
|
graph: Rack
|
||||||
node: Rack
|
node: Rack
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
parent: BaseStructure
|
parent: BaseStructure
|
||||||
name: bar sign
|
name: bar sign
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Effects/glass_hit.ogg"
|
||||||
- type: WallMount
|
- type: WallMount
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
drawdepth: Objects
|
drawdepth: Objects
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
name: fire axe cabinet
|
name: fire axe cabinet
|
||||||
description: There is a small label that reads "For Emergency use only" along with details for safe use of the axe. As if.
|
description: There is a small label that reads "For Emergency use only" along with details for safe use of the axe. As if.
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Effects/glass_hit.ogg"
|
||||||
- type: WallMount
|
- type: WallMount
|
||||||
- type: Clickable
|
- type: Clickable
|
||||||
- type: InteractionOutline
|
- type: InteractionOutline
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
description: "An unpowered light."
|
description: "An unpowered light."
|
||||||
suffix: Unpowered
|
suffix: Unpowered
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Effects/glass_hit.ogg"
|
||||||
- type: Transform
|
- type: Transform
|
||||||
anchored: true
|
anchored: true
|
||||||
- type: Clickable
|
- type: Clickable
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
name: grille
|
name: grille
|
||||||
description: A flimsy framework of iron rods.
|
description: A flimsy framework of iron rods.
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Weapons/grille_hit.ogg"
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- RCDDeconstructWhitelist
|
- RCDDeconstructWhitelist
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
snap:
|
snap:
|
||||||
- Window
|
- Window
|
||||||
components:
|
components:
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Effects/glass_hit.ogg"
|
||||||
- type: WallMount
|
- type: WallMount
|
||||||
arc: 360 # interact despite grilles
|
arc: 360 # interact despite grilles
|
||||||
- type: Tag
|
- type: Tag
|
||||||
|
|||||||
Reference in New Issue
Block a user