Make clown clumsy. (#1481)
Co-authored-by: scuffedjays <yetanotherscuffed@gmail.com>
This commit is contained in:
committed by
GitHub
parent
fbbe43fff8
commit
2bd318e83f
12
Content.Client/Jobs/ClownSpecial.cs
Normal file
12
Content.Client/Jobs/ClownSpecial.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Content.Server.Jobs;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
|
namespace Content.Client.Jobs
|
||||||
|
{
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed class ClownSpecial : JobSpecial
|
||||||
|
{
|
||||||
|
// Dummy class that exists solely to avoid an exception on the client,
|
||||||
|
// but allow the server-side counterpart to exist.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Mobs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A simple clumsy tag-component.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public class ClumsyComponent : Component
|
||||||
|
{
|
||||||
|
public override string Name => "Clumsy";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ using Robust.Shared.Prototypes;
|
|||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
using Content.Server.Interfaces;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
||||||
{
|
{
|
||||||
@@ -41,6 +42,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
|||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[Dependency] private IGameTiming _gameTiming;
|
[Dependency] private IGameTiming _gameTiming;
|
||||||
[Dependency] private IRobustRandom _robustRandom;
|
[Dependency] private IRobustRandom _robustRandom;
|
||||||
|
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
public override FireRateSelector FireRateSelector => _fireRateSelector;
|
public override FireRateSelector FireRateSelector => _fireRateSelector;
|
||||||
@@ -235,6 +237,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Barrels
|
|||||||
recoilComponent.Kick(-angle.ToVec() * 0.15f);
|
recoilComponent.Kick(-angle.ToVec() * 0.15f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This section probably needs tweaking so there can be caseless hitscan etc.
|
// This section probably needs tweaking so there can be caseless hitscan etc.
|
||||||
if (projectile.TryGetComponent(out HitscanComponent hitscan))
|
if (projectile.TryGetComponent(out HitscanComponent hitscan))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,17 +2,27 @@ using System;
|
|||||||
using Content.Server.GameObjects.Components.GUI;
|
using Content.Server.GameObjects.Components.GUI;
|
||||||
using Content.Server.GameObjects.Components.Mobs;
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels;
|
using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels;
|
||||||
|
using Content.Shared.GameObjects;
|
||||||
using Content.Shared.GameObjects.Components.Weapons.Ranged;
|
using Content.Shared.GameObjects.Components.Weapons.Ranged;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.Interfaces;
|
||||||
using Content.Shared.Interfaces.GameObjects.Components;
|
using Content.Shared.Interfaces.GameObjects.Components;
|
||||||
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Network;
|
using Robust.Shared.Interfaces.Network;
|
||||||
|
using Robust.Shared.Interfaces.Random;
|
||||||
using Robust.Shared.Interfaces.Timing;
|
using Robust.Shared.Interfaces.Timing;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Log;
|
using Robust.Shared.Log;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Players;
|
using Robust.Shared.Players;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Weapon.Ranged
|
namespace Content.Server.GameObjects.Components.Weapon.Ranged
|
||||||
{
|
{
|
||||||
@@ -21,6 +31,11 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
|
|||||||
{
|
{
|
||||||
private TimeSpan _lastFireTime;
|
private TimeSpan _lastFireTime;
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool ClumsyCheck { get; set; }
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float ClumsyExplodeChance { get; set; }
|
||||||
|
|
||||||
public Func<bool> WeaponCanFireHandler;
|
public Func<bool> WeaponCanFireHandler;
|
||||||
public Func<IEntity, bool> UserCanFireHandler;
|
public Func<IEntity, bool> UserCanFireHandler;
|
||||||
public Action<IEntity, GridCoordinates> FireHandler;
|
public Action<IEntity, GridCoordinates> FireHandler;
|
||||||
@@ -54,6 +69,14 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
|
|||||||
return (UserCanFireHandler == null || UserCanFireHandler(user)) && ActionBlockerSystem.CanAttack(user);
|
return (UserCanFireHandler == null || UserCanFireHandler(user)) && ActionBlockerSystem.CanAttack(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
|
serializer.DataField(this, p => p.ClumsyCheck, "clumsyCheck", true);
|
||||||
|
serializer.DataField(this, p => p.ClumsyExplodeChance, "clumsyExplodeChance", 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null)
|
public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession session = null)
|
||||||
{
|
{
|
||||||
base.HandleNetworkMessage(message, channel, session);
|
base.HandleNetworkMessage(message, channel, session);
|
||||||
@@ -106,6 +129,35 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged
|
|||||||
}
|
}
|
||||||
|
|
||||||
_lastFireTime = curTime;
|
_lastFireTime = curTime;
|
||||||
|
|
||||||
|
if (ClumsyCheck &&
|
||||||
|
user.HasComponent<ClumsyComponent>() &&
|
||||||
|
IoCManager.Resolve<IRobustRandom>().Prob(ClumsyExplodeChance))
|
||||||
|
{
|
||||||
|
var soundSystem = EntitySystem.Get<AudioSystem>();
|
||||||
|
soundSystem.PlayAtCoords("/Audio/Items/bikehorn.ogg",
|
||||||
|
Owner.Transform.GridPosition, AudioParams.Default, 5);
|
||||||
|
|
||||||
|
soundSystem.PlayAtCoords("/Audio/Weapons/Guns/Gunshots/bang.ogg",
|
||||||
|
Owner.Transform.GridPosition, AudioParams.Default, 5);
|
||||||
|
|
||||||
|
if (user.TryGetComponent(out DamageableComponent health))
|
||||||
|
{
|
||||||
|
health.TakeDamage(DamageType.Brute, 10);
|
||||||
|
health.TakeDamage(DamageType.Heat, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.TryGetComponent(out StunnableComponent stun))
|
||||||
|
{
|
||||||
|
stun.Paralyze(3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
user.PopupMessage(user, Loc.GetString("The gun blows up in your face!"));
|
||||||
|
|
||||||
|
Owner.Delete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FireHandler?.Invoke(user, coordinates);
|
FireHandler?.Invoke(user, coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -777,6 +777,7 @@ namespace Content.Server.GameTicking
|
|||||||
AddManifestEntry(character.Name, jobId);
|
AddManifestEntry(character.Name, jobId);
|
||||||
AddSpawnedPosition(jobId);
|
AddSpawnedPosition(jobId);
|
||||||
EquipIdCard(mob, character.Name, jobPrototype);
|
EquipIdCard(mob, character.Name, jobPrototype);
|
||||||
|
jobPrototype.Special?.AfterEquip(mob);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EquipIdCard(IEntity mob, string characterName, JobPrototype jobPrototype)
|
private void EquipIdCard(IEntity mob, string characterName, JobPrototype jobPrototype)
|
||||||
|
|||||||
18
Content.Server/Jobs/ClownSpecial.cs
Normal file
18
Content.Server/Jobs/ClownSpecial.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.Jobs
|
||||||
|
{
|
||||||
|
// Used by clown job def.
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed class ClownSpecial : JobSpecial
|
||||||
|
{
|
||||||
|
public override void AfterEquip(IEntity mob)
|
||||||
|
{
|
||||||
|
base.AfterEquip(mob);
|
||||||
|
|
||||||
|
mob.AddComponent<ClumsyComponent>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using Content.Server.Jobs;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Serialization;
|
||||||
using YamlDotNet.RepresentationModel;
|
using YamlDotNet.RepresentationModel;
|
||||||
|
|
||||||
namespace Content.Shared.Jobs
|
namespace Content.Shared.Jobs
|
||||||
@@ -41,44 +41,25 @@ namespace Content.Shared.Jobs
|
|||||||
|
|
||||||
public string Icon { get; private set; }
|
public string Icon { get; private set; }
|
||||||
|
|
||||||
|
public JobSpecial Special { get; private set; }
|
||||||
|
|
||||||
public IReadOnlyCollection<string> Department { get; private set; }
|
public IReadOnlyCollection<string> Department { get; private set; }
|
||||||
public IReadOnlyCollection<string> Access { get; private set; }
|
public IReadOnlyCollection<string> Access { get; private set; }
|
||||||
|
|
||||||
public void LoadFrom(YamlMappingNode mapping)
|
public void LoadFrom(YamlMappingNode mapping)
|
||||||
{
|
{
|
||||||
ID = mapping.GetNode("id").AsString();
|
var srz = YamlObjectSerializer.NewReader(mapping);
|
||||||
Name = Loc.GetString(mapping.GetNode("name").ToString());
|
ID = srz.ReadDataField<string>("id");
|
||||||
StartingGear = mapping.GetNode("startingGear").ToString();
|
Name = Loc.GetString(srz.ReadDataField<string>("name"));
|
||||||
Department = mapping.GetNode("department").AllNodes.Select(i => i.ToString()).ToList();
|
StartingGear = srz.ReadDataField<string>("startingGear");
|
||||||
TotalPositions = mapping.GetNode("positions").AsInt();
|
Department = srz.ReadDataField<List<string>>("department");
|
||||||
|
TotalPositions = srz.ReadDataField<int>("positions");
|
||||||
|
|
||||||
if (mapping.TryGetNode("spawnPositions", out var positionsNode))
|
srz.DataField(this, p => p.SpawnPositions, "spawnPositions", TotalPositions);
|
||||||
{
|
srz.DataField(this, p => p.IsHead, "head", false);
|
||||||
SpawnPositions = positionsNode.AsInt();
|
srz.DataField(this, p => p.Access, "access", Array.Empty<string>());
|
||||||
}
|
srz.DataField(this, p => p.Icon, "icon", null);
|
||||||
else
|
srz.DataField(this, p => p.Special, "special", null);
|
||||||
{
|
|
||||||
SpawnPositions = TotalPositions;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapping.TryGetNode("head", out var headNode))
|
|
||||||
{
|
|
||||||
IsHead = headNode.AsBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapping.TryGetNode("access", out YamlSequenceNode accessNode))
|
|
||||||
{
|
|
||||||
Access = accessNode.Select(i => i.ToString()).ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Access = Array.Empty<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapping.TryGetNode("icon", out var iconNode))
|
|
||||||
{
|
|
||||||
Icon = iconNode.AsString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
Content.Shared/Roles/JobSpecial.cs
Normal file
26
Content.Shared/Roles/JobSpecial.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Serialization;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Server.Jobs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides special hooks for when jobs get spawned in/equipped.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class JobSpecial : IExposeData
|
||||||
|
{
|
||||||
|
void IExposeData.ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
ExposeData(serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void AfterEquip(IEntity mob)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
icon: "Clown"
|
icon: "Clown"
|
||||||
access:
|
access:
|
||||||
- Theatre
|
- Theatre
|
||||||
|
special: !type:ClownSpecial {}
|
||||||
|
|
||||||
- type: startingGear
|
- type: startingGear
|
||||||
id: ClownGear
|
id: ClownGear
|
||||||
|
|||||||
Reference in New Issue
Block a user