Tweaks: разные мелкие исправления и корректировки (#22)
* add: система улучшения зрения для слепых * tweak: повышен урон дробовиков, повышен разброс * tweak: скорость снарядов лазеров увеличена вдвое * fix: фикс отображение веревки крюка-кошки * fix: исправлено отображение воспоминаний * tweak: перевод геймпресета революции * fix: фикс отображения цели и рефактор правила культа * add: Теперь помповые ружья нужно перезаряжать вручную * tweak: повышен урон других снарядов дробовиков * tweak: вещмешок синдиката больше не замедляет * fix: исправлено отображение слота хранилища костюма в инвентаре
This commit is contained in:
@@ -20,7 +20,7 @@ public sealed class CharacterInfoSystem : EntitySystem
|
||||
|
||||
public void RequestCharacterInfo()
|
||||
{
|
||||
var entity = _players.LocalPlayer?.ControlledEntity;
|
||||
var entity = _players.LocalSession?.AttachedEntity;
|
||||
if (entity == null)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
using Content.Client.Movement.Systems;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.Eye.Blinding;
|
||||
using Content.Shared.Eye.Blinding.Components;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
|
||||
namespace Content.Client.Eye.Blinding
|
||||
{
|
||||
@@ -18,7 +14,9 @@ namespace Content.Client.Eye.Blinding
|
||||
[Dependency] private readonly ILightManager _lightManager = default!;
|
||||
|
||||
public override bool RequestScreenTexture => true;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
private readonly ShaderInstance _greyscaleShader;
|
||||
private readonly ShaderInstance _circleMaskShader;
|
||||
|
||||
@@ -30,6 +28,7 @@ namespace Content.Client.Eye.Blinding
|
||||
_greyscaleShader = _prototypeManager.Index<ShaderPrototype>("GreyscaleFullscreen").InstanceUnique();
|
||||
_circleMaskShader = _prototypeManager.Index<ShaderPrototype>("CircleMask").InstanceUnique();
|
||||
}
|
||||
|
||||
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (!_entityManager.TryGetComponent(_playerManager.LocalSession?.AttachedEntity, out EyeComponent? eyeComp))
|
||||
@@ -50,15 +49,13 @@ namespace Content.Client.Eye.Blinding
|
||||
|
||||
var blind = _blindableComponent.IsBlind;
|
||||
|
||||
if (!blind && _blindableComponent.LightSetup) // Turn FOV back on if we can see again
|
||||
{
|
||||
_lightManager.Enabled = true;
|
||||
_blindableComponent.LightSetup = false;
|
||||
_blindableComponent.GraceFrame = true;
|
||||
return true;
|
||||
}
|
||||
if (blind || !_blindableComponent.LightSetup) // Turn FOV back on if we can see again
|
||||
return blind;
|
||||
|
||||
return blind;
|
||||
_lightManager.Enabled = true;
|
||||
_blindableComponent.LightSetup = false;
|
||||
_blindableComponent.GraceFrame = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
@@ -75,7 +72,8 @@ namespace Content.Client.Eye.Blinding
|
||||
{
|
||||
_blindableComponent.LightSetup = true; // Ok we touched the lights
|
||||
_lightManager.Enabled = false;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
_blindableComponent.GraceFrame = false;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ public sealed class BlindingSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||
[Dependency] ILightManager _lightManager = default!;
|
||||
|
||||
[Dependency] private readonly ILightManager _lightManager = default!;
|
||||
|
||||
private BlindOverlay _overlay = default!;
|
||||
|
||||
@@ -27,7 +26,7 @@ public sealed class BlindingSystem : EntitySystem
|
||||
|
||||
SubscribeNetworkEvent<RoundRestartCleanupEvent>(RoundRestartCleanup);
|
||||
|
||||
_overlay = new();
|
||||
_overlay = new BlindOverlay();
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(EntityUid uid, BlindableComponent component, LocalPlayerAttachedEvent args)
|
||||
@@ -43,13 +42,13 @@ public sealed class BlindingSystem : EntitySystem
|
||||
|
||||
private void OnBlindInit(EntityUid uid, BlindableComponent component, ComponentInit args)
|
||||
{
|
||||
if (_player.LocalPlayer?.ControlledEntity == uid)
|
||||
if (_player.LocalSession?.AttachedEntity == uid)
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
|
||||
private void OnBlindShutdown(EntityUid uid, BlindableComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (_player.LocalPlayer?.ControlledEntity == uid)
|
||||
if (_player.LocalSession?.AttachedEntity == uid)
|
||||
{
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public sealed class BlurryVisionSystem : EntitySystem
|
||||
SubscribeLocalEvent<BlurryVisionComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<BlurryVisionComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
|
||||
|
||||
_overlay = new();
|
||||
_overlay = new BlurryVisionOverlay();
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(EntityUid uid, BlurryVisionComponent component, LocalPlayerAttachedEvent args)
|
||||
@@ -36,13 +36,13 @@ public sealed class BlurryVisionSystem : EntitySystem
|
||||
|
||||
private void OnBlurryInit(EntityUid uid, BlurryVisionComponent component, ComponentInit args)
|
||||
{
|
||||
if (_player.LocalPlayer?.ControlledEntity == uid)
|
||||
if (_player.LocalSession?.AttachedEntity == uid)
|
||||
_overlayMan.AddOverlay(_overlay);
|
||||
}
|
||||
|
||||
private void OnBlurryShutdown(EntityUid uid, BlurryVisionComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (_player.LocalPlayer?.ControlledEntity == uid)
|
||||
if (_player.LocalSession?.AttachedEntity == uid)
|
||||
{
|
||||
_overlayMan.RemoveOverlay(_overlay);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,6 @@ public sealed class CharacterUIController : UIController, IOnStateEntered<Gamepl
|
||||
_window.SubText.Text = job;
|
||||
_window.Objectives.RemoveAllChildren();
|
||||
_window.Memories.RemoveAllChildren();
|
||||
_window.ObjectivesLabel.Visible = objectives.Any();
|
||||
|
||||
foreach (var (groupId, conditions) in objectives)
|
||||
{
|
||||
@@ -183,7 +182,8 @@ public sealed class CharacterUIController : UIController, IOnStateEntered<Gamepl
|
||||
_window.Objectives.AddChild(control);
|
||||
}
|
||||
|
||||
_window.RolePlaceholder.Visible = briefing == null && !controls.Any() && !objectives.Any();
|
||||
_window.RolePlaceholder.Visible = briefing == null && controls.Count == 0 && objectives.Count == 0;
|
||||
_window.MemoriesPlaceholder.Visible = memories.Count == 0;
|
||||
}
|
||||
|
||||
private void CharacterDetached(EntityUid uid)
|
||||
|
||||
@@ -8,22 +8,25 @@
|
||||
<ScrollContainer>
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<SpriteView OverrideDirection="South" Scale="2 2" Name="SpriteView" Access="Public" SetSize="64 64"/>
|
||||
<SpriteView OverrideDirection="South" Scale="2 2" Name="SpriteView" Access="Public" SetSize="64 64" />
|
||||
<BoxContainer Orientation="Vertical" VerticalAlignment="Top">
|
||||
<Label Name="NameLabel" Access="Public"/>
|
||||
<Label Name="SubText" VerticalAlignment="Top" StyleClasses="LabelSubText" Access="Public"/>
|
||||
<Label Name="NameLabel" Access="Public" />
|
||||
<Label Name="SubText" VerticalAlignment="Top" StyleClasses="LabelSubText" Access="Public" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- WD EDIT -->
|
||||
<Label Text="{Loc 'character-info-memories-label'}" HorizontalAlignment="Center"/>
|
||||
<BoxContainer Orientation="Vertical" Name="Memories" Access="Public"/>
|
||||
<cc:Placeholder PlaceholderText="{Loc 'character-info-memories-placeholder-text'}"/>
|
||||
<Label Text="{Loc 'character-info-memories-label'}" HorizontalAlignment="Center" />
|
||||
<BoxContainer Orientation="Vertical" Name="Memories" Access="Public" />
|
||||
<cc:Placeholder Name="MemoriesPlaceholder" Access="Public"
|
||||
PlaceholderText="{Loc 'character-info-memories-placeholder-text'}" />
|
||||
<!-- WD EDIT END -->
|
||||
|
||||
<Label Name="ObjectivesLabel" Access="Public" Text="{Loc 'character-info-objectives-label'}" HorizontalAlignment="Center"/>
|
||||
<BoxContainer Orientation="Vertical" Name="Objectives" Access="Public"/>
|
||||
<cc:Placeholder Name="RolePlaceholder" Access="Public" PlaceholderText="{Loc 'character-info-roles-antagonist-text'}"/>
|
||||
<Label Name="ObjectivesLabel" Access="Public" Text="{Loc 'character-info-objectives-label'}"
|
||||
HorizontalAlignment="Center" />
|
||||
<BoxContainer Orientation="Vertical" Name="Objectives" Access="Public" />
|
||||
<cc:Placeholder Name="RolePlaceholder" Access="Public"
|
||||
PlaceholderText="{Loc 'character-info-roles-antagonist-text'}" />
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
</windows:CharacterWindow>
|
||||
|
||||
@@ -12,7 +12,10 @@ public sealed partial class GunSystem
|
||||
SubscribeLocalEvent<BallisticAmmoProviderComponent, UpdateAmmoCounterEvent>(OnBallisticAmmoCount);
|
||||
}
|
||||
|
||||
private void OnBallisticAmmoCount(EntityUid uid, BallisticAmmoProviderComponent component, UpdateAmmoCounterEvent args)
|
||||
private void OnBallisticAmmoCount(
|
||||
EntityUid uid,
|
||||
BallisticAmmoProviderComponent component,
|
||||
UpdateAmmoCounterEvent args)
|
||||
{
|
||||
if (args.Control is DefaultStatusControl control)
|
||||
{
|
||||
@@ -25,6 +28,9 @@ public sealed partial class GunSystem
|
||||
if (!Timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
if (!component.IsCycled)
|
||||
return;
|
||||
|
||||
EntityUid? ent = null;
|
||||
|
||||
// TODO: Combine with TakeAmmo
|
||||
@@ -48,5 +54,6 @@ public sealed partial class GunSystem
|
||||
|
||||
var cycledEvent = new GunCycledEvent();
|
||||
RaiseLocalEvent(uid, ref cycledEvent);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,14 +172,13 @@ public sealed partial class AdminVerbSystem
|
||||
{
|
||||
Text = "Сделать культистом.",
|
||||
Category = VerbCategory.Antag,
|
||||
Icon = new SpriteSpecifier.Rsi(new("/Textures/White/Cult/interface.rsi"), "icon"),
|
||||
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/White/Cult/interface.rsi"), "icon"),
|
||||
Act = () =>
|
||||
{
|
||||
if (!_minds.TryGetSession(targetMindComp.Mind, out var session))
|
||||
return;
|
||||
|
||||
var playerSession = session;
|
||||
_cultRule.MakeCultist(playerSession!);
|
||||
_cultRule.MakeCultist(session);
|
||||
}
|
||||
};
|
||||
args.Verbs.Add(cultist);
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
using Content.Server.Objectives.Systems;
|
||||
|
||||
namespace Content.Server.Objectives.Components;
|
||||
|
||||
[RegisterComponent, Access(typeof(KillCultistTargetConditionSystem))]
|
||||
public sealed partial class KillCultistTargetConditionComponent : Component
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Content.Server.Objectives.Systems;
|
||||
|
||||
namespace Content.Server.Objectives.Components;
|
||||
|
||||
[RegisterComponent, Access(typeof(KillPersonConditionSystem))]
|
||||
public sealed partial class PickCultTargetComponent : Component
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server._White.Cult.GameRule;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Objectives.Conditions;
|
||||
|
||||
[DataDefinition]
|
||||
public sealed partial class KillCultistTarget : IObjectiveCondition
|
||||
{
|
||||
private IEntityManager EntityManager => IoCManager.Resolve<IEntityManager>();
|
||||
|
||||
protected EntityUid? TargetMindId;
|
||||
protected MindComponent? TargetMind => EntityManager.GetComponentOrNull<MindComponent>(TargetMindId);
|
||||
|
||||
protected SharedJobSystem Jobs => EntityManager.System<SharedJobSystem>();
|
||||
|
||||
|
||||
public IObjectiveCondition GetAssigned(EntityUid mindId, MindComponent mind)
|
||||
{
|
||||
var cultistRule = EntityManager.EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
Debug.Assert(cultistRule != null, nameof(cultistRule) + " != null");
|
||||
var target = cultistRule.CultTarget;
|
||||
|
||||
return new KillCultistTarget()
|
||||
{
|
||||
TargetMindId = target
|
||||
};
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
var targetName = string.Empty;
|
||||
var jobName = Jobs.MindTryGetJobName(TargetMindId) ?? "Unknown";
|
||||
|
||||
if (TargetMindId == null)
|
||||
return Loc.GetString("objective-condition-kill-person-title", ("targetName", targetName), ("job", jobName));
|
||||
|
||||
if (TargetMind?.OwnedEntity is {Valid: true} owned)
|
||||
targetName = EntityManager.GetComponent<MetaDataComponent>(owned).EntityName;
|
||||
|
||||
return Loc.GetString("objective-condition-kill-person-title", ("targetName", targetName), ("job", jobName));
|
||||
}
|
||||
}
|
||||
|
||||
public string Description => Loc.GetString("objective-condition-kill-person-description");
|
||||
|
||||
public SpriteSpecifier Icon => new SpriteSpecifier.Rsi(new ("Objects/Weapons/Guns/Pistols/viper.rsi"), "icon");
|
||||
|
||||
public float Progress
|
||||
{
|
||||
get
|
||||
{
|
||||
var entityManager = IoCManager.Resolve<EntityManager>();
|
||||
var mindSystem = entityManager.System<MindSystem>();
|
||||
return TargetMindId == null || TargetMind == null || mindSystem.IsCharacterDeadIc(TargetMind!) ? 1f : 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public float Difficulty => 2f;
|
||||
|
||||
public bool Equals(IObjectiveCondition? other)
|
||||
{
|
||||
return other is KillCultistTarget kpc && Equals(TargetMindId, kpc.TargetMindId);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj))
|
||||
return false;
|
||||
|
||||
if (ReferenceEquals(this, obj))
|
||||
return true;
|
||||
|
||||
return obj.GetType() == GetType() && Equals((KillCultistTarget) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return TargetMindId?.GetHashCode() ?? 0;
|
||||
}
|
||||
}*/
|
||||
@@ -1,61 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Content.Server.Objectives.Components;
|
||||
using Content.Server._White.Cult.GameRule;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Objectives.Components;
|
||||
|
||||
namespace Content.Server.Objectives.Systems;
|
||||
|
||||
public sealed class KillCultistTargetConditionSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedMindSystem _mind = default!;
|
||||
[Dependency] private readonly TargetObjectiveSystem _target = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<KillCultistTargetConditionComponent, ObjectiveGetProgressEvent>(OnGetProgress);
|
||||
|
||||
SubscribeLocalEvent<KillCultistTargetConditionComponent, ObjectiveAssignedEvent>(OnPersonAssigned);
|
||||
}
|
||||
|
||||
private void OnGetProgress(EntityUid uid, KillCultistTargetConditionComponent comp, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
if (!_target.GetTarget(uid, out var target))
|
||||
return;
|
||||
|
||||
args.Progress = GetProgress(target.Value);
|
||||
}
|
||||
|
||||
private void OnPersonAssigned(EntityUid uid, KillCultistTargetConditionComponent component, ref ObjectiveAssignedEvent args)
|
||||
{
|
||||
if (!TryComp<TargetObjectiveComponent>(uid, out var target))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// target already assigned
|
||||
if (target.Target != null)
|
||||
return;
|
||||
|
||||
var cultistRule = EntityManager.EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
Debug.Assert(cultistRule != null, nameof(cultistRule) + " != null");
|
||||
var cultTarget = cultistRule.CultTarget;
|
||||
|
||||
if (cultTarget != null)
|
||||
_target.SetTarget(uid, cultTarget.Value, target);
|
||||
}
|
||||
|
||||
private float GetProgress(EntityUid target)
|
||||
{
|
||||
// deleted or gibbed or something, counts as dead
|
||||
if (!TryComp<MindComponent>(target, out var mind) || mind.OwnedEntity == null)
|
||||
return 1f;
|
||||
|
||||
// dead is success
|
||||
return _mind.IsCharacterDeadIc(mind) ? 1f : 0f;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Linq;
|
||||
using Content.Server._White.Cult.GameRule;
|
||||
using Content.Server.Objectives.Components;
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Content.Shared.CCVar;
|
||||
@@ -30,6 +32,8 @@ public sealed class KillPersonConditionSystem : EntitySystem
|
||||
SubscribeLocalEvent<PickRandomPersonComponent, ObjectiveAssignedEvent>(OnPersonAssigned);
|
||||
|
||||
SubscribeLocalEvent<PickRandomHeadComponent, ObjectiveAssignedEvent>(OnHeadAssigned);
|
||||
|
||||
SubscribeLocalEvent<PickCultTargetComponent, ObjectiveAssignedEvent>(OnCultTargetAssigned);
|
||||
}
|
||||
|
||||
private void OnGetProgress(EntityUid uid, KillPersonConditionComponent comp, ref ObjectiveGetProgressEvent args)
|
||||
@@ -99,6 +103,28 @@ public sealed class KillPersonConditionSystem : EntitySystem
|
||||
_target.SetTarget(uid, _random.Pick(allHeads), target);
|
||||
}
|
||||
|
||||
private void OnCultTargetAssigned(Entity<PickCultTargetComponent> ent, ref ObjectiveAssignedEvent args)
|
||||
{
|
||||
// invalid prototype
|
||||
if (!TryComp<TargetObjectiveComponent>(ent.Owner, out var target))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// target already assigned
|
||||
if (target.Target != null)
|
||||
return;
|
||||
|
||||
var cultistRule = EntityManager.EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultistRule?.CultTarget is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_target.SetTarget(ent.Owner, cultistRule.CultTarget.Value);
|
||||
}
|
||||
|
||||
private float GetProgress(EntityUid target, bool requireDead)
|
||||
{
|
||||
// deleted or gibbed or something, counts as dead
|
||||
|
||||
@@ -12,6 +12,9 @@ public sealed partial class GunSystem
|
||||
|
||||
protected override void Cycle(EntityUid uid, BallisticAmmoProviderComponent component, MapCoordinates coordinates)
|
||||
{
|
||||
if (!component.IsCycled)
|
||||
return;
|
||||
|
||||
EntityUid? ent = null;
|
||||
|
||||
// TODO: Combine with TakeAmmo
|
||||
|
||||
@@ -54,11 +54,11 @@ public sealed partial class CultRuleComponent : Component
|
||||
/// <summary>
|
||||
/// Players who played as an cultist at some point in the round.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> CultistsList = new();
|
||||
public Dictionary<string, string> CultistsCache = new();
|
||||
|
||||
public EntityUid? CultTarget;
|
||||
|
||||
public List<CultistComponent> Cultists = new();
|
||||
public List<CultistComponent> CurrentCultists = new();
|
||||
|
||||
public List<ConstructComponent> Constructs = new();
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.NPC.Systems;
|
||||
using Content.Server.Roles;
|
||||
using Content.Server.Roles.Jobs;
|
||||
using Content.Server.RoundEnd;
|
||||
using Content.Server.Shuttles.Components;
|
||||
@@ -16,23 +14,15 @@ using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Objectives;
|
||||
using Content.Shared.Players;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared._White.Cult;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Shared._White;
|
||||
using Content.Shared._White.Cult.Components;
|
||||
using Content.Shared.Mind;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using CultistComponent = Content.Shared._White.Cult.Components.CultistComponent;
|
||||
|
||||
namespace Content.Server._White.Cult.GameRule;
|
||||
|
||||
@@ -43,7 +33,6 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||
[Dependency] private readonly StorageSystem _storageSystem = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly NpcFactionSystem _factionSystem = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
@@ -86,147 +75,127 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
|
||||
public MindComponent? GetTarget()
|
||||
{
|
||||
var querry = EntityQueryEnumerator<CultRuleComponent, GameRuleComponent>();
|
||||
var cultistsRule = EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
|
||||
while (querry.MoveNext(out _, out var cultRuleComponent, out _))
|
||||
if (cultistsRule?.CultTarget == null || !TryComp<MindComponent>(cultistsRule.CultTarget.Value, out var mind))
|
||||
{
|
||||
if (cultRuleComponent.CultTarget.HasValue && TryComp<MindComponent>(cultRuleComponent.CultTarget.Value, out var mind))
|
||||
{
|
||||
return mind;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return null!;
|
||||
return mind;
|
||||
}
|
||||
|
||||
public bool CanSummonNarsie()
|
||||
{
|
||||
var querry = EntityQueryEnumerator<CultRuleComponent, GameRuleComponent>();
|
||||
|
||||
while (querry.MoveNext(out _, out var cultRuleComponent, out _))
|
||||
var cultistsRule = EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultistsRule is null)
|
||||
{
|
||||
var cultistsAmount = cultRuleComponent.Cultists.Count;
|
||||
var constructsAmount = cultRuleComponent.Constructs.Count;
|
||||
var enoughCultists = cultistsAmount + constructsAmount > 10;
|
||||
|
||||
if (!enoughCultists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var target = GetTarget();
|
||||
var targetKilled = target == null || _mindSystem.IsCharacterDeadIc(target);
|
||||
|
||||
if (targetKilled)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
var cultistsAmount = cultistsRule.CurrentCultists.Count;
|
||||
var constructsAmount = cultistsRule.Constructs.Count;
|
||||
var enoughCultists = cultistsAmount + constructsAmount > 10;
|
||||
|
||||
if (!enoughCultists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var target = GetTarget();
|
||||
var targetKilled = target == null || _mindSystem.IsCharacterDeadIc(target);
|
||||
|
||||
return targetKilled;
|
||||
}
|
||||
|
||||
private void CheckRoundShouldEnd()
|
||||
{
|
||||
var querry = EntityQueryEnumerator<CultRuleComponent, GameRuleComponent>();
|
||||
var aliveCultistsCount = 0;
|
||||
|
||||
while (querry.MoveNext(out _, out var cultRuleComponent, out _))
|
||||
var cultistsRule = EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultistsRule is null)
|
||||
{
|
||||
var cultists = 0;
|
||||
foreach (var cultistComponent in cultRuleComponent.Cultists)
|
||||
return;
|
||||
}
|
||||
|
||||
var aliveCultists = 0;
|
||||
|
||||
foreach (var cultistComponent in cultistsRule.CurrentCultists)
|
||||
{
|
||||
var owner = cultistComponent.Owner;
|
||||
if (!TryComp<MobStateComponent>(owner, out var mobState))
|
||||
continue;
|
||||
|
||||
if (_mobStateSystem.IsAlive(owner, mobState))
|
||||
{
|
||||
var owner = cultistComponent.Owner;
|
||||
if (!TryComp<MobStateComponent>(owner, out var mobState))
|
||||
continue;
|
||||
|
||||
if (_mobStateSystem.IsAlive(owner, mobState))
|
||||
{
|
||||
cultists++;
|
||||
}
|
||||
aliveCultists++;
|
||||
}
|
||||
|
||||
if (cultists == 0)
|
||||
cultRuleComponent.WinCondition = CultWinCondition.CultFailure;
|
||||
|
||||
aliveCultistsCount += cultists;
|
||||
}
|
||||
|
||||
if (aliveCultistsCount == 0)
|
||||
{
|
||||
_roundEndSystem.EndRound();
|
||||
}
|
||||
if (aliveCultists != 0)
|
||||
return;
|
||||
|
||||
cultistsRule.WinCondition = CultWinCondition.CultFailure;
|
||||
_roundEndSystem.EndRound();
|
||||
}
|
||||
|
||||
private void OnCultistComponentInit(EntityUid uid, CultistComponent component, ComponentInit args)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CultRuleComponent, GameRuleComponent>();
|
||||
|
||||
while (query.MoveNext(out var ruleEnt, out var cultRuleComponent, out _))
|
||||
var cultistsRule = EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultistsRule is null)
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEnt))
|
||||
continue;
|
||||
|
||||
if (!TryComp<MindContainerComponent>(uid, out var mindComponent))
|
||||
return;
|
||||
|
||||
if (!mindComponent.HasMind)
|
||||
return;
|
||||
|
||||
cultRuleComponent.Cultists.Add(component);
|
||||
|
||||
if (TryComp<ActorComponent>(component.Owner, out var actor))
|
||||
{
|
||||
cultRuleComponent.CultistsList.Add(MetaData(component.Owner).EntityName, actor.PlayerSession.Name);
|
||||
}
|
||||
|
||||
var traitorRole = new TraitorRoleComponent()
|
||||
{
|
||||
PrototypeId = cultRuleComponent.CultistRolePrototype
|
||||
};
|
||||
|
||||
_roleSystem.MindAddRole(mindComponent.Mind.Value, traitorRole);
|
||||
|
||||
UpdateCultistsAppearance(cultRuleComponent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp<MindContainerComponent>(uid, out var mindComponent))
|
||||
return;
|
||||
|
||||
if (!mindComponent.HasMind)
|
||||
return;
|
||||
|
||||
cultistsRule.CurrentCultists.Add(component);
|
||||
|
||||
if (TryComp<ActorComponent>(uid, out var actor))
|
||||
{
|
||||
cultistsRule.CultistsCache.Add(MetaData(uid).EntityName, actor.PlayerSession.Name);
|
||||
}
|
||||
|
||||
UpdateCultistsAppearance(cultistsRule);
|
||||
}
|
||||
|
||||
private void OnCultistComponentRemoved(EntityUid uid, CultistComponent component, ComponentRemove args)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CultRuleComponent, GameRuleComponent>();
|
||||
|
||||
while (query.MoveNext(out var ruleEnt, out var cultRuleComponent, out _))
|
||||
var cultistsRule = EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultistsRule is null)
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(ruleEnt))
|
||||
continue;
|
||||
|
||||
cultRuleComponent.Cultists.Remove(component);
|
||||
|
||||
RemoveCultistAppearance(component);
|
||||
|
||||
CheckRoundShouldEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
cultistsRule.CurrentCultists.Remove(component);
|
||||
|
||||
RemoveCultistAppearance(uid);
|
||||
CheckRoundShouldEnd();
|
||||
}
|
||||
|
||||
private void RemoveCultistAppearance(CultistComponent component)
|
||||
private void RemoveCultistAppearance(EntityUid cultist)
|
||||
{
|
||||
if (TryComp<HumanoidAppearanceComponent>(component.Owner, out var appearanceComponent))
|
||||
if (TryComp<HumanoidAppearanceComponent>(cultist, out var appearanceComponent))
|
||||
{
|
||||
//Потому что я так сказал
|
||||
appearanceComponent.EyeColor = Color.White;
|
||||
Dirty(appearanceComponent);
|
||||
Dirty(cultist, appearanceComponent);
|
||||
}
|
||||
|
||||
RemComp<PentagramComponent>(component.Owner);
|
||||
RemComp<PentagramComponent>(cultist);
|
||||
}
|
||||
|
||||
private void UpdateCultistsAppearance(CultRuleComponent cultRuleComponent)
|
||||
{
|
||||
var cultistsCount = cultRuleComponent.Cultists.Count;
|
||||
var cultistsCount = cultRuleComponent.CurrentCultists.Count;
|
||||
var constructsCount = cultRuleComponent.Constructs.Count;
|
||||
var totalCultMembers = cultistsCount + constructsCount;
|
||||
if (totalCultMembers < CultRuleComponent.ReadEyeThreshold)
|
||||
return;
|
||||
|
||||
foreach (var cultistComponent in cultRuleComponent.Cultists)
|
||||
foreach (var cultistComponent in cultRuleComponent.CurrentCultists)
|
||||
{
|
||||
if (TryComp<HumanoidAppearanceComponent>(cultistComponent.Owner, out var appearanceComponent))
|
||||
{
|
||||
@@ -243,76 +212,74 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
|
||||
private void OnRoundEndText(RoundEndTextAppendEvent ev)
|
||||
{
|
||||
var querry = EntityQuery<CultRuleComponent>();
|
||||
|
||||
foreach (var cultRuleComponent in querry)
|
||||
var cultistsRule = EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultistsRule is null)
|
||||
{
|
||||
var winText = Loc.GetString($"cult-cond-{cultRuleComponent.WinCondition.ToString().ToLower()}");
|
||||
ev.AddLine(winText);
|
||||
return;
|
||||
}
|
||||
|
||||
ev.AddLine(Loc.GetString("cultists-list-start"));
|
||||
var winText = Loc.GetString($"cult-cond-{cultistsRule.WinCondition.ToString().ToLower()}");
|
||||
ev.AddLine(winText);
|
||||
|
||||
foreach (var (entityName, ckey) in cultRuleComponent.CultistsList)
|
||||
{
|
||||
var lising = Loc.GetString("cultists-list-name", ("name", entityName), ("user", ckey));
|
||||
ev.AddLine(lising);
|
||||
}
|
||||
ev.AddLine(Loc.GetString("cultists-list-start"));
|
||||
|
||||
foreach (var (entityName, ckey) in cultistsRule.CultistsCache)
|
||||
{
|
||||
var lising = Loc.GetString("cultists-list-name", ("name", entityName), ("user", ckey));
|
||||
ev.AddLine(lising);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStartAttempt(RoundStartAttemptEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CultRuleComponent, GameRuleComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out _, out var gameRule))
|
||||
var cultistsRule = EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultistsRule is null)
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
|
||||
continue;
|
||||
|
||||
var minPlayers = _cultGameRuleMinimapPlayers;
|
||||
if (!ev.Forced && ev.Players.Length < minPlayers)
|
||||
{
|
||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("traitor-not-enough-ready-players",
|
||||
("readyPlayersCount", ev.Players.Length), ("minimumPlayers", minPlayers)));
|
||||
|
||||
ev.Cancel();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev.Players.Length == 0)
|
||||
{
|
||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("traitor-no-one-ready"));
|
||||
ev.Cancel();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var minPlayers = _cultGameRuleMinimapPlayers;
|
||||
if (!ev.Forced && ev.Players.Length < minPlayers)
|
||||
{
|
||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("traitor-not-enough-ready-players",
|
||||
("readyPlayersCount", ev.Players.Length), ("minimumPlayers", minPlayers)));
|
||||
|
||||
ev.Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev.Players.Length != 0)
|
||||
return;
|
||||
|
||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("traitor-no-one-ready"));
|
||||
ev.Cancel();
|
||||
}
|
||||
|
||||
private void OnPlayersSpawned(RulePlayerJobsAssignedEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CultRuleComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var uid, out var cultRule, out var gameRule))
|
||||
var cultistsRule = EntityQuery<CultRuleComponent>().FirstOrDefault();
|
||||
if (cultistsRule is null)
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var player in ev.Players)
|
||||
{
|
||||
if (!ev.Profiles.ContainsKey(player.UserId))
|
||||
continue;
|
||||
|
||||
foreach (var player in ev.Players)
|
||||
{
|
||||
if (!ev.Profiles.ContainsKey(player.UserId))
|
||||
continue;
|
||||
cultistsRule.StarCandidates[player] = ev.Profiles[player.UserId];
|
||||
}
|
||||
|
||||
cultRule.StarCandidates[player] = ev.Profiles[player.UserId];
|
||||
}
|
||||
var potentialCultists = FindPotentialCultist(cultistsRule.StarCandidates);
|
||||
var pickedCultist = PickCultists(potentialCultists);
|
||||
var potentialTargets = FindPotentialTargets(pickedCultist);
|
||||
|
||||
var potentialCultists = FindPotentialCultist(cultRule.StarCandidates);
|
||||
var pickedCultist = PickCultists(potentialCultists);
|
||||
var potentialTargets = FindPotentialTargets(pickedCultist);
|
||||
cultistsRule.CultTarget = _random.PickAndTake(potentialTargets).Mind;
|
||||
|
||||
cultRule.CultTarget = _random.PickAndTake(potentialTargets).Mind;
|
||||
|
||||
foreach (var pickerCultist in pickedCultist)
|
||||
{
|
||||
MakeCultist(pickerCultist);
|
||||
}
|
||||
foreach (var pickerCultist in pickedCultist)
|
||||
{
|
||||
MakeCultist(pickerCultist);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +307,8 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
return potentialTargets;
|
||||
}
|
||||
|
||||
private List<ICommonSession> FindPotentialCultist(in Dictionary<ICommonSession, HumanoidCharacterProfile> candidates)
|
||||
private List<ICommonSession> FindPotentialCultist(
|
||||
in Dictionary<ICommonSession, HumanoidCharacterProfile> candidates)
|
||||
{
|
||||
var list = new List<ICommonSession>();
|
||||
var pendingQuery = GetEntityQuery<PendingClockInComponent>();
|
||||
@@ -348,7 +316,8 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
foreach (var player in candidates.Keys)
|
||||
{
|
||||
// Role prevents antag.
|
||||
if (!_jobSystem.CanBeAntag(player)) continue;
|
||||
if (!_jobSystem.CanBeAntag(player))
|
||||
continue;
|
||||
|
||||
// Latejoin
|
||||
if (player.AttachedEntity != null && pendingQuery.HasComponent(player.AttachedEntity.Value))
|
||||
@@ -428,35 +397,34 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
cultistRule = Comp<CultRuleComponent>(ruleEntity);
|
||||
}
|
||||
|
||||
var mind = cultist.Data.ContentData()?.Mind;
|
||||
|
||||
if (mind == null)
|
||||
if (!_mindSystem.TryGetMind(cultist, out var mindId, out var mind))
|
||||
{
|
||||
_sawmill.Info("Failed getting mind for picked cultist.");
|
||||
Log.Info("Failed getting mind for picked thief.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var playerEntity = cultist.AttachedEntity;
|
||||
|
||||
if (!playerEntity.HasValue)
|
||||
if (mind.OwnedEntity is not { } playerEntity)
|
||||
{
|
||||
_sawmill.Error("Mind picked for cultist did not have an attached entity.");
|
||||
Log.Error("Mind picked for cultist did not have an attached entity.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var mindComponent = Comp<MindComponent>(mind.Value);
|
||||
var cultistComponent = new CultistRoleComponent
|
||||
{
|
||||
PrototypeId = cultistRule.CultistRolePrototype
|
||||
};
|
||||
|
||||
DebugTools.AssertNotNull(playerEntity.Value);
|
||||
EnsureComp<CultistComponent>(playerEntity.Value);
|
||||
_roleSystem.MindAddRole(mindId, cultistComponent);
|
||||
EnsureComp<CultistComponent>(playerEntity);
|
||||
|
||||
_factionSystem.RemoveFaction(playerEntity.Value, "NanoTrasen", false);
|
||||
_factionSystem.AddFaction(playerEntity.Value, "Cultist");
|
||||
_factionSystem.RemoveFaction(playerEntity, "NanoTrasen", false);
|
||||
_factionSystem.AddFaction(playerEntity, "Cultist");
|
||||
|
||||
if (_inventorySystem.TryGetSlotEntity(playerEntity.Value, "back", out var backPack))
|
||||
if (_inventorySystem.TryGetSlotEntity(playerEntity, "back", out var backPack))
|
||||
{
|
||||
foreach (var itemPrototype in cultistRule.StartingItems)
|
||||
{
|
||||
var itemEntity = Spawn(itemPrototype, Transform(playerEntity.Value).Coordinates);
|
||||
var itemEntity = Spawn(itemPrototype, Transform(playerEntity).Coordinates);
|
||||
|
||||
if (backPack != null)
|
||||
{
|
||||
@@ -465,12 +433,14 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
}
|
||||
}
|
||||
|
||||
_audioSystem.PlayGlobal(cultistRule.GreatingsSound, Filter.Empty().AddPlayer(cultist), false,
|
||||
AudioParams.Default);
|
||||
// Notificate player about new role assignment
|
||||
if (_mindSystem.TryGetSession(mindId, out var session))
|
||||
{
|
||||
_audioSystem.PlayGlobal(cultistRule.GreatingsSound, session);
|
||||
_chatManager.DispatchServerMessage(session, Loc.GetString("cult-role-greeting"));
|
||||
}
|
||||
|
||||
_chatManager.DispatchServerMessage(cultist, Loc.GetString("cult-role-greeting"));
|
||||
|
||||
_mindSystem.TryAddObjective(mind.Value, mindComponent, "CultistKillObjective");
|
||||
_mindSystem.TryAddObjective(mindId, mind, "KillCultTargetObjective");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -484,19 +454,19 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
|
||||
|
||||
_roundEndSystem.EndRound();
|
||||
|
||||
var query = EntityQuery<MobStateComponent, MindContainerComponent, CultistComponent>().ToList();
|
||||
var query = EntityQueryEnumerator<MobStateComponent, MindContainerComponent, CultistComponent>();
|
||||
|
||||
foreach (var (mobState, mindContainer, _) in query)
|
||||
while (query.MoveNext(out var uid, out _, out var mindContainer, out _))
|
||||
{
|
||||
if (!mindContainer.HasMind || mindContainer.Mind is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var reaper = Spawn(CultRuleComponent.ReaperPrototype, Transform(mobState.Owner).Coordinates);
|
||||
var reaper = Spawn(CultRuleComponent.ReaperPrototype, Transform(uid).Coordinates);
|
||||
_mindSystem.TransferTo(mindContainer.Mind.Value, reaper);
|
||||
|
||||
_bodySystem.GibBody(mobState.Owner);
|
||||
_bodySystem.GibBody(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,9 @@ public abstract class SharedGrapplingGunSystem : EntitySystem
|
||||
visuals.Sprite = component.RopeSprite;
|
||||
visuals.OffsetA = new Vector2(0f, 0.5f);
|
||||
visuals.Target = uid;
|
||||
|
||||
component.Joint = visuals.Target;
|
||||
|
||||
Dirty(shotUid.Value, visuals);
|
||||
}
|
||||
|
||||
@@ -91,7 +94,7 @@ public abstract class SharedGrapplingGunSystem : EntitySystem
|
||||
|
||||
if (msg.Reeling &&
|
||||
(!TryComp<CombatModeComponent>(player, out var combatMode) ||
|
||||
!combatMode.IsInCombatMode))
|
||||
!combatMode.IsInCombatMode))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -132,7 +135,7 @@ public abstract class SharedGrapplingGunSystem : EntitySystem
|
||||
|
||||
component.Projectile = null;
|
||||
SetReeling(uid, component, false, args.User);
|
||||
_gun.ChangeBasicEntityAmmoCount(uid, 1);
|
||||
_gun.ChangeBasicEntityAmmoCount(uid, 1);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,24 @@ public sealed partial class BallisticAmmoProviderComponent : Component
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
|
||||
public bool Cycleable = true;
|
||||
|
||||
/// <summary>
|
||||
/// Is the firearm currently cycled?
|
||||
/// It cannot fire if is it not cycled.
|
||||
/// Must be manually cycled if it is not cycled.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
||||
[AutoNetworkedField]
|
||||
public bool? Cycled = true;
|
||||
|
||||
public bool IsCycled => Cycled is true or null;
|
||||
|
||||
/// <summary>
|
||||
/// Automatically cycles the firearm after firing a round
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
||||
[AutoNetworkedField]
|
||||
public bool AutoCycle = true;
|
||||
|
||||
/// <summary>
|
||||
/// Is it okay for this entity to directly transfer its valid ammunition into another provider?
|
||||
/// </summary>
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Content.Shared.Weapons.Ranged.Components;
|
||||
public sealed partial class GrapplingGunComponent : Component
|
||||
{
|
||||
[DataField("jointId"), AutoNetworkedField]
|
||||
public string Joint = string.Empty;
|
||||
public EntityUid? Joint;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? Projectile;
|
||||
|
||||
@@ -206,6 +206,7 @@ public abstract partial class SharedGunSystem
|
||||
|
||||
var shots = GetBallisticShots(component);
|
||||
Cycle(uid, component, coordinates);
|
||||
component.Cycled = true;
|
||||
|
||||
var text = Loc.GetString(shots == 0 ? "gun-ballistic-cycled-empty" : "gun-ballistic-cycled");
|
||||
|
||||
@@ -243,6 +244,9 @@ public abstract partial class SharedGunSystem
|
||||
|
||||
private void OnBallisticTakeAmmo(EntityUid uid, BallisticAmmoProviderComponent component, TakeAmmoEvent args)
|
||||
{
|
||||
if (!component.IsCycled)
|
||||
return;
|
||||
|
||||
for (var i = 0; i < args.Shots; i++)
|
||||
{
|
||||
EntityUid entity;
|
||||
@@ -263,6 +267,10 @@ public abstract partial class SharedGunSystem
|
||||
}
|
||||
}
|
||||
|
||||
//un-cycle the firearm
|
||||
if (!component.AutoCycle)
|
||||
component.Cycled = false;
|
||||
|
||||
UpdateBallisticAppearance(uid, component);
|
||||
Dirty(uid, component);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using Content.Shared.Roles;
|
||||
|
||||
namespace Content.Shared._White.Cult.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CultistRoleComponent : AntagonistRoleComponent
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Content.Shared._White.ReduceBlindness;
|
||||
|
||||
[RegisterComponent, AutoGenerateComponentState]
|
||||
public sealed partial class ReduceBlindnessComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
|
||||
public float ReduceAmount { get; set; } = 1.5f;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Content.Shared.Eye.Blinding.Components;
|
||||
using Content.Shared.Hands;
|
||||
|
||||
namespace Content.Shared._White.ReduceBlindness;
|
||||
|
||||
public sealed class ReduceBlindnessSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ReduceBlindnessComponent, GotEquippedHandEvent>(OnEquipepd);
|
||||
SubscribeLocalEvent<ReduceBlindnessComponent, GotUnequippedHandEvent>(OnUnequipped);
|
||||
}
|
||||
|
||||
private void OnEquipepd(Entity<ReduceBlindnessComponent> ent, ref GotEquippedHandEvent args)
|
||||
{
|
||||
if (!TryComp(args.User, out BlurryVisionComponent? blurryVisionComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
blurryVisionComponent.Magnitude -= ent.Comp.ReduceAmount;
|
||||
}
|
||||
|
||||
private void OnUnequipped(Entity<ReduceBlindnessComponent> ent, ref GotUnequippedHandEvent args)
|
||||
{
|
||||
if (!TryComp(args.User, out BlurryVisionComponent? blurryVisionComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
blurryVisionComponent.Magnitude += ent.Comp.ReduceAmount;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,75 @@
|
||||
rev-title = Революция
|
||||
rev-name = Глава революции
|
||||
rev-description = Группа бунтовщиков тайком пробралась на станцию для того чтобы убить всех глав и захватить её. Они вербуют новых сторонников при помощи устройства-вспышки. Постарайтесь выследить и уничтожить их!
|
||||
rev-welcome-headrev =
|
||||
Вы - главный революционер. Ваша задача - завербовать как можно больше членов экипажа в свои ряды и захватить станцию, убив глав всех отделов и капитана.
|
||||
В вашем кармане находится вспышка. Используйте её на другом члене экипажа для того чтобы путем гипноза передать ему свои революционные идеалы.
|
||||
Работайте сообща с другими зачинщиками мятежа и постарайтесь не попасться Службе Безопасности.
|
||||
Да здравствует Революция! За старый космос
|
||||
rev-welcome-rev =
|
||||
В свете вспышки вы увидели объятую пламенем штаб-квартиру НаноТрейзен, и вам понравилось это зрелище. Хотите вы того или нет, но теперь вы - революционер.
|
||||
Вы загипнотизированы и обязаны слепо подчиняться приказам главных революционеров. Ваши новые идеалы запрещают вам мешать ходу революции, сдаваться Службе Безопасности или сдавать ей своих товарищей. Ваша задача - захватить станцию, убив глав всех отделов и капитана.
|
||||
Да здравствует Революция! За старый космос!
|
||||
rev-revmajor = Крупная победа Революции!
|
||||
rev-neutral = Ничейный исход!
|
||||
rev-crewmajor = Крупная победа экипажа!
|
||||
rev-cond-allheadrevsdead = Все лидеры революции погибли.
|
||||
rev-cond-allcrewheadsdead = Все главы станции погибли.
|
||||
rev-list-revs-start = Революционерами были:
|
||||
rev-list = - [color=White]{ $name }[/color] ([color=gray]{ $user }[/color]) { $headrev }
|
||||
rev-list-heads-start = Главами станции были:
|
||||
rev-not-enough-ready-players = Недостаточно игроков готовы к игре! { $readyPlayersCount } игроков из необходимых { $minimumPlayers } готовы. Нельзя начать режим: Revolution.
|
||||
rev-no-one-ready = Нет готовых игроков! Нельзя начать Revolution.
|
||||
rev-list-headrevbool = [color=Red]Глава революции[/color]
|
||||
rev-objective = Убить глав всех отделов и капитана!
|
||||
## Rev Head
|
||||
|
||||
roles-antag-rev-head-name = Глава Революции
|
||||
roles-antag-rev-head-objective = Группа бунтовщиков тайком пробралась на станцию для того чтобы убить всех глав и захватить её. Они вербуют новых сторонников при помощи устройства-вспышки. Постарайтесь выследить и уничтожить их!
|
||||
|
||||
head-rev-role-greeting =
|
||||
Вы - Глава Революции.
|
||||
Вашей целью является убрать весь коммандный состав станции - убив их или изгнав.
|
||||
Синдикат снабдил вас вспышками, которые могут быть использованы для вербовки персонала станции на свою сторону.
|
||||
Однако, это не сработает на Службу Безопасности, Командный состав или на тех, кто носит защиту от вспышек.
|
||||
Да здравствует Революция! За старый космос
|
||||
|
||||
head-rev-briefing =
|
||||
Используйте вспышку чтобы вербовать людей на свою сторону.
|
||||
Убейте всех глав, чтобы захватить станцию.
|
||||
|
||||
head-rev-break-mindshield = Имплант защиты разума сломался!
|
||||
|
||||
## Rev
|
||||
|
||||
roles-antag-rev-name = Революционер
|
||||
roles-antag-rev-objective = Ваша задача - обеспечить безопасность и выполнять приказы Глав Революции, а также убить весь командный состав станции.
|
||||
|
||||
rev-break-control = {$name} вспомнили о своей истинной преданности!
|
||||
|
||||
rev-role-greeting =
|
||||
Вы - революционер.
|
||||
Вам поручено захватить станцию и защитить Глав Революции.
|
||||
Уничтожьте весь командный состав.
|
||||
Да здравствует революция!
|
||||
|
||||
rev-briefing = Помогите Главам Революции убить весь командный состав, чтобы захватить станцию.
|
||||
|
||||
## General
|
||||
|
||||
rev-title = Революционеры
|
||||
rev-description = Революционеры среди нас.
|
||||
|
||||
rev-not-enough-ready-players = Недостаточно игроков чтобы запустить режим. Готово {$readyPlayersCount} игроков из {$minimumPlayers} необходимых. Невозможно запустить режим Революция.
|
||||
rev-no-one-ready = Нет готовых игроков! Невозможно запустить режим Революция.
|
||||
rev-no-heads = Не удалось выбрать Глав Революции. Невозможно запустить режим Революция.
|
||||
|
||||
rev-all-heads-dead = Все главы мертвы, теперь прикончите остальных членов экипажа!
|
||||
|
||||
rev-won = Главы Революции выжили и убили весь командный состав.
|
||||
|
||||
rev-lost = Командный состав выжил и убили всех Глав Революции.
|
||||
|
||||
rev-stalemate = И Глав Революции, и командный состав погибли. Ничья.
|
||||
|
||||
rev-reverse-stalemate = Обе команды выжили. Ничья.
|
||||
|
||||
rev-headrev-count = {$initialCount ->
|
||||
[one] Был один Глава Революции:
|
||||
*[other] Было {$initialCount} Глав Революции:
|
||||
}
|
||||
|
||||
rev-headrev-name-user = [color=#5e9cff]{$name}[/color] ([color=gray]{$username}[/color]) завербовал {$count} {$count ->
|
||||
[one] человека
|
||||
*[other] человек
|
||||
}
|
||||
|
||||
rev-headrev-name = [color=#5e9cff]{$name}[/color] завербовал {$count} {$count ->
|
||||
[one] человека
|
||||
*[other] человек
|
||||
}
|
||||
|
||||
## Deconverted window
|
||||
|
||||
rev-deconverted-title = Деконвертирован!
|
||||
rev-deconverted-text =
|
||||
Поскольку последний Глава Революции умер, революция закончилась.
|
||||
|
||||
Вы больше не революционер, так что будьте спокойны.
|
||||
rev-deconverted-confirm = Принять
|
||||
|
||||
@@ -169,6 +169,9 @@
|
||||
sprite: Clothing/Back/Duffels/syndicate.rsi
|
||||
- type: ExplosionResistance
|
||||
damageCoefficient: 0.1
|
||||
- type: ClothingSpeedModifier
|
||||
walkModifier: 1
|
||||
sprintModifier: 1
|
||||
|
||||
- type: entity
|
||||
parent: ClothingBackpackDuffelSyndicate
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
- ShellShotgun
|
||||
- type: CartridgeAmmo
|
||||
count: 6
|
||||
spread: 15
|
||||
spread: 22
|
||||
soundEject:
|
||||
collection: ShellEject
|
||||
- type: Sprite
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Piercing: 28
|
||||
Piercing: 34
|
||||
|
||||
- type: entity
|
||||
id: PelletShotgunBeanbag
|
||||
@@ -40,7 +40,7 @@
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Piercing: 10
|
||||
Piercing: 13
|
||||
|
||||
- type: entity
|
||||
id: PelletShotgunIncendiary
|
||||
@@ -54,7 +54,7 @@
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Blunt: 3
|
||||
Blunt: 6
|
||||
Heat: 7
|
||||
- type: IgnitionSource
|
||||
ignited: true
|
||||
@@ -85,8 +85,8 @@
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Piercing: 3
|
||||
Slash: 3 #remember, it's metal shrapnel!
|
||||
Piercing: 5
|
||||
Slash: 5 #remember, it's metal shrapnel!
|
||||
|
||||
- type: entity
|
||||
id: PelletShotgunTranquilizer
|
||||
@@ -177,8 +177,8 @@
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Radiation: 5
|
||||
Piercing: 5
|
||||
Radiation: 6
|
||||
Piercing: 7
|
||||
|
||||
- type: entity
|
||||
id: PelletGrapeshot #tally fucking ho
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
- type: AmmoCounter
|
||||
- type: Gun
|
||||
fireRate: 2
|
||||
projectileSpeed: 48
|
||||
selectedMode: SemiAuto
|
||||
availableModes:
|
||||
- SemiAuto
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
proto: GrenadeFrag
|
||||
soundInsert:
|
||||
path: /Audio/Weapons/Guns/MagIn/batrifle_magin.ogg
|
||||
autoCycle: false
|
||||
|
||||
- type: entity
|
||||
name: RPG-7
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
proto: ShellShotgun
|
||||
soundInsert:
|
||||
path: /Audio/Weapons/Guns/MagIn/shotgun_insert.ogg
|
||||
autoCycle: false
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
ballistic-ammo: !type:Container
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
whitelist:
|
||||
tags:
|
||||
- CartridgeLightRifle
|
||||
autoCycle: false
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
ballistic-ammo: !type:Container
|
||||
@@ -63,6 +64,7 @@
|
||||
- CartridgeAntiMateriel
|
||||
capacity: 5
|
||||
proto: CartridgeAntiMateriel
|
||||
autoCycle: true
|
||||
- type: Wieldable
|
||||
wieldTime: 0
|
||||
forceTwoHanded: True
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
- type: StaminaDamageOnHit
|
||||
damage: 5
|
||||
- type: Wieldable
|
||||
- type: ReduceBlindness
|
||||
- type: IncreaseDamageOnWield
|
||||
damage:
|
||||
types:
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
- name: suitstorage
|
||||
slotTexture: suit_storage
|
||||
slotFlags: SUITSTORAGE
|
||||
slotGroup: MainHotbar
|
||||
slotGroup: SecondHotbar
|
||||
stripTime: 3
|
||||
uiWindowPos: 2,0
|
||||
strippingWindowPos: 2,5
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
- type: entity
|
||||
noSpawn: true
|
||||
parent: BaseObjective
|
||||
id: CultistKillObjective
|
||||
description: objective-condition-kill-person-description
|
||||
components:
|
||||
- type: Objective
|
||||
difficulty: 1.5
|
||||
issuer: Cult
|
||||
icon:
|
||||
sprite: White/Cult/interface.rsi
|
||||
state: icon
|
||||
- type: KillCultistTargetCondition
|
||||
22
Resources/Prototypes/_White/Objectives/cult.yml
Normal file
22
Resources/Prototypes/_White/Objectives/cult.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
- type: entity
|
||||
noSpawn: true
|
||||
parent: BaseTargetObjective
|
||||
id: KillCultTargetObjective
|
||||
description: This fool person should be sacrificed in the glory of our God.
|
||||
components:
|
||||
- type: Objective
|
||||
issuer: cult
|
||||
unique: true
|
||||
difficulty: 3
|
||||
icon:
|
||||
sprite: Objects/Weapons/Melee/cult_dagger.rsi
|
||||
state: icon
|
||||
- type: RoleRequirement
|
||||
roles:
|
||||
components:
|
||||
- CultistRole
|
||||
- type: TargetObjective
|
||||
title: objective-condition-kill-person-title
|
||||
- type: PickCultTarget
|
||||
- type: KillPersonCondition
|
||||
requireDead: true
|
||||
Reference in New Issue
Block a user