Make clown clumsy. (#1481)

Co-authored-by: scuffedjays <yetanotherscuffed@gmail.com>
This commit is contained in:
Pieter-Jan Briers
2020-07-26 14:08:09 +02:00
committed by GitHub
parent fbbe43fff8
commit 2bd318e83f
9 changed files with 141 additions and 34 deletions

View 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.
}
}

View File

@@ -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";
}
}

View File

@@ -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))
{ {

View File

@@ -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);
} }

View File

@@ -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)

View 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>();
}
}
}

View File

@@ -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();
}
} }
} }
} }

View 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)
{
}
}
}

View File

@@ -8,6 +8,7 @@
icon: "Clown" icon: "Clown"
access: access:
- Theatre - Theatre
special: !type:ClownSpecial {}
- type: startingGear - type: startingGear
id: ClownGear id: ClownGear