More robust bullet impact sounds (#8325)

This commit is contained in:
metalgearsloth
2022-05-22 18:23:37 +10:00
committed by GitHub
parent 4a86f38251
commit 0084ca721b
27 changed files with 322 additions and 185 deletions

View File

@@ -350,6 +350,7 @@ namespace Content.Client.Entry
"RandomArtifactSprite", "RandomArtifactSprite",
"EnergySword", "EnergySword",
"MeleeSound", "MeleeSound",
"RangedDamageSound",
"DoorRemote", "DoorRemote",
"InteractionPopup", "InteractionPopup",
"HealthAnalyzer", "HealthAnalyzer",

View File

@@ -1,3 +1,4 @@
using Content.Server.Weapon.Ranged;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.Physics; using Content.Shared.Physics;
using Content.Shared.Sound; using Content.Shared.Sound;
@@ -38,8 +39,12 @@ namespace Content.Server.Projectiles.Components
private string? _muzzleFlash; private string? _muzzleFlash;
[DataField("impactFlash")] [DataField("impactFlash")]
private string? _impactFlash; private string? _impactFlash;
[DataField("soundHitWall")]
private SoundSpecifier _soundHitWall = new SoundPathSpecifier("/Audio/Weapons/Guns/Hits/laser_sear_wall.ogg"); [DataField("soundHit")]
public SoundSpecifier? SoundHit;
[DataField("soundForce")]
public bool ForceSound = false;
public void FireEffects(EntityUid user, float distance, Angle angle, EntityUid? hitEntity = null) public void FireEffects(EntityUid user, float distance, Angle angle, EntityUid? hitEntity = null)
{ {
@@ -80,14 +85,6 @@ namespace Content.Server.Projectiles.Components
} }
} }
if (hitEntity != null && _soundHitWall != null)
{
// TODO: No wall component so ?
var offset = localAngle.ToVec().Normalized / 2;
var coordinates = localCoordinates.Offset(offset);
SoundSystem.Play(Filter.Pvs(coordinates), _soundHitWall.GetSound(), coordinates);
}
Owner.SpawnTimer((int) _deathTime.TotalMilliseconds, () => Owner.SpawnTimer((int) _deathTime.TotalMilliseconds, () =>
{ {
if (!_entMan.Deleted(Owner)) if (!_entMan.Deleted(Owner))

View File

@@ -17,7 +17,9 @@ namespace Content.Server.Projectiles.Components
// Get that juicy FPS hit sound // Get that juicy FPS hit sound
[DataField("soundHit")] public SoundSpecifier? SoundHit; [DataField("soundHit")] public SoundSpecifier? SoundHit;
[DataField("soundHitSpecies")] public SoundSpecifier? SoundHitSpecies;
[DataField("soundForce")]
public bool ForceSound = false;
public bool DamagedEntity; public bool DamagedEntity;

View File

@@ -1,5 +1,8 @@
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.Projectiles.Components; using Content.Server.Projectiles.Components;
using Content.Server.Weapon.Melee;
using Content.Server.Weapon.Ranged;
using Content.Shared.Audio;
using Content.Shared.Body.Components; using Content.Shared.Body.Components;
using Content.Shared.Camera; using Content.Shared.Camera;
using Content.Shared.Damage; using Content.Shared.Damage;
@@ -10,6 +13,7 @@ using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Physics.Dynamics; using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Prototypes;
namespace Content.Server.Projectiles namespace Content.Server.Projectiles
{ {
@@ -19,6 +23,7 @@ namespace Content.Server.Projectiles
[Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly AdminLogSystem _adminLogSystem = default!; [Dependency] private readonly AdminLogSystem _adminLogSystem = default!;
[Dependency] private readonly CameraRecoilSystem _cameraRecoil = default!; [Dependency] private readonly CameraRecoilSystem _cameraRecoil = default!;
[Dependency] private readonly GunSystem _guns = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -36,42 +41,27 @@ namespace Content.Server.Projectiles
var otherEntity = args.OtherFixture.Body.Owner; var otherEntity = args.OtherFixture.Body.Owner;
var coordinates = EntityManager.GetComponent<TransformComponent>(args.OtherFixture.Body.Owner).Coordinates; var modifiedDamage = _damageableSystem.TryChangeDamage(otherEntity, component.Damage);
var playerFilter = Filter.Pvs(coordinates, entityMan: EntityManager); component.DamagedEntity = true;
if (!EntityManager.GetComponent<MetaDataComponent>(otherEntity).EntityDeleted && component.SoundHitSpecies != null && if (modifiedDamage is not null && EntityManager.EntityExists(component.Shooter))
EntityManager.HasComponent<SharedBodyComponent>(otherEntity))
{ {
SoundSystem.Play(playerFilter, component.SoundHitSpecies.GetSound(), coordinates); _adminLogSystem.Add(LogType.BulletHit,
} HasComp<ActorComponent>(otherEntity) ? LogImpact.Extreme : LogImpact.High,
else $"Projectile {ToPrettyString(component.Owner):projectile} shot by {ToPrettyString(component.Shooter):user} hit {ToPrettyString(otherEntity):target} and dealt {modifiedDamage.Total:damage} damage");
{
var soundHit = component.SoundHit?.GetSound();
if (!string.IsNullOrEmpty(soundHit))
SoundSystem.Play(playerFilter, soundHit, coordinates);
} }
if (!EntityManager.GetComponent<MetaDataComponent>(otherEntity).EntityDeleted) _guns.PlaySound(otherEntity, modifiedDamage, component.SoundHit, component.ForceSound);
{
var dmg = _damageableSystem.TryChangeDamage(otherEntity, component.Damage);
component.DamagedEntity = true;
if (dmg is not null && EntityManager.EntityExists(component.Shooter))
_adminLogSystem.Add(LogType.BulletHit,
HasComp<ActorComponent>(otherEntity) ? LogImpact.Extreme : LogImpact.High,
$"Projectile {ToPrettyString(component.Owner):projectile} shot by {ToPrettyString(component.Shooter):user} hit {ToPrettyString(otherEntity):target} and dealt {dmg.Total:damage} damage");
}
// Damaging it can delete it // Damaging it can delete it
if (!Deleted(otherEntity) && HasComp<CameraRecoilComponent>(otherEntity)) if (HasComp<CameraRecoilComponent>(otherEntity))
{ {
var direction = args.OurFixture.Body.LinearVelocity.Normalized; var direction = args.OurFixture.Body.LinearVelocity.Normalized;
_cameraRecoil.KickCamera(otherEntity, direction); _cameraRecoil.KickCamera(otherEntity, direction);
} }
if (component.DeleteOnCollide) if (component.DeleteOnCollide)
EntityManager.QueueDeleteEntity(uid); QueueDel(uid);
} }
public override void Update(float frameTime) public override void Update(float frameTime)

View File

@@ -33,7 +33,7 @@ namespace Content.Server.Weapon.Melee
[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 const float DamagePitchVariation = 0.15f;
public override void Initialize() public override void Initialize()
{ {
@@ -107,7 +107,7 @@ 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");
} }
PlayHitSound(target, GetHighestDamageSound(modifiedDamage), hitEvent.HitSoundOverride, comp.HitSound); PlayHitSound(target, GetHighestDamageSound(modifiedDamage, _protoManager), hitEvent.HitSoundOverride, comp.HitSound);
} }
} }
else else
@@ -165,7 +165,7 @@ namespace Content.Server.Weapon.Melee
var target = entities.First(); var target = entities.First();
TryComp<MeleeWeaponComponent>(target, out var meleeWeapon); TryComp<MeleeWeaponComponent>(target, out var meleeWeapon);
PlayHitSound(target, GetHighestDamageSound(modifiedDamage), hitEvent.HitSoundOverride, meleeWeapon?.HitSound); PlayHitSound(target, GetHighestDamageSound(modifiedDamage, _protoManager), hitEvent.HitSoundOverride, meleeWeapon?.HitSound);
} }
else else
{ {
@@ -196,9 +196,9 @@ 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) public static string? GetHighestDamageSound(DamageSpecifier modifiedDamage, IPrototypeManager protoManager)
{ {
var groups = modifiedDamage.GetDamagePerGroup(_protoManager); var groups = modifiedDamage.GetDamagePerGroup(protoManager);
// Use group if it's exclusive, otherwise fall back to type. // Use group if it's exclusive, otherwise fall back to type.
if (groups.Count == 1) if (groups.Count == 1)

View File

@@ -3,12 +3,16 @@ using Content.Server.CombatMode;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.Interaction.Components; using Content.Server.Interaction.Components;
using Content.Server.Projectiles.Components; using Content.Server.Projectiles.Components;
using Content.Server.Weapon.Melee;
using Content.Server.Weapon.Ranged.Ammunition.Components; using Content.Server.Weapon.Ranged.Ammunition.Components;
using Content.Server.Weapon.Ranged.Barrels.Components; using Content.Server.Weapon.Ranged.Barrels.Components;
using Content.Shared.Audio;
using Content.Shared.Camera; using Content.Shared.Camera;
using Content.Shared.Damage;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Interaction.Events; using Content.Shared.Interaction.Events;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Sound;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Physics; using Robust.Shared.Physics;
@@ -239,10 +243,12 @@ public sealed partial class GunSystem
var result = rayCastResults[0]; var result = rayCastResults[0];
var distance = result.Distance; var distance = result.Distance;
hitscan.FireEffects(shooter, distance, angle, result.HitEntity); hitscan.FireEffects(shooter, distance, angle, result.HitEntity);
var dmg = _damageable.TryChangeDamage(result.HitEntity, hitscan.Damage); var modifiedDamage = _damageable.TryChangeDamage(result.HitEntity, hitscan.Damage);
if (dmg != null) if (modifiedDamage != null)
_logs.Add(LogType.HitScanHit, _logs.Add(LogType.HitScanHit,
$"{EntityManager.ToPrettyString(shooter):user} hit {EntityManager.ToPrettyString(result.HitEntity):target} using {EntityManager.ToPrettyString(hitscan.Owner):used} and dealt {dmg.Total:damage} damage"); $"{EntityManager.ToPrettyString(shooter):user} hit {EntityManager.ToPrettyString(result.HitEntity):target} using {EntityManager.ToPrettyString(hitscan.Owner):used} and dealt {modifiedDamage.Total:damage} damage");
PlaySound(rayCastResults[0].HitEntity, modifiedDamage, hitscan.SoundHit, hitscan.ForceSound);
} }
else else
{ {
@@ -251,4 +257,46 @@ public sealed partial class GunSystem
} }
#endregion #endregion
#region Impact sounds
public void PlaySound(EntityUid otherEntity, DamageSpecifier? modifiedDamage, SoundSpecifier? weaponSound, bool forceWeaponSound)
{
// Like projectiles and melee,
// 1. Entity specific sound
// 2. Ammo's sound
// 3. Nothing
var playedSound = false;
if (!forceWeaponSound && modifiedDamage != null && modifiedDamage.Total > 0 && TryComp<RangedDamageSoundComponent>(otherEntity, out var rangedSound))
{
var type = MeleeWeaponSystem.GetHighestDamageSound(modifiedDamage, _protoManager);
if (type != null && rangedSound.SoundTypes?.TryGetValue(type, out var damageSoundType) == true)
{
SoundSystem.Play(
Filter.Pvs(otherEntity, entityManager: EntityManager),
damageSoundType!.GetSound(),
otherEntity,
AudioHelpers.WithVariation(DamagePitchVariation));
playedSound = true;
}
else if (type != null && rangedSound.SoundGroups?.TryGetValue(type, out var damageSoundGroup) == true)
{
SoundSystem.Play(
Filter.Pvs(otherEntity, entityManager: EntityManager),
damageSoundGroup!.GetSound(),
otherEntity,
AudioHelpers.WithVariation(DamagePitchVariation));
playedSound = true;
}
}
if (!playedSound && weaponSound != null)
SoundSystem.Play(Filter.Pvs(otherEntity, entityManager: EntityManager), weaponSound.GetSound(), otherEntity);
}
#endregion
} }

View File

@@ -3,6 +3,7 @@ using Content.Server.Atmos.EntitySystems;
using Content.Server.Hands.Components; using Content.Server.Hands.Components;
using Content.Server.PowerCell; using Content.Server.PowerCell;
using Content.Server.Stunnable; using Content.Server.Stunnable;
using Content.Server.Weapon.Melee;
using Content.Server.Weapon.Ranged.Ammunition.Components; using Content.Server.Weapon.Ranged.Ammunition.Components;
using Content.Server.Weapon.Ranged.Barrels.Components; using Content.Server.Weapon.Ranged.Barrels.Components;
using Content.Shared.ActionBlocker; using Content.Shared.ActionBlocker;
@@ -22,6 +23,7 @@ using Robust.Shared.Containers;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Timing; using Robust.Shared.Timing;
@@ -30,6 +32,7 @@ namespace Content.Server.Weapon.Ranged;
public sealed partial class GunSystem : EntitySystem public sealed partial class GunSystem : EntitySystem
{ {
[Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ActionBlockerSystem _blocker = default!; [Dependency] private readonly ActionBlockerSystem _blocker = default!;
[Dependency] private readonly AdminLogSystem _logs = default!; [Dependency] private readonly AdminLogSystem _logs = default!;
@@ -44,6 +47,8 @@ public sealed partial class GunSystem : EntitySystem
[Dependency] private readonly StunSystem _stun = default!; [Dependency] private readonly StunSystem _stun = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
public const float DamagePitchVariation = MeleeWeaponSystem.DamagePitchVariation;
/// <summary> /// <summary>
/// How many sounds are allowed to be played on ejecting multiple casings. /// How many sounds are allowed to be played on ejecting multiple casings.
/// </summary> /// </summary>

View File

@@ -0,0 +1,30 @@
using Content.Shared.Damage.Prototypes;
using Content.Shared.Sound;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
namespace Content.Server.Weapon.Ranged;
/// <summary>
/// Plays the specified sound upon receiving damage of that type.
/// </summary>
[RegisterComponent]
public sealed class RangedDamageSoundComponent : Component
{
// TODO: Limb damage changing sound type.
/// <summary>
/// Specified sounds to apply when the entity takes damage with the specified group.
/// Will fallback to defaults if none specified.
/// </summary>
[ViewVariables, 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>
[ViewVariables, DataField("soundTypes",
customTypeSerializer: typeof(PrototypeIdDictionarySerializer<SoundSpecifier, DamageTypePrototype>))]
public Dictionary<string, SoundSpecifier>? SoundTypes;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,16 @@
Taken from https://github.com/Citadel-Station-13/Citadel-Station-13-RP/tree/cc701aedb633d83eae8339a8b3712ad8ad99cca0/sound licensed under CC BY-SA 3.0. Remixed to mono where it was stereo by metalgearsloth:
- bullet_meat1.ogg
- bullet_meat2.ogg
- bullet_meat3.ogg
- bullet_meat4.ogg
- energy_meat1.ogg
- energy_meat2.ogg
- energy_metal1.ogg
- energy_metal2.ogg
Taken from https://github.com/tgstation/tgstation/tree/7501504b0ea029d2cf1c0336d09db5c0959aa412/sound/weapons/effects CC BY-SA 3.0.
- ric1.ogg
- ric2.ogg
- ric3.ogg
- ric4.ogg
- ric5.ogg

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -6,6 +6,15 @@
description: A miserable pile of secrets. description: A miserable pile of secrets.
noSpawn: true noSpawn: true
components: components:
- type: RangedDamageSound
soundGroups:
Brute:
collection:
MeatBulletImpact
soundTypes:
Heat:
collection:
MeatLaserImpact
- type: Tag - type: Tag
tags: tags:
- CanPilot - CanPilot

View File

@@ -5,148 +5,148 @@
description: A miserable pile of slime. description: A miserable pile of slime.
abstract: true abstract: true
components: components:
- type: Icon - type: Icon
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: full state: full
- type: Sprite - type: Sprite
netsync: false netsync: false
drawdepth: Mobs drawdepth: Mobs
layers: layers:
- map: [ "enum.HumanoidVisualLayers.Chest" ] - map: [ "enum.HumanoidVisualLayers.Chest" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: torso_m state: torso_m
- map: [ "enum.HumanoidVisualLayers.Head" ] - map: [ "enum.HumanoidVisualLayers.Head" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: head_m state: head_m
- map: [ "enum.HumanoidVisualLayers.Eyes" ] - map: [ "enum.HumanoidVisualLayers.Eyes" ]
color: "#008800" color: "#008800"
sprite: Mobs/Customization/eyes.rsi sprite: Mobs/Customization/eyes.rsi
state: eyes state: eyes
- map: [ "enum.HumanoidVisualLayers.RArm" ] - map: [ "enum.HumanoidVisualLayers.RArm" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: r_arm state: r_arm
- map: [ "enum.HumanoidVisualLayers.LArm" ] - map: [ "enum.HumanoidVisualLayers.LArm" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: l_arm state: l_arm
- map: [ "enum.HumanoidVisualLayers.RLeg" ] - map: [ "enum.HumanoidVisualLayers.RLeg" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: r_leg state: r_leg
- map: [ "enum.HumanoidVisualLayers.LLeg" ] - map: [ "enum.HumanoidVisualLayers.LLeg" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: l_leg state: l_leg
- shader: StencilClear - shader: StencilClear
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: l_leg state: l_leg
- shader: StencilMask - shader: StencilMask
map: [ "enum.HumanoidVisualLayers.StencilMask" ] map: [ "enum.HumanoidVisualLayers.StencilMask" ]
sprite: Mobs/Customization/masking_helpers.rsi sprite: Mobs/Customization/masking_helpers.rsi
state: female_full state: female_full
visible: false visible: false
- map: [ "jumpsuit" ] - map: [ "jumpsuit" ]
shader: StencilDraw shader: StencilDraw
- map: [ "enum.HumanoidVisualLayers.LHand" ] - map: [ "enum.HumanoidVisualLayers.LHand" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: l_hand state: l_hand
- map: [ "enum.HumanoidVisualLayers.RHand" ] - map: [ "enum.HumanoidVisualLayers.RHand" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: r_hand state: r_hand
- map: [ "enum.HumanoidVisualLayers.LFoot" ] - map: [ "enum.HumanoidVisualLayers.LFoot" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: l_foot state: l_foot
- map: [ "enum.HumanoidVisualLayers.RFoot" ] - map: [ "enum.HumanoidVisualLayers.RFoot" ]
color: "#b8b8b8" color: "#b8b8b8"
sprite: Mobs/Species/Slime/parts.rsi sprite: Mobs/Species/Slime/parts.rsi
state: r_foot state: r_foot
- map: [ "enum.HumanoidVisualLayers.Handcuffs" ] - map: [ "enum.HumanoidVisualLayers.Handcuffs" ]
color: "#ffffff" color: "#ffffff"
sprite: Objects/Misc/handcuffs.rsi sprite: Objects/Misc/handcuffs.rsi
state: body-overlay-2 state: body-overlay-2
visible: false visible: false
- map: [ "id" ] - map: [ "id" ]
- map: [ "gloves" ] - map: [ "gloves" ]
- map: [ "shoes" ] - map: [ "shoes" ]
- map: [ "ears" ] - map: [ "ears" ]
- map: [ "outerClothing" ] - map: [ "outerClothing" ]
- map: [ "eyes" ] - map: [ "eyes" ]
- map: [ "belt" ] - map: [ "belt" ]
- map: [ "neck" ] - map: [ "neck" ]
- map: [ "back" ] - map: [ "back" ]
- map: [ "enum.HumanoidVisualLayers.FacialHair" ] - map: [ "enum.HumanoidVisualLayers.FacialHair" ]
state: shaved state: shaved
sprite: Mobs/Customization/human_facial_hair.rsi sprite: Mobs/Customization/human_facial_hair.rsi
- map: [ "enum.HumanoidVisualLayers.Hair" ] - map: [ "enum.HumanoidVisualLayers.Hair" ]
state: bald state: bald
sprite: Mobs/Customization/human_hair.rsi sprite: Mobs/Customization/human_hair.rsi
- map: [ "mask" ] - map: [ "mask" ]
- map: [ "head" ] - map: [ "head" ]
- map: [ "pocket1" ] - map: [ "pocket1" ]
- map: [ "pocket2" ] - map: [ "pocket2" ]
- type: Markings - type: Markings
layerPoints: layerPoints:
Legs: Legs:
points: 2 points: 2
required: false required: false
Arms: Arms:
points: 4 points: 4
required: false required: false
- type: Body - type: Body
template: HumanoidTemplate template: HumanoidTemplate
preset: SlimePreset preset: SlimePreset
- type: HumanoidAppearance - type: HumanoidAppearance
hairMatchesSkin: true hairMatchesSkin: true
hairAlpha: 0.5 hairAlpha: 0.5
- type: Damageable - type: Damageable
damageContainer: Biological damageContainer: Biological
damageModifierSet: Slime damageModifierSet: Slime
- type: Bloodstream - type: Bloodstream
bloodReagent: Slime # TODO Color slime blood based on their slime color or smth bloodReagent: Slime # TODO Color slime blood based on their slime color or smth
bloodlossDamage: bloodlossDamage:
types: types:
Bloodloss: Bloodloss:
1 1
bloodlossHealDamage: bloodlossHealDamage:
types: types:
Bloodloss: Bloodloss:
-0.25 -0.25
- type: Barotrauma - type: Barotrauma
damage: damage:
types: types:
Blunt: 1.4 #per second, scales with pressure and other constants. Twice as much as humans. Blunt: 1.4 #per second, scales with pressure and other constants. Twice as much as humans.
- type: Reactive - type: Reactive
groups: groups:
Flammable: [ Touch ] Flammable: [ Touch ]
Extinguish: [ Touch ] Extinguish: [ Touch ]
reactions: reactions:
- reagents: [ Water, SpaceCleaner ] - reagents: [ Water, SpaceCleaner ]
methods: [ Touch ] methods: [ Touch ]
effects: effects:
- !type:WashCreamPieReaction - !type:WashCreamPieReaction
- reagents: [ Water ] - reagents: [ Water ]
methods: [ Touch ] methods: [ Touch ]
effects: effects:
- !type:HealthChange - !type:HealthChange
scaled: true scaled: true
damage: damage:
types: types:
Heat: 2 Heat: 2
- !type:PopupMessage - !type:PopupMessage
type: Local type: Local
messages: [ "slime-hurt-by-water-popup" ] messages: [ "slime-hurt-by-water-popup" ]
probability: 0.25 probability: 0.25
- type: Butcherable - type: Butcherable
butcheringType: Spike butcheringType: Spike
spawned: spawned:
- id: FoodMeatSlime - id: FoodMeatSlime
amount: 5 amount: 5
- type: entity - type: entity
save: false save: false

View File

@@ -147,6 +147,7 @@
Heat: 5 Heat: 5
soundHit: soundHit:
path: "/Audio/Weapons/Guns/Hits/taser_hit.ogg" path: "/Audio/Weapons/Guns/Hits/taser_hit.ogg"
soundForce: true
- type: StunOnCollide - type: StunOnCollide
stunAmount: 5 stunAmount: 5
knockdownAmount: 5 knockdownAmount: 5

View File

@@ -9,6 +9,15 @@
snap: snap:
- Wall - Wall
components: components:
- type: RangedDamageSound
soundGroups:
Brute:
collection:
MetalBulletImpact
soundTypes:
Heat:
collection:
MetalLaserImpact
- type: Tag - type: Tag
tags: tags:
- Wall - Wall

View File

@@ -0,0 +1,29 @@
- type: soundCollection
id: MeatBulletImpact
files:
- "/Audio/Weapons/Guns/Hits/bullet_meat1.ogg"
- "/Audio/Weapons/Guns/Hits/bullet_meat2.ogg"
- "/Audio/Weapons/Guns/Hits/bullet_meat3.ogg"
- "/Audio/Weapons/Guns/Hits/bullet_meat4.ogg"
- type: soundCollection
id: MeatLaserImpact
files:
- "/Audio/Weapons/Guns/Hits/energy_meat1.ogg"
- "/Audio/Weapons/Guns/Hits/energy_meat2.ogg"
- type: soundCollection
id: MetalBulletImpact
files:
- "/Audio/Weapons/Guns/Hits/ric1.ogg"
- "/Audio/Weapons/Guns/Hits/ric2.ogg"
- "/Audio/Weapons/Guns/Hits/ric3.ogg"
- "/Audio/Weapons/Guns/Hits/ric4.ogg"
- "/Audio/Weapons/Guns/Hits/ric5.ogg"
- type: soundCollection
id: MetalLaserImpact
files:
- "/Audio/Weapons/Guns/Hits/energy_metal1.ogg"
- "/Audio/Weapons/Guns/Hits/energy_metal2.ogg"