Chaplain stuff (#98)

* - add: Null rod.

* - add: Only chaplain can use holy weapons.

* - add: Chaplain is cult immune.

* - fix: Fix component granting.

* - add: Only chaplain can use null rod.

* - add: Armaments beacon.

* - add: Chaplain playtime requirement.
This commit is contained in:
Aviu00
2024-02-20 19:28:44 +09:00
committed by GitHub
parent e6b6274874
commit 03fed0caa7
158 changed files with 2342 additions and 14 deletions

View File

@@ -0,0 +1,39 @@
using Content.Server.Hands.Systems;
using Content.Server.Popups;
using Content.Shared._White.Chaplain;
using Content.Shared.Ghost;
using Content.Shared.Inventory;
namespace Content.Server._White.Chaplain;
public sealed class ArmamentsBeaconSystem : EntitySystem
{
[Dependency] private readonly InventorySystem _inventorySystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ArmamentsBeaconComponent, ArmorSelectedEvent>(OnArmorSelected);
}
private void OnArmorSelected(Entity<ArmamentsBeaconComponent> ent, ref ArmorSelectedEvent args)
{
var entity = args.Session.AttachedEntity;
var index = args.SelectedIndex;
if (index < 0 || index >= ent.Comp.Armor.Count || entity == null)
return;
_inventorySystem.TryUnequip(entity.Value, "outerClothing", true);
_inventorySystem.SpawnItemInSlot(entity.Value, "outerClothing", ent.Comp.Armor[index], silent: true);
if (index < ent.Comp.Helmets.Count && ent.Comp.Helmets[index] != null)
{
_inventorySystem.TryUnequip(entity.Value, "head", true);
_inventorySystem.SpawnItemInSlot(entity.Value, "head", ent.Comp.Helmets[index]!.Value, silent: true);
}
Del(ent);
}
}

View File

@@ -0,0 +1,40 @@
using Content.Server.Hands.Systems;
using Content.Server.Popups;
using Content.Shared._White.Chaplain;
using Content.Shared.Ghost;
namespace Content.Server._White.Chaplain;
public sealed class NullRodSystem : EntitySystem
{
[Dependency] private readonly HandsSystem _hands = default!;
[Dependency] private readonly PopupSystem _popup = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<NullRodComponent, WeaponSelectedEvent>(OnWeaponSelected);
}
private void OnWeaponSelected(Entity<NullRodComponent> ent, ref WeaponSelectedEvent args)
{
var entity = args.Session.AttachedEntity;
if (args.SelectedWeapon == string.Empty || entity == null)
return;
if (!HasComp<HolyComponent>(entity.Value) && !HasComp<GhostComponent>(entity.Value))
{
_popup.PopupEntity($"Вам не хватает веры, чтобы использовать {Name(ent)}", entity.Value, entity.Value);
return;
}
var weapon = Spawn(args.SelectedWeapon, Transform(entity.Value).Coordinates);
EnsureComp<HolyWeaponComponent>(weapon);
Del(ent);
_hands.PickupOrDrop(entity.Value, weapon, true, false, false);
}
}

View File

@@ -22,6 +22,7 @@ using Robust.Shared.Configuration;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Content.Shared._White;
using Content.Shared._White.Chaplain;
using Content.Shared._White.Cult.Components;
using Content.Shared.Mind;
using Robust.Shared.Audio.Systems;
@@ -327,9 +328,10 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
if (!_jobSystem.CanBeAntag(player))
continue;
// Gulag
// Gulag & chaplain
if (!_mindSystem.TryGetMind(player, out _, out var mind) ||
mind.OwnedEntity is not { } ownedEntity || HasComp<GulagBoundComponent>(ownedEntity))
mind.OwnedEntity is not { } ownedEntity || HasComp<GulagBoundComponent>(ownedEntity) ||
HasComp<HolyComponent>(ownedEntity))
continue;
// Latejoin
@@ -414,7 +416,7 @@ public sealed class CultRuleSystem : GameRuleSystem<CultRuleComponent>
if (!_mindSystem.TryGetMind(cultist, out var mindId, out var mind))
{
Log.Info("Failed getting mind for picked thief.");
Log.Info("Failed getting mind for picked cultist.");
return false;
}

View File

@@ -10,6 +10,7 @@ using Content.Server.Hands.Systems;
using Content.Server.Weapons.Ranged.Systems;
using Content.Server._White.Cult.GameRule;
using Content.Server._White.Cult.Runes.Comps;
using Content.Shared._White.Chaplain;
using Content.Shared.Actions;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Cuffs.Components;
@@ -423,7 +424,8 @@ public sealed partial class CultSystem : EntitySystem
var isTarget = mind!.Mind!.Value == targetMind?.Mind!.Value;
// Выполнение действия в зависимости от условий
if (canBeConverted && !HasComp<MindShieldComponent>(victim.Value) && !isTarget)
if (canBeConverted && !HasComp<HolyComponent>(victim.Value) &&
!HasComp<MindShieldComponent>(victim.Value) && !isTarget)
{
result = Convert(uid, victim.Value, args.User, args.Cultists);
}

View File

@@ -1,8 +1,13 @@
using Content.Server.Doors.Systems;
using Content.Shared._White.Chaplain;
using Content.Shared.Doors;
using Content.Shared.Humanoid;
using Content.Shared.Stunnable;
using Content.Shared._White.Cult;
using Content.Shared.Doors.Components;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Physics.Systems;
using CultistComponent = Content.Shared._White.Cult.Components.CultistComponent;
@@ -13,6 +18,7 @@ public sealed class RunicDoorSystem : EntitySystem
[Dependency] private readonly DoorSystem _doorSystem = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
public override void Initialize()
{
@@ -20,6 +26,18 @@ public sealed class RunicDoorSystem : EntitySystem
SubscribeLocalEvent<RunicDoorComponent, BeforeDoorOpenedEvent>(OnBeforeDoorOpened);
SubscribeLocalEvent<RunicDoorComponent, BeforeDoorClosedEvent>(OnBeforeDoorClosed);
SubscribeLocalEvent<RunicDoorComponent, AttackedEvent>(OnGetAttacked);
}
private void OnGetAttacked(Entity<RunicDoorComponent> ent, ref AttackedEvent args)
{
if (!HasComp<HolyWeaponComponent>(args.Used) || !TryComp<DoorComponent>(ent, out var doorComp) ||
doorComp.State is not DoorState.Closed)
return;
_audio.PlayPvs(new SoundPathSpecifier("/Audio/Magic/knock.ogg"), ent);
_doorSystem.StartOpening(ent, doorComp);
}
private void OnBeforeDoorOpened(EntityUid uid, RunicDoorComponent component, BeforeDoorOpenedEvent args)
@@ -61,7 +79,7 @@ public sealed class RunicDoorSystem : EntitySystem
_doorSystem.Deny(airlock);
if (!HasComp<HumanoidAppearanceComponent>(user))
if (!HasComp<HumanoidAppearanceComponent>(user) || HasComp<HolyComponent>(user))
return false;
var direction = Transform(user).MapPosition.Position - Transform(airlock).MapPosition.Position;

View File

@@ -0,0 +1,8 @@
namespace Content.Server._White.Other.MeleeBlockSystem;
[RegisterComponent]
public sealed partial class MeleeBlockComponent : Component
{
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float BlockChance = 0.4f;
}

View File

@@ -0,0 +1,37 @@
using Content.Shared.Hands.Components;
using Content.Shared.Popups;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Random;
namespace Content.Server._White.Other.MeleeBlockSystem;
public sealed class MeleeBlockSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HandsComponent, MeleeBlockAttemptEvent>(OnBlockAttempt);
}
private void OnBlockAttempt(Entity<HandsComponent> ent, ref MeleeBlockAttemptEvent args)
{
if (ent.Owner == args.Attacker ||
!TryComp(ent.Comp.ActiveHandEntity, out MeleeBlockComponent? blockComponent) ||
!_random.Prob(blockComponent.BlockChance))
return;
args.Blocked = true;
_popupSystem.PopupEntity("заблокировал!", ent);
_audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/block_metal1.ogg"), ent,
AudioParams.Default.WithVariation(0.25f));
}
}

View File

@@ -0,0 +1,8 @@
namespace Content.Server._White.Other.RandomDamageSystem;
[RegisterComponent]
public sealed partial class RandomDamageComponent : Component
{
[DataField, ViewVariables(VVAccess.ReadWrite)]
public float Max = 50f;
}

View File

@@ -0,0 +1,26 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server._White.Other.RandomDamageSystem;
public sealed class RandomDamageSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RandomDamageComponent, MeleeHitEvent>(HandleHit);
}
private void HandleHit(Entity<RandomDamageComponent> ent, ref MeleeHitEvent args)
{
var damage = _random.NextFloat() * ent.Comp.Max;
args.BonusDamage = new DamageSpecifier(_prototypeManager.Index<DamageTypePrototype>("Slash"), damage);
}
}