Культ плоти (#871)
* Культ плоти * Мейби это скорет ноги для паучих ног * фикс ног и иконок (#986) Co-authored-by: Vigers Ray <vigersray@gmail.com> --------- Co-authored-by: Babaev <129369024+babaevlsdd@users.noreply.github.com>
This commit is contained in:
parent
a7b97e299f
commit
6304ac7e6f
224 changed files with 6813 additions and 77 deletions
32
Content.Client/_Sunrise/FleshCult/FleshCultistSystem.cs
Normal file
32
Content.Client/_Sunrise/FleshCult/FleshCultistSystem.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.StatusIcon.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
namespace Content.Client._Sunrise.FleshCult;
|
||||
|
||||
public sealed class FleshCultistSystem : SharedFleshMobSystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FleshCultistComponent, GetStatusIconsEvent>(GetFleshCultistIcon);
|
||||
SubscribeLocalEvent<FleshMobComponent, GetStatusIconsEvent>(GetFleshMobIcon);
|
||||
}
|
||||
|
||||
private void GetFleshCultistIcon(Entity<FleshCultistComponent> ent, ref GetStatusIconsEvent args)
|
||||
{
|
||||
var iconPrototype = _prototype.Index(ent.Comp.StatusIcon);
|
||||
args.StatusIcons.Add(iconPrototype);
|
||||
}
|
||||
|
||||
private void GetFleshMobIcon(Entity<FleshMobComponent> ent, ref GetStatusIconsEvent args)
|
||||
{
|
||||
if (HasComp<FleshCultistComponent>(ent))
|
||||
return;
|
||||
|
||||
var iconPrototype = _prototype.Index(ent.Comp.StatusIcon);
|
||||
args.StatusIcons.Add(iconPrototype);
|
||||
}
|
||||
}
|
||||
23
Content.Client/_Sunrise/FleshCult/FleshHeartVisualSystem.cs
Normal file
23
Content.Client/_Sunrise/FleshCult/FleshHeartVisualSystem.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.Flesh;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client._Sunrise.FleshCult;
|
||||
|
||||
public sealed class FleshHeartSystem : VisualizerSystem<FleshHeartComponent>
|
||||
{
|
||||
protected override void OnAppearanceChange(EntityUid uid, FleshHeartComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<FleshHeartStatus>(uid, FleshHeartVisuals.State, out var state, args.Component))
|
||||
return;
|
||||
var layer = args.Sprite.LayerMapGet(FleshHeartLayers.Base);
|
||||
|
||||
if (state == FleshHeartStatus.Active)
|
||||
{
|
||||
args.Sprite.LayerSetState(layer, component.FinalState);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Content.Client/_Sunrise/FleshCult/FleshHuggerSystem.cs
Normal file
11
Content.Client/_Sunrise/FleshCult/FleshHuggerSystem.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using Content.Server.Flesh;
|
||||
|
||||
namespace Content.Client._Sunrise.FleshCult;
|
||||
|
||||
public sealed class FleshHuggerSystem: SharedFleshHuggerSystem
|
||||
{
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
}
|
||||
}
|
||||
11
Content.Client/_Sunrise/FleshCult/FleshMobSystem.cs
Normal file
11
Content.Client/_Sunrise/FleshCult/FleshMobSystem.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using Content.Shared._Sunrise.FleshCult;
|
||||
|
||||
namespace Content.Client._Sunrise.FleshCult;
|
||||
|
||||
public sealed class FleshMobSystem : SharedFleshCultistSystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using Content.Server._Sunrise.AssaultOps;
|
||||
using Content.Server._Sunrise.FleshCult.GameRule;
|
||||
using Content.Server.Administration.Commands;
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
|
|
@ -194,5 +195,19 @@ public sealed partial class AdminVerbSystem
|
|||
Message = Loc.GetString("admin-verb-make-assault-operative"),
|
||||
};
|
||||
args.Verbs.Add(assaultOperative);
|
||||
|
||||
Verb fleshCultist = new()
|
||||
{
|
||||
Text = "Make Flesh Cultist",
|
||||
Category = VerbCategory.Antag,
|
||||
Icon = new SpriteSpecifier.Texture(new ResPath("_Sunrise/FleshCult/Interface/Actions/fleshCultistFleshHeart.png")),
|
||||
Act = () =>
|
||||
{
|
||||
_antag.ForceMakeAntag<FleshCultRuleComponent>(targetPlayer, "FleshCult");
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
Message = Loc.GetString("admin-verb-make-flesh-cultist"),
|
||||
};
|
||||
args.Verbs.Add(fleshCultist);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,5 +92,12 @@ namespace Content.Server.Destructible.Thresholds
|
|||
behavior.Execute(owner, system, cause);
|
||||
}
|
||||
}
|
||||
|
||||
// Sunrise-Start
|
||||
public void AddBehavior(IThresholdBehavior behavior)
|
||||
{
|
||||
_behaviors.Add(behavior);
|
||||
}
|
||||
// Sunrise-End
|
||||
}
|
||||
}
|
||||
|
|
|
|||
18
Content.Server/_Sunrise/FleshCult/CauseFleshCultInfection.cs
Normal file
18
Content.Server/_Sunrise/FleshCult/CauseFleshCultInfection.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
using Content.Server.Sunrise.FleshCult;
|
||||
using Content.Shared.EntityEffects;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult;
|
||||
|
||||
public sealed partial class CauseFleshCultInfection : EntityEffect
|
||||
{
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-cause-flesh-cultist-infection", ("chance", Probability));
|
||||
|
||||
public override void Effect(EntityEffectBaseArgs args)
|
||||
{
|
||||
var entityManager = args.EntityManager;
|
||||
entityManager.EnsureComponent<PendingFleshCultistComponent>(args.TargetEntity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
namespace Content.Server._Sunrise.FleshCult.Events;
|
||||
|
||||
[RegisterComponent, Access(typeof(VentFleshWormsRule))]
|
||||
public sealed partial class VentFleshWormsRuleComponent : Component
|
||||
{
|
||||
[DataField("spawnedPrototypeWorm")]
|
||||
public string SpawnedPrototypeWorm = "MobFleshWorm";
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
using System.Linq;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.StationEvents.Components;
|
||||
using Content.Server.StationEvents.Events;
|
||||
using Content.Shared.GameTicking.Components;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult.Events;
|
||||
|
||||
public sealed class VentFleshWormsRule : StationEventSystem<VentFleshWormsRuleComponent>
|
||||
{
|
||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||
|
||||
protected override void Started(EntityUid uid, VentFleshWormsRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
var targetStation = _stationSystem.GetStations().FirstOrNull();
|
||||
|
||||
if (!TryComp(targetStation, out StationDataComponent? data))
|
||||
{
|
||||
Logger.Info("TargetStation not have StationDataComponent");
|
||||
return;
|
||||
}
|
||||
|
||||
var spawnLocations = EntityManager.EntityQuery<VentCritterSpawnLocationComponent, TransformComponent>().ToList();
|
||||
|
||||
var grids = data.Grids.ToHashSet();
|
||||
spawnLocations.RemoveAll(
|
||||
backupSpawnLoc =>
|
||||
backupSpawnLoc.Item2.GridUid.HasValue && !grids.Contains(backupSpawnLoc.Item2.GridUid.Value));
|
||||
|
||||
RobustRandom.Shuffle(spawnLocations);
|
||||
|
||||
var spawnAmount = RobustRandom.Next(10, 20);
|
||||
Sawmill.Info($"Spawning {spawnAmount} of {component.SpawnedPrototypeWorm}");
|
||||
foreach (var location in spawnLocations)
|
||||
{
|
||||
if (spawnAmount-- == 0)
|
||||
break;
|
||||
|
||||
var coords = Transform(location.Item1.Owner);
|
||||
Spawn(component.SpawnedPrototypeWorm, coords.Coordinates);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
using Content.Shared.Roles;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class FleshCultistRoleComponent : BaseMindRoleComponent
|
||||
{
|
||||
[DataField("fleshHearts")]
|
||||
public int FleshHearts;
|
||||
}
|
||||
|
|
@ -0,0 +1,644 @@
|
|||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server.Construction.Components;
|
||||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Coordinates.Helpers;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult;
|
||||
|
||||
public sealed partial class FleshCultistSystem
|
||||
{
|
||||
private void InitializeAbilities()
|
||||
{
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistBladeActionEvent>(OnBladeActionEvent);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistClawActionEvent>(OnClawActionEvent);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistFistActionEvent>(OnFistActionEvent);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistSpikeHandGunActionEvent>(OnSpikeHandGunActionEvent);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistArmorActionEvent>(OnArmorActionEvent);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistHeavyArmorActionEvent>(OnHeavyArmorActionEvent);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistSpiderLegsActionEvent>(OnSpiderLegsActionEvent);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistAdrenalinActionEvent>(OnAdrenalinActionEvent);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistCreateFleshHeartActionEvent>(OnCreateFleshHeartActionEvent);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistThrowHuggerActionEvent>(OnThrowHugger);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistAcidSpitActionEvent>(OnAcidSpit);
|
||||
}
|
||||
|
||||
private void OnAcidSpit(EntityUid uid, FleshCultistComponent component, FleshCultistAcidSpitActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
var acidBullet = Spawn(component.BulletAcidSpawnId, Transform(uid).Coordinates);
|
||||
var xform = Transform(uid);
|
||||
var mapCoords = args.Target.ToMap(_entityManager, _transformSystem);
|
||||
var direction = mapCoords.Position - xform.MapPosition.Position;
|
||||
var userVelocity = _physics.GetMapLinearVelocity(uid);
|
||||
|
||||
_gunSystem.ShootProjectile(acidBullet, direction, userVelocity, uid, uid);
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
}
|
||||
|
||||
private void OnBladeActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistBladeActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
if (TryComp<CuffableComponent>(uid, out var cuffableComponent))
|
||||
{
|
||||
if (cuffableComponent.CuffedHandCount > 0)
|
||||
_cuffable.Uncuff(uid, uid, cuffableComponent.LastAddedCuffs);
|
||||
}
|
||||
var hands = _handsSystem.EnumerateHands(uid);
|
||||
var enumerateHands = hands as Hand[] ?? Enumerable.ToArray<Hand>(hands);
|
||||
foreach (var enumerateHand in enumerateHands)
|
||||
{
|
||||
if (enumerateHand.Container == null)
|
||||
continue;
|
||||
foreach (var containerContainedEntity in enumerateHand.Container.ContainedEntities)
|
||||
{
|
||||
if (!TryComp(containerContainedEntity, out MetaDataComponent? metaData))
|
||||
continue;
|
||||
if (metaData.EntityPrototype == null)
|
||||
continue;
|
||||
if (!HasComp<_Sunrise.FleshCult.FleshHandModComponent>(containerContainedEntity))
|
||||
{
|
||||
if (enumerateHand != enumerateHands.First())
|
||||
continue;
|
||||
var isDrop = _handsSystem.TryDrop(uid, checkActionBlocker: false);
|
||||
if (metaData.EntityPrototype.ID == component.BladeSpawnId)
|
||||
continue;
|
||||
if (isDrop)
|
||||
continue;
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-user-hand-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
{
|
||||
if (enumerateHand != enumerateHands.First())
|
||||
{
|
||||
if (metaData.EntityPrototype.ID != component.BladeSpawnId)
|
||||
continue;
|
||||
QueueDel(containerContainedEntity);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (metaData.EntityPrototype.ID != component.BladeSpawnId)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-user-hand-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueueDel(containerContainedEntity);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-blade-in-hand",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
EnsureComp<CuffableComponent>(uid);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var blade = Spawn(component.BladeSpawnId, Transform(uid).Coordinates);
|
||||
var isPickup = _handsSystem.TryPickup(uid, blade, checkActionBlocker: false,
|
||||
animateUser: false, animate: false);
|
||||
if (isPickup)
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-hand-in-blade", ("Entity", uid)),
|
||||
uid, PopupType.LargeCaution);
|
||||
if (HasComp<CuffableComponent>(uid))
|
||||
{
|
||||
EntityManager.RemoveComponent<CuffableComponent>(uid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error("Failed to equip blade to hand, removing blade");
|
||||
QueueDel(blade);
|
||||
}
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnClawActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistClawActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
if (TryComp<CuffableComponent>(uid, out var cuffableComponent))
|
||||
{
|
||||
if (cuffableComponent.CuffedHandCount > 0)
|
||||
_cuffable.Uncuff(uid, uid, cuffableComponent.LastAddedCuffs);
|
||||
}
|
||||
var hands = _handsSystem.EnumerateHands(uid);
|
||||
var enumerateHands = hands as Hand[] ?? Enumerable.ToArray<Hand>(hands);
|
||||
foreach (var enumerateHand in enumerateHands)
|
||||
{
|
||||
if (enumerateHand.Container == null)
|
||||
continue;
|
||||
foreach (var containerContainedEntity in enumerateHand.Container.ContainedEntities)
|
||||
{
|
||||
if (!TryComp(containerContainedEntity, out MetaDataComponent? metaData))
|
||||
continue;
|
||||
if (metaData.EntityPrototype == null)
|
||||
continue;
|
||||
if (!HasComp<_Sunrise.FleshCult.FleshHandModComponent>(containerContainedEntity))
|
||||
{
|
||||
if (enumerateHand != enumerateHands.First())
|
||||
continue;
|
||||
var isDrop = _handsSystem.TryDrop(uid, checkActionBlocker: false);
|
||||
if (metaData.EntityPrototype.ID == component.ClawSpawnId)
|
||||
continue;
|
||||
if (isDrop)
|
||||
continue;
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-user-hand-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
{
|
||||
if (enumerateHand != enumerateHands.First())
|
||||
{
|
||||
if (metaData.EntityPrototype.ID != component.ClawSpawnId)
|
||||
continue;
|
||||
QueueDel(containerContainedEntity);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (metaData.EntityPrototype.ID != component.ClawSpawnId)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-user-hand-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueueDel(containerContainedEntity);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-claw-in-hand",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
EnsureComp<CuffableComponent>(uid);
|
||||
args.Handled = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var claw = Spawn(component.ClawSpawnId, Transform(uid).Coordinates);
|
||||
var isPickup = _handsSystem.TryPickup(uid, claw, checkActionBlocker: false,
|
||||
animateUser: false, animate: false);
|
||||
if (isPickup)
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-hand-in-claw", ("Entity", uid)),
|
||||
uid, PopupType.LargeCaution);
|
||||
if (HasComp<CuffableComponent>(uid))
|
||||
EntityManager.RemoveComponent<CuffableComponent>(uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueueDel(claw);
|
||||
}
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
|
||||
private void OnFistActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistFistActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
if (TryComp<CuffableComponent>(uid, out var cuffableComponent))
|
||||
{
|
||||
if (cuffableComponent.CuffedHandCount > 0)
|
||||
_cuffable.Uncuff(uid, uid, cuffableComponent.LastAddedCuffs);
|
||||
}
|
||||
var hands = _handsSystem.EnumerateHands(uid);
|
||||
var enumerateHands = hands as Hand[] ?? Enumerable.ToArray<Hand>(hands);
|
||||
foreach (var enumerateHand in enumerateHands)
|
||||
{
|
||||
if (enumerateHand.Container == null)
|
||||
continue;
|
||||
foreach (var containerContainedEntity in enumerateHand.Container.ContainedEntities)
|
||||
{
|
||||
if (!TryComp(containerContainedEntity, out MetaDataComponent? metaData))
|
||||
continue;
|
||||
if (metaData.EntityPrototype == null)
|
||||
continue;
|
||||
if (!HasComp<_Sunrise.FleshCult.FleshHandModComponent>(containerContainedEntity))
|
||||
{
|
||||
if (enumerateHand != enumerateHands.First())
|
||||
continue;
|
||||
var isDrop = _handsSystem.TryDrop(uid, checkActionBlocker: false);
|
||||
if (metaData.EntityPrototype.ID == component.FistSpawnId)
|
||||
continue;
|
||||
if (isDrop)
|
||||
continue;
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-user-hand-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
{
|
||||
if (enumerateHand != enumerateHands.First())
|
||||
{
|
||||
if (metaData.EntityPrototype.ID != component.FistSpawnId)
|
||||
continue;
|
||||
QueueDel(containerContainedEntity);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (metaData.EntityPrototype.ID != component.FistSpawnId)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-user-hand-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueueDel(containerContainedEntity);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-claw-in-hand",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
EnsureComp<CuffableComponent>(uid);
|
||||
args.Handled = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var fist = Spawn(component.FistSpawnId, Transform(uid).Coordinates);
|
||||
var isPickup = _handsSystem.TryPickup(uid, fist, checkActionBlocker: false,
|
||||
animateUser: false, animate: false);
|
||||
if (isPickup)
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-hand-in-claw", ("Entity", uid)),
|
||||
uid, PopupType.LargeCaution);
|
||||
if (HasComp<CuffableComponent>(uid))
|
||||
EntityManager.RemoveComponent<CuffableComponent>(uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueueDel(fist);
|
||||
}
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnSpikeHandGunActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistSpikeHandGunActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
if (TryComp<CuffableComponent>(uid, out var cuffableComponent))
|
||||
{
|
||||
if (cuffableComponent.CuffedHandCount > 0)
|
||||
_cuffable.Uncuff(uid, uid, cuffableComponent.LastAddedCuffs);
|
||||
}
|
||||
var hands = _handsSystem.EnumerateHands(uid);
|
||||
var enumerateHands = hands as Hand[] ?? Enumerable.ToArray<Hand>(hands);
|
||||
foreach (var enumerateHand in enumerateHands)
|
||||
{
|
||||
if (enumerateHand.Container == null)
|
||||
continue;
|
||||
foreach (var containerContainedEntity in enumerateHand.Container.ContainedEntities)
|
||||
{
|
||||
if (!TryComp(containerContainedEntity, out MetaDataComponent? metaData))
|
||||
continue;
|
||||
if (metaData.EntityPrototype == null)
|
||||
continue;
|
||||
if (!HasComp<_Sunrise.FleshCult.FleshHandModComponent>(containerContainedEntity))
|
||||
{
|
||||
if (enumerateHand != enumerateHands.First())
|
||||
continue;
|
||||
var isDrop = _handsSystem.TryDrop(uid, checkActionBlocker: false);
|
||||
if (metaData.EntityPrototype.ID == component.SpikeHandGunSpawnId)
|
||||
continue;
|
||||
if (isDrop)
|
||||
continue;
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-user-hand-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
{
|
||||
if (enumerateHand != enumerateHands.First())
|
||||
{
|
||||
if (metaData.EntityPrototype.ID != component.SpikeHandGunSpawnId)
|
||||
continue;
|
||||
QueueDel(containerContainedEntity);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (metaData.EntityPrototype.ID != component.SpikeHandGunSpawnId)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-user-hand-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueueDel(containerContainedEntity);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-spike-gun-in-hand",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
EnsureComp<CuffableComponent>(uid);
|
||||
args.Handled = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var claw = Spawn(component.SpikeHandGunSpawnId, Transform(uid).Coordinates);
|
||||
var isPickup = _handsSystem.TryPickup(uid, claw, checkActionBlocker: false,
|
||||
animateUser: false, animate: false);
|
||||
if (isPickup)
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-hand-in-spike-gun", ("Entity", uid)),
|
||||
uid, PopupType.LargeCaution);
|
||||
if (HasComp<CuffableComponent>(uid))
|
||||
RemComp<CuffableComponent>(uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueueDel(claw);
|
||||
}
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnArmorActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistArmorActionEvent args)
|
||||
{
|
||||
_inventory.TryGetSlotEntity(uid, "outerClothing", out var outerClothing);
|
||||
if (outerClothing != null)
|
||||
{
|
||||
if (!TryComp(outerClothing, out MetaDataComponent? metaData))
|
||||
return;
|
||||
if (metaData.EntityPrototype == null)
|
||||
return;
|
||||
if (metaData.EntityPrototype.ID == component.HeavyArmorSpawnId)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-armor-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
}
|
||||
else if (metaData.EntityPrototype.ID != component.ArmorSpawnId)
|
||||
{
|
||||
_inventory.TryUnequip(uid, "outerClothing", true, true);
|
||||
var armor = Spawn(component.ArmorSpawnId, Transform(uid).Coordinates);
|
||||
var equipped = _inventory.TryEquip(uid, armor, "outerClothing", true);
|
||||
if (!equipped)
|
||||
{
|
||||
QueueDel(armor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-armor-on",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-armor-off",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
EntityManager.DeleteEntity(outerClothing.Value);
|
||||
_movement.RefreshMovementSpeedModifiers(uid);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var armor = Spawn(component.ArmorSpawnId, Transform(uid).Coordinates);
|
||||
var equipped = _inventory.TryEquip(uid, armor, "outerClothing", true);
|
||||
if (!equipped)
|
||||
{
|
||||
QueueDel(armor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-armor-on",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHeavyArmorActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistHeavyArmorActionEvent args)
|
||||
{
|
||||
_inventory.TryGetSlotEntity(uid, "shoes", out var shoes);
|
||||
if (shoes != null)
|
||||
{
|
||||
if (!TryComp(shoes, out MetaDataComponent? metaData))
|
||||
return;
|
||||
if (metaData.EntityPrototype == null)
|
||||
return;
|
||||
if (metaData.EntityPrototype.ID == component.SpiderLegsSpawnId)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-armor-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_inventory.TryGetSlotEntity(uid, "outerClothing", out var outerClothing);
|
||||
if (outerClothing != null)
|
||||
{
|
||||
if (!TryComp(outerClothing, out MetaDataComponent? metaData))
|
||||
return;
|
||||
if (metaData.EntityPrototype == null)
|
||||
return;
|
||||
if (metaData.EntityPrototype.ID == component.ArmorSpawnId)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-armor-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
}
|
||||
else if (metaData.EntityPrototype.ID != component.HeavyArmorSpawnId)
|
||||
{
|
||||
_inventory.TryUnequip(uid, "outerClothing", true, true);
|
||||
var armor = Spawn(component.HeavyArmorSpawnId, Transform(uid).Coordinates);
|
||||
var equipped = _inventory.TryEquip(uid, armor, "outerClothing", true);
|
||||
if (!equipped)
|
||||
{
|
||||
QueueDel(armor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-armor-on",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-armor-off",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
EntityManager.DeleteEntity(outerClothing.Value);
|
||||
_movement.RefreshMovementSpeedModifiers(uid);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var armor = Spawn(component.HeavyArmorSpawnId, Transform(uid).Coordinates);
|
||||
var equipped = _inventory.TryEquip(uid, armor, "outerClothing", true);
|
||||
if (!equipped)
|
||||
{
|
||||
QueueDel(armor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-armor-on",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSpiderLegsActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistSpiderLegsActionEvent args)
|
||||
{
|
||||
_inventory.TryGetSlotEntity(uid, "outerClothing", out var outerClothing);
|
||||
if (outerClothing != null)
|
||||
{
|
||||
if (!TryComp(outerClothing, out MetaDataComponent? metaData))
|
||||
return;
|
||||
if (metaData.EntityPrototype == null)
|
||||
return;
|
||||
if (metaData.EntityPrototype.ID == component.ArmorSpawnId || metaData.EntityPrototype.ID == component.HeavyArmorSpawnId)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-spider-legs-blocked"),
|
||||
uid, uid, PopupType.Large);
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_tagSystem.HasTag(outerClothing.Value, "FullBodyOuter"))
|
||||
{
|
||||
_inventory.TryUnequip(uid, "outerClothing", true, true);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
_inventory.TryGetSlotEntity(uid, "shoes", out var shoes);
|
||||
if (shoes != null)
|
||||
{
|
||||
if (!TryComp(shoes, out MetaDataComponent? metaData))
|
||||
return;
|
||||
if (metaData.EntityPrototype == null)
|
||||
return;
|
||||
|
||||
if (metaData.EntityPrototype.ID == component.SpiderLegsSpawnId)
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-spider-legs-off",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
EntityManager.DeleteEntity(shoes.Value);
|
||||
_movement.RefreshMovementSpeedModifiers(uid);
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_inventory.TryUnequip(uid, "shoes", true, true);
|
||||
}
|
||||
_inventory.TryUnequip(uid, "socks", true, true);
|
||||
var legs = Spawn(component.SpiderLegsSpawnId, Transform(uid).Coordinates);
|
||||
var equipped = _inventory.TryEquip(uid, legs, "shoes", true, true);
|
||||
if (!equipped)
|
||||
{
|
||||
QueueDel(legs);
|
||||
}
|
||||
else
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-transform-spider-legs-on",
|
||||
("Entity", uid)), uid, PopupType.LargeCaution);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAdrenalinActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistAdrenalinActionEvent args)
|
||||
{
|
||||
if (!_solutionContainerSystem.TryGetInjectableSolution(uid, out var injectableSolution, out var _))
|
||||
return;
|
||||
var transferSolution = new Solution();
|
||||
foreach (var solution in component.AdrenalinReagents)
|
||||
{
|
||||
transferSolution.AddReagent(solution.Reagent, solution.Quantity);
|
||||
}
|
||||
_solutionContainerSystem.TryAddSolution(injectableSolution.Value, transferSolution);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnCreateFleshHeartActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistCreateFleshHeartActionEvent args)
|
||||
{
|
||||
var xform = Transform(uid);
|
||||
var radius = 1.5f;
|
||||
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-cant-spawn-flesh-heart-in-space",
|
||||
("Entity", uid)), uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
|
||||
var offsetValue = Vector2Helpers.Normalized(xform.LocalRotation.ToWorldVec());
|
||||
var targetCord = xform.Coordinates.Offset(offsetValue).SnapToGrid(EntityManager);
|
||||
var tilerefs = Enumerable.ToArray<TileRef>(grid.GetLocalTilesIntersecting(
|
||||
new Box2(targetCord.Position + new Vector2(-radius, -radius), targetCord.Position + new Vector2(radius, radius))));
|
||||
foreach (var tileref in tilerefs)
|
||||
{
|
||||
foreach (var entity in tileref.GetEntitiesInTile())
|
||||
{
|
||||
PhysicsComponent? physics = null; // We use this to check if it's impassable
|
||||
if (HasComp<MobStateComponent>(entity) && entity != uid || // Is it a mob?
|
||||
Resolve(entity, ref physics, false) && (physics.CollisionLayer & (int) CollisionGroup.Impassable) != 0 ||
|
||||
HasComp<ConstructionComponent>(entity) && entity != uid) // Is construction?
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-cant-spawn-flesh-heart-here",
|
||||
("Entity", uid)), uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
EntityManager.SpawnEntity(component.FleshHeartId, targetCord);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnThrowHugger(EntityUid uid, FleshCultistComponent component, FleshCultistThrowHuggerActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
var hugger = Spawn(component.HuggerMobSpawnId, Transform(uid).Coordinates);
|
||||
var xform = Transform(uid);
|
||||
var mapCoords = args.Target.ToMap(_entityManager, _transformSystem);
|
||||
var direction = mapCoords.Position - xform.MapPosition.Position;
|
||||
|
||||
_throwing.TryThrow(hugger, direction, 7F, uid, 10F);
|
||||
if (component.SoundThrowHugger != null)
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundThrowHugger, uid, component.SoundThrowHugger.Params);
|
||||
}
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-throw-hugger"), uid, uid,
|
||||
PopupType.LargeCaution);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-throw-hugger-others", ("Entity", uid)),
|
||||
uid, Filter.PvsExcept(uid), true, PopupType.LargeCaution);
|
||||
}
|
||||
|
||||
}
|
||||
808
Content.Server/_Sunrise/FleshCult/FleshCultistSystem.cs
Normal file
808
Content.Server/_Sunrise/FleshCult/FleshCultistSystem.cs
Normal file
|
|
@ -0,0 +1,808 @@
|
|||
using System.Linq;
|
||||
using Content.Server._Sunrise.FleshCult.GameRule;
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Cuffs;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.Flash.Components;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Server.Forensics;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Server.Sunrise.FleshCult;
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Server.Traits.Assorted;
|
||||
using Content.Server.Weapons.Ranged.Systems;
|
||||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Cuffs.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Electrocution;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Fluids.Components;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Interaction.Components;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Jittering;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Mindshield.Components;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Nutrition.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Speech.EntitySystems;
|
||||
using Content.Shared.Store.Components;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared.Sunrise.CollectiveMind;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult;
|
||||
|
||||
public sealed partial class FleshCultistSystem : SharedFleshCultistSystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly ActionsSystem _action = default!;
|
||||
[Dependency] private readonly AlertsSystem _alerts = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly StoreSystem _store = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly PuddleSystem _puddleSystem = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly HumanoidAppearanceSystem _sharedHuApp = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _sharedAppearance = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly BodySystem _body = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||
[Dependency] private readonly GunSystem _gunSystem = default!;
|
||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||
[Dependency] private readonly CuffableSystem _cuffable = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
|
||||
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
|
||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly SharedStunSystem _stunSystem = default!;
|
||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||
[Dependency] private readonly FleshCultRuleSystem _fleshCultRule = default!;
|
||||
[Dependency] private readonly SharedJitteringSystem _jittering = default!;
|
||||
[Dependency] private readonly SharedStutteringSystem _stuttering = default!;
|
||||
[Dependency] private readonly ExplosionSystem _explosionSystem = default!;
|
||||
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||
[Dependency] private readonly ContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FleshCultistComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistShopActionEvent>(OnShop);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistInsulatedImmunityMutationEvent>(OnInsulatedImmunityMutation);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistPressureImmunityMutationEvent>(OnPressureImmunityMutation);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistFlashImmunityMutationEvent>(OnFlashImmunityMutation);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistRespiratorImmunityMutationEvent>(OnRespiratorImmunityMutation);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistColdTempImmunityMutationEvent>(OnColdTempImmunityMutation);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistDevourActionEvent>(OnDevourAction);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistDevourDoAfterEvent>(OnDevourDoAfter);
|
||||
SubscribeLocalEvent<FleshCultistComponent, IsEquippingAttemptEvent>(OnBeingEquippedAttempt);
|
||||
SubscribeLocalEvent<FleshCultistComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
SubscribeLocalEvent<FleshCultistComponent, FleshCultistAbsorbBloodPoolActionEvent>(OnAbsormBloodPoolActionEvent);
|
||||
|
||||
SubscribeLocalEvent<PendingFleshCultistComponent, MapInitEvent>(OnPendingMapInit);
|
||||
|
||||
InitializeAbilities();
|
||||
}
|
||||
|
||||
private void OnPendingMapInit(EntityUid uid, PendingFleshCultistComponent component, MapInitEvent args)
|
||||
{
|
||||
component.NextParalyze = _timing.CurTime + TimeSpan.FromSeconds(1f);
|
||||
component.NextScream = _timing.CurTime + TimeSpan.FromSeconds(1f);
|
||||
}
|
||||
|
||||
private void OnMobStateChanged(EntityUid uid, FleshCultistComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
switch (args.NewMobState)
|
||||
{
|
||||
case MobState.Critical:
|
||||
{
|
||||
EnsureComp<CuffableComponent>(uid);
|
||||
var hands = _handsSystem.EnumerateHands(uid);
|
||||
var enumerateHands = hands as Hand[] ?? hands.ToArray();
|
||||
foreach (var enumerateHand in enumerateHands)
|
||||
{
|
||||
if (enumerateHand.Container == null)
|
||||
continue;
|
||||
foreach (var containerContainedEntity in enumerateHand.Container.ContainedEntities)
|
||||
{
|
||||
if (HasComp<_Sunrise.FleshCult.FleshHandModComponent>(containerContainedEntity))
|
||||
continue;
|
||||
QueueDel(containerContainedEntity);
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MobState.Dead:
|
||||
{
|
||||
_inventory.TryGetSlotEntity(uid, "shoes", out var shoes);
|
||||
if (shoes != null)
|
||||
{
|
||||
if (TryComp(shoes, out MetaDataComponent? metaData))
|
||||
{
|
||||
if (metaData.EntityPrototype != null)
|
||||
{
|
||||
if (metaData.EntityPrototype.ID == component.SpiderLegsSpawnId)
|
||||
{
|
||||
EntityManager.DeleteEntity(shoes.Value);
|
||||
_movement.RefreshMovementSpeedModifiers(uid);
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_inventory.TryGetSlotEntity(uid, "outerClothing", out var outerClothing);
|
||||
if (outerClothing != null)
|
||||
{
|
||||
if (TryComp(outerClothing, out MetaDataComponent? metaData))
|
||||
{
|
||||
if (metaData.EntityPrototype != null)
|
||||
{
|
||||
if (metaData.EntityPrototype.ID == component.ArmorSpawnId ||
|
||||
metaData.EntityPrototype.ID == component.HeavyArmorSpawnId)
|
||||
{
|
||||
EntityManager.DeleteEntity(outerClothing.Value);
|
||||
_movement.RefreshMovementSpeedModifiers(uid);
|
||||
_audioSystem.PlayPvs(component.SoundMutation, uid, component.SoundMutation.Params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParasiteComesOut(uid, component);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBeingEquippedAttempt(EntityUid uid, FleshCultistComponent component, IsEquippingAttemptEvent args)
|
||||
{
|
||||
if (args.Slot is not ("socks" or "outerClothing"))
|
||||
return;
|
||||
_inventory.TryGetSlotEntity(uid, "shoes", out var shoes);
|
||||
if (shoes == null)
|
||||
return;
|
||||
if (!TryComp(shoes, out MetaDataComponent? metaData))
|
||||
return;
|
||||
if (metaData.EntityPrototype == null)
|
||||
return;
|
||||
if (metaData.EntityPrototype.ID != component.SpiderLegsSpawnId)
|
||||
return;
|
||||
if (args.Slot is "outerClothing" && !_tagSystem.HasTag(args.Equipment, "FullBodyOuter"))
|
||||
return;
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-equiped-outer-clothing-blocked",
|
||||
("Entity", uid)), uid, PopupType.Large);
|
||||
args.Cancel();
|
||||
|
||||
}
|
||||
|
||||
private void OnStartup(EntityUid uid, FleshCultistComponent component, ComponentStartup args)
|
||||
{
|
||||
ChangeParasiteHunger(uid, 0, component);
|
||||
|
||||
_action.AddAction(uid, "FleshCultistShop");
|
||||
_action.AddAction(uid, "FleshCultistDevour");
|
||||
_action.AddAction(uid, "FleshCultistAbsorbBloodPool");
|
||||
|
||||
var storeComp = EnsureComp<StoreComponent>(uid);
|
||||
|
||||
var collectiveMindComponent = EnsureComp<CollectiveMindComponent>(uid);
|
||||
if (!collectiveMindComponent.Minds.Contains("FleshCult"))
|
||||
collectiveMindComponent.Minds.Add("FleshCult");
|
||||
|
||||
storeComp.Categories.Add("FleshCultistPassiveSkills");
|
||||
storeComp.Categories.Add("FleshCultistActiveSkills");
|
||||
storeComp.Categories.Add("FleshCultistWeapon");
|
||||
storeComp.Categories.Add("FleshCultistArmor");
|
||||
storeComp.CurrencyWhitelist.Add("StolenMutationPoint");
|
||||
storeComp.BuySuccessSound = component.BuySuccesSound;
|
||||
storeComp.RefundAllowed = false;
|
||||
|
||||
EnsureComp<IgnoreFleshSpiderWebComponent>(uid);
|
||||
|
||||
if (HasComp<HungerComponent>(uid))
|
||||
RemComp<HungerComponent>(uid);
|
||||
|
||||
if (HasComp<ThirstComponent>(uid))
|
||||
RemComp<ThirstComponent>(uid);
|
||||
|
||||
_tagSystem.AddTag(uid, "Flesh");
|
||||
|
||||
if (TryComp<HumanoidAppearanceComponent>(uid, out var appearance))
|
||||
{
|
||||
appearance.HideLayersOnEquip.Add(HumanoidVisualLayers.RLeg);
|
||||
appearance.HideLayersOnEquip.Add(HumanoidVisualLayers.LLeg);
|
||||
appearance.HideLayersOnEquip.Add(HumanoidVisualLayers.RFoot);
|
||||
appearance.HideLayersOnEquip.Add(HumanoidVisualLayers.LFoot);
|
||||
Dirty(uid, appearance);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInsulatedImmunityMutation(EntityUid uid, FleshCultistComponent component,
|
||||
FleshCultistInsulatedImmunityMutationEvent args)
|
||||
{
|
||||
EnsureComp<InsulatedComponent>(uid);
|
||||
}
|
||||
|
||||
|
||||
private void OnPressureImmunityMutation(EntityUid uid, FleshCultistComponent component,
|
||||
FleshCultistPressureImmunityMutationEvent args)
|
||||
{
|
||||
EnsureComp<PressureImmunityComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnFlashImmunityMutation(EntityUid uid, FleshCultistComponent component,
|
||||
FleshCultistFlashImmunityMutationEvent args)
|
||||
{
|
||||
EnsureComp<FlashImmunityComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnRespiratorImmunityMutation(EntityUid uid, FleshCultistComponent component,
|
||||
FleshCultistRespiratorImmunityMutationEvent args)
|
||||
{
|
||||
EnsureComp<RespiratorImmunityComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnColdTempImmunityMutation(EntityUid uid, FleshCultistComponent component,
|
||||
FleshCultistColdTempImmunityMutationEvent args)
|
||||
{
|
||||
if (TryComp<TemperatureComponent>(uid, out var tempComponent))
|
||||
{
|
||||
tempComponent.ColdDamageThreshold = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnShop(EntityUid uid, FleshCultistComponent component, FleshCultistShopActionEvent args)
|
||||
{
|
||||
if (!TryComp<StoreComponent>(uid, out var store))
|
||||
return;
|
||||
_store.ToggleUi(uid, uid, store);
|
||||
}
|
||||
|
||||
private bool ChangeParasiteHunger(EntityUid uid, FixedPoint2 amount, FleshCultistComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return false;
|
||||
|
||||
component.Hunger += amount;
|
||||
|
||||
if (TryComp<StoreComponent>(uid, out var store))
|
||||
_store.UpdateUserInterface(uid, uid, store);
|
||||
|
||||
_alerts.ShowAlert(uid, component.MutationPointAlert, (short) Math.Clamp(Math.Round(component.Hunger.Float() / 10f), 0, 16));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnDevourAction(EntityUid uid, FleshCultistComponent component, FleshCultistDevourActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
var target = args.Target;
|
||||
|
||||
if (!TryComp<MobStateComponent>(target, out var targetState))
|
||||
return;
|
||||
if (!TryComp<BloodstreamComponent>(target, out var bloodstream))
|
||||
return;
|
||||
var hasAppearance = false;
|
||||
{
|
||||
switch (targetState.CurrentState)
|
||||
{
|
||||
case MobState.Dead:
|
||||
if (EntityManager.TryGetComponent(target, out HumanoidAppearanceComponent? humanoidAppearance))
|
||||
{
|
||||
if (!component.SpeciesWhitelist.Contains(humanoidAppearance.Species))
|
||||
{
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("flesh-cultist-devout-target-not-have-flesh"),
|
||||
uid, uid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryComp<FixturesComponent>(target, out var fixturesComponent))
|
||||
{
|
||||
if (fixturesComponent.Fixtures["fix1"].Density <= 60)
|
||||
{
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("flesh-cultist-devout-target-invalid"),
|
||||
uid, uid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hasAppearance = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bloodstream.BloodReagent != "Blood")
|
||||
{
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("flesh-cultist-devout-target-not-have-flesh"),
|
||||
uid, uid);
|
||||
return;
|
||||
}
|
||||
if (bloodstream.BloodMaxVolume < 30)
|
||||
{
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("flesh-cultist-devout-target-invalid"),
|
||||
uid, uid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
var saturation = MatchSaturation(bloodstream.BloodMaxVolume.Value / 100, hasAppearance);
|
||||
if (component.Hunger + saturation >= component.MaxHunger)
|
||||
{
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("flesh-cultist-devout-not-hungry"),
|
||||
uid, uid);
|
||||
return;
|
||||
}
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager ,uid, component.DevourTime,
|
||||
new FleshCultistDevourDoAfterEvent(), uid, target: target, used: uid)
|
||||
{
|
||||
BreakOnMove = true,
|
||||
});
|
||||
args.Handled = true;
|
||||
break;
|
||||
|
||||
case MobState.Invalid:
|
||||
case MobState.Critical:
|
||||
case MobState.Alive:
|
||||
default:
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("flesh-cultist-devout-target-alive"),
|
||||
uid, uid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDevourDoAfter(EntityUid uid, FleshCultistComponent component, FleshCultistDevourDoAfterEvent args)
|
||||
{
|
||||
if (args.Handled || args.Cancelled)
|
||||
return;
|
||||
|
||||
if (args.Args.Target == null)
|
||||
return;
|
||||
|
||||
if (!TryComp<BloodstreamComponent>(args.Args.Target.Value, out var bloodstream))
|
||||
return;
|
||||
|
||||
var hasAppearance = false;
|
||||
|
||||
var xform = Transform(args.Args.Target.Value);
|
||||
var coordinates = xform.Coordinates;
|
||||
_audioSystem.PlayPvs(component.DevourSound, coordinates, AudioParams.Default.WithVariation(0.025f).WithMaxDistance(5f));
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-devour-target",
|
||||
("Entity", uid), ("Target", args.Args.Target)), uid);
|
||||
|
||||
if (bloodstream.BloodSolution != null)
|
||||
{
|
||||
_bloodstreamSystem.SpillAllSolutions(args.Args.Target.Value, bloodstream);
|
||||
}
|
||||
|
||||
if (TryComp<HumanoidAppearanceComponent>(args.Args.Target, out var HuAppComponent))
|
||||
{
|
||||
if (TryComp(args.Args.Target.Value, out ContainerManagerComponent? container))
|
||||
{
|
||||
foreach (var cont in container.GetAllContainers().ToArray())
|
||||
{
|
||||
foreach (var ent in cont.ContainedEntities.ToArray())
|
||||
{
|
||||
if (HasComp<BodyPartComponent>(ent))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
_containerSystem.Remove(ent, cont, force: true);
|
||||
Transform(ent).Coordinates = coordinates;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TryComp<BodyComponent>(args.Args.Target, out var bodyComponent))
|
||||
{
|
||||
var parts = _body.GetBodyChildren(args.Args.Target, bodyComponent).ToArray();
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
if (part.Component.PartType == BodyPartType.Head)
|
||||
continue;
|
||||
|
||||
if (part.Component.PartType == BodyPartType.Torso)
|
||||
{
|
||||
foreach (var organ in _body.GetPartOrgans(part.Id, part.Component))
|
||||
{
|
||||
//_body.RemoveOrgan(organ.Id);
|
||||
QueueDel(organ.Id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QueueDel(part.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var skeletonSprites = _proto.Index<HumanoidSpeciesBaseSpritesPrototype>("MobSkeletonSprites");
|
||||
foreach (var (key, id) in skeletonSprites.Sprites)
|
||||
{
|
||||
if (key != HumanoidVisualLayers.Head)
|
||||
{
|
||||
_sharedHuApp.SetBaseLayerId(args.Args.Target.Value, key, id, humanoid: HuAppComponent);
|
||||
}
|
||||
}
|
||||
|
||||
if (TryComp<FixturesComponent>(args.Args.Target, out var fixturesComponent))
|
||||
{
|
||||
_physics.SetDensity(args.Args.Target.Value, "fix1", fixturesComponent.Fixtures["fix1"], 50);
|
||||
}
|
||||
|
||||
if (TryComp<AppearanceComponent>(args.Args.Target, out var appComponent))
|
||||
{
|
||||
_sharedAppearance.SetData(args.Args.Target.Value, DamageVisualizerKeys.Disabled, true, appComponent);
|
||||
}
|
||||
|
||||
hasAppearance = true;
|
||||
}
|
||||
|
||||
var saturation = MatchSaturation(bloodstream.BloodMaxVolume.Value / 100, hasAppearance);
|
||||
var evolutionPoint = MatchEvolutionPoint(bloodstream.BloodMaxVolume.Value / 100, hasAppearance);
|
||||
var healPoint = MatchHealPoint(bloodstream.BloodMaxVolume.Value / 100, hasAppearance);
|
||||
|
||||
RemComp<BloodstreamComponent>(args.Args.Target.Value);
|
||||
|
||||
EnsureComp<UnrevivableComponent>(args.Args.Target.Value);
|
||||
|
||||
if (!hasAppearance)
|
||||
{
|
||||
QueueDel(args.Args.Target.Value);
|
||||
}
|
||||
|
||||
if (_solutionContainerSystem.TryGetInjectableSolution(uid, out var injectableSolution, out _))
|
||||
{
|
||||
var transferSolution = new Solution();
|
||||
foreach (var solution in component.HealDevourReagents)
|
||||
{
|
||||
transferSolution.AddReagent(solution.Reagent, solution.Quantity * healPoint);
|
||||
}
|
||||
_solutionContainerSystem.TryAddSolution(injectableSolution.Value, transferSolution);
|
||||
}
|
||||
|
||||
component.Hunger += saturation;
|
||||
_store.TryAddCurrency(new Dictionary<string, FixedPoint2>
|
||||
{ {component.StolenCurrencyPrototype, evolutionPoint} }, uid);
|
||||
}
|
||||
|
||||
private int MatchSaturation(int bloodVolume, bool hasAppearance)
|
||||
{
|
||||
if (hasAppearance)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
return bloodVolume switch
|
||||
{
|
||||
>= 300 => 80,
|
||||
>= 150 => 60,
|
||||
>= 100 => 40,
|
||||
_ => 20
|
||||
};
|
||||
}
|
||||
|
||||
private int MatchEvolutionPoint(int bloodVolume, bool hasAppearance)
|
||||
{
|
||||
if (hasAppearance)
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
return bloodVolume switch
|
||||
{
|
||||
>= 300 => 15,
|
||||
>= 150 => 10,
|
||||
>= 100 => 5,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
private float MatchHealPoint(int bloodVolume, bool hasAppearance)
|
||||
{
|
||||
if (hasAppearance)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return bloodVolume switch
|
||||
{
|
||||
>= 300 => 0.8f,
|
||||
>= 150 => 0.6f,
|
||||
>= 100 => 0.4f,
|
||||
_ => 0.2f
|
||||
};
|
||||
}
|
||||
|
||||
private bool ParasiteComesOut(EntityUid uid, FleshCultistComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return false;
|
||||
|
||||
var xform = Transform(uid);
|
||||
var coordinates = xform.Coordinates;
|
||||
|
||||
var abommob = Spawn(component.FleshMutationMobId, _transformSystem.GetMapCoordinates(uid));
|
||||
|
||||
if (_mindSystem.TryGetMind(uid, out var mindId, out var mind))
|
||||
{
|
||||
_mindSystem.TransferTo(mindId, abommob, ghostCheckOverride: true);
|
||||
}
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-pudge-transform-user", ("EntityTransform", uid)),
|
||||
uid, uid, PopupType.LargeCaution);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-pudge-transform-others",
|
||||
("Entity", uid), ("EntityTransform", abommob)), abommob, Filter.PvsExcept(abommob),
|
||||
true, PopupType.LargeCaution);
|
||||
|
||||
_audioSystem.PlayPvs(component.SoundMutation, coordinates, AudioParams.Default.WithVariation(0.025f));
|
||||
|
||||
if (TryComp(uid, out ContainerManagerComponent? container))
|
||||
{
|
||||
foreach (var cont in container.GetAllContainers().ToArray())
|
||||
{
|
||||
foreach (var ent in cont.ContainedEntities.ToArray())
|
||||
{
|
||||
if (HasComp<BodyPartComponent>(ent))
|
||||
continue;
|
||||
if (HasComp<UnremoveableComponent>(ent))
|
||||
continue;
|
||||
_containerSystem.Remove(ent, cont, force: true);
|
||||
Transform(ent).Coordinates = coordinates;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TryComp<BloodstreamComponent>(uid, out var bloodstream))
|
||||
{
|
||||
var tempSol = new Solution() { MaxVolume = 5 };
|
||||
|
||||
if (bloodstream.BloodSolution == null)
|
||||
return false;
|
||||
|
||||
tempSol.AddSolution(bloodstream.BloodSolution.Value.Comp.Solution, _proto);
|
||||
|
||||
if (_puddleSystem.TrySpillAt(uid, tempSol.SplitSolution(50), out var puddleUid))
|
||||
{
|
||||
if (TryComp<DnaComponent>(uid, out var dna))
|
||||
{
|
||||
var comp = EnsureComp<ForensicsComponent>(puddleUid);
|
||||
comp.DNAs.Add(dna.DNA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QueueDel(uid);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
var curTime = _timing.CurTime;
|
||||
|
||||
var query = EntityQueryEnumerator<PendingFleshCultistComponent>();
|
||||
while (query.MoveNext(out var uid, out var comp))
|
||||
{
|
||||
if (comp.CurrentStage == PendingFleshCultistStage.Final)
|
||||
continue;
|
||||
|
||||
comp.Accumulator += frameTime;
|
||||
|
||||
var stageTimer = comp.CurrentStage switch
|
||||
{
|
||||
PendingFleshCultistStage.First => comp.FirstStageTimer,
|
||||
PendingFleshCultistStage.Second => comp.SecondStageTimer,
|
||||
_ => 0f
|
||||
};
|
||||
|
||||
if (comp.Accumulator >= stageTimer)
|
||||
{
|
||||
comp.Accumulator = 0f;
|
||||
comp.CurrentStage = GetNextStage(comp.CurrentStage);
|
||||
}
|
||||
|
||||
switch (comp.CurrentStage)
|
||||
{
|
||||
case PendingFleshCultistStage.First:
|
||||
if (comp.NextScream <= curTime)
|
||||
{
|
||||
comp.NextScream = curTime + TimeSpan.FromSeconds(comp.ScreamInterval);
|
||||
_chatSystem.TryEmoteWithChat(uid, "Scream");
|
||||
}
|
||||
if (comp.NextStutter <= curTime)
|
||||
{
|
||||
comp.NextStutter = curTime + TimeSpan.FromSeconds(comp.ScreamInterval);
|
||||
_stuttering.DoStutter(uid, TimeSpan.FromSeconds(comp.StutterTime), true);
|
||||
}
|
||||
break;
|
||||
case PendingFleshCultistStage.Second:
|
||||
if (comp.NextParalyze <= curTime)
|
||||
{
|
||||
comp.NextParalyze = curTime + TimeSpan.FromSeconds(comp.ParalyzeInterval);
|
||||
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(comp.ParalyzeTime), true);
|
||||
}
|
||||
if (comp.NextJitter <= curTime)
|
||||
{
|
||||
comp.NextJitter = curTime + TimeSpan.FromSeconds(comp.JitterInterval);
|
||||
_jittering.DoJitter(uid, TimeSpan.FromSeconds(comp.JitterTime), true);
|
||||
}
|
||||
break;
|
||||
case PendingFleshCultistStage.Third:
|
||||
{
|
||||
if (!TryComp<MindContainerComponent>(uid, out var targetMindComp))
|
||||
return;
|
||||
|
||||
if (HasComp<MindShieldComponent>(uid))
|
||||
{
|
||||
_popupSystem.PopupEntity("Активация самоуничтожения импланта защиты разума", uid, PopupType.LargeCaution);
|
||||
_body.GibBody(uid, true);
|
||||
_explosionSystem.QueueExplosion(uid, "Default", 50, 5, 30, canCreateVacuum: false);
|
||||
return;
|
||||
}
|
||||
|
||||
var fleshCultRule = _fleshCultRule.StartGameRule();
|
||||
_fleshCultRule.MakeCultist(uid, 0, fleshCultRule);
|
||||
|
||||
comp.CurrentStage = PendingFleshCultistStage.Final;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var rev in EntityQuery<FleshCultistComponent>())
|
||||
{
|
||||
rev.Accumulator += frameTime;
|
||||
|
||||
if (rev.Accumulator <= 1)
|
||||
continue;
|
||||
rev.Accumulator -= 1;
|
||||
|
||||
if (rev.Hunger <= 40)
|
||||
{
|
||||
rev.AccumulatorStarveNotify += 1;
|
||||
if (rev.AccumulatorStarveNotify > 30)
|
||||
{
|
||||
rev.AccumulatorStarveNotify = 0;
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-hungry"),
|
||||
rev.Owner, rev.Owner, PopupType.Large);
|
||||
}
|
||||
}
|
||||
|
||||
if (rev.Hunger < 0)
|
||||
{
|
||||
ParasiteComesOut(rev.Owner, rev);
|
||||
}
|
||||
|
||||
ChangeParasiteHunger(rev.Owner, rev.HungerСonsumption, rev);
|
||||
}
|
||||
}
|
||||
|
||||
private PendingFleshCultistStage GetNextStage(PendingFleshCultistStage currentStage)
|
||||
{
|
||||
return currentStage switch
|
||||
{
|
||||
PendingFleshCultistStage.First => PendingFleshCultistStage.Second,
|
||||
PendingFleshCultistStage.Second => PendingFleshCultistStage.Third,
|
||||
PendingFleshCultistStage.Third => PendingFleshCultistStage.Final,
|
||||
_ => currentStage,
|
||||
};
|
||||
}
|
||||
|
||||
private void OnAbsormBloodPoolActionEvent(EntityUid uid, FleshCultistComponent component,
|
||||
FleshCultistAbsorbBloodPoolActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
var xform = Transform(uid);
|
||||
var puddles = new ValueList<(EntityUid Entity, string Solution)>();
|
||||
puddles.Clear();
|
||||
foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, 1f))
|
||||
{
|
||||
if (TryComp<PuddleComponent>(entity, out var puddle))
|
||||
{
|
||||
puddles.Add((entity, puddle.SolutionName));
|
||||
}
|
||||
}
|
||||
|
||||
if (puddles.Count == 0)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-not-find-puddles"),
|
||||
uid, uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
|
||||
var absorbBlood = new Solution();
|
||||
foreach (var (puddle, solution) in puddles)
|
||||
{
|
||||
if (!_solutionContainerSystem.TryGetSolution(puddle, solution, out var puddleSolution))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (var puddleSolutionContent in puddleSolution.Value.Comp.Solution.ToList())
|
||||
{
|
||||
if (!component.BloodWhitelist.Contains(puddleSolutionContent.Reagent.Prototype))
|
||||
continue;
|
||||
|
||||
var blood = puddleSolution.Value.Comp.Solution.SplitSolutionWithOnly(
|
||||
puddleSolutionContent.Quantity, puddleSolutionContent.Reagent.Prototype);
|
||||
|
||||
absorbBlood.AddSolution(blood, _proto);
|
||||
}
|
||||
|
||||
var ev = new SolutionContainerChangedEvent(puddleSolution.Value.Comp.Solution, solution);
|
||||
RaiseLocalEvent(puddle, ref ev);
|
||||
}
|
||||
|
||||
if (absorbBlood.Volume == 0)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-cant-absorb-puddle"),
|
||||
uid, uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
|
||||
_audioSystem.PlayPvs(component.BloodAbsorbSound, uid, component.BloodAbsorbSound.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-absorb-puddle", ("Entity", uid)),
|
||||
uid, uid, PopupType.Large);
|
||||
|
||||
var transferSolution = new Solution();
|
||||
foreach (var solution in component.HealBloodAbsorbReagents)
|
||||
{
|
||||
transferSolution.AddReagent(solution.Reagent, solution.Quantity * (absorbBlood.Volume / 10));
|
||||
}
|
||||
|
||||
if (_solutionContainerSystem.TryGetInjectableSolution(uid, out var injectableSolution, out var _))
|
||||
{
|
||||
_solutionContainerSystem.TryAddSolution(injectableSolution.Value, transferSolution);
|
||||
}
|
||||
absorbBlood.RemoveAllSolution();
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
namespace Content.Server._Sunrise.FleshCult.FleshGrowth;
|
||||
|
||||
[RegisterComponent, Access(typeof(SpreaderFleshSystem), typeof(FleshHeartSystem))]
|
||||
public sealed partial class SpreaderFleshComponent : Component
|
||||
{
|
||||
[DataField("chance", required: true)]
|
||||
public float Chance = 1f;
|
||||
|
||||
[DataField("growthResult", required: true)]
|
||||
public string GrowthResult = "Flesh";
|
||||
|
||||
[DataField("wallResult", required: true)]
|
||||
public string WallResult = "WallFlesh";
|
||||
|
||||
[DataField("enabled")]
|
||||
public bool Enabled = true;
|
||||
|
||||
[DataField("source")]
|
||||
public EntityUid? Source;
|
||||
}
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
using System.Linq;
|
||||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Destructible;
|
||||
using Content.Server.Destructible.Thresholds;
|
||||
using Content.Server.Destructible.Thresholds.Behaviors;
|
||||
using Content.Server.Destructible.Thresholds.Triggers;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Destructible.Thresholds;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult.FleshGrowth;
|
||||
|
||||
// Future work includes making the growths per interval thing not global, but instead per "group"
|
||||
public sealed class SpreaderFleshSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of edges that can grow out every interval.
|
||||
/// </summary>
|
||||
private const int GrowthsPerInterval = 5;
|
||||
|
||||
private float _accumulatedFrameTime;
|
||||
|
||||
private readonly HashSet<EntityUid> _edgeGrowths = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<SpreaderFleshComponent, ComponentAdd>(SpreaderAddHandler);
|
||||
SubscribeLocalEvent<AirtightChanged>(OnAirtightChanged);
|
||||
}
|
||||
|
||||
private void OnAirtightChanged(ref AirtightChanged ev)
|
||||
{
|
||||
UpdateNearbySpreaders(ev.Entity, ev.Airtight);
|
||||
}
|
||||
|
||||
private void SpreaderAddHandler(EntityUid uid, SpreaderFleshComponent component, ComponentAdd args)
|
||||
{
|
||||
if (component.Enabled)
|
||||
_edgeGrowths.Add(uid); // ez
|
||||
}
|
||||
|
||||
public void UpdateNearbySpreaders(EntityUid blocker, AirtightComponent comp)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent<TransformComponent>(blocker, out var transform))
|
||||
return; // how did we get here?
|
||||
|
||||
if (!TryComp<MapGridComponent>(transform.GridUid, out var grid))
|
||||
return;
|
||||
|
||||
var spreaderQuery = GetEntityQuery<SpreaderFleshComponent>();
|
||||
var tile = grid.TileIndicesFor(transform.Coordinates);
|
||||
|
||||
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||
{
|
||||
var direction = (AtmosDirection) (1 << i);
|
||||
if (!comp.AirBlockedDirection.IsFlagSet(direction))
|
||||
continue;
|
||||
|
||||
var directionEnumerator =
|
||||
grid.GetAnchoredEntitiesEnumerator(SharedMapSystem.GetDirection(tile, direction.ToDirection()));
|
||||
|
||||
while (directionEnumerator.MoveNext(out var ent))
|
||||
{
|
||||
if (spreaderQuery.TryGetComponent(ent, out var s) && s.Enabled)
|
||||
_edgeGrowths.Add(ent.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
_accumulatedFrameTime += frameTime;
|
||||
|
||||
if (!(_accumulatedFrameTime >= 1.0f))
|
||||
return;
|
||||
|
||||
_accumulatedFrameTime -= 1.0f;
|
||||
|
||||
var growthList = _edgeGrowths.ToList();
|
||||
_robustRandom.Shuffle(growthList);
|
||||
|
||||
var successes = 0;
|
||||
foreach (var entity in growthList)
|
||||
{
|
||||
if (!TryGrow(entity))
|
||||
continue;
|
||||
|
||||
successes += 1;
|
||||
if (successes >= GrowthsPerInterval)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGrow(EntityUid ent, TransformComponent? transform = null, SpreaderFleshComponent? spreader = null)
|
||||
{
|
||||
if (!Resolve(ent, ref transform, ref spreader, false))
|
||||
return false;
|
||||
|
||||
if (spreader.Enabled == false)
|
||||
return false;
|
||||
|
||||
if (!TryComp<MapGridComponent>(transform.GridUid, out var grid))
|
||||
return false;
|
||||
|
||||
var didGrow = false;
|
||||
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
var direction = (DirectionFlag) (1 << i);
|
||||
var coords = transform.Coordinates.Offset(direction.AsDir().ToVec());
|
||||
if (grid.GetTileRef(coords).Tile.IsEmpty || _robustRandom.Prob(1 - spreader.Chance))
|
||||
continue;
|
||||
var ents = _mapSystem.GetLocal(transform.GridUid.Value, grid, coords);
|
||||
|
||||
var entityUids = ents as EntityUid[] ?? ents.ToArray();
|
||||
if (entityUids.Any(x => IsTileBlockedFrom(x, direction)))
|
||||
continue;
|
||||
|
||||
var canSpawnWall = true;
|
||||
var canSpawnFloor = true;
|
||||
string entityStrucrureId = String.Empty;
|
||||
foreach (var entityUid in entityUids)
|
||||
{
|
||||
if (_tagSystem.HasAnyTag(entityUid, "Wall", "Window"))
|
||||
{
|
||||
if (!_tagSystem.HasAnyTag(entityUid, "Directional"))
|
||||
{
|
||||
if (TryComp(entityUid, out MetaDataComponent? metaData))
|
||||
{
|
||||
if (metaData.EntityPrototype != null)
|
||||
entityStrucrureId = metaData.EntityPrototype.ID;
|
||||
}
|
||||
|
||||
canSpawnFloor = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_tagSystem.HasAnyTag(entityUid, "Flesh", "Directional"))
|
||||
{
|
||||
canSpawnWall = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (canSpawnFloor)
|
||||
{
|
||||
didGrow = true;
|
||||
var fleshFloor = EntityManager.SpawnEntity(spreader.GrowthResult,
|
||||
transform.Coordinates.Offset(direction.AsDir().ToVec()));
|
||||
var spreaderFleshComponent = EnsureComp<SpreaderFleshComponent>(fleshFloor);
|
||||
spreaderFleshComponent.Source = spreader.Source;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!canSpawnWall)
|
||||
continue;
|
||||
didGrow = true;
|
||||
var fleshWall = EntityManager.SpawnEntity(spreader.WallResult,
|
||||
transform.Coordinates.Offset(direction.AsDir().ToVec()));
|
||||
var spreaderFleshComponent = EnsureComp<SpreaderFleshComponent>(fleshWall);
|
||||
spreaderFleshComponent.Source = spreader.Source;
|
||||
if (EntityManager.TryGetComponent(fleshWall, out DestructibleComponent? destructible))
|
||||
{
|
||||
destructible.Thresholds.Clear();
|
||||
var damageThreshold = new DamageThreshold
|
||||
{
|
||||
Trigger = new DamageTrigger { Damage = 5 }
|
||||
};
|
||||
damageThreshold.AddBehavior(new SpawnEntitiesBehavior
|
||||
{
|
||||
Spawn = new Dictionary<EntProtoId, MinMax> { { entityStrucrureId, new MinMax{Min = 1, Max = 1} } },
|
||||
Offset = 0f
|
||||
});
|
||||
damageThreshold.AddBehavior(new DoActsBehavior
|
||||
{
|
||||
Acts = ThresholdActs.Destruction
|
||||
});
|
||||
destructible.Thresholds.Add(damageThreshold);
|
||||
}
|
||||
|
||||
foreach (var entityUid in entityUids)
|
||||
{
|
||||
if (_tagSystem.HasAnyTag(entityUid, "Wall", "Window"))
|
||||
EntityManager.DeleteEntity(entityUid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return didGrow;
|
||||
}
|
||||
|
||||
private bool IsTileBlockedFrom(EntityUid ent, DirectionFlag dir)
|
||||
{
|
||||
if (EntityManager.TryGetComponent<SpreaderFleshComponent>(ent, out _))
|
||||
return true;
|
||||
|
||||
if (!EntityManager.TryGetComponent<AirtightComponent>(ent, out var airtight))
|
||||
return false;
|
||||
|
||||
// var oppositeDir = dir.AsDir().GetOpposite().ToAtmosDirection();
|
||||
|
||||
// return airtight.AirBlocked && airtight.AirBlockedDirection.IsFlagSet(oppositeDir);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
namespace Content.Server._Sunrise.FleshCult
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class FleshHandModComponent : Component
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
466
Content.Server/_Sunrise/FleshCult/FleshHeartSystem.cs
Normal file
466
Content.Server/_Sunrise/FleshCult/FleshHeartSystem.cs
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server._Sunrise.FleshCult.FleshGrowth;
|
||||
using Content.Server._Sunrise.FleshCult.GameRule;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.RoundEnd;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.Traits.Assorted;
|
||||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Destructible;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.DragDrop;
|
||||
using Content.Shared.Flesh;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Random.Helpers;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult
|
||||
{
|
||||
public sealed class FleshHeartSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly ContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
[Dependency] private readonly ChatSystem _chat = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly BodySystem _body = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||
[Dependency] private readonly HumanoidAppearanceSystem _sharedHuApp = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _sharedAppearance = default!;
|
||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FleshHeartComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<FleshHeartComponent, DestructionEventArgs>(OnDestruction);
|
||||
SubscribeLocalEvent<FleshHeartComponent, DragDropTargetEvent>(HandleDragDropOn);
|
||||
SubscribeLocalEvent<FleshHeartComponent, FleshHeartDragFinished>(OnDragFinished);
|
||||
SubscribeLocalEvent<FleshHeartComponent, ComponentInit>(OnComponentInit);
|
||||
}
|
||||
|
||||
private void OnShutdown(EntityUid uid, FleshHeartComponent component, ComponentShutdown args)
|
||||
{
|
||||
_audioSystem.Stop(component.AmbientAudioStream);
|
||||
}
|
||||
|
||||
private void OnDestruction(EntityUid uid, FleshHeartComponent component, DestructionEventArgs args)
|
||||
{
|
||||
if (component.State != HeartStates.Base)
|
||||
{
|
||||
_audioSystem.Stop(component.AmbientAudioStream);
|
||||
//var stationUid = _stationSystem.GetOwningStation(uid);
|
||||
//if (stationUid != null)
|
||||
//{
|
||||
// _alertLevel.SetLevel(stationUid.Value, component.AlertLevelOnDeactivate, true,
|
||||
// true, true);
|
||||
//}
|
||||
var xform = Transform(uid);
|
||||
var coordinates = xform.Coordinates;
|
||||
foreach (var ent in component.BodyContainer.ContainedEntities.ToArray())
|
||||
{
|
||||
_containerSystem.Remove(ent, component.BodyContainer, force: true);
|
||||
Transform(ent).Coordinates = coordinates;
|
||||
}
|
||||
var fleshTilesQuery = EntityQueryEnumerator<SpreaderFleshComponent>();
|
||||
while (fleshTilesQuery.MoveNext(out var ent, out var comp))
|
||||
{
|
||||
if (comp.Source != uid)
|
||||
continue;
|
||||
if (!TryComp<TagComponent>(ent, out var tagComponent))
|
||||
continue;
|
||||
if (_tagSystem.HasAllTags(tagComponent, "Wall", "Flesh"))
|
||||
_damageableSystem.TryChangeDamage(ent, component.DamageMobsIfHeartDestruct);
|
||||
else
|
||||
QueueDel(ent);
|
||||
|
||||
}
|
||||
var fleshWalls = new List<EntityUid>();
|
||||
var fleshWallsQuery = EntityQueryEnumerator<TagComponent>();
|
||||
while (fleshWallsQuery.MoveNext(out var ent, out var comp))
|
||||
{
|
||||
if (!TryComp<TagComponent>(ent, out var tagComponent))
|
||||
continue;
|
||||
var isFleshWall = _tagSystem.HasAllTags(tagComponent, "Wall", "Flesh");
|
||||
if (isFleshWall)
|
||||
{
|
||||
fleshWalls.Add(ent);
|
||||
}
|
||||
}
|
||||
foreach (var mob in component.EdgeMobs.ToArray())
|
||||
{
|
||||
_damageableSystem.TryChangeDamage(mob, component.DamageMobsIfHeartDestruct);
|
||||
}
|
||||
RaiseLocalEvent(new FleshHeartDestructionEvent()
|
||||
{
|
||||
FleshHeardUid = uid,
|
||||
OwningStation = xform.GridUid
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
var fleshHeartQuery = EntityQueryEnumerator<FleshHeartComponent, TransformComponent>();
|
||||
while (fleshHeartQuery.MoveNext(out var ent, out var comp, out var xform))
|
||||
{
|
||||
var fleshCultRule = EntityQuery<FleshCultRuleComponent>().FirstOrDefault();
|
||||
if (fleshCultRule == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var owningStation = _stationSystem.GetOwningStation(ent, xform);
|
||||
|
||||
if (owningStation != fleshCultRule.TargetStation)
|
||||
continue;
|
||||
|
||||
switch (comp.State)
|
||||
{
|
||||
case HeartStates.Base:
|
||||
{
|
||||
comp.Accumulator += frameTime;
|
||||
|
||||
if (comp.Accumulator <= 1)
|
||||
continue;
|
||||
|
||||
comp.Accumulator -= 1;
|
||||
if (comp.BodyContainer.ContainedEntities.Count >= comp.BodyToFinalStage)
|
||||
{
|
||||
comp.SpawnMobsAccumulator = 500;
|
||||
comp.State = HeartStates.Active;
|
||||
RaiseLocalEvent(new FleshHeartActivateEvent()
|
||||
{
|
||||
FleshHeardUid = ent,
|
||||
OwningStation = xform.GridUid
|
||||
});
|
||||
_chat.DispatchGlobalAnnouncement(
|
||||
Loc.GetString("flesh-heart-activate-warning"),
|
||||
colorOverride: Color.Red);
|
||||
// _audioSystem.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true);
|
||||
var stationUid = _stationSystem.GetOwningStation(ent);
|
||||
//if (stationUid != null)
|
||||
//{
|
||||
// _alertLevel.SetLevel(stationUid.Value, comp.AlertLevelOnActivate, false,
|
||||
// true, true, true);
|
||||
//}
|
||||
//_audioSystem.PlayGlobal(
|
||||
// "/Audio/_Sunrise/FleshCult/flesh_heart_activate.ogg", Filter.Broadcast(), true,
|
||||
// AudioParams.Default);
|
||||
SpawnFleshFloorOnOpenTiles(ent, comp, Transform(ent), 1);
|
||||
_roundEndSystem.CancelRoundEndCountdown(stationUid);
|
||||
_audioSystem.PlayPvs(comp.TransformSound, ent, comp.TransformSound.Params);
|
||||
comp.AmbientAudioStream = _audioSystem.PlayGlobal(
|
||||
"/Audio/_Sunrise/FleshCult/flesh_heart.ogg", Filter.Broadcast(), true,
|
||||
AudioParams.Default.WithLoop(true).WithVolume(-3f))!.Value.Entity;
|
||||
_appearance.SetData(ent, FleshHeartVisuals.State, FleshHeartStatus.Active);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HeartStates.Active:
|
||||
{
|
||||
comp.SpawnMobsAccumulator += frameTime;
|
||||
comp.SpawnObjectsAccumulator += frameTime;
|
||||
comp.FinalStageAccumulator += frameTime;
|
||||
if (comp.SpawnMobsAccumulator >= comp.SpawnMobsFrequency)
|
||||
{
|
||||
comp.SpawnMobsAccumulator = 0;
|
||||
SpawnMonstersOnOpenTiles(comp, xform, comp.SpawnMobsAmount, comp.SpawnMobsRadius);
|
||||
}
|
||||
|
||||
if (comp.SpawnObjectsAccumulator >= comp.SpawnObjectsFrequency)
|
||||
{
|
||||
comp.SpawnObjectsAccumulator = 0;
|
||||
// SpawnObjectsOnOpenTiles(comp, xform, comp.SpawnObjectsAmount, comp.SpawnObjectsRadius);
|
||||
}
|
||||
|
||||
if (comp.FinalStageAccumulator >= comp.TimeLiveFinalHeartToWin)
|
||||
{
|
||||
comp.State = HeartStates.Disable;
|
||||
RaiseLocalEvent(new FleshHeartFinalEvent()
|
||||
{
|
||||
FleshHeardUid = ent,
|
||||
OwningStation = owningStation,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HeartStates.Disable:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Interaction
|
||||
|
||||
private void HandleDragDropOn(EntityUid uid, FleshHeartComponent component, ref DragDropTargetEvent args)
|
||||
{
|
||||
|
||||
if (!CanAbsorb(uid, args.Dragged, component))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("flesh-heart-cant-absorb-targer"),
|
||||
args.User, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp<FixturesComponent>(args.Dragged, out var fixturesComponent))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("flesh-heart-cant-absorb-targer"),
|
||||
args.User, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fixturesComponent.Fixtures["fix1"].Density <= 60)
|
||||
{
|
||||
_popup.PopupEntity(
|
||||
Loc.GetString("flesh-heart-cant-absorb-targer"),
|
||||
uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager, args.User, component.EntryDelay, new FleshHeartDragFinished(), uid, target: args.Dragged, used: uid)
|
||||
{
|
||||
BreakOnDamage = true,
|
||||
BreakOnMove = true,
|
||||
NeedHand = false,
|
||||
};
|
||||
_doAfterSystem.TryStartDoAfter(doAfterArgs);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
protected void OnComponentInit(EntityUid uid, FleshHeartComponent cryoPodComponent, ComponentInit args)
|
||||
{
|
||||
cryoPodComponent.BodyContainer = _containerSystem.EnsureContainer<Container>(uid, "bodyContainer");
|
||||
}
|
||||
|
||||
private void OnDragFinished(EntityUid uid, FleshHeartComponent component, FleshHeartDragFinished args)
|
||||
{
|
||||
if (args.Cancelled || args.Handled || args.Args.Target == null)
|
||||
return;
|
||||
|
||||
if (!TryComp<FixturesComponent>(args.Args.Target.Value, out var fixturesComponent))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("flesh-heart-cant-absorb-targer"),
|
||||
args.User, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
|
||||
var xform = Transform(args.Args.Target.Value);
|
||||
|
||||
if (TryComp(args.Args.Target.Value, out ContainerManagerComponent? container))
|
||||
{
|
||||
foreach (var cont in container.GetAllContainers().ToArray())
|
||||
{
|
||||
foreach (var ent in cont.ContainedEntities.ToArray())
|
||||
{
|
||||
{
|
||||
if (HasComp<BodyPartComponent>(ent))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
_containerSystem.Remove(ent, cont, force: true);
|
||||
Transform(ent).Coordinates = xform.Coordinates;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TryComp<HumanoidAppearanceComponent>(args.Args.Target.Value, out var HuAppComponent))
|
||||
{
|
||||
if (TryComp<BodyComponent>(args.Args.Target.Value, out var bodyComponent))
|
||||
{
|
||||
var parts = _body.GetBodyChildren(args.Args.Target.Value, bodyComponent).ToArray();
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
if (part.Component.PartType == BodyPartType.Head)
|
||||
continue;
|
||||
|
||||
if (part.Component.PartType == BodyPartType.Torso)
|
||||
{
|
||||
foreach (var organ in _body.GetPartOrgans(part.Id, part.Component))
|
||||
{
|
||||
_body.RemoveOrgan(organ.Id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QueueDel(part.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_bloodstreamSystem.TryModifyBloodLevel(args.Args.Target.Value, -300);
|
||||
|
||||
var skeletonSprites = _proto.Index<HumanoidSpeciesBaseSpritesPrototype>("MobSkeletonSprites");
|
||||
foreach (var (key, id) in skeletonSprites.Sprites)
|
||||
{
|
||||
if (key != HumanoidVisualLayers.Head)
|
||||
{
|
||||
_sharedHuApp.SetBaseLayerId(args.Args.Target.Value, key, id, humanoid: HuAppComponent);
|
||||
}
|
||||
}
|
||||
|
||||
_physics.SetDensity(args.Args.Target.Value, "fix1", fixturesComponent.Fixtures["fix1"], 50);
|
||||
|
||||
if (TryComp<AppearanceComponent>(args.Args.Target.Value, out var appComponent))
|
||||
{
|
||||
_sharedAppearance.SetData(args.Args.Target.Value, DamageVisualizerKeys.Disabled, true, appComponent);
|
||||
_damageableSystem.TryChangeDamage(args.Args.Target.Value,
|
||||
new DamageSpecifier() { DamageDict = { { "Slash", 100 } } });
|
||||
}
|
||||
|
||||
EnsureComp<UnrevivableComponent>(args.Args.Target.Value);
|
||||
|
||||
_containerSystem.Insert(args.Args.Target.Value, component.BodyContainer, force: true);
|
||||
_audioSystem.PlayPvs(component.TransformSound, uid, component.TransformSound.Params);
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private bool CanAbsorb(EntityUid uid, EntityUid dragged, FleshHeartComponent component)
|
||||
{
|
||||
if (!TryComp<MobStateComponent>(dragged, out var stateComponent))
|
||||
return false;
|
||||
|
||||
if (stateComponent.CurrentState != MobState.Dead)
|
||||
return false;
|
||||
|
||||
if (!Transform(uid).Anchored)
|
||||
return false;
|
||||
|
||||
if (!TryComp<HumanoidAppearanceComponent>(dragged, out var humanoidAppearance))
|
||||
return false;
|
||||
|
||||
if (!(component.SpeciesWhitelist.Contains(humanoidAppearance.Species)))
|
||||
return false;
|
||||
|
||||
return !TryComp<MindContainerComponent>(dragged, out var mindComp) || true;
|
||||
}
|
||||
|
||||
private void SpawnFleshFloorOnOpenTiles(EntityUid fleshHeart, FleshHeartComponent component, TransformComponent xform, float radius)
|
||||
{
|
||||
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
|
||||
return;
|
||||
|
||||
var localpos = xform.Coordinates.Position;
|
||||
var tilerefs = grid.GetLocalTilesIntersecting(
|
||||
new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius))).ToArray();
|
||||
foreach (var tileref in tilerefs)
|
||||
{
|
||||
var canSpawnFloor = true;
|
||||
foreach (var ent in grid.GetAnchoredEntities(tileref.GridIndices).ToList())
|
||||
{
|
||||
if (_tagSystem.HasAnyTag(ent, "Wall", "Window", "Flesh"))
|
||||
canSpawnFloor = false;
|
||||
}
|
||||
if (canSpawnFloor)
|
||||
{
|
||||
var location = _mapSystem.ToCenterCoordinates(tileref, grid);
|
||||
var fleshTile = EntityManager.SpawnEntity(component.FleshTileId, location);
|
||||
var spreaderFleshComponent = EnsureComp<SpreaderFleshComponent>(fleshTile);
|
||||
spreaderFleshComponent.Source = fleshHeart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SpawnMonstersOnOpenTiles(FleshHeartComponent component, TransformComponent xform, int amount, float radius)
|
||||
{
|
||||
if (!TryComp<MapGridComponent>(xform.GridUid, out var grid))
|
||||
return;
|
||||
|
||||
var localpos = xform.Coordinates.Position;
|
||||
var tilerefs = grid.GetLocalTilesIntersecting(
|
||||
new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius))).ToArray();
|
||||
_random.Shuffle(tilerefs);
|
||||
var physQuery = GetEntityQuery<PhysicsComponent>();
|
||||
var amountCounter = 0;
|
||||
foreach (var tileref in tilerefs)
|
||||
{
|
||||
var valid = true;
|
||||
foreach (var ent in grid.GetAnchoredEntities(tileref.GridIndices))
|
||||
{
|
||||
if (!physQuery.TryGetComponent(ent, out var body))
|
||||
continue;
|
||||
if (body.BodyType != BodyType.Static ||
|
||||
!body.Hard ||
|
||||
(body.CollisionLayer & (int) CollisionGroup.Impassable) == 0)
|
||||
continue;
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if (!valid)
|
||||
continue;
|
||||
amountCounter++;
|
||||
|
||||
var randomMob = _random.Pick(component.Spawns);
|
||||
var location = _mapSystem.ToCenterCoordinates(tileref, grid);
|
||||
var mob = Spawn(randomMob, location);
|
||||
component.EdgeMobs.Add(mob);
|
||||
if (amountCounter >= amount)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FleshHeartFinalEvent : EntityEventArgs
|
||||
{
|
||||
public EntityUid FleshHeardUid;
|
||||
public EntityUid? OwningStation;
|
||||
}
|
||||
|
||||
public sealed class FleshHeartActivateEvent : EntityEventArgs
|
||||
{
|
||||
public EntityUid FleshHeardUid;
|
||||
public EntityUid? OwningStation;
|
||||
}
|
||||
|
||||
public sealed class FleshHeartDestructionEvent : EntityEventArgs
|
||||
{
|
||||
public EntityUid FleshHeardUid;
|
||||
public EntityUid? OwningStation;
|
||||
}
|
||||
}
|
||||
}
|
||||
283
Content.Server/_Sunrise/FleshCult/FleshHuggerSystem.cs
Normal file
283
Content.Server/_Sunrise/FleshCult/FleshHuggerSystem.cs
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
using System.Linq;
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Flesh;
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.CombatMode;
|
||||
using Content.Shared.CombatMode.Pacification;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Eye.Blinding.Components;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.IdentityManagement.Components;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Stunnable;
|
||||
using Content.Shared.Throwing;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using FleshHuggerComponent = Content.Shared._Sunrise.FleshCult.FleshHuggerComponent;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult
|
||||
{
|
||||
public sealed class FleshHuggerSystem : SharedFleshHuggerSystem
|
||||
{
|
||||
[Dependency] private SharedStunSystem _stunSystem = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly ActionsSystem _action = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<FleshHuggerComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<FleshHuggerComponent, MeleeHitEvent>(OnMeleeHit);
|
||||
SubscribeLocalEvent<FleshHuggerComponent, ThrowDoHitEvent>(OnWormDoHit);
|
||||
SubscribeLocalEvent<FleshHuggerComponent, GotEquippedEvent>(OnGotEquipped);
|
||||
SubscribeLocalEvent<FleshHuggerComponent, GotUnequippedEvent>(OnGotUnequipped);
|
||||
SubscribeLocalEvent<FleshHuggerComponent, GotEquippedHandEvent>(OnGotEquippedHand);
|
||||
SubscribeLocalEvent<FleshHuggerComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
SubscribeLocalEvent<FleshHuggerComponent, FleshHuggerJumpActionEvent>(OnJump);
|
||||
SubscribeLocalEvent<FleshHuggerComponent, FleshHuggerGetOffFromFaceActionEvent>(OnGetOff);
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, FleshHuggerComponent component, MapInitEvent args)
|
||||
{
|
||||
_action.AddAction(uid, component.ActionFleshHuggerJumpId);
|
||||
_action.AddAction(uid, component.ActionFleshHuggerGetOffId);
|
||||
}
|
||||
|
||||
private void OnWormDoHit(EntityUid uid, FleshHuggerComponent component, ThrowDoHitEvent args)
|
||||
{
|
||||
if (component.IsDeath)
|
||||
return;
|
||||
if (HasComp<FleshCultistComponent>(args.Target))
|
||||
return;
|
||||
if (!HasComp<HumanoidAppearanceComponent>(args.Target))
|
||||
return;
|
||||
if (TryComp(args.Target, out MobStateComponent? mobState))
|
||||
{
|
||||
if (mobState.CurrentState is not MobState.Alive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
_inventory.TryGetSlotEntity(args.Target, "head", out var headItem);
|
||||
if (HasComp<IngestionBlockerComponent>(headItem))
|
||||
return;
|
||||
|
||||
_inventory.TryGetSlotEntity(args.Target, "mask", out var maskItem);
|
||||
if (HasComp<IdentityBlockerComponent>(maskItem))
|
||||
return;
|
||||
|
||||
_inventory.TryUnequip(args.Target, "head", true);
|
||||
_inventory.TryUnequip(args.Target, "eyes", true);
|
||||
_inventory.TryUnequip(args.Target, "mask", true);
|
||||
|
||||
var equipped = _inventory.TryEquip(args.Target, uid, "mask", true);
|
||||
if (!equipped)
|
||||
return;
|
||||
|
||||
component.EquipedOn = args.Target;
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-hit-user"),
|
||||
args.Target, args.Target, PopupType.LargeCaution);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-hit-mob",
|
||||
("entity", args.Target)),
|
||||
uid, uid, PopupType.LargeCaution);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-eat-face-others",
|
||||
("entity", args.Target)), args.Target, Filter.PvsExcept(uid), true, PopupType.Large);
|
||||
|
||||
EntityManager.EnsureComponent<PacifiedComponent>(uid);
|
||||
_stunSystem.TryParalyze(args.Target, TimeSpan.FromSeconds(component.ParalyzeTime), true);
|
||||
_damageableSystem.TryChangeDamage(args.Target, component.Damage, origin: args.Thrown);
|
||||
}
|
||||
|
||||
private void OnGotEquipped(EntityUid uid, FleshHuggerComponent component, GotEquippedEvent args)
|
||||
{
|
||||
if (args.Slot != "mask")
|
||||
return;
|
||||
component.EquipedOn = args.Equipee;
|
||||
EntityManager.EnsureComponent<TemporaryBlindnessComponent>(args.Equipee);
|
||||
EntityManager.EnsureComponent<PacifiedComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnGotEquippedHand(EntityUid uid, FleshHuggerComponent component, GotEquippedHandEvent args)
|
||||
{
|
||||
if (HasComp<_Sunrise.FleshCult.FleshPudgeComponent>(args.User))
|
||||
return;
|
||||
if (HasComp<FleshCultistComponent>(args.User))
|
||||
return;
|
||||
if (component.IsDeath)
|
||||
return;
|
||||
_damageableSystem.TryChangeDamage(args.User, component.Damage);
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-bite-user"),
|
||||
args.User, args.User);
|
||||
}
|
||||
|
||||
private void OnGotUnequipped(EntityUid uid, FleshHuggerComponent component, GotUnequippedEvent args)
|
||||
{
|
||||
if (args.Slot != "mask")
|
||||
return;
|
||||
if (HasComp<PacifiedComponent>(uid))
|
||||
EntityManager.RemoveComponent<PacifiedComponent>(uid);
|
||||
if (HasComp<TemporaryBlindnessComponent>(component.EquipedOn))
|
||||
EntityManager.RemoveComponent<TemporaryBlindnessComponent>(args.Equipee);
|
||||
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(3), true);
|
||||
component.EquipedOn = new EntityUid();
|
||||
}
|
||||
|
||||
private void OnMeleeHit(EntityUid uid, FleshHuggerComponent component, MeleeHitEvent args)
|
||||
{
|
||||
if (!args.HitEntities.Any())
|
||||
return;
|
||||
|
||||
foreach (var entity in args.HitEntities)
|
||||
{
|
||||
if (!HasComp<HumanoidAppearanceComponent>(entity))
|
||||
return;
|
||||
|
||||
if (TryComp(entity, out MobStateComponent? mobState))
|
||||
{
|
||||
if (mobState.CurrentState is not MobState.Alive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_inventory.TryGetSlotEntity(entity, "head", out var headItem);
|
||||
if (HasComp<IngestionBlockerComponent>(headItem))
|
||||
return;
|
||||
|
||||
_inventory.TryGetSlotEntity(entity, "mask", out var maskItem);
|
||||
if (HasComp<IdentityBlockerComponent>(maskItem))
|
||||
return;
|
||||
|
||||
var random = new Random();
|
||||
var shouldEquip = random.Next(1, 101) <= component.ChansePounce;
|
||||
if (!shouldEquip)
|
||||
return;
|
||||
|
||||
_inventory.TryUnequip(entity, "head", true);
|
||||
_inventory.TryUnequip(entity, "eyes", true);
|
||||
_inventory.TryUnequip(entity, "mask", true);
|
||||
|
||||
var equipped = _inventory.TryEquip(entity, uid, "mask", true);
|
||||
if (!equipped)
|
||||
return;
|
||||
|
||||
component.EquipedOn = entity;
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-hit-user"),
|
||||
entity, entity, PopupType.LargeCaution);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-hit-mob", ("entity", entity)),
|
||||
uid, uid, PopupType.LargeCaution);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-eat-face-others",
|
||||
("entity", entity)), entity, Filter.PvsExcept(entity), true, PopupType.Large);
|
||||
EntityManager.EnsureComponent<PacifiedComponent>(uid);
|
||||
_stunSystem.TryParalyze(entity, TimeSpan.FromSeconds(component.ParalyzeTime), true);
|
||||
_damageableSystem.TryChangeDamage(entity, component.Damage, origin: entity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnMobStateChanged(EntityUid uid, FleshHuggerComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
if (args.NewMobState == MobState.Dead)
|
||||
{
|
||||
component.IsDeath = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGetOff(EntityUid uid, FleshHuggerComponent component, FleshHuggerGetOffFromFaceActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (component.EquipedOn is not { Valid: true } targetId)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("flesh-worm-cant-get-off"),
|
||||
uid, uid, PopupType.LargeCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
_inventory.TryUnequip(targetId, "mask", true, true);
|
||||
component.EquipedOn = new EntityUid();
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnJump(EntityUid uid, FleshHuggerComponent component, FleshHuggerJumpActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (component.EquipedOn is { Valid: true })
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("flesh-worm-cant-jump"),
|
||||
uid, uid, PopupType.LargeCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
var xform = Transform(uid);
|
||||
var mapCoords = args.Target.ToMap(_entityManager, _transformSystem);
|
||||
var direction = mapCoords.Position - xform.MapPosition.Position;
|
||||
|
||||
_throwing.TryThrow(uid, direction, 7F, uid, 10F);
|
||||
if (component.SoundJump != null)
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundJump, uid, component.SoundJump.Params);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
foreach (var comp in EntityQuery<FleshHuggerComponent>())
|
||||
{
|
||||
comp.Accumulator += frameTime;
|
||||
|
||||
if (comp.Accumulator <= comp.DamageFrequency)
|
||||
continue;
|
||||
|
||||
comp.Accumulator = 0;
|
||||
|
||||
if (comp.EquipedOn is not { Valid: true } targetId)
|
||||
continue;
|
||||
if (HasComp<FleshCultistComponent>(comp.EquipedOn))
|
||||
return;
|
||||
if (TryComp(targetId, out MobStateComponent? mobState))
|
||||
{
|
||||
if (mobState.CurrentState is not MobState.Alive)
|
||||
{
|
||||
_inventory.TryUnequip(targetId, "mask", true, true);
|
||||
comp.EquipedOn = new EntityUid();
|
||||
return;
|
||||
}
|
||||
}
|
||||
_damageableSystem.TryChangeDamage(targetId, comp.Damage);
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-eat-face-user"),
|
||||
targetId, targetId, PopupType.LargeCaution);
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-eat-face-others",
|
||||
("entity", targetId)), targetId, Filter.PvsExcept(targetId), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Content.Server/_Sunrise/FleshCult/FleshMobSystem.cs
Normal file
38
Content.Server/_Sunrise/FleshCult/FleshMobSystem.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.Flesh;
|
||||
using Content.Shared.Mobs;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult
|
||||
{
|
||||
public sealed class FleshMobSystem : SharedFleshMobSystem
|
||||
{
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FleshMobComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
}
|
||||
|
||||
private void OnMobStateChanged(EntityUid uid, FleshMobComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
if (args.NewMobState != MobState.Dead)
|
||||
return;
|
||||
if (component.SoundDeath == null)
|
||||
return;
|
||||
_audioSystem.PlayPvs(component.SoundDeath, uid, component.SoundDeath.Params);
|
||||
|
||||
var coords = _transformSystem.GetMapCoordinates(uid);
|
||||
|
||||
for (var i = 0; i < component.DeathMobSpawnCount; i++)
|
||||
{
|
||||
Spawn(component.DeathMobSpawnId, coords);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
Content.Server/_Sunrise/FleshCult/FleshPudgeComponent.cs
Normal file
53
Content.Server/_Sunrise/FleshCult/FleshPudgeComponent.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class FleshPudgeComponent : Component
|
||||
{
|
||||
[DataField("actionThrowWorm", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ActionThrowWormId = "FleshThrowWorm";
|
||||
|
||||
[DataField("actionAcidSpit", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ActionAcidSpitId = "FleshAcidSpit";
|
||||
|
||||
[DataField("actionAbsorbBloodPool", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ActionAbsorbBloodPoolId = "AbsorbBloodPool";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("soundThrowWorm")]
|
||||
public SoundSpecifier? SoundThrowWorm = new SoundPathSpecifier("/Audio/_Sunrise/FleshCult/throw_worm.ogg");
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("faceHuggerMobSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string FaceHuggerMobSpawnId = "MobFleshHugger";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("bulletAcidSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string BulletAcidSpawnId = "BulletSplashAcid";
|
||||
|
||||
[DataField("healBloodAbsorbReagents")] public Solution HealBloodAbsorbReagents = new()
|
||||
{
|
||||
Contents =
|
||||
{
|
||||
new ReagentQuantity(new ReagentId("Carol", null), 1),
|
||||
}
|
||||
};
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("bloodWhitelist")]
|
||||
public List<string> BloodWhitelist = new()
|
||||
{
|
||||
"Blood",
|
||||
"CopperBlood",
|
||||
"InsectBlood",
|
||||
"AmmoniaBlood",
|
||||
"ZombieBlood"
|
||||
};
|
||||
|
||||
[DataField("bloodAbsorbSound")]
|
||||
public SoundSpecifier BloodAbsorbSound = new SoundPathSpecifier("/Audio/Effects/Fluids/splat.ogg");
|
||||
}
|
||||
}
|
||||
155
Content.Server/_Sunrise/FleshCult/FleshPudgeSystem.cs
Normal file
155
Content.Server/_Sunrise/FleshCult/FleshPudgeSystem.cs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
using System.Linq;
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Weapons.Ranged.Systems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Fluids.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult
|
||||
{
|
||||
public sealed class FleshPudgeSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly ActionsSystem _action = default!;
|
||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionSystem = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly GunSystem _gunSystem = default!;
|
||||
[Dependency] private readonly PhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FleshPudgeComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<FleshPudgeComponent, FleshPudgeThrowFaceHuggerActionEvent>(OnThrowFaceHugger);
|
||||
SubscribeLocalEvent<FleshPudgeComponent, FleshPudgeAbsorbBloodPoolActionEvent>(OnAbsorbBloodPoolActionEvent);
|
||||
SubscribeLocalEvent<FleshPudgeComponent, FleshPudgeAcidSpitActionEvent>(OnAcidSpit);
|
||||
}
|
||||
|
||||
private void OnThrowFaceHugger(EntityUid uid, FleshPudgeComponent component, FleshPudgeThrowFaceHuggerActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
var worm = Spawn(component.FaceHuggerMobSpawnId, Transform(uid).Coordinates);
|
||||
var xform = Transform(uid);
|
||||
var mapCoords = args.Target.ToMap(_entityManager, _transformSystem);
|
||||
var direction = mapCoords.Position - xform.MapPosition.Position;
|
||||
|
||||
_throwing.TryThrow(worm, direction, 7F, uid, 10F);
|
||||
if (component.SoundThrowWorm != null)
|
||||
{
|
||||
_audioSystem.PlayPvs(component.SoundThrowWorm, uid, component.SoundThrowWorm.Params);
|
||||
}
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-popup"), uid, PopupType.LargeCaution);
|
||||
}
|
||||
|
||||
private void OnAcidSpit(EntityUid uid, FleshPudgeComponent component, FleshPudgeAcidSpitActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
var acidBullet = Spawn(component.BulletAcidSpawnId, Transform(uid).Coordinates);
|
||||
var xform = Transform(uid);
|
||||
var mapCoords = args.Target.ToMap(_entityManager, _transformSystem);
|
||||
var direction = mapCoords.Position - xform.MapPosition.Position;
|
||||
var userVelocity = _physics.GetMapLinearVelocity(uid);
|
||||
|
||||
_gunSystem.ShootProjectile(acidBullet, direction, userVelocity, uid, uid);
|
||||
_audioSystem.PlayPvs(component.BloodAbsorbSound, uid, component.BloodAbsorbSound.Params);
|
||||
}
|
||||
|
||||
private void OnAbsorbBloodPoolActionEvent(EntityUid uid, FleshPudgeComponent component,
|
||||
FleshPudgeAbsorbBloodPoolActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
var xform = Transform(uid);
|
||||
var puddles = new ValueList<(EntityUid Entity, string Solution)>();
|
||||
puddles.Clear();
|
||||
foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, 1f))
|
||||
{
|
||||
if (TryComp<PuddleComponent>(entity, out var puddle))
|
||||
{
|
||||
puddles.Add((entity, puddle.SolutionName));
|
||||
}
|
||||
}
|
||||
|
||||
if (puddles.Count == 0)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-not-find-puddles"),
|
||||
uid, uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
|
||||
var absorbBlood = new Solution();
|
||||
foreach (var (puddle, solution) in puddles)
|
||||
{
|
||||
if (!_solutionSystem.TryGetSolution(puddle, solution, out var puddleSolution))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (var puddleSolutionContent in puddleSolution.Value.Comp.Solution.ToList())
|
||||
{
|
||||
if (!component.BloodWhitelist.Contains(puddleSolutionContent.Reagent.Prototype))
|
||||
continue;
|
||||
|
||||
var blood = puddleSolution.Value.Comp.Solution.SplitSolutionWithOnly(
|
||||
puddleSolutionContent.Quantity, puddleSolutionContent.Reagent.Prototype);
|
||||
|
||||
absorbBlood.AddSolution(blood, _prototypeManager);
|
||||
}
|
||||
|
||||
var ev = new SolutionContainerChangedEvent(puddleSolution.Value.Comp.Solution, solution);
|
||||
RaiseLocalEvent(puddle, ref ev);
|
||||
}
|
||||
|
||||
if (absorbBlood.Volume == 0)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-cant-absorb-puddle"),
|
||||
uid, uid, PopupType.Large);
|
||||
return;
|
||||
}
|
||||
|
||||
_audioSystem.PlayPvs(component.BloodAbsorbSound, uid, component.BloodAbsorbSound.Params);
|
||||
_popupSystem.PopupEntity(Loc.GetString("flesh-cultist-absorb-puddle", ("Entity", uid)),
|
||||
uid, uid, PopupType.Large);
|
||||
|
||||
var transferSolution = new Solution();
|
||||
foreach (var solution in component.HealBloodAbsorbReagents)
|
||||
{
|
||||
transferSolution.AddReagent(solution.Reagent, solution.Quantity * (absorbBlood.Volume / 10));
|
||||
}
|
||||
|
||||
if (_solutionSystem.TryGetInjectableSolution(uid, out var injectableSolution, out var _))
|
||||
{
|
||||
_solutionSystem.TryAddSolution(injectableSolution.Value, transferSolution);
|
||||
}
|
||||
absorbBlood.RemoveAllSolution();
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnStartup(EntityUid uid, FleshPudgeComponent component, ComponentStartup args)
|
||||
{
|
||||
_action.AddAction(uid, component.ActionAcidSpitId);
|
||||
_action.AddAction(uid, component.ActionThrowWormId);
|
||||
_action.AddAction(uid, component.ActionAbsorbBloodPoolId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.NPC.Prototypes;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult.GameRule;
|
||||
|
||||
[RegisterComponent, Access(typeof(FleshCultRuleSystem))]
|
||||
public sealed partial class FleshCultRuleComponent : Component
|
||||
{
|
||||
public EntityUid CultistsLeaderMind = new();
|
||||
|
||||
public SoundSpecifier AddedSound = new SoundPathSpecifier(
|
||||
"/Audio/_Sunrise/FleshCult/flesh_culstis_greeting.ogg");
|
||||
|
||||
public Dictionary<string, EntityUid> Cultists = new();
|
||||
|
||||
[DataField("fleshCultistPrototypeId", customTypeSerializer: typeof(PrototypeIdSerializer<AntagPrototype>))]
|
||||
public string FleshCultistPrototypeId = "FleshCultist";
|
||||
|
||||
[DataField("fleshCultistLeaderPrototypeID", customTypeSerializer: typeof(PrototypeIdSerializer<AntagPrototype>))]
|
||||
public string FleshCultistLeaderPrototypeId = "FleshCultistLeader";
|
||||
|
||||
[DataField("faction", customTypeSerializer: typeof(PrototypeIdSerializer<NpcFactionPrototype>), required: true)]
|
||||
public string Faction = default!;
|
||||
|
||||
public int TotalCultists => Cultists.Count;
|
||||
|
||||
public readonly List<string> CultistsNames = new();
|
||||
|
||||
public WinTypes WinType = WinTypes.Fail;
|
||||
|
||||
public bool FleshHeartActive = false;
|
||||
|
||||
public Dictionary<EntityUid, FleshHeartStatus> FleshHearts = new();
|
||||
|
||||
public EntityUid? TargetStation;
|
||||
|
||||
[DataField]
|
||||
public List<string> StarterItems = new() { "SyringeCarolNT", "SyringeCarolNT", "SyringeCarolNT" };
|
||||
|
||||
public List<string> SpeciesWhitelist = new()
|
||||
{
|
||||
"Human",
|
||||
"Reptilian",
|
||||
"Dwarf",
|
||||
"Vulpkanin",
|
||||
"Felinid",
|
||||
"Moth",
|
||||
"Swine",
|
||||
"Arachnid"
|
||||
};
|
||||
|
||||
public enum WinTypes
|
||||
{
|
||||
FleshHeartFinal,
|
||||
AllCultistsDead,
|
||||
Fail
|
||||
}
|
||||
|
||||
public TimeSpan AnnounceAt = TimeSpan.Zero;
|
||||
public Dictionary<ICommonSession, HumanoidCharacterProfile> StartCandidates = new();
|
||||
}
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
using System.Linq;
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.GameTicking.Rules;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Objectives;
|
||||
using Content.Server.RoundEnd;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Store.Systems;
|
||||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.GameTicking.Components;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.NPC.Systems;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult.GameRule;
|
||||
|
||||
public sealed class FleshCultRuleSystem : GameRuleSystem<FleshCultRuleComponent>
|
||||
{
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly RoundEndSystem _roundEndSystem = default!;
|
||||
[Dependency] private readonly StoreSystem _store = default!;
|
||||
[Dependency] private readonly MindSystem _mindSystem = default!;
|
||||
[Dependency] private readonly NpcFactionSystem _npcFaction = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FleshCultRuleComponent, AfterAntagEntitySelectedEvent>(AfterEntitySelected);
|
||||
|
||||
SubscribeLocalEvent<FleshHeartSystem.FleshHeartActivateEvent>(OnFleshHeartActivate);
|
||||
SubscribeLocalEvent<FleshHeartSystem.FleshHeartDestructionEvent>(OnFleshHeartDestruction);
|
||||
SubscribeLocalEvent<FleshHeartSystem.FleshHeartFinalEvent>(OnFleshHeartFinal);
|
||||
|
||||
SubscribeLocalEvent<FleshCultRuleComponent, ObjectivesTextPrependEvent>(OnObjectivesTextPrepend);
|
||||
}
|
||||
|
||||
private void OnObjectivesTextPrepend(EntityUid uid, FleshCultRuleComponent comp, ref ObjectivesTextPrependEvent args)
|
||||
{
|
||||
if (!TryComp(comp.CultistsLeaderMind, out MindComponent? mind) && mind == null)
|
||||
return;
|
||||
_mindSystem.TryGetSession(comp.CultistsLeaderMind, out var session);
|
||||
args.Text += "\n" + Loc.GetString("flesh-cult-round-end-leader", ("name", mind.CharacterName)!, ("username", session!.Name));
|
||||
}
|
||||
|
||||
private void OnFleshHeartActivate(FleshHeartSystem.FleshHeartActivateEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<FleshCultRuleComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var uid, out var fleshCult, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev.OwningStation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fleshCult.TargetStation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp(fleshCult.TargetStation, out StationDataComponent? data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var grid in data.Grids)
|
||||
{
|
||||
if (grid != ev.OwningStation)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fleshCult.FleshHearts.Add(ev.FleshHeardUid, FleshHeartStatus.Active);
|
||||
fleshCult.FleshHeartActive = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFleshHeartDestruction(FleshHeartSystem.FleshHeartDestructionEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<FleshCultRuleComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var uid, out var fleshCult, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev.OwningStation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fleshCult.TargetStation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp(fleshCult.TargetStation, out StationDataComponent? data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var grid in data.Grids)
|
||||
{
|
||||
if (grid != ev.OwningStation)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fleshCult.FleshHearts.ContainsKey(ev.FleshHeardUid))
|
||||
{
|
||||
fleshCult.FleshHearts[ev.FleshHeardUid] = FleshHeartStatus.Destruction;
|
||||
}
|
||||
fleshCult.FleshHeartActive = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFleshHeartFinal(FleshHeartSystem.FleshHeartFinalEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<FleshCultRuleComponent, GameRuleComponent>();
|
||||
while (query.MoveNext(out var uid, out var fleshCult, out var gameRule))
|
||||
{
|
||||
if (!GameTicker.IsGameRuleAdded(uid, gameRule))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev.OwningStation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fleshCult.TargetStation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp(fleshCult.TargetStation, out StationDataComponent? data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var grid in data.Grids)
|
||||
{
|
||||
if (grid != ev.OwningStation)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fleshCult.WinType = FleshCultRuleComponent.WinTypes.FleshHeartFinal;
|
||||
_roundEndSystem.EndRound();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AfterEntitySelected(Entity<FleshCultRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
|
||||
{
|
||||
MakeCultist(args.EntityUid, 15, ent.Comp);
|
||||
}
|
||||
|
||||
public void MakeCultistAdmin(EntityUid target, FixedPoint2 startingPoints)
|
||||
{
|
||||
var fleshCultRule = StartGameRule();
|
||||
MakeCultist(target, startingPoints, fleshCultRule);
|
||||
}
|
||||
|
||||
public FleshCultRuleComponent StartGameRule()
|
||||
{
|
||||
var comp = EntityQuery<FleshCultRuleComponent>().FirstOrDefault();
|
||||
if (comp == null)
|
||||
{
|
||||
GameTicker.StartGameRule("FleshCult", out var ruleEntity);
|
||||
comp = Comp<FleshCultRuleComponent>(ruleEntity);
|
||||
}
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
public bool MakeCultist(EntityUid fleshCultist, FixedPoint2 startingPoints, FleshCultRuleComponent fleshCultRule)
|
||||
{
|
||||
if (!_mindSystem.TryGetMind(fleshCultist, out var mindId, out var mind))
|
||||
return false;
|
||||
|
||||
if (mind.OwnedEntity is not { } entity)
|
||||
{
|
||||
Logger.ErrorS("preset", "Mind picked for cultist did not have an attached entity.");
|
||||
return false;
|
||||
}
|
||||
|
||||
SendCultistBriefing(mindId, fleshCultRule.CultistsNames);
|
||||
|
||||
if (_mindSystem.TryGetSession(mindId, out var session))
|
||||
{
|
||||
_audioSystem.PlayGlobal(fleshCultRule.AddedSound, session);
|
||||
}
|
||||
|
||||
_npcFaction.RemoveFaction(entity, "NanoTrasen", false);
|
||||
_npcFaction.AddFaction(entity, "FleshHuman");
|
||||
|
||||
var fleshCultistComponent = EnsureComp<FleshCultistComponent>(mind.OwnedEntity.Value);
|
||||
|
||||
_store.TryAddCurrency(new Dictionary<string, FixedPoint2>
|
||||
{ {fleshCultistComponent.StolenCurrencyPrototype, startingPoints} }, mind.OwnedEntity.Value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SendCultistBriefing(EntityUid mind, List<string> cultistsNames)
|
||||
{
|
||||
if (!_mindSystem.TryGetSession(mind, out var session))
|
||||
return;
|
||||
_chatManager.DispatchServerMessage(session, Loc.GetString("flesh-cult-role-greeting"));
|
||||
_chatManager.DispatchServerMessage(session, Loc.GetString("flesh-cult-role-cult-members", ("cultMembers", string.Join(", ", cultistsNames))));
|
||||
}
|
||||
|
||||
private void SendCultistLeaderBriefing(EntityUid mind, List<string> cultistsNames)
|
||||
{
|
||||
if (!_mindSystem.TryGetSession(mind, out var session))
|
||||
return;
|
||||
_chatManager.DispatchServerMessage(session, Loc.GetString("flesh-cult-role-greeting-leader"));
|
||||
_chatManager.DispatchServerMessage(session, Loc.GetString("flesh-cult-role-cult-members", ("cultMembers", string.Join(", ", cultistsNames))));
|
||||
}
|
||||
|
||||
protected override void AppendRoundEndText(EntityUid uid,
|
||||
FleshCultRuleComponent component,
|
||||
GameRuleComponent gameRule,
|
||||
ref RoundEndTextAppendEvent args)
|
||||
{
|
||||
var result = Loc.GetString("flesh-cult-round-end-count-create-flesh-hearts", ("heartsCount",
|
||||
component.FleshHearts.Count));
|
||||
|
||||
var destroyHearts = 0;
|
||||
var activateHearts = 0;
|
||||
|
||||
foreach (var (heartUid, heartStatus) in component.FleshHearts)
|
||||
{
|
||||
switch (heartStatus)
|
||||
{
|
||||
case FleshHeartStatus.Destruction:
|
||||
destroyHearts++;
|
||||
break;
|
||||
case FleshHeartStatus.Active:
|
||||
activateHearts++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (component.FleshHearts.Count > 0)
|
||||
{
|
||||
if (activateHearts > 0)
|
||||
{
|
||||
result += "\n" + Loc.GetString("flesh-cult-round-end-count-activate-flesh-hearts", ("heartsCount",
|
||||
activateHearts));
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "\n" + Loc.GetString("flesh-cult-round-end-count-no-activate-flesh-hearts");
|
||||
}
|
||||
|
||||
if (destroyHearts > 0)
|
||||
{
|
||||
result += "\n" + Loc.GetString("flesh-cult-round-end-count-destroy-flesh-hearts", ("heartsCount",
|
||||
destroyHearts));
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "\n" + Loc.GetString("flesh-cult-round-end-count-no-destroy-flesh-hearts");
|
||||
}
|
||||
}
|
||||
|
||||
if (component.FleshHeartActive)
|
||||
{
|
||||
result += "\n" + Loc.GetString("flesh-cult-round-end-flesh-heart-succes");
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "\n" + Loc.GetString("flesh-cult-round-end-flesh-heart-fail");
|
||||
}
|
||||
|
||||
args.AddLine("\n" + result);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using Content.Server._Sunrise.FleshCult.Objectives;
|
||||
using Content.Server.Objectives.Systems;
|
||||
|
||||
namespace Content.Server.Objectives.Components;
|
||||
|
||||
[RegisterComponent, Access(typeof(FleshCultConditionsSystem))]
|
||||
public sealed partial class CreateFleshHeartConditionComponent : Component
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using Content.Server._Sunrise.FleshCult.GameRule;
|
||||
using Content.Server.Objectives.Components;
|
||||
using Content.Server.Objectives.Systems;
|
||||
using Content.Shared.GameTicking.Components;
|
||||
using Content.Shared.Objectives.Components;
|
||||
|
||||
namespace Content.Server._Sunrise.FleshCult.Objectives;
|
||||
|
||||
public sealed class FleshCultConditionsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly NumberObjectiveSystem _number = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<CreateFleshHeartConditionComponent, ObjectiveGetProgressEvent>(OnFleshHeartGetProgress);
|
||||
}
|
||||
|
||||
private void OnFleshHeartGetProgress(EntityUid uid, CreateFleshHeartConditionComponent comp, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
args.Progress = FleshHeartProgress(args.MindId, _number.GetTarget(uid));
|
||||
}
|
||||
|
||||
private float FleshHeartProgress(EntityUid? mindId, int target)
|
||||
{
|
||||
// prevent divide-by-zero
|
||||
if (target == 0)
|
||||
return 1f;
|
||||
|
||||
if (!TryComp<FleshCultistRoleComponent>(mindId, out var role))
|
||||
return 0f;
|
||||
|
||||
var query = EntityQueryEnumerator<FleshCultRuleComponent, GameRuleComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out var fleshCult, out var gameRule))
|
||||
{
|
||||
return fleshCult.FleshHeartActive ? 1f : 0f;
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Server.Sunrise.FleshCult;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class PendingFleshCultistComponent : Component
|
||||
{
|
||||
[DataField("firstStageTimer")]
|
||||
public float FirstStageTimer = 30;
|
||||
|
||||
[DataField("secondStageTimer")]
|
||||
public float SecondStageTimer = 30;
|
||||
|
||||
[DataField("currentStage")]
|
||||
public PendingFleshCultistStage CurrentStage;
|
||||
|
||||
[DataField("nextParalyze", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||
public TimeSpan NextParalyze;
|
||||
|
||||
[DataField("paralyzeInterval")]
|
||||
public float ParalyzeInterval = 10;
|
||||
|
||||
[DataField("paralyzeTime")]
|
||||
public float ParalyzeTime = 5;
|
||||
|
||||
[DataField("nextScream", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||
public TimeSpan NextScream;
|
||||
|
||||
[DataField("screamInterval")]
|
||||
public float ScreamInterval = 5;
|
||||
|
||||
[DataField("nextStutter", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||
public TimeSpan NextStutter;
|
||||
|
||||
[DataField("stutterTime")]
|
||||
public float StutterTime = 10;
|
||||
|
||||
[DataField("stutterInterval")]
|
||||
public float StutterInterval = 3;
|
||||
|
||||
[DataField("nextJitter", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||
public TimeSpan NextJitter;
|
||||
|
||||
[DataField("jitterTime")]
|
||||
public float JitterTime = 10;
|
||||
|
||||
[DataField("jitterInterval")]
|
||||
public float JitterInterval = 5;
|
||||
|
||||
public float Accumulator = 0;
|
||||
}
|
||||
|
||||
public enum PendingFleshCultistStage
|
||||
{
|
||||
First,
|
||||
Second,
|
||||
Third,
|
||||
Final,
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using Content.Shared.Chemistry.Components;
|
||||
|
||||
namespace Content.Server._Sunrise.SplashOnTrigger
|
||||
{
|
||||
|
||||
[RegisterComponent]
|
||||
internal sealed partial class SplashOnTriggerComponent : Component
|
||||
{
|
||||
[DataField("splashReagents")] public Solution SplashReagents = new()
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Content.Server._Sunrise.SplashOnTrigger;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed partial class SplashOnTriggerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionSystem = default!;
|
||||
[Dependency] private readonly PuddleSystem _puddleSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SplashOnTriggerComponent, TriggerEvent>(OnSplashTrigger);
|
||||
}
|
||||
|
||||
private void OnSplashTrigger(EntityUid uid, SplashOnTriggerComponent component, TriggerEvent args)
|
||||
{
|
||||
var xform = Transform(uid);
|
||||
|
||||
var coords = xform.Coordinates;
|
||||
|
||||
if (!coords.IsValid(EntityManager))
|
||||
return;
|
||||
|
||||
var transferSolution = new Solution();
|
||||
foreach (var solution in component.SplashReagents)
|
||||
{
|
||||
transferSolution.AddReagent(solution.Reagent, solution.Quantity);
|
||||
}
|
||||
|
||||
if (_solutionSystem.TryGetInjectableSolution(uid, out var injectableSolution, out _))
|
||||
{
|
||||
_solutionSystem.TryAddSolution(injectableSolution.Value, transferSolution);
|
||||
}
|
||||
|
||||
_puddleSystem.TrySplashSpillAt(uid, coords, transferSolution, out var puddleUid);
|
||||
}
|
||||
}
|
||||
142
Content.Shared/_Sunrise/FleshCult/FleshCultistComponent.cs
Normal file
142
Content.Shared/_Sunrise/FleshCult/FleshCultistComponent.cs
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
using Content.Shared.Alert;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.StatusIcon;
|
||||
using Content.Shared.Store;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared._Sunrise.FleshCult;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class FleshCultistComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite)] public FixedPoint2 Hunger = 100;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("hungerСonsumption")]
|
||||
public FixedPoint2 HungerСonsumption = -0.05; // 200 hunger in 60 minutes
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("maxHunger")]
|
||||
public FixedPoint2 MaxHunger = 200;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("bulletAcidSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string BulletAcidSpawnId = "BulletSplashAcid";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("speciesWhitelist")]
|
||||
public List<string> SpeciesWhitelist = new()
|
||||
{
|
||||
"Human",
|
||||
"Reptilian",
|
||||
"Dwarf",
|
||||
"Vulpkanin",
|
||||
"Felinid",
|
||||
"Moth",
|
||||
"Swine",
|
||||
"Arachnid",
|
||||
};
|
||||
|
||||
[DataField("adrenalinReagents")] public Solution AdrenalinReagents = new()
|
||||
{
|
||||
Contents = { new ReagentQuantity(new ReagentId("Ephedrine", null), 10) }
|
||||
};
|
||||
|
||||
[DataField("healDevourReagents")] public Solution HealDevourReagents = new()
|
||||
{
|
||||
Contents =
|
||||
{
|
||||
new ReagentQuantity(new ReagentId("Carol", null), 20),
|
||||
}
|
||||
};
|
||||
|
||||
[DataField("healBloodAbsorbReagents")] public Solution HealBloodAbsorbReagents = new()
|
||||
{
|
||||
Contents =
|
||||
{
|
||||
new ReagentQuantity(new ReagentId("Carol", null), 1),
|
||||
}
|
||||
};
|
||||
|
||||
[DataField("bloodAbsorbSound")]
|
||||
public SoundSpecifier BloodAbsorbSound = new SoundPathSpecifier("/Audio/Effects/Fluids/splat.ogg");
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("bloodWhitelist")]
|
||||
public List<string> BloodWhitelist = new()
|
||||
{
|
||||
"Blood",
|
||||
"CopperBlood",
|
||||
"InsectBlood",
|
||||
"AmmoniaBlood",
|
||||
"ZombieBlood"
|
||||
};
|
||||
|
||||
[DataField("devourTime")] public float DevourTime = 10f;
|
||||
|
||||
[DataField("devourSound")]
|
||||
public SoundSpecifier DevourSound = new SoundPathSpecifier("/Audio/_Sunrise/FleshCult/devour_flesh_cultist.ogg");
|
||||
|
||||
[DataField("stolenCurrencyPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<CurrencyPrototype>))]
|
||||
public string StolenCurrencyPrototype = "StolenMutationPoint";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("fleshBladeSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string BladeSpawnId = "FleshBlade";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("fleshFistSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string FistSpawnId = "FleshFist";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("clawSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ClawSpawnId = "FleshClaw";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("spikeHandGunSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string SpikeHandGunSpawnId = "FleshSpikeHandGun";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("armorSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ArmorSpawnId = "ClothingOuterArmorFlesh";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("heavyArmorSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string HeavyArmorSpawnId = "ClothingOuterHeavyArmorFlesh";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("spiderLegsSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string SpiderLegsSpawnId = "ClothingFleshSpiderLegs";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("fleshMutationMobId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string FleshMutationMobId = "MobFleshPudge";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("soundMutation")]
|
||||
public SoundSpecifier SoundMutation = new SoundPathSpecifier("/Audio/_Sunrise/FleshCult/flesh_cultist_mutation.ogg");
|
||||
|
||||
[DataField("fleshHeartId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>)),
|
||||
ViewVariables(VVAccess.ReadWrite)]
|
||||
public string FleshHeartId = "FleshHeart";
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("soundThrowWorm")]
|
||||
public SoundSpecifier? SoundThrowHugger = new SoundPathSpecifier("/Audio/_Sunrise/FleshCult/throw_worm.ogg");
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("huggerMobSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string HuggerMobSpawnId = "MobFleshHugger";
|
||||
|
||||
public SoundSpecifier BuySuccesSound = new SoundPathSpecifier(
|
||||
"/Audio/_Sunrise/FleshCult/flesh_cultist_buy_succes.ogg");
|
||||
|
||||
[ViewVariables] public float Accumulator = 0;
|
||||
|
||||
[ViewVariables] public float AccumulatorStarveNotify = 0;
|
||||
|
||||
[DataField("fleshStatusIcon")]
|
||||
public ProtoId<FactionIconPrototype> StatusIcon { get; set; } = "FleshFaction";
|
||||
|
||||
[DataField]
|
||||
public ProtoId<AlertPrototype> MutationPointAlert = "MutationPoint";
|
||||
}
|
||||
101
Content.Shared/_Sunrise/FleshCult/FleshHeartComponent.cs
Normal file
101
Content.Shared/_Sunrise/FleshCult/FleshHeartComponent.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Flesh
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class FleshHeartComponent : Component
|
||||
{
|
||||
[DataField("transformSound")] public SoundSpecifier TransformSound = new SoundCollectionSpecifier("gib");
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("speciesWhitelist")]
|
||||
public List<string> SpeciesWhitelist = new()
|
||||
{
|
||||
"Human",
|
||||
"Reptilian",
|
||||
"Dwarf",
|
||||
"Vulpkanin",
|
||||
"Felinid",
|
||||
"Moth",
|
||||
"Swine",
|
||||
"Arachnid",
|
||||
};
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("entryDelay")]
|
||||
public float EntryDelay = 10f;
|
||||
|
||||
public Container BodyContainer = default!;
|
||||
|
||||
[DataField("alertLevelOnActivate")] public string AlertLevelOnActivate = "gamma";
|
||||
|
||||
[DataField("alertLevelOnDeactivate")] public string AlertLevelOnDeactivate = "green";
|
||||
|
||||
public EntityUid? AmbientAudioStream = default;
|
||||
|
||||
[DataField("bodyToFinalStage"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int BodyToFinalStage = 3; // default 3
|
||||
|
||||
[DataField("timeLiveFinalHeartToWin"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int TimeLiveFinalHeartToWin = 900; // default 600
|
||||
|
||||
[DataField("spawnObjectsFrequency"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpawnObjectsFrequency = 60;
|
||||
|
||||
[DataField("spawnObjectsAmount"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int SpawnObjectsAmount = 6;
|
||||
|
||||
[DataField("spawnObjectsRadius"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpawnObjectsRadius = 5;
|
||||
|
||||
[DataField("fleshTileId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>)),
|
||||
ViewVariables(VVAccess.ReadWrite)]
|
||||
public string FleshTileId = "Flesh";
|
||||
|
||||
[DataField("spawns"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public Dictionary<string, float> Spawns = new();
|
||||
|
||||
[DataField("spawnMobsFrequency"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpawnMobsFrequency = 120;
|
||||
|
||||
[DataField("spawnMobsAmount"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int SpawnMobsAmount = 10;
|
||||
|
||||
[DataField("spawnMobsRadius"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float SpawnMobsRadius = 3;
|
||||
|
||||
[ViewVariables]
|
||||
public float Accumulator = 0;
|
||||
|
||||
[ViewVariables]
|
||||
public float SpawnMobsAccumulator = 110;
|
||||
|
||||
[ViewVariables]
|
||||
public float SpawnObjectsAccumulator = 0;
|
||||
|
||||
[ViewVariables]
|
||||
public float FinalStageAccumulator = 0;
|
||||
|
||||
[ViewVariables]
|
||||
public HeartStates State = HeartStates.Base;
|
||||
|
||||
public readonly HashSet<EntityUid> EdgeMobs = new();
|
||||
|
||||
[DataField("damageMobsIfHeartDestruct", required: true)]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageSpecifier DamageMobsIfHeartDestruct = default!;
|
||||
|
||||
[DataField("finalState")]
|
||||
public string? FinalState = "underpowered";
|
||||
}
|
||||
}
|
||||
|
||||
public enum HeartStates
|
||||
{
|
||||
Base,
|
||||
Active,
|
||||
Disable
|
||||
}
|
||||
23
Content.Shared/_Sunrise/FleshCult/FleshHeartVisuals.cs
Normal file
23
Content.Shared/_Sunrise/FleshCult/FleshHeartVisuals.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Sunrise.FleshCult;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum FleshHeartVisuals : byte
|
||||
{
|
||||
State
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum FleshHeartStatus
|
||||
{
|
||||
Active,
|
||||
Disable,
|
||||
Destruction
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum FleshHeartLayers : byte
|
||||
{
|
||||
Base
|
||||
}
|
||||
42
Content.Shared/_Sunrise/FleshCult/FleshHuggerComponent.cs
Normal file
42
Content.Shared/_Sunrise/FleshCult/FleshHuggerComponent.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using Content.Server.Flesh;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared._Sunrise.FleshCult
|
||||
{
|
||||
[Access(typeof(SharedFleshHuggerSystem))]
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class FleshHuggerComponent : Component
|
||||
{
|
||||
[DataField("actionJump", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ActionFleshHuggerJumpId = "FleshHuggerJump";
|
||||
|
||||
[DataField("actionGetOff", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ActionFleshHuggerGetOffId = "FleshHuggerGetOff";
|
||||
|
||||
[DataField("paralyzeTime"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float ParalyzeTime = 3f;
|
||||
|
||||
[DataField("chansePounce"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int ChansePounce = 33;
|
||||
|
||||
[DataField("damage", required: true)]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageSpecifier Damage = default!;
|
||||
|
||||
public bool IsDeath = false;
|
||||
|
||||
public EntityUid EquipedOn;
|
||||
|
||||
[ViewVariables] public float Accumulator = 0;
|
||||
|
||||
[DataField("damageFrequency"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float DamageFrequency = 5;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("soundJump")]
|
||||
public SoundSpecifier? SoundJump = new SoundPathSpecifier("/Audio/_Sunrise/FleshCult/flesh_worm_scream.ogg");
|
||||
}
|
||||
}
|
||||
42
Content.Shared/_Sunrise/FleshCult/FleshMobComponent.cs
Normal file
42
Content.Shared/_Sunrise/FleshCult/FleshMobComponent.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using Content.Shared.Actions;
|
||||
using Content.Shared.StatusIcon;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared._Sunrise.FleshCult
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class FleshMobComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("soundDeath")]
|
||||
public SoundSpecifier? SoundDeath = new SoundPathSpecifier("/Audio/_Sunrise/FleshCult/flesh_pudge_dead.ogg");
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("deathMobSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string DeathMobSpawnId = "MobFleshWorm";
|
||||
|
||||
[DataField("deathMobSpawnCount"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public int DeathMobSpawnCount;
|
||||
|
||||
[DataField("fleshStatusIcon")]
|
||||
public ProtoId<FactionIconPrototype> StatusIcon { get; set; } = "FleshFaction";
|
||||
|
||||
public bool IsDeath = false;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class FleshPudgeThrowFaceHuggerActionEvent : WorldTargetActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshPudgeAcidSpitActionEvent : WorldTargetActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshPudgeAbsorbBloodPoolActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._Sunrise.FleshCult;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class IgnoreFleshSpiderWebComponent : Component
|
||||
{
|
||||
|
||||
}
|
||||
122
Content.Shared/_Sunrise/FleshCult/SharedFleshCultist.cs
Normal file
122
Content.Shared/_Sunrise/FleshCult/SharedFleshCultist.cs
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
using Content.Shared.Actions;
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Sunrise.FleshCult;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class FleshCultistDevourDoAfterEvent : SimpleDoAfterEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class FleshCultistInfectionDoAfterEvent : SimpleDoAfterEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class FleshCultistInsulatedImmunityMutationEvent : SimpleDoAfterEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class FleshCultistPressureImmunityMutationEvent : SimpleDoAfterEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class FleshCultistFlashImmunityMutationEvent : SimpleDoAfterEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class FleshCultistRespiratorImmunityMutationEvent : SimpleDoAfterEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class FleshCultistColdTempImmunityMutationEvent : SimpleDoAfterEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistAcidSpitActionEvent : WorldTargetActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistShopActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistBladeActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public sealed partial class FleshCultistClawActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistFistActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistSpikeHandGunActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistArmorActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistHeavyArmorActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistSpiderLegsActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public sealed partial class FleshCultistAdrenalinActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistCreateFleshHeartActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistThrowHuggerActionEvent : WorldTargetActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistAbsorbBloodPoolActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public sealed partial class FleshCultistDevourActionEvent : EntityTargetActionEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
namespace Content.Shared._Sunrise.FleshCult;
|
||||
|
||||
public abstract class SharedFleshCultistSystem : EntitySystem
|
||||
{
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Sunrise.FleshCult
|
||||
{
|
||||
[NetworkedComponent()]
|
||||
[Virtual]
|
||||
public partial class SharedFleshHeartComponent : Component
|
||||
{
|
||||
[DataField("finalState")]
|
||||
public string? FinalState = "underpowered";
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class FleshHeartDragFinished : SimpleDoAfterEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
40
Content.Shared/_Sunrise/FleshCult/SharedFleshHuggerSystem.cs
Normal file
40
Content.Shared/_Sunrise/FleshCult/SharedFleshHuggerSystem.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
using Content.Shared._Sunrise.FleshCult;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Popups;
|
||||
|
||||
namespace Content.Server.Flesh
|
||||
{
|
||||
public class SharedFleshHuggerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<FleshHuggerComponent, BeingUnequippedAttemptEvent>(OnUnequipAttempt);
|
||||
}
|
||||
|
||||
private void OnUnequipAttempt(EntityUid uid, FleshHuggerComponent component, BeingUnequippedAttemptEvent args)
|
||||
{
|
||||
if (args.Slot != "mask")
|
||||
return;
|
||||
if (component.EquipedOn != args.Unequipee)
|
||||
return;
|
||||
if (HasComp<FleshCultistComponent>(args.Unequipee))
|
||||
return;
|
||||
_popup.PopupEntity(Loc.GetString("flesh-pudge-throw-hugger-try-unequip"),
|
||||
args.Unequipee, args.Unequipee, PopupType.Large);
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class FleshHuggerJumpActionEvent : WorldTargetActionEvent
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
public sealed partial class FleshHuggerGetOffFromFaceActionEvent : InstantActionEvent
|
||||
{
|
||||
|
||||
};
|
||||
44
Content.Shared/_Sunrise/FleshCult/SharedFleshMobSystem.cs
Normal file
44
Content.Shared/_Sunrise/FleshCult/SharedFleshMobSystem.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
using Content.Shared.Flesh;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Popups;
|
||||
|
||||
namespace Content.Shared._Sunrise.FleshCult;
|
||||
|
||||
public abstract class SharedFleshMobSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FleshMobComponent, AttackAttemptEvent>(OnAttackAttempt);
|
||||
}
|
||||
|
||||
private void OnAttackAttempt(EntityUid uid, FleshMobComponent component, AttackAttemptEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
if (HasComp<FleshMobComponent>(args.Target))
|
||||
{
|
||||
_popup.PopupCursor(Loc.GetString("flesh-mob-cant-atack-flesh-mob"), uid,
|
||||
PopupType.LargeCaution);
|
||||
args.Cancel();
|
||||
}
|
||||
if (HasComp<_Sunrise.FleshCult.FleshCultistComponent>(args.Target))
|
||||
{
|
||||
_popup.PopupCursor(Loc.GetString("flesh-mob-cant-atack-flesh-cultist"), uid,
|
||||
PopupType.LargeCaution);
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
if (HasComp<FleshHeartComponent>(args.Target))
|
||||
{
|
||||
_popup.PopupCursor(Loc.GetString("flesh-mob-cant-atack-flesh-heart"), uid,
|
||||
PopupType.LargeCaution);
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
BIN
Resources/Audio/_Sunrise/FleshCult/abom_scream.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/abom_scream.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/devour_flesh_cultist.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/devour_flesh_cultist.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_blade.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_blade.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_culstis_greeting.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_culstis_greeting.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_cultist_buy_succes.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_cultist_buy_succes.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_cultist_mutation.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_cultist_mutation.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_heart.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_heart.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_heart_activate.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_heart_activate.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_pudge_dead.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_pudge_dead.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_worm_scream.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/flesh_worm_scream.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/spike_gun_reload.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/spike_gun_reload.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/spike_gun_shot.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/spike_gun_shot.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/_Sunrise/FleshCult/throw_worm.ogg
Normal file
BIN
Resources/Audio/_Sunrise/FleshCult/throw_worm.ogg
Normal file
Binary file not shown.
|
|
@ -1,2 +1,4 @@
|
|||
ent-SyringeRomerolNT = { ent-BaseSyringe }
|
||||
.desc = { ent-BaseSyringe.desc }
|
||||
ent-SyringeCarolNT = { ent-BaseSyringe }
|
||||
.desc = { ent-BaseSyringe.desc }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
admin-verb-text-make-flesh-cultist = Сделать цель культистом плоти.
|
||||
admin-verb-make-flesh-cultist = Сделать цель культистом плоти.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
roles-antag-flesh-cultist-name = Культист плоти
|
||||
roles-antag-flesh-cultist-objective = Оставайтесь в тени подготавливая погибель для станции.
|
||||
roles-antag-flesh-cultist-leader-name = Лидер культа плоти
|
||||
roles-antag-flesh-cultist-leader-objective = Воплотите цели культа в реальность. Убедитесь что все участники культа выживут.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
store-category-flesh-passive-skills = Улучшения
|
||||
store-category-flesh-active-skills = Умения
|
||||
store-category-flesh-weapon = Модификации рук
|
||||
store-category-flesh-armor = Модификации тела
|
||||
|
|
@ -0,0 +1 @@
|
|||
store-currency-display-stolen-mutation-points = Очки Эволюции
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
ent-Flesh = живая плоть
|
||||
.desc = Оно живое!
|
||||
.suffix = { "" }
|
||||
ent-FleshBlade = рука-линок из плоти
|
||||
.desc = Почти как у генокрада, только лучше.
|
||||
.suffix = { "" }
|
||||
ent-FleshClaw = клешня из плоти
|
||||
.desc = Нею можно вскрывать как двери так и людей.
|
||||
.suffix = { "" }
|
||||
ent-ClothingFleshSpiderLegs = паучьи ноги
|
||||
.desc = 2 ноги хорошо, 8 лучше.
|
||||
.suffix = { "" }
|
||||
ent-ClothingOuterArmorFlesh = броня из плоти
|
||||
.desc = А где кожа?
|
||||
.suffix = { "" }
|
||||
ent-FleshSpikeHandGun = рука-шипострел
|
||||
.desc = Пиу-Пау
|
||||
.suffix = { "" }
|
||||
ent-FleshFist = кулак из плоти
|
||||
.desc = Fisting is three hundred bucks
|
||||
.suffix = { "" }
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
flesh-pudge-throw-hugger-name = Выблевать червя
|
||||
flesh-pudge-throw-hugger-popup = Выблевывает червя
|
||||
flesh-pudge-throw-hugger-eat-face-user = Червь ест ваше лицо!
|
||||
flesh-pudge-throw-hugger-bite-user = Червь укусил вас за руку!
|
||||
flesh-pudge-throw-hugger-try-unequip = Вы не можете снять червя с лица.
|
||||
flesh-pudge-throw-hugger-eat-face-others = Червь ест лицо { CAPITALIZE($entity) }!
|
||||
flesh-pudge-throw-hugger-hit-others = К лицу { CAPITALIZE($entity) } присосался червь!
|
||||
flesh-pudge-throw-hugger-hit-mob = Вы присосались к лицу { CAPITALIZE($entity) }!
|
||||
flesh-pudge-throw-hugger-hit-user = К вашему лицу присосался червь!
|
||||
flesh-pudge-throw-hugger-desc = Выблюйте червя из плоти и возьмите его в свою руку для броска во врагов.
|
||||
flesh-pudge-transform-user = Вы превращаетесь в { CAPITALIZE($EntityTransform) }
|
||||
flesh-pudge-transform-others = { CAPITALIZE($Entity) } превращается в { CAPITALIZE($EntityTransform) }
|
||||
flesh-pudge-transform-begin-user = Вы начинаете превращаться.
|
||||
flesh-pudge-transform-begin-others = { CAPITALIZE($Entity) } начинает превращается.
|
||||
|
||||
flesh-mob-cant-atack-flesh-heart = Вы не можете атаковать сердце плоти.
|
||||
flesh-mob-cant-atack-flesh-mob = Вы не можете атаковать монстров из плоти.
|
||||
flesh-mob-cant-atack-flesh-cultist = Вы не можете атаковать культистов плоти.
|
||||
flesh-hugger-jump-name = Прыжок
|
||||
flesh-hugger-jump-desc = Позволяет вам прыгнуть в выбраном направлении. Если вы попадете в гуманоида без маски вы зацепитесь за его лицо.
|
||||
flesh-hugger-get-off-name = Слезть с лица
|
||||
flesh-hugger-get-off-desc = Позволяет вам спуститься с лица.
|
||||
|
||||
mob-flesh-ghost-role-rules = Не атакуйте культистов плоти, не ломайте ДАМы, сервера, консоли и прочее. Не делайте разгерметизацию.
|
||||
mob-flesh-abom-ghost-role-name = Ужасное порождение из плоти
|
||||
mob-flesh-abom-ghost-role-decs = Вы разумная плоть, кооперируйтесь с другими существами из плоти для захвата станции.
|
||||
mob-flesh-pudge-ghost-role-name = Толстяк из плоти
|
||||
mob-flesh-pudge-ghost-role-decs = Вы разумная плоть, кооперируйтесь с другими существами из плоти для захвата станции.
|
||||
mob-flesh-spider-ghost-role-name = Тарантул из плоти
|
||||
mob-flesh-spider-ghost-role-decs = Вы разумная плоть, кооперируйтесь с другими существами из плоти для захвата станции.
|
||||
mob-flesh-ball-ghost-role-name = Мячик из плоти
|
||||
mob-flesh-ball-ghost-role-decs = Вы разумная плоть, кооперируйтесь с другими существами из плоти для захвата станции.
|
||||
mob-flesh-bat-ghost-role-name = Летащая мышь из плоти
|
||||
mob-flesh-bat-ghost-role-decs = Вы разумная плоть, кооперируйтесь с другими существами из плоти для захвата станции.
|
||||
mob-flesh-worm-ghost-role-name = Червь из плоти
|
||||
mob-flesh-worm-ghost-role-decs = Вы разумная плоть, кооперируйтесь с другими существами из плоти для захвата станции.
|
||||
mob-flesh-small-worm-ghost-role-name = Маленьнький червь из плоти
|
||||
mob-flesh-small-worm-ghost-role-decs = Вы разумная плоть, кооперируйтесь с другими существами из плоти для захвата станции.
|
||||
mob-flesh-hugger-ghost-role-name = лицехват из плоти
|
||||
mob-flesh-hugger-ghost-role-decs = Вы разумная плоть, кооперируйтесь с другими существами из плоти для захвата станции.
|
||||
|
||||
flesh-worm-cant-get-off = Вы не на лице.
|
||||
flesh-worm-cant-jump = Вы не можете прыгать будучи на лице.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
ent-FleshHeart = сердце плоти
|
||||
.desc = Такой хуйни вы еще не видели.
|
||||
|
||||
flesh-heart-cant-absorb-targer = Сердце не хочет поглощать это.
|
||||
flesh-heart-activate-warning = Внимание! На станции была замечена аномальная биологическая сигнатура. Всему персоналу отдела службы безопастности начать немедленную ликвидацию цели.
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
flesh-cultist-transform-hand-in-blade = Рука { CAPITALIZE($Entity) } превращается в клинок из плоти.
|
||||
flesh-cultist-transform-hand-in-claw = Рука { CAPITALIZE($Entity) } превращается в клешню из плоти.
|
||||
flesh-cultist-transform-hand-in-spike-gun = Рука { CAPITALIZE($Entity) } превращается в шипострел из плоти.
|
||||
flesh-cultist-transform-blade-in-hand = Клинок из плоти { CAPITALIZE($Entity) } превращается обратно в руку.
|
||||
flesh-cultist-transform-claw-in-hand = Клешня из плоти { CAPITALIZE($Entity) } превращается обратно в руку.
|
||||
flesh-cultist-transform-spike-gun-in-hand = Шипострел из плоти { CAPITALIZE($Entity) } превращается обратно в руку.
|
||||
flesh-cultist-transform-armor-on = { CAPITALIZE($Entity) } покрывается броней из плоти.
|
||||
flesh-cultist-transform-armor-off = { CAPITALIZE($Entity) } убирает свою броню из плоти.
|
||||
flesh-cultist-transform-spider-legs-on = Ноги { CAPITALIZE($Entity) } превращаются в паучьи лапы из плоти.
|
||||
flesh-cultist-transform-spider-legs-off = Паучьи лапы { CAPITALIZE($Entity) } превращаются обратно в человеческие ноги.
|
||||
flesh-cultist-transform-user-hand-blocked = Данная рука занята другой модификацией.
|
||||
flesh-cultist-transform-armor-blocked = Вы не можете использовать паучьи ноги и броню одновременно.
|
||||
flesh-cultist-transform-spider-legs-blocked = Вы не можете использовать броню с паучьими лапами.
|
||||
flesh-cultist-infection-target-critical = Вы не можете заразить умирающее существо.
|
||||
flesh-cultist-infection-target-dead = Вы не можете заразить мертвое существо.
|
||||
flesh-cultist-infection-target-invalid = Вы не можете заразить данное существо.
|
||||
flesh-cultist-equiped-outer-clothing-blocked = Вы не можете это одеть.
|
||||
flesh-cultist-infected-user = Вы чувствуете, что внутри вас что-то развивается.
|
||||
flesh-cultist-devout-target-not-have-flesh = Вы не можете поглощать существа, не состоящие из плоти.
|
||||
flesh-cultist-devout-target-alive = Вы не можете поглощать живых существ.
|
||||
flesh-cultist-devout-target-invalid = Вы не можете поглотить это.
|
||||
flesh-cultist-devout-not-hungry = Паразит не достаточно голоден, чтобы поглотить это.
|
||||
flesh-cultist-hungry = Паразит голоден.
|
||||
flesh-cultist-equipped-outer-clothing-blocked = Вы не можете одеть это, пока у вас есть паучьи ноги.
|
||||
flesh-cultist-cant-spawn-flesh-heart-in-space = Сердце плоти невозможно создать в космосе.
|
||||
flesh-cultist-cant-spawn-flesh-heart-here = Слишком мало места для сердца плоти.
|
||||
flesh-cultist-cant-absorb-puddle = Рядом нету крови.
|
||||
flesh-cultist-absorb-puddle = { CAPITALIZE($Entity) } поглощает лужу крови.
|
||||
flesh-cultist-devour-target = { CAPITALIZE($Entity) } поглощает { CAPITALIZE($Target) }.
|
||||
flesh-cultist-not-find-puddles = Рядом нету никаких луж.
|
||||
flesh-cultist-throw-hugger = Вы бросата лицехвата.
|
||||
flesh-cultist-throw-hugger-others = { CAPITALIZE($Entity) } бросает лицехвата.
|
||||
|
||||
flesh-cultist-hunger-name = Голод паразита
|
||||
flesh-cultist-hunger-desc = Когда голод паразита достигнет нуля, он вырвется наружу, и вы потеряете контроль над своим телом.
|
||||
flesh-cultist-shop-name = Магазин эволюции
|
||||
flesh-cultist-shop-desc = Здесь вы можете приобрести активные навыки и пассивные улучшения.
|
||||
flesh-cultist-blade-name = Клинок из плоти
|
||||
flesh-cultist-blade-desc = Превращает активную руку в смертоносный клинок из плоти и костей.
|
||||
flesh-cultist-break-cuffs-name = Сброс оков
|
||||
flesh-cultist-break-cuffs-desc = Вы можете сорвать с себя любые наручники или смирительную рубашку.
|
||||
flesh-cultist-adrenalin-name = Синтез эпинефрина
|
||||
flesh-cultist-adrenalin-desc = Паразит синтезирует и вводит вам дозу эпинефрина, что повышает вашу скорость и сопротивление оглушению.
|
||||
flesh-cultist-claw-name = Клешня из плоти
|
||||
flesh-cultist-claw-desc = Превращает активную руку в функциональную клешню из плоти и костей.
|
||||
flesh-cultist-fist-name = Кулак из плоти
|
||||
flesh-cultist-fist-desc = Превращает активную руку в массивный кулак из плоти которым можно легко ломать любые структуры.
|
||||
flesh-cultist-spike-gun-name = Рука шипострел
|
||||
flesh-cultist-spike-gun-desc = Превращает активную руку в смертоносный шипострел из плоти.
|
||||
flesh-cultist-armor-name = Броня из плоти
|
||||
flesh-cultist-armor-desc = Облачает вас в броню из плоти и костей.
|
||||
flesh-cultist-spider-legs-name = Паучий облик
|
||||
flesh-cultist-spider-legs-desc = Превращает часть вашего тела в паучий вид, давая небольшую защиту и большой прирост скорости.
|
||||
flesh-cultist-absorb-blood-pool-name = Поглощение лужи крови
|
||||
flesh-cultist-absorb-blood-pool-desc = Позволяет поглотить чистые лужи крови для лечения.
|
||||
flesh-cultist-devour-name = Поглощение трупа
|
||||
flesh-cultist-devour-desc = Вы можете поглотить любое существо из плоти, чтобы получить очки эволюции и исцелить раны.
|
||||
flesh-cultist-create-flesh-heart-name = Создание сердца из плоти
|
||||
flesh-cultist-create-flesh-heart-desc = Создает сердце из плоти перед вами. Его создание - ваша ключевая задача на станции. Для активации необходимо использовать 3 тела развитых существ из плоти. После активации будьте готовы защищать его от сотрудников службы безопасности.
|
||||
flesh-cultist-throw-hugger-name = Бросок лицехвата
|
||||
flesh-cultist-throw-hugger-desc = Создайте и метните в лица врагов лицехвата из плоти.
|
||||
flesh-cultist-acid-spit-name = Кислотный плевок
|
||||
flesh-cultist-acid-spit-desc = Плюйтесь кислотой в ваших врагов
|
||||
|
||||
flesh-cultist-blade-evolution-name = Клинок из плоти
|
||||
flesh-cultist-blade-evolution-desc = Получите возможность превратить свою руку в смертоносный клинок из плоти и костей.
|
||||
flesh-cultist-claw-evolution-name = Клешня из плоти
|
||||
flesh-cultist-claw-evolution-desc = Получите возможность превратить свою руку в функциональную клешню из плоти и костей.
|
||||
flesh-cultist-fist-evolution-name = Кулак из плоти
|
||||
flesh-cultist-fist-evolution-desc = Получите возможность превратить свою руку в массивный кулак из плоти которым можно легко ломать любые структуры.
|
||||
flesh-cultist-spike-gun-evolution-name = Рука шипострел
|
||||
flesh-cultist-spike-gun-evolution-desc = Превратите активную руку в смертоносный шипострел из плоти.
|
||||
flesh-cultist-medium-armor-evolution-name = Броня из плоти
|
||||
flesh-cultist-medium-armor-evolution-desc = Получите способность облачать себя в среднюю броню из плоти и костей.
|
||||
flesh-cultist-heavy-armor-evolution-name = Тяжелая броня из плоти
|
||||
flesh-cultist-heavy-armor-evolution-desc = Получите способность облачать себя в тяжелую броню из плоти и костей которая дает невероятную защиту и возможность отражать выстрелы но сильно замедляет движение.
|
||||
flesh-cultist-spider-legs-evolution-name = Паучий облик
|
||||
flesh-cultist-spider-legs-evolution-desc = Получите возможность превратить часть тела в паука, чтобы получить небольшую защиту и большой прирост скорости.
|
||||
flesh-cultist-break-cuffs-evolution-name = Сброс оков
|
||||
flesh-cultist-break-cuffs-evolution-desc = Получите возможность высвободиться от наручников или смирительной рубашки.
|
||||
flesh-cultist-adrenaline-evolution-name = Синтез адреналина
|
||||
flesh-cultist-adrenaline-evolution-desc = Получите возможность получать дозу адреналина для повышения скорости и устойчивости к оглушению.
|
||||
flesh-cultist-throw-hugger-evolution-name = Бросок лицехвата
|
||||
flesh-cultist-throw-hugger-evolution-desc = Получите возможность создать и кинуть лицехвата из плоти, который будет цеплятся за лица врагов.
|
||||
flesh-cultist-acid-spit-evolution-name = Кислотный плевок
|
||||
flesh-cultist-acid-spit-evolution-desc = Получите возможность преваться кислотой в ваших врагов.
|
||||
flesh-cultist-create-flesh-heart-evolution-name = Создание сердца из плоти
|
||||
flesh-cultist-create-flesh-heart-evolution-desc = Получите возможность создать сердце из плоти.
|
||||
Его создание и пробуждение - ваша ключевая задача на станции.
|
||||
Для пробуждения потребуется три тела развитых существ из плоти. После активации будьте готовы защищать его от любой угрозы.
|
||||
|
||||
flesh-cultist-insulated-immunity-evolution-name = Сопротивление
|
||||
flesh-cultist-insulated-immunity-evolution-desc = Вы сможете спокойно работать с электричеством не опасаясь поражения напряжением.
|
||||
flesh-cultist-pressure-immunity-evolution-name = Уплотнение
|
||||
flesh-cultist-pressure-immunity-evolution-desc = Вам больше не будет угрожать низкое давление окружающей среды.
|
||||
flesh-cultist-cold-teml-immunity-evolution-name = Термо-синтез
|
||||
flesh-cultist-cold-teml-immunity-evolution-desc = Вы сможете поддерживать температуру тела стабильной в условиях холодного космоса.
|
||||
flesh-cultist-flash-immunity-evolution-name = Защита глаз
|
||||
flesh-cultist-flash-immunity-evolution-desc = Вас больше не будут ослеплять яркие вспышки.
|
||||
flesh-cultist-respirator-immunity-evolution-name = Закрытая система дыхания.
|
||||
flesh-cultist-respirator-immunity-evolution-desc = Вам больше не нужен кислород.
|
||||
14
Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/mobs.ftl
Normal file
14
Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/mobs.ftl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
ent-MobFleshSpider = тарантул из плоти
|
||||
.desc = Очень похоже на паука, только вывернутого наизнанку
|
||||
ent-MobFleshPudge = толстяк из плоти
|
||||
.desc = Большой мальчик
|
||||
ent-MobFleshBall = мячик из плоти
|
||||
.desc = Лучше не играть ним в футбол
|
||||
ent-MobFleshBat = летающая мышь из плоти
|
||||
.desc = Она не дружит с священником
|
||||
ent-MobFleshWorm = червь из плоти
|
||||
.desc = Вот что будет внутри вас если есть много конфет
|
||||
ent-MobSmallFleshWorm = маленький червь из плоти
|
||||
.desc = { ent-MobFleshWorm.desc }
|
||||
ent-MobFleshHugger = лицехват из плоти
|
||||
.desc = Он хочет сесть тебе на лицо
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
flesh-cult = Культ плоти
|
||||
flesh-cult-round-end-result =
|
||||
{ $cultistsCount ->
|
||||
[one] Был один культист плоти.
|
||||
*[other] Было { $cultistsCount } культистов плоти.
|
||||
}
|
||||
flesh-cult-and-traitor-title = Культ плоти и Предатели
|
||||
flesh-cult-and-traitor-description = На станции одновременно действует культ плоти и предатели.
|
||||
flesh-cult-round-end-agent-name = культист плоти
|
||||
flesh-cult-round-end-cultist-live-amount-none = [color=green]Все культисты были уничтожены![/color]
|
||||
flesh-cult-round-end-cultist-live-amount-low = [color=green]Почти все культисты были уничтожены.[/color]
|
||||
flesh-cult-round-end-flesh-heart-succes = [bold][color=red]Станция была обращена в обитель плоти![/color][/bold]
|
||||
flesh-cult-round-end-flesh-heart-fail = [bold][color=green]Культу плоти не удалось выполнить свою цель![/color][/bold]
|
||||
# Shown at the end of a round of Traitor
|
||||
flesh-cult-user-was-a-cultist = [color=gray]{ $user }[/color] был(а) культистом плоти.
|
||||
flesh-cult-user-was-a-cultist-named = [color=White]{ $name }[/color] ([color=gray]{ $user }[/color]) был(а) культистом плоти.
|
||||
flesh-cult-was-a-traitor-named = [color=White]{ $name }[/color] был(а) культистом плоти.
|
||||
|
||||
flesh-cult-user-was-a-cultist-leader = [color=gray]{ $user }[/color] был(а) лидером культа плоти.
|
||||
flesh-cult-user-was-a-cultist-leader-named = [color=White]{ $name }[/color] ([color=gray]{ $user }[/color]) был(а) лидером культа плоти.
|
||||
flesh-cult-was-a-cultist-leader-named = [color=White]{ $name }[/color] был(а) лидером культа плоти.
|
||||
|
||||
flesh-cult-user-was-a-cultist-with-objectives = [color=gray]{ $user }[/color] был(а) культистом плоти со следующими целями:
|
||||
flesh-cult-user-was-a-cultist-with-objectives-named = [color=White]{ $name }[/color] ([color=gray]{ $user }[/color]) был(а) культистом плоти со следующими целями:
|
||||
flesh-cult-was-a-cultist-with-objectives-named = [color=White]{ $name }[/color] был(а) культистом плоти со следующими целями:
|
||||
|
||||
flesh-cult-user-was-a-cultist-leader-with-objectives = [color=gray]{ $user }[/color] был(а) лидером культа плоти со следующими целями:
|
||||
flesh-cult-user-was-a-cultist-leader-with-objectives-named = [color=White]{ $name }[/color] ([color=gray]{ $user }[/color]) был(а) лидером культа плоти со следующими целями:
|
||||
flesh-cult-was-a-cultist-leader-with-objectives-named = [color=White]{ $name }[/color] был(а) лидером культа плоти со следующими целями:
|
||||
|
||||
flesh-cult-round-end-leader = [bold]Лидером культа плоти был [color=White]{ $name }[/color] ([color=gray]{ $username }[/color])[/bold]
|
||||
|
||||
preset-flesh-cult-objective-issuer-flesh-cult = [color=#e0106a]Культ плоти[/color]
|
||||
objective-issuer-flesh-cult = [color=#e0106a]Культ плоти[/color]
|
||||
# Shown at the end of a round of Traitor
|
||||
flesh-cult-objective-condition-success = { $condition } | [color={ $markupColor }]Успех![/color]
|
||||
# Shown at the end of a round of Traitor
|
||||
flesh-cult-objective-condition-fail = { $condition } | [color={ $markupColor }]Провал![/color] ({ $progress }%)
|
||||
flesh-cult-title = Культ плоти
|
||||
flesh-cult-description = На станции появился культ, который желает захватить станцию.
|
||||
flesh-cult-not-enough-ready-players = Недостаточно игроков готовы к игре! Из { $minimumPlayers } необходимых игроков готовы { $readyPlayersCount }.
|
||||
flesh-cult-no-one-ready = Нет готовых игроков! Не удалось начать режим Культа плоти.
|
||||
|
||||
# TraitorRole
|
||||
flesh-cult-role-greeting =
|
||||
Вы - участник культа плоти.
|
||||
Ваши цели и соратники указаны в меню персонажа.
|
||||
Поедайте существ из плоти чтобы получить новые навыки, оставайтесь в тени и готовите пришествие плоти на станцию.
|
||||
flesh-cult-role-cult-members =
|
||||
Ваши соратники:
|
||||
{ $cultMembers }
|
||||
Не позволяйте им умереть напрасно.
|
||||
|
||||
# TraitorRole
|
||||
flesh-cult-role-greeting-leader =
|
||||
Вы - лидер культа плоти.
|
||||
Ваши цели и соратники указаны в меню персонажа.
|
||||
Поедайте существ из плоти чтобы получить новые навыки, оставайтесь в тени и готовите пришествие плоти на станцию.
|
||||
Убедитесь что никто из участников вашего культа не погибнет напрасно.
|
||||
|
||||
flesh-cult-round-end-count-create-flesh-hearts =
|
||||
{ $heartsCount ->
|
||||
[one] Было создано одно сердце плоти.
|
||||
*[other] Было создано { $heartsCount } сердец плоти.
|
||||
}
|
||||
|
||||
flesh-cult-round-end-count-activate-flesh-hearts =
|
||||
{ $heartsCount ->
|
||||
[one] Было пробуждено одно сердце плоти.
|
||||
*[other] Было пробуждено { $heartsCount } сердец плоти.
|
||||
}
|
||||
|
||||
flesh-cult-round-end-count-no-activate-flesh-hearts = Ни одно сердце плоти не было пробуждено.
|
||||
|
||||
flesh-cult-round-end-count-destroy-flesh-hearts =
|
||||
{ $heartsCount ->
|
||||
[one] Было уничтожено одно сердце плоти.
|
||||
*[other] Было уничтожено { $heartsCount } сердец плоти.
|
||||
}
|
||||
|
||||
flesh-cult-round-end-count-no-destroy-flesh-hearts = Ни одно сердце плоти не было уничтожено.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
reagent-name-carol = ??????
|
||||
reagent-desc-carol = ??????
|
||||
reagent-name-flesh-acid = ??????
|
||||
reagent-desc-flesh-acid = ??????
|
||||
|
|
@ -455,22 +455,22 @@ station-goal-training-crew =
|
|||
⠀=============================================
|
||||
⠀Приветствую, уважаемое командование станции!
|
||||
⠀Цель вашей текущей смены - [bold]ОБУЧЕНИЕ ЭКИПАЖА ПОСРЕДСТВОМ ОТКРЫТЫХ ЛЕКЦИЙ[/bold]
|
||||
⠀Каждый отдел должен выбрать [bold]одного или двух ораторов[/bold] и подготовить свой план лекции отдела, который должен быть заверен печатью главы,
|
||||
⠀Каждый отдел должен выбрать [bold]одного или двух ораторов[/bold] и подготовить свой план лекции отдела, который должен быть заверен печатью главы,
|
||||
а после провести эту лекцию публично.
|
||||
Условия:[bold]
|
||||
1. Допускается проведение лекции как в отделе, так и на отдельно подготовленной сцене.
|
||||
2. Лекция считается выполненной успешно, если на ней было обучено минимум 10 членов ДРУГИХ отделов.
|
||||
3. Цель считается выполненной, если было успешно проведено минимум 3 лекции с подготовленными о них отчётами, в которых должно указываться:
|
||||
- Количество пришедших;
|
||||
- Количество обученных;
|
||||
- Какие навыки отдела затрагивает лекция;
|
||||
- Имена ораторов;
|
||||
3. Цель считается выполненной, если было успешно проведено минимум 3 лекции с подготовленными о них отчётами, в которых должно указываться:
|
||||
- Количество пришедших;
|
||||
- Количество обученных;
|
||||
- Какие навыки отдела затрагивает лекция;
|
||||
- Имена ораторов;
|
||||
- Место проведения;[/bold]
|
||||
Всё отчёты должны быть доставлены на эвакуационном шаттле.
|
||||
|
||||
Ответственные за цель: [bold]ИНЖЕНЕРНЫЙ ОТДЕЛ, НАУЧНЫЙ ОТДЕЛ, ОТДЕЛ СНАБЖЕНИЯ, СЕРВИСНЫЙ ОТДЕЛ, ОТДЕЛ СЛУЖБЫ БЕЗОПАСНОСТИ,
|
||||
Ответственные за цель: [bold]ИНЖЕНЕРНЫЙ ОТДЕЛ, НАУЧНЫЙ ОТДЕЛ, ОТДЕЛ СНАБЖЕНИЯ, СЕРВИСНЫЙ ОТДЕЛ, ОТДЕЛ СЛУЖБЫ БЕЗОПАСНОСТИ,
|
||||
МЕДИЦИНСКИЙ ОТДЕЛ, КАПИТАН СТАНЦИИ { $station }[/bold].
|
||||
|
||||
|
||||
=============================================
|
||||
⠀ [italic]Место для печатей[/italic]
|
||||
|
||||
|
|
@ -492,11 +492,11 @@ station-goal-creation-of-furs =
|
|||
3. Мех модели "Дюранд" (1 шт.).
|
||||
4. Каждому меху по 2 запасных энергоячейки. [/bold]
|
||||
Отделу снабжения даётся задача заказать и добыть все необходимые материалы для создания мехов.
|
||||
Службе безопасности в обязательном порядке даётся задача проконтролировать доставку ВСЕХ созданных из списка мехов и
|
||||
Службе безопасности в обязательном порядке даётся задача проконтролировать доставку ВСЕХ созданных из списка мехов и
|
||||
запасных энергоячеек на эвакуационном шаттле.
|
||||
|
||||
Ответственные за цель: [bold]НАУЧНЫЙ ОТДЕЛ, ОТДЕЛ СНАБЖЕНИЯ, ОТДЕЛ СЛУЖБЫ БЕЗОПАСНОСТИ, КАПИТАН СТАНЦИИ { $station }[/bold].
|
||||
|
||||
|
||||
=============================================
|
||||
⠀ [italic]Место для печатей[/italic]
|
||||
|
||||
|
|
@ -517,15 +517,15 @@ station-goal-saboteurs =
|
|||
Условия:
|
||||
1. Выбранный офицер не должен нарушать статьи корпоративного закона выше 4XX, статьи с кодом 3 и 7 нарушать [bold]СТРОГО[/bold] запрещено.
|
||||
2. Выбранный офицер имеет право оказывать любое [bold]нелетальное[/bold] сопротивление ловящим его сотрудникам службы безопасности.
|
||||
3. В случае подтверждения угрозы на станции и введение красного кода, учения должны быть немедленно остановлены,
|
||||
3. В случае подтверждения угрозы на станции и введение красного кода, учения должны быть немедленно остановлены,
|
||||
диверсанты обязаны оказать помощь отделу в устранении угрозы. После ликвидации, учения должны породолжаться в прежнем режиме.
|
||||
Задача отдела безопасности найти "нарушителя" и в соответствии с процедурами ареста, КЗ и СРП провести его задержание, допрос и вынесение приговора.
|
||||
После этого рекрутированный офицер должен быть освобождён. ГСБ должен составить отчёт о действиях диверсанта и работе СБ.
|
||||
В случае, если диверсант так и не был установлен и арестован, учения заканчиваются. ГСБ так же должен составить отчёт о действиях диверсанта и
|
||||
После этого рекрутированный офицер должен быть освобождён. ГСБ должен составить отчёт о действиях диверсанта и работе СБ.
|
||||
В случае, если диверсант так и не был установлен и арестован, учения заканчиваются. ГСБ так же должен составить отчёт о действиях диверсанта и
|
||||
работе СБ.
|
||||
|
||||
Ответственные за цель: [bold]ОТДЕЛ СЛУЖБЫ БЕЗОПАСНОСТИ, КАПИТАН СТАНЦИИ { $station }[/bold].
|
||||
|
||||
|
||||
=============================================
|
||||
⠀ [italic]Место для печатей[/italic]
|
||||
|
||||
|
|
@ -539,7 +539,7 @@ station-goal-reconnaissance-in-force =
|
|||
⠀ ЦЕЛЬ СМЕНЫ { $station }
|
||||
⠀=============================================
|
||||
⠀Приветствую, уважаемое командование станции!
|
||||
⠀Цель вашей смены - провести 3 успешных полётов на планеты с уровнем сложности "высокая" и подготовить отчёт о каждом вылете
|
||||
⠀Цель вашей смены - провести 3 успешных полётов на планеты с уровнем сложности "высокая" и подготовить отчёт о каждом вылете
|
||||
в соответствии с формой "отчёт об экспедиции".
|
||||
⠀Руководство недовольно потерей ряда объектов в вашем секторе, по этому необходимо направить экспедиционные команды для расследования этих инцидентов.
|
||||
⠀Необходимо собрать отряд добровольцев, который будет включать в себя:[bold]
|
||||
|
|
@ -550,7 +550,7 @@ station-goal-reconnaissance-in-force =
|
|||
⠀При возникновений сложностей с фауной, вы имеете право запросить огневую поддержку у сил службы безопасности вашей станции.
|
||||
|
||||
⠀Ответственные за цель: [bold]НАУЧНЫЙ ОТДЕЛ, МЕДИЦИНСКИЙ ОТДЕЛ, ОТДЕЛ СНАБЖЕНИЯ, КАПИТАН СТАНЦИИ { $station }[/bold].
|
||||
|
||||
|
||||
=============================================
|
||||
⠀ [italic]Место для печатей[/italic]
|
||||
|
||||
|
|
@ -575,10 +575,10 @@ station-goal-reports =
|
|||
-Подготовить Отчёт о одобренных заказах.
|
||||
-Подготовить Отчёт об исследованиях артефактов.
|
||||
-Подготовить Отчёт об использованных за смену препаратах.[/bold]
|
||||
На выполнение данной задачи у вас 2 часа, после ПЦК может известить о своем прибытии для личной проверки всех отчётов.
|
||||
На выполнение данной задачи у вас 2 часа, после ПЦК может известить о своем прибытии для личной проверки всех отчётов.
|
||||
В противном случае все отчёты должны быть доставлены на СЦК
|
||||
|
||||
Ответственные за цель: [bold]ОТДЕЛ СНАБЖЕНИЯ, НАУЧНЫЙ ОТДЕЛ, МЕДИЦИНСКИЙ ОТДЕЛ, ОТДЕЛ СЛУЖБЫ БЕЗОПАСНОСТИ,
|
||||
Ответственные за цель: [bold]ОТДЕЛ СНАБЖЕНИЯ, НАУЧНЫЙ ОТДЕЛ, МЕДИЦИНСКИЙ ОТДЕЛ, ОТДЕЛ СЛУЖБЫ БЕЗОПАСНОСТИ,
|
||||
СЕРВИСНЫЙ ОТДЕЛ, КАПИТАН СТАНЦИИ { $station }[/bold].
|
||||
|
||||
=============================================
|
||||
|
|
@ -596,21 +596,21 @@ station-goal-intelligent-weapons =
|
|||
⠀Приветствую, уважаемое командование станции!
|
||||
⠀Цель вашей текущей смены - [bold]СОЗДАНИЕ РАЗУМНОГО ОРУЖИЯ[/bold]
|
||||
Было принято решение о создании нового вида оружия для защиты наших колоний. Для выполения цели потребуется:[bold]
|
||||
1. Отделу снабжения необходимо привезти туши ксеноморфов двух видов, а также заказать все необходимые ресурсы для постройки
|
||||
1. Отделу снабжения необходимо привезти туши ксеноморфов двух видов, а также заказать все необходимые ресурсы для постройки
|
||||
камер содержания в ксеноархеологии для них.
|
||||
2. Медицинскому отделу необходимо реанимировать туши ксеноморфов, а также ввести в каждого из них когнизин и
|
||||
2. Медицинскому отделу необходимо реанимировать туши ксеноморфов, а также ввести в каждого из них когнизин и
|
||||
поддерживать здоровое состояние каждой особи до окончания смены.
|
||||
3. Научному отделу необходимо изучить способности, степень работоспособности каждой особи, а также заставить каждую особь повиноваться и слушать вас.
|
||||
4. Инженерному отделу даётся задача не просто восстановить ксеноархеологию а укрепить и поддерживать ее целостность на протяжении всей смены.
|
||||
5. Службе безопасности даётся задача проконтролировать содержание существ, не давая им выйти из зоны содержания, на протяжении всей смены. [/bold]
|
||||
По окончанию выполенения цели необходимо доставить особей на СЦК.
|
||||
По окончанию выполенения цели необходимо доставить особей на СЦК.
|
||||
В случае, если особи окажутся невосприимчивы к препарату, они должны быть уничтожены.
|
||||
В случае побега особей из камеры содержания, из-за недостатка её прочности, ответственные сотрудники инженерного отдела должны быть
|
||||
задержаны по статье 402 КЗ а особи найдены и ликвидированы.
|
||||
В случае побега особей из камеры содержания, из-за недостатка её прочности, ответственные сотрудники инженерного отдела должны быть
|
||||
задержаны по статье 402 КЗ а особи найдены и ликвидированы.
|
||||
|
||||
Ответственные за цель: [bold]ОТДЕЛ СНАБЖЕНИЯ, НАУЧНЫЙ ОТДЕЛ, МЕДИЦИНСКИЙ ОТДЕЛ, ОТДЕЛ СЛУЖБЫ БЕЗОПАСНОСТИ, ИНЖЕНЕРНЫЙ ОТДЕЛ,
|
||||
Ответственные за цель: [bold]ОТДЕЛ СНАБЖЕНИЯ, НАУЧНЫЙ ОТДЕЛ, МЕДИЦИНСКИЙ ОТДЕЛ, ОТДЕЛ СЛУЖБЫ БЕЗОПАСНОСТИ, ИНЖЕНЕРНЫЙ ОТДЕЛ,
|
||||
КАПИТАН СТАНЦИИ { $station }[/bold].
|
||||
|
||||
|
||||
=============================================
|
||||
⠀ [italic]Место для печатей[/italic]
|
||||
|
||||
|
|
@ -624,8 +624,8 @@ station-goal-medical-replenishment =
|
|||
⠀ ЦЕЛЬ СМЕНЫ { $station }
|
||||
⠀=============================================
|
||||
⠀Приветствую, уважаемое командование станции!
|
||||
⠀Цель вашей текущей смены - [bold]ПРОИЗВОДСТВО ПОПОЛНЕНИЯ ЛЕКАРСТВ ДЛЯ СЦК [/bold]
|
||||
Одна из наших колоний слишком сильно пострадала от нападения ксеноморфов. В данный момент колония не может нормально функционировать и
|
||||
⠀Цель вашей текущей смены - [bold]ПРОИЗВОДСТВО ПОПОЛНЕНИЯ ЛЕКАРСТВ ДЛЯ СЦК [/bold]
|
||||
Одна из наших колоний слишком сильно пострадала от нападения ксеноморфов. В данный момент колония не может нормально функционировать и
|
||||
все раненные были перемещены на СЦК, потому медицинскому отделу даётся задача произвести следующий список лекарств:[bold]
|
||||
1. Сигинат (200 унций).
|
||||
2. Дексалин плюс (200 унций).
|
||||
|
|
@ -656,12 +656,12 @@ station-goal-medical-replenishment =
|
|||
6. Набор для выведения радиации (2 шт.).
|
||||
7. Коробка мешков для тел (6 шт.).[/bold]
|
||||
|
||||
ЦК заботится о своих сотрудниках поэтому запрещает приступать к цели пока не выполнен
|
||||
ЦК заботится о своих сотрудниках поэтому запрещает приступать к цели пока не выполнен
|
||||
"заказ изготовление основных препаратов для оказания медицинской помощи".
|
||||
Все препараты и наборы должны быть аккуратно собраны в ящики и доставленны на СЦК.
|
||||
|
||||
|
||||
Ответственные за цель: [bold]МЕДИЦИНСКИЙ ОТДЕЛ, СЕРВИСНЫЙ ОТДЕЛ, КАПИТАН СТАНЦИИ { $station }[/bold].
|
||||
|
||||
|
||||
=============================================
|
||||
⠀ [italic]Место для печатей[/italic]
|
||||
station-goal-anomaly =
|
||||
|
|
@ -677,11 +677,11 @@ station-goal-anomaly =
|
|||
⠀Цель вашей текущей смены - [bold]ГЕНЕРАЦИЯ АНОМАЛИЙ[/bold].
|
||||
Корпорация планирует продвинуться в изучении аномальных объектов и РедСпейса в частности.
|
||||
Научному отдела ставится задача сгенерировать или найти на станции [bold]4 аномалии разного типа[/bold],
|
||||
осуществить подробное изучение объектов и составить на основе полученных данных отчёты
|
||||
с отправкой энных на ЦентКом.
|
||||
Научный отдел вправе привлекать другие отделы для выполнения цели.
|
||||
Заказы учёных в Карго получают приоритет и должны быть рассмотрены в кратчайшие сроки,
|
||||
при условии, что они требуются для успешного выполнения задачи.
|
||||
осуществить подробное изучение объектов и составить на основе полученных данных отчёты
|
||||
с отправкой энных на ЦентКом.
|
||||
Научный отдел вправе привлекать другие отделы для выполнения цели.
|
||||
Заказы учёных в Карго получают приоритет и должны быть рассмотрены в кратчайшие сроки,
|
||||
при условии, что они требуются для успешного выполнения задачи.
|
||||
Инженерный отдел может помогать аномалистам в создании благоприятных условий для сдерживания объектов.
|
||||
В условии к оформлению отчёта может быть указано:
|
||||
- Внешнее описание аномальных объектов;
|
||||
|
|
@ -702,7 +702,7 @@ station-goal-testing-sb =
|
|||
⠀=============================================
|
||||
⠀Приветствую, уважаемое командование станции!
|
||||
⠀Цель вашей текущей смены - [bold]ТЕСТИРОВАНИЕ ДЛЯ ВСЕГО ОТДЕЛА СЛУЖБЫ БЕЗОПАСНОСТИ[/bold].
|
||||
В последнее время от многих станций стало поступать огромное количество жалоб на работу службы безопасности,
|
||||
В последнее время от многих станций стало поступать огромное количество жалоб на работу службы безопасности,
|
||||
в связи с этим нами было принято решение провести повторное тестирование службы безопасности на каждой станции!
|
||||
Для этого вам потребуется:[bold]
|
||||
- Организовать Тестирование СБ по СРП, КЗ и всяческим процедурам.
|
||||
|
|
@ -711,10 +711,10 @@ station-goal-testing-sb =
|
|||
- Подготовить полосу с препятствиями ввиде луж, стен, ограждений и т.п.
|
||||
- Произвести оценку по навыкам управления и стрельбы из мехов службы безопасности.
|
||||
- Произвести Учения, по работе при ЧС.[/bold]
|
||||
|
||||
|
||||
Для выполнения цели отдел службы безопасности вправе попросить помощи у других отделов для организации тестирования
|
||||
По завершении цели отослать отчёты с показателем каждого в СБ, включая ГСБ.
|
||||
|
||||
|
||||
⠀Ответственные за цель: [bold]ОТДЕЛ СЛУЖБЫ БЕЗОПАСНОСТИ, КАПИТАН СТАНЦИИ { $station }[/bold].
|
||||
⠀
|
||||
⠀=============================================
|
||||
|
|
@ -755,10 +755,10 @@ station-goal-delegates =
|
|||
⠀=============================================
|
||||
⠀Приветствую, уважаемое командование станции!
|
||||
⠀Цель вашей смены - [bold]ПОДГОТОВИТЬ СТАНЦИЮ К ПРИНЯТИЮ ДЕЛЕГАТОВ[/bold].
|
||||
В связи с недавними событиями различные корпорации и государства в том числе и NanoTrasen решили провести переговоры для состовления
|
||||
В связи с недавними событиями различные корпорации и государства в том числе и NanoTrasen решили провести переговоры для состовления
|
||||
плана сотрудничества на ближайшее время, поэтому нами было принято решение выбрать вашу станцию для проведения переговоров.
|
||||
|
||||
Сервисному отделу даётся задача привести и поддерживать на станции чистоту вплоть до конца смены, заменить лампы, подготовить по 10 сложных блюд и
|
||||
Сервисному отделу даётся задача привести и поддерживать на станции чистоту вплоть до конца смены, заменить лампы, подготовить по 10 сложных блюд и
|
||||
напитков (в шейкерах) и разместить их в холодильнике.
|
||||
|
||||
Научному отделу даётся задача модифицировать отделы, добавив по 8-10 нового оборудования в каждый отдел и изучив хотя бы одну ветку изучений до третьего уровня
|
||||
|
|
@ -774,3 +774,28 @@ station-goal-delegates =
|
|||
⠀
|
||||
⠀=============================================
|
||||
⠀ [italic]Место для печатей[/italic]
|
||||
station-goal-virus =
|
||||
║[color=#1b487e]███╗░░██╗████████╗[/color]
|
||||
║[color=#1b487e]████╗░██║╚══██╔══╝[/color] [head=3]Цель смены[/head]
|
||||
║[color=#1b487e]██╔██╗██║░░░██║░░░[/color] [head=3]NanoTrasen[/head]
|
||||
║[color=#1b487e]██║╚████║░░░██║░░░[/color]
|
||||
║[color=#1b487e]██║░╚███║░░░██║░░░[/color]
|
||||
║[color=#1b487e]╚═╝░░╚══╝░░░╚═╝░░░[/color]
|
||||
║═════════════════════════════════════════
|
||||
ЦЕЛЬ СМЕНЫ
|
||||
║═════════════════════════════════════════
|
||||
Уважаемый Капитан Станции. Вашей смене поставлена совершенно секретная цель. Вы, получив и прочитав данный документ, соглашаетесь с политикой неразглашения. Вам позволительно разглашать детали этой цели Командному составу, как и необходимым сотрудникам, которые будут исполнять поставленную задачу, но будьте бдительны, СМИ не должны заполучить данный документ или узнать об этом эксперименте.
|
||||
|
||||
1. Необходимо построить укреплённую камеру из армированного стекла для проведения опытов вблизи РНД, минимальный размер внутренней части должен быть не меньше 2x2 метра, вокруг оградить решеткой, запитанную электричеством. В зону проведения опытов должна быть проведена труба, которая, в случае неудачи, сможет подать газ в камеру, тем самым убив всё содержимое.
|
||||
|
||||
2. Вам необходимо найти двух, но не более четырёх добровольцев (не обязательно говорить им об опасности и их дальнейшей смерти). Ими могут быть пассажиры, обычные сотрудники станции или заключенные, включая приговорённых к смертной казни.
|
||||
|
||||
3. В вашем шкафу находится шприц с неизвестным вирусом, этот химический состав вы должны ввести в испытуемых в построенной камере.
|
||||
3.1. Исследовать рацион заражённых.
|
||||
3.2. Исследовать естественное распространение вируса на другое живое существо - это может быть как член экипажа, так и животное.
|
||||
3.3. Исследовать возможную коммуникацию с данными существами.
|
||||
|
||||
4. Эксперимент должен письменно фиксироваться, а документ о ходе эксперимента нужно будет предоставить Центральному Командованию. После дождаться прибытия Представителя Центрального Командования, или разрешения процедуры эвакуации.
|
||||
Слава NanoTrasen!
|
||||
║═════════════════════════════════════════
|
||||
║ [italic]Место для печатей[/italic]
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@
|
|||
- type: Tag
|
||||
tags:
|
||||
- Window
|
||||
- Directional # Sunrise-Edit
|
||||
- type: MeleeSound
|
||||
soundGroups:
|
||||
Brute:
|
||||
|
|
@ -284,4 +285,4 @@
|
|||
sprite: Structures/Windows/cracks_diagonal.rsi
|
||||
- type: Construction
|
||||
graph: WindowDiagonal
|
||||
node: windowDiagonal
|
||||
node: windowDiagonal
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
- id: SpiderClownSpawn
|
||||
- id: SpiderSpawn
|
||||
- id: VentClog
|
||||
- id: VentFleshWorms
|
||||
|
||||
- type: entityTable
|
||||
id: BasicAntagEventsTable
|
||||
|
|
|
|||
|
|
@ -12,3 +12,18 @@
|
|||
- type: Injector
|
||||
injectOnly: false
|
||||
toggleState: Inject
|
||||
|
||||
- type: entity
|
||||
parent: BaseSyringe
|
||||
id: SyringeCarolNT
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
injector:
|
||||
maxVol: 15
|
||||
reagents:
|
||||
- ReagentId: Carol
|
||||
Quantity: 5
|
||||
- type: Injector
|
||||
injectOnly: false
|
||||
toggleState: Inject
|
||||
|
|
|
|||
|
|
@ -0,0 +1,182 @@
|
|||
- type: entity
|
||||
id: FleshCultistShop
|
||||
name: flesh-cultist-shop-name
|
||||
description: flesh-cultist-shop-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistShop.png
|
||||
event: !type:FleshCultistShopActionEvent
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistBlade
|
||||
name: flesh-cultist-blade-name
|
||||
description: flesh-cultist-blade-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistBlade.png
|
||||
event: !type:FleshCultistBladeActionEvent
|
||||
itemIconStyle: NoItem
|
||||
useDelay: 10
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistAdrenalin
|
||||
name: flesh-cultist-adrenalin-name
|
||||
description: flesh-cultist-adrenalin-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistAdrenalin.png
|
||||
event: !type:FleshCultistAdrenalinActionEvent
|
||||
itemIconStyle: NoItem
|
||||
useDelay: 180
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistCreateFleshHeart
|
||||
name: flesh-cultist-create-flesh-heart-name
|
||||
description: flesh-cultist-create-flesh-heart-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistFleshHeart.png
|
||||
event: !type:FleshCultistCreateFleshHeartActionEvent
|
||||
itemIconStyle: NoItem
|
||||
useDelay: 360
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistClaw
|
||||
name: flesh-cultist-claw-name
|
||||
description: flesh-cultist-claw-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistClaw.png
|
||||
event: !type:FleshCultistClawActionEvent
|
||||
itemIconStyle: NoItem
|
||||
useDelay: 10
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistThrowHugger
|
||||
name: flesh-cultist-throw-hugger-name
|
||||
description: flesh-cultist-throw-hugger-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshThrowHugger.png
|
||||
itemIconStyle: NoItem
|
||||
event: !type:FleshCultistThrowHuggerActionEvent
|
||||
range: 200
|
||||
useDelay: 240
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistAcidSpit
|
||||
name: flesh-cultist-acid-spit-name
|
||||
description: flesh-cultist-acid-spit-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshAcidSpit.png
|
||||
itemIconStyle: NoItem
|
||||
event: !type:FleshCultistAcidSpitActionEvent
|
||||
range: 200
|
||||
useDelay: 60
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistFist
|
||||
name: flesh-cultist-fist-name
|
||||
description: flesh-cultist-fist-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistFist.png
|
||||
event: !type:FleshCultistFistActionEvent
|
||||
itemIconStyle: NoItem
|
||||
useDelay: 10
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistSpikeGun
|
||||
name: flesh-cultist-spike-gun-name
|
||||
description: flesh-cultist-spike-gun-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistSpikeGun.png
|
||||
event: !type:FleshCultistSpikeHandGunActionEvent
|
||||
itemIconStyle: NoItem
|
||||
useDelay: 10
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistArmor
|
||||
name: flesh-cultist-armor-name
|
||||
description: flesh-cultist-armor-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistArmor.png
|
||||
event: !type:FleshCultistArmorActionEvent
|
||||
itemIconStyle: NoItem
|
||||
useDelay: 30
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistHeavyArmor
|
||||
name: flesh-cultist-heavy-armor-name
|
||||
description: flesh-cultist-heavy-armor-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistHeavyArmor.png
|
||||
event: !type:FleshCultistHeavyArmorActionEvent
|
||||
itemIconStyle: NoItem
|
||||
useDelay: 30
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistSpiderlegs
|
||||
name: flesh-cultist-spider-legs-name
|
||||
description: flesh-cultist-spider-legs-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistSpiderLegs.png
|
||||
event: !type:FleshCultistSpiderLegsActionEvent
|
||||
itemIconStyle: NoItem
|
||||
useDelay: 30
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistAbsorbBloodPool
|
||||
name: flesh-cultist-absorb-blood-pool-name
|
||||
description: flesh-cultist-absorb-blood-pool-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistAbsorbBloodPool.png
|
||||
event: !type:FleshCultistAbsorbBloodPoolActionEvent
|
||||
useDelay: 30
|
||||
checkCanInteract: false
|
||||
|
||||
- type: entity
|
||||
id: FleshCultistDevour
|
||||
name: flesh-cultist-devour-name
|
||||
description: flesh-cultist-devour-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: EntityTargetAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistDevour.png
|
||||
itemIconStyle: NoItem
|
||||
event: !type:FleshCultistDevourActionEvent
|
||||
checkCanInteract: false
|
||||
useDelay: 5
|
||||
whitelist:
|
||||
components:
|
||||
- MobState
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
- type: entity
|
||||
id: FleshHuggerJump
|
||||
name: flesh-hugger-jump-name
|
||||
description: flesh-hugger-jump-description
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
useDelay: 3
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshThrowHugger.png
|
||||
itemIconStyle: NoItem
|
||||
checkCanAccess: false
|
||||
range: 200
|
||||
event: !type:FleshHuggerJumpActionEvent
|
||||
|
||||
- type: entity
|
||||
id: FleshHuggerGetOff
|
||||
name: flesh-hugger-get-off-name
|
||||
description: flesh-hugger-get-off-description
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
useDelay: 5
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshHuggerGetOff.png
|
||||
itemIconStyle: NoItem
|
||||
event: !type:FleshHuggerGetOffFromFaceActionEvent
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
- type: entity
|
||||
id: FleshThrowWorm
|
||||
name: flesh-pudge-throw-hugger-name
|
||||
description: flesh-pudge-throw-hugger-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshThrowHugger.png
|
||||
itemIconStyle: NoItem
|
||||
checkCanAccess: false
|
||||
range: 200
|
||||
event: !type:FleshPudgeThrowFaceHuggerActionEvent
|
||||
useDelay: 240
|
||||
|
||||
- type: entity
|
||||
id: FleshAcidSpit
|
||||
name: flesh-cultist-acid-spit-name
|
||||
description: flesh-cultist-acid-spit-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshAcidSpit.png
|
||||
itemIconStyle: NoItem
|
||||
checkCanAccess: false
|
||||
range: 200
|
||||
event: !type:FleshPudgeAcidSpitActionEvent
|
||||
useDelay: 60
|
||||
|
||||
- type: entity
|
||||
id: AbsorbBloodPool
|
||||
name: flesh-cultist-absorb-blood-pool-name
|
||||
description: flesh-cultist-absorb-blood-pool-desc
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistAbsorbBloodPool.png
|
||||
event: !type:FleshPudgeAbsorbBloodPoolActionEvent
|
||||
useDelay: 30
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
- type: entity
|
||||
id: FleshSpiderWebAction
|
||||
name: spider-web-action-name
|
||||
description: spider-web-action-description
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: InstantAction
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/flesh_web.png
|
||||
event: !type:SpiderWebActionEvent
|
||||
useDelay: 30
|
||||
217
Resources/Prototypes/_Sunrise/FleshCult/Store/catalog.yml
Normal file
217
Resources/Prototypes/_Sunrise/FleshCult/Store/catalog.yml
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
- type: listing
|
||||
id: FleshCultistBlade
|
||||
name: flesh-cultist-blade-evolution-name
|
||||
description: flesh-cultist-blade-evolution-desc
|
||||
productAction: FleshCultistBlade
|
||||
cost:
|
||||
StolenMutationPoint: 45
|
||||
categories:
|
||||
- FleshCultistWeapon
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistInsulatedImmunityMutationEvent
|
||||
name: flesh-cultist-insulated-immunity-evolution-name
|
||||
description: flesh-cultist-insulated-immunity-evolution-desc
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistInsulatedImmunityMutation.png
|
||||
productEvent: !type:FleshCultistInsulatedImmunityMutationEvent
|
||||
raiseProductEventOnUser: true
|
||||
cost:
|
||||
StolenMutationPoint: 10
|
||||
categories:
|
||||
- FleshCultistPassiveSkills
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistPressureImmunityMutationEvent
|
||||
name: flesh-cultist-pressure-immunity-evolution-name
|
||||
description: flesh-cultist-pressure-immunity-evolution-desc
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistPressureImmunityMutation.png
|
||||
productEvent: !type:FleshCultistPressureImmunityMutationEvent
|
||||
raiseProductEventOnUser: true
|
||||
cost:
|
||||
StolenMutationPoint: 5
|
||||
categories:
|
||||
- FleshCultistPassiveSkills
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistColdTempImmunityMutationEvent
|
||||
name: flesh-cultist-cold-teml-immunity-evolution-name
|
||||
description: flesh-cultist-cold-teml-immunity-evolution-desc
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistColdTempImmunityMutation.png
|
||||
productEvent: !type:FleshCultistColdTempImmunityMutationEvent
|
||||
raiseProductEventOnUser: true
|
||||
cost:
|
||||
StolenMutationPoint: 5
|
||||
categories:
|
||||
- FleshCultistPassiveSkills
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistFlashImmunityMutationEvent
|
||||
name: flesh-cultist-flash-immunity-evolution-name
|
||||
description: flesh-cultist-flash-immunity-evolution-desc
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistFlashImmunityMutation.png
|
||||
productEvent: !type:FleshCultistFlashImmunityMutationEvent
|
||||
raiseProductEventOnUser: true
|
||||
cost:
|
||||
StolenMutationPoint: 10
|
||||
categories:
|
||||
- FleshCultistPassiveSkills
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistRespiratorImmunityMutationEvent
|
||||
name: flesh-cultist-respirator-immunity-evolution-name
|
||||
description: flesh-cultist-respirator-immunity-evolution-desc
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistRespiratorImmunityMutation.png
|
||||
productEvent: !type:FleshCultistRespiratorImmunityMutationEvent
|
||||
raiseProductEventOnUser: true
|
||||
cost:
|
||||
StolenMutationPoint: 5
|
||||
categories:
|
||||
- FleshCultistPassiveSkills
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistClaw
|
||||
name: flesh-cultist-claw-evolution-name
|
||||
description: flesh-cultist-claw-evolution-desc
|
||||
productAction: FleshCultistClaw
|
||||
cost:
|
||||
StolenMutationPoint: 10
|
||||
categories:
|
||||
- FleshCultistWeapon
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistFist
|
||||
name: flesh-cultist-fist-evolution-name
|
||||
description: flesh-cultist-fist-evolution-desc
|
||||
productAction: FleshCultistFist
|
||||
cost:
|
||||
StolenMutationPoint: 25
|
||||
categories:
|
||||
- FleshCultistWeapon
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistSpikeGun
|
||||
name: flesh-cultist-spike-gun-evolution-name
|
||||
description: flesh-cultist-spike-gun-evolution-desc
|
||||
productAction: FleshCultistSpikeGun
|
||||
cost:
|
||||
StolenMutationPoint: 35
|
||||
categories:
|
||||
- FleshCultistWeapon
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistMediumArmor
|
||||
name: flesh-cultist-medium-armor-evolution-name
|
||||
description: flesh-cultist-medium-armor-evolution-desc
|
||||
productAction: FleshCultistArmor
|
||||
cost:
|
||||
StolenMutationPoint: 25
|
||||
categories:
|
||||
- FleshCultistArmor
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistHeavyArmor
|
||||
name: flesh-cultist-heavy-armor-evolution-name
|
||||
description: flesh-cultist-heavy-armor-evolution-desc
|
||||
productAction: FleshCultistHeavyArmor
|
||||
cost:
|
||||
StolenMutationPoint: 45
|
||||
categories:
|
||||
- FleshCultistArmor
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistSpiderlegs
|
||||
name: flesh-cultist-spider-legs-evolution-name
|
||||
description: flesh-cultist-spider-legs-evolution-desc
|
||||
productAction: FleshCultistSpiderlegs
|
||||
cost:
|
||||
StolenMutationPoint: 20
|
||||
categories:
|
||||
- FleshCultistArmor
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistAdrenalin
|
||||
name: flesh-cultist-adrenaline-evolution-name
|
||||
description: flesh-cultist-adrenaline-evolution-desc
|
||||
productAction: FleshCultistAdrenalin
|
||||
cost:
|
||||
StolenMutationPoint: 30
|
||||
categories:
|
||||
- FleshCultistActiveSkills
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistCreateFleshHeart
|
||||
name: flesh-cultist-create-flesh-heart-evolution-name
|
||||
description: flesh-cultist-create-flesh-heart-evolution-desc
|
||||
productAction: FleshCultistCreateFleshHeart
|
||||
cost:
|
||||
StolenMutationPoint: 50
|
||||
categories:
|
||||
- FleshCultistActiveSkills
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistThrowHugger
|
||||
name: flesh-cultist-throw-hugger-evolution-name
|
||||
description: flesh-cultist-throw-hugger-evolution-desc
|
||||
productAction: FleshCultistThrowHugger
|
||||
cost:
|
||||
StolenMutationPoint: 30
|
||||
categories:
|
||||
- FleshCultistActiveSkills
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
|
||||
- type: listing
|
||||
id: FleshCultistAcidSpit
|
||||
name: flesh-cultist-acid-spit-evolution-name
|
||||
description: flesh-cultist-acid-spit-evolution-desc
|
||||
productAction: FleshCultistAcidSpit
|
||||
cost:
|
||||
StolenMutationPoint: 30
|
||||
categories:
|
||||
- FleshCultistActiveSkills
|
||||
conditions:
|
||||
- !type:ListingLimitedStockCondition
|
||||
stock: 1
|
||||
15
Resources/Prototypes/_Sunrise/FleshCult/Store/categories.yml
Normal file
15
Resources/Prototypes/_Sunrise/FleshCult/Store/categories.yml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
- type: storeCategory
|
||||
id: FleshCultistPassiveSkills
|
||||
name: store-category-flesh-passive-skills
|
||||
|
||||
- type: storeCategory
|
||||
id: FleshCultistActiveSkills
|
||||
name: store-category-flesh-active-skills
|
||||
|
||||
- type: storeCategory
|
||||
id: FleshCultistWeapon
|
||||
name: store-category-flesh-weapon
|
||||
|
||||
- type: storeCategory
|
||||
id: FleshCultistArmor
|
||||
name: store-category-flesh-armor
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
- type: currency
|
||||
id: StolenMutationPoint
|
||||
displayName: store-currency-display-stolen-mutation-points
|
||||
canWithdraw: false
|
||||
17
Resources/Prototypes/_Sunrise/FleshCult/ai_factions.yml
Normal file
17
Resources/Prototypes/_Sunrise/FleshCult/ai_factions.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
- type: npcFaction
|
||||
id: Flesh
|
||||
hostile:
|
||||
- NanoTrasen
|
||||
- Syndicate
|
||||
- Xeno
|
||||
- SimpleHostile
|
||||
- Carps
|
||||
- Zombie
|
||||
- Revolutionary
|
||||
- PetsNT
|
||||
- Vampire
|
||||
- Changeling
|
||||
- Thief
|
||||
|
||||
- type: npcFaction
|
||||
id: FleshHuman
|
||||
41
Resources/Prototypes/_Sunrise/FleshCult/alerts.yml
Normal file
41
Resources/Prototypes/_Sunrise/FleshCult/alerts.yml
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
- type: alert
|
||||
id: MutationPoint
|
||||
icons:
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point0
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point1
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point2
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point3
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point4
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point5
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point6
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point7
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point8
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point9
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point10
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point11
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point12
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point13
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point14
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point15
|
||||
- sprite: /Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi
|
||||
state: flesh_point16
|
||||
name: flesh-cultist-hunger-name
|
||||
description: flesh-cultist-hunger-desc
|
||||
minSeverity: 0
|
||||
maxSeverity: 16
|
||||
19
Resources/Prototypes/_Sunrise/FleshCult/antag.yml
Normal file
19
Resources/Prototypes/_Sunrise/FleshCult/antag.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
- type: antag
|
||||
id: FleshCultist
|
||||
name: roles-antag-flesh-cultist-name
|
||||
antagonist: true
|
||||
setPreference: true
|
||||
objective: roles-antag-flesh-cultist-objective
|
||||
requirements:
|
||||
- !type:OverallPlaytimeRequirement
|
||||
time: 86400 # 24h # Sunrise-Roletime
|
||||
|
||||
- type: antag
|
||||
id: FleshCultistLeader
|
||||
name: roles-antag-flesh-cultist-leader-name
|
||||
antagonist: true
|
||||
setPreference: true
|
||||
objective: roles-antag-flesh-cultist-leader-objective
|
||||
requirements:
|
||||
- !type:OverallPlaytimeRequirement
|
||||
time: 86400 # 24h # Sunrise-Roletime
|
||||
113
Resources/Prototypes/_Sunrise/FleshCult/body_mods.yml
Normal file
113
Resources/Prototypes/_Sunrise/FleshCult/body_mods.yml
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
parent: ClothingShoesBase
|
||||
id: ClothingFleshSpiderLegs
|
||||
name: Flesh Spider Legs
|
||||
description: "Flesh Spider Legs."
|
||||
suffix: Flesh Cult
|
||||
components:
|
||||
- type: ClothingSpeedModifier
|
||||
walkModifier: 1.1
|
||||
sprintModifier: 1.15
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi
|
||||
- type: Clothing
|
||||
sprite: _Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: NoSlip
|
||||
- type: FootstepModifier
|
||||
footstepSoundCollection:
|
||||
collection: FootstepSpiderLegs
|
||||
params:
|
||||
volume: 10
|
||||
- type: HideLayerClothing
|
||||
slots:
|
||||
- RFoot
|
||||
- LFoot
|
||||
- RLeg
|
||||
- LLeg
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
parent: ClothingOuterBaseLarge
|
||||
id: ClothingOuterArmorFlesh
|
||||
name: flesh armor
|
||||
description: flesh armor
|
||||
suffix: Flesh Cult
|
||||
components:
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi
|
||||
- type: Clothing
|
||||
sprite: _Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi
|
||||
- type: Armor
|
||||
modifiers:
|
||||
coefficients:
|
||||
Blunt: 0.5
|
||||
Slash: 0.5
|
||||
Piercing: 0.2
|
||||
Heat: 0.8
|
||||
- type: ExplosionResistance
|
||||
damageCoefficient: 0.9
|
||||
- type: GroupExamine
|
||||
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
parent: ClothingOuterHardsuitBase
|
||||
id: ClothingOuterHeavyArmorFlesh
|
||||
name: heavy flesh armor
|
||||
description: heavy flesh armor
|
||||
suffix: Flesh Cult
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi
|
||||
- type: Clothing
|
||||
sprite: _Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi
|
||||
- type: PressureProtection
|
||||
highPressureMultiplier: 0.2
|
||||
lowPressureMultiplier: 1000
|
||||
- type: ExplosionResistance
|
||||
damageCoefficient: 0.5
|
||||
- type: Armor
|
||||
modifiers:
|
||||
coefficients:
|
||||
Blunt: 0.6
|
||||
Slash: 0.6
|
||||
Piercing: 0.3
|
||||
Heat: 0.9
|
||||
- type: ClothingSpeedModifier
|
||||
walkModifier: 0.8
|
||||
sprintModifier: 0.8
|
||||
- type: Tag
|
||||
tags:
|
||||
- FullBodyOuter
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: ToggleableClothing
|
||||
clothingPrototype: ClothingHeadHelmetHeavyArmorFlesh
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: ClothingHeadHardsuitBase
|
||||
id: ClothingHeadHelmetHeavyArmorFlesh
|
||||
categories: [ HideSpawnMenu ]
|
||||
name: heavy flesh helmet
|
||||
description: heavy flesh helmet
|
||||
suffix: Flesh Cult
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi
|
||||
- type: Clothing
|
||||
sprite: _Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi
|
||||
- type: PressureProtection
|
||||
highPressureMultiplier: 0.3
|
||||
lowPressureMultiplier: 1000
|
||||
- type: Armor
|
||||
modifiers:
|
||||
coefficients:
|
||||
Blunt: 0.95
|
||||
Slash: 0.95
|
||||
Piercing: 0.95
|
||||
11
Resources/Prototypes/_Sunrise/FleshCult/events.yml
Normal file
11
Resources/Prototypes/_Sunrise/FleshCult/events.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
- type: entity
|
||||
id: VentFleshWorms
|
||||
parent: BaseGameRule
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: StationEvent
|
||||
earliestStart: 15
|
||||
minimumPlayers: 20
|
||||
weight: 5
|
||||
duration: 60
|
||||
- type: VentFleshWormsRule
|
||||
14
Resources/Prototypes/_Sunrise/FleshCult/explosion.yml
Normal file
14
Resources/Prototypes/_Sunrise/FleshCult/explosion.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
- type: explosion
|
||||
id: Flesh
|
||||
damagePerIntensity:
|
||||
types:
|
||||
Heat: 5
|
||||
Poison: 3
|
||||
tileBreakChance: [0, 0.25, 0.5]
|
||||
tileBreakIntensity: [0, 5, 15]
|
||||
tileBreakRerollReduction: 20
|
||||
lightColor: Red
|
||||
fireColor: Red
|
||||
texturePath: /Textures/Effects/fire.rsi
|
||||
fireStates: 3
|
||||
sound: /Audio/Effects/Fluids/splat.ogg
|
||||
66
Resources/Prototypes/_Sunrise/FleshCult/flesh_heart.yml
Normal file
66
Resources/Prototypes/_Sunrise/FleshCult/flesh_heart.yml
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
- type: entity
|
||||
id: FleshHeart
|
||||
parent: BaseStructure
|
||||
name: Flesh Heart
|
||||
description: Flesh Heart
|
||||
placement:
|
||||
mode: AlignTileAny
|
||||
components:
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
bodyContainer: !type:Container
|
||||
- type: Appearance
|
||||
- type: SpriteFade
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
drawdepth: Mobs
|
||||
sprite: _Sunrise/FleshCult/flesh_heart.rsi
|
||||
layers:
|
||||
- state: base_heart
|
||||
map: ["enum.FleshHeartLayers.Base"]
|
||||
- type: Transform
|
||||
anchored: true
|
||||
- type: Physics
|
||||
bodyType: Static
|
||||
- type: Climbable
|
||||
delay: 5
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeAabb
|
||||
bounds: "-1.5,-1.4,1.5,0.3"
|
||||
density: 50
|
||||
mask:
|
||||
- MachineMask
|
||||
layer:
|
||||
- MachineLayer
|
||||
- type: Damageable
|
||||
damageContainer: Biological
|
||||
damageModifierSet: FleshHeart
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 1000
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: [ "Destruction" ]
|
||||
- type: PointLight
|
||||
radius: 10
|
||||
energy: 1
|
||||
castShadows: true
|
||||
color: "#87031f"
|
||||
- type: FleshHeart
|
||||
finalState: "final_heart"
|
||||
fleshTileId: Flesh
|
||||
damageMobsIfHeartDestruct:
|
||||
types:
|
||||
Slash: 700
|
||||
spawns:
|
||||
MobFleshSpider: 0.20
|
||||
MobFleshPudge: 0.20
|
||||
MobFleshBall: 0.30
|
||||
MobFleshBat: 0.30
|
||||
spawnMobsAmount: 3
|
||||
spawnMobsFrequency: 180
|
||||
65
Resources/Prototypes/_Sunrise/FleshCult/flesh_tile.yml
Normal file
65
Resources/Prototypes/_Sunrise/FleshCult/flesh_tile.yml
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
- type: entity
|
||||
id: Flesh
|
||||
name: flesh
|
||||
description: A rapidly growing, dangerous plant. WHY ARE YOU STOPPING TO LOOK AT IT?!
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
snap:
|
||||
- Wall
|
||||
components:
|
||||
- type: Tag
|
||||
tags:
|
||||
- Flesh
|
||||
- type: MeleeSound
|
||||
soundGroups:
|
||||
Brute:
|
||||
path:
|
||||
"/Audio/Weapons/slash.ogg"
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/flesh_tile.rsi
|
||||
state: flesh_11
|
||||
drawdepth: LowFloors
|
||||
netsync: false
|
||||
- type: Appearance
|
||||
- type: Clickable
|
||||
- type: Transform
|
||||
anchored: true
|
||||
- type: Physics
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
hard: false
|
||||
density: 7
|
||||
shape:
|
||||
!type:PhysShapeAabb
|
||||
bounds: "-0.5,-0.5,0.5,0.5"
|
||||
layer:
|
||||
- MidImpassable
|
||||
- type: Damageable
|
||||
damageModifierSet: Wood
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 10
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: [ "Destruction" ]
|
||||
- type: Temperature
|
||||
heatDamage:
|
||||
types:
|
||||
Heat: 5
|
||||
coldDamage: {}
|
||||
- type: Flammable
|
||||
fireSpread: true
|
||||
damage:
|
||||
types:
|
||||
Heat: 5
|
||||
- type: Reactive
|
||||
groups:
|
||||
Flammable: [Touch]
|
||||
Extinguish: [Touch]
|
||||
- type: FireVisuals
|
||||
sprite: Effects/fire.rsi
|
||||
normalState: 1
|
||||
- type: AtmosExposed
|
||||
45
Resources/Prototypes/_Sunrise/FleshCult/flesh_walls.yml
Normal file
45
Resources/Prototypes/_Sunrise/FleshCult/flesh_walls.yml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
- type: entity
|
||||
parent: BaseWall
|
||||
id: WallFlesh
|
||||
name: flesh wall
|
||||
components:
|
||||
- type: Appearance
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/flesh_wall.rsi
|
||||
- type: Icon
|
||||
sprite: _Sunrise/FleshCult/flesh_wall.rsi
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 10
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: ["Destruction"]
|
||||
- type: Damageable
|
||||
damageModifierSet: Wood
|
||||
- type: IconSmooth
|
||||
key: walls
|
||||
base: flesh
|
||||
- type: Tag
|
||||
tags:
|
||||
- Flesh
|
||||
- Wall
|
||||
- Window
|
||||
- type: Temperature
|
||||
heatDamage:
|
||||
types:
|
||||
Heat: 5
|
||||
coldDamage: {}
|
||||
- type: Flammable
|
||||
fireSpread: true
|
||||
damage:
|
||||
types:
|
||||
Heat: 1
|
||||
- type: Reactive
|
||||
groups:
|
||||
Flammable: [Touch]
|
||||
Extinguish: [Touch]
|
||||
- type: FireVisuals
|
||||
sprite: Effects/fire.rsi
|
||||
normalState: 1
|
||||
14
Resources/Prototypes/_Sunrise/FleshCult/game_preset.yml
Normal file
14
Resources/Prototypes/_Sunrise/FleshCult/game_preset.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
- type: gamePreset
|
||||
id: FleshCult
|
||||
alias:
|
||||
- fleshcult
|
||||
- fs
|
||||
name: flesh-cult-title
|
||||
description: flesh-cult-description
|
||||
showInVote: true
|
||||
hide: true
|
||||
rules:
|
||||
- FleshCult
|
||||
- LiteSubGamemodesRule
|
||||
- BasicStationEventScheduler
|
||||
- BasicRoundstartVariation
|
||||
137
Resources/Prototypes/_Sunrise/FleshCult/hands_mods.yml
Normal file
137
Resources/Prototypes/_Sunrise/FleshCult/hands_mods.yml
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
name: Flesh Claw
|
||||
parent: BaseItem
|
||||
id: FleshClaw
|
||||
description: Flesh Claw
|
||||
suffix: Flesh Cult
|
||||
components:
|
||||
- type: FleshHandMod
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi
|
||||
state: icon
|
||||
netsync: false
|
||||
- type: Item
|
||||
size: Huge
|
||||
- type: ToolTileCompatible
|
||||
- type: Tool
|
||||
qualities:
|
||||
- Prying
|
||||
useSound: /Audio/Effects/gib2.ogg
|
||||
- type: Prying
|
||||
speedModifier: 2.5
|
||||
pryPowered: true
|
||||
force: true
|
||||
- type: MeleeWeapon
|
||||
damage:
|
||||
types:
|
||||
Slash: 13
|
||||
- type: MultipleTool
|
||||
statusShowBehavior: true
|
||||
entries:
|
||||
- behavior: Prying
|
||||
sprite:
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi
|
||||
state: icon
|
||||
useSound: /Audio/Effects/gib2.ogg
|
||||
changeSound: /Audio/Effects/gib3.ogg
|
||||
- behavior: Cutting
|
||||
sprite:
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi
|
||||
state: icon
|
||||
useSound: /Audio/Effects/gib2.ogg
|
||||
changeSound: /Audio/Effects/gib3.ogg
|
||||
- behavior: Anchoring
|
||||
sprite:
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi
|
||||
state: icon
|
||||
useSound: /Audio/Effects/gib2.ogg
|
||||
changeSound: /Audio/Effects/gib3.ogg
|
||||
- behavior: Screwing
|
||||
sprite:
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi
|
||||
state: icon
|
||||
useSound: /Audio/Effects/gib2.ogg
|
||||
changeSound: /Audio/Effects/gib3.ogg
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
name: flesh fist
|
||||
parent: BaseItem
|
||||
id: FleshFist
|
||||
description: Fisting is three hundred bucks
|
||||
suffix: Flesh Cult
|
||||
components:
|
||||
- type: FleshHandMod
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi
|
||||
state: icon
|
||||
- type: MeleeWeapon
|
||||
attackRate: 0.75
|
||||
damage:
|
||||
types:
|
||||
Blunt: 20
|
||||
Structural: 300
|
||||
- type: Item
|
||||
size: Ginormous
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
name: Flesh blade
|
||||
parent: BaseItem
|
||||
id: FleshBlade
|
||||
description: Flesh blade
|
||||
suffix: Flesh Cult
|
||||
components:
|
||||
- type: FleshHandMod
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: Sharp
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi
|
||||
state: icon
|
||||
- type: MeleeWeapon
|
||||
damage:
|
||||
types:
|
||||
Slash: 25
|
||||
- type: Item
|
||||
size: Huge
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi
|
||||
- type: DisarmMalus
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
name: spike gun
|
||||
id: FleshSpikeHandGun
|
||||
parent: BaseItem
|
||||
suffix: Flesh Cult
|
||||
components:
|
||||
- type: FleshHandMod
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi
|
||||
state: icon
|
||||
- type: Item
|
||||
sprite: _Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi
|
||||
size: Ginormous
|
||||
- type: Gun
|
||||
fireRate: 3
|
||||
selectedMode: SemiAuto
|
||||
availableModes:
|
||||
- SemiAuto
|
||||
soundGunshot:
|
||||
path: /Audio/_Sunrise/FleshCult/spike_gun_shot.ogg
|
||||
- type: AmmoCounter
|
||||
- type: Appearance
|
||||
- type: RechargeBasicEntityAmmo
|
||||
rechargeCooldown: 2
|
||||
rechargeSound: /Audio/_Sunrise/FleshCult/spike_gun_reload.ogg
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: BasicEntityAmmoProvider
|
||||
proto: BulletSpike
|
||||
capacity: 10
|
||||
count: 5
|
||||
21
Resources/Prototypes/_Sunrise/FleshCult/mind_roles.yml
Normal file
21
Resources/Prototypes/_Sunrise/FleshCult/mind_roles.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
- type: entity
|
||||
parent: BaseMindRoleAntag
|
||||
id: MindRoleFleshCultist
|
||||
name: Flesh Cultist Role
|
||||
# description: mind-role-flesh-cultist-description
|
||||
components:
|
||||
- type: MindRole
|
||||
antagPrototype: FleshCultist
|
||||
exclusiveAntag: true
|
||||
- type: FleshCultistRole
|
||||
|
||||
- type: entity
|
||||
parent: BaseMindRoleAntag
|
||||
id: MindRoleFleshCultistLeader
|
||||
name: Flesh Leader Cultist Role
|
||||
# description: mind-role-flesh-leader-cultist-description
|
||||
components:
|
||||
- type: MindRole
|
||||
antagPrototype: FleshCultistLeader
|
||||
exclusiveAntag: true
|
||||
- type: FleshCultistRole
|
||||
591
Resources/Prototypes/_Sunrise/FleshCult/mobs.yml
Normal file
591
Resources/Prototypes/_Sunrise/FleshCult/mobs.yml
Normal file
|
|
@ -0,0 +1,591 @@
|
|||
- type: entity
|
||||
parent: SimpleSpaceMobBase
|
||||
id: BaseMobFleshCult
|
||||
name: flesh mob
|
||||
description: A shambling mass of flesh, animated through anomalous energy.
|
||||
abstract: true
|
||||
components:
|
||||
- type: Reactive
|
||||
groups:
|
||||
Flammable: [Touch]
|
||||
Extinguish: [Touch]
|
||||
- type: Damageable
|
||||
damageContainer: Biological
|
||||
damageModifierSet: FleshMob
|
||||
- type: HTN
|
||||
rootTask:
|
||||
task: SimpleHostileCompound
|
||||
- type: NpcFactionMember
|
||||
factions:
|
||||
- Flesh
|
||||
- type: Tag
|
||||
tags:
|
||||
- DoorBumpOpener
|
||||
- Flesh
|
||||
- CannotSuicide
|
||||
- FootstepSound
|
||||
- type: Sprite
|
||||
drawdepth: Mobs
|
||||
sprite: _Sunrise/FleshCult/flesh_cult_mobs.rsi
|
||||
- type: MovementAlwaysTouching
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 2
|
||||
baseSprintSpeed: 3
|
||||
- type: MobState
|
||||
allowedStates:
|
||||
- Alive
|
||||
- Dead
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
75: Dead
|
||||
- type: Appearance
|
||||
- type: Butcherable
|
||||
spawned:
|
||||
- id: FoodMeat
|
||||
amount: 1
|
||||
- type: CombatMode
|
||||
- type: MeleeWeapon
|
||||
hidden: true
|
||||
soundHit:
|
||||
path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg
|
||||
angle: 0
|
||||
animation: WeaponArcClaw
|
||||
damage:
|
||||
types:
|
||||
Slash: 3
|
||||
- type: ReplacementAccent
|
||||
accent: genericAggressive
|
||||
- type: CollectiveMind
|
||||
minds:
|
||||
- FleshCult
|
||||
- type: IgnoreFleshSpiderWeb
|
||||
|
||||
- type: entity
|
||||
parent: BaseMobFleshCult
|
||||
id: MobFleshSpider
|
||||
components:
|
||||
# - type: VentCrawler
|
||||
- type: HTN
|
||||
rootTask:
|
||||
task: XenoCompound
|
||||
blackboard:
|
||||
NavInteract: !type:Bool
|
||||
true
|
||||
NavPry: !type:Bool
|
||||
false
|
||||
NavSmash: !type:Bool
|
||||
true
|
||||
- type: Butcherable
|
||||
spawned:
|
||||
- id: FoodMeat
|
||||
amount: 2
|
||||
- type: FleshMob
|
||||
soundDeath: /Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg
|
||||
deathMobSpawnId: MobFleshWorm
|
||||
deathMobSpawnCount: 2
|
||||
- type: Sprite
|
||||
layers:
|
||||
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
state: spider
|
||||
- type: Vocal
|
||||
sounds:
|
||||
Unsexed: FleshWormEmote
|
||||
- type: DamageStateVisuals
|
||||
states:
|
||||
Alive:
|
||||
Base: spider
|
||||
Dead:
|
||||
Base: spider_dead
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
125: Dead
|
||||
- type: Bloodstream
|
||||
bloodMaxVolume: 300
|
||||
bloodReagent: Blood
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 3
|
||||
baseSprintSpeed: 4.5
|
||||
- type: GhostRole
|
||||
allowMovement: true
|
||||
allowSpeech: true
|
||||
makeSentient: true
|
||||
name: mob-flesh-spider-ghost-role-name
|
||||
description: mob-flesh-spider-ghost-role-name
|
||||
rules: Не атакуйте культистов плоти, не ломайте ДАМы, сервера, консоли и прочее. Не делайте разгерметизацию.
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: MeleeWeapon
|
||||
hidden: true
|
||||
soundHit:
|
||||
path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg
|
||||
angle: 0
|
||||
animation: WeaponArcClaw
|
||||
damage:
|
||||
types:
|
||||
Piercing: 5
|
||||
Poison: 3
|
||||
- type: Spider
|
||||
webPrototype: FleshSpiderWeb
|
||||
webAction: FleshSpiderWebAction
|
||||
- type: Puller
|
||||
needsHands: false
|
||||
- type: FootstepModifier
|
||||
footstepSoundCollection:
|
||||
collection: FootstepSpiderLegs
|
||||
params:
|
||||
volume: 10
|
||||
|
||||
- type: entity
|
||||
parent: BaseMobFleshCult
|
||||
id: MobFleshPudge
|
||||
components:
|
||||
- type: Tool
|
||||
qualities:
|
||||
- Prying
|
||||
- type: HTN
|
||||
rootTask:
|
||||
task: XenoCompound
|
||||
blackboard:
|
||||
NavInteract: !type:Bool
|
||||
true
|
||||
NavPry: !type:Bool
|
||||
true
|
||||
NavSmash: !type:Bool
|
||||
true
|
||||
- type: Prying
|
||||
pryPowered: true
|
||||
force: true
|
||||
speedModifier: 1.5
|
||||
useSound:
|
||||
path: /Audio/Items/crowbar.ogg
|
||||
- type: Butcherable
|
||||
spawned:
|
||||
- id: FoodMeat
|
||||
amount: 5
|
||||
- type: FleshPudge
|
||||
bloodAbsorbSound:
|
||||
path: /Audio/Effects/Fluids/splat.ogg
|
||||
healBloodAbsorbReagents:
|
||||
reagents:
|
||||
- data: null
|
||||
ReagentId: Carol
|
||||
Quantity: 1
|
||||
bulletAcidSpawnId: BulletSplashAcid
|
||||
faceHuggerMobSpawnId: MobFleshHugger
|
||||
soundThrowWorm: !type:SoundPathSpecifier
|
||||
path: /Audio/_Sunrise/FleshCult/throw_worm.ogg
|
||||
actionAbsorbBloodPool: AbsorbBloodPool
|
||||
actionAcidSpit: FleshAcidSpit
|
||||
actionThrowWorm: FleshThrowWorm
|
||||
- type: Vocal
|
||||
sounds:
|
||||
Unsexed: FleshPudgeEmote
|
||||
- type: FleshMob
|
||||
deathMobSpawnCount: 3
|
||||
deathMobSpawnId: MobFleshWorm
|
||||
soundDeath:
|
||||
path: /Audio/_Sunrise/FleshCult/flesh_pudge_dead.ogg
|
||||
- type: Sprite
|
||||
drawdepth: Mobs
|
||||
sprite: _Sunrise/FleshCult/flesh_cult_pudge.rsi
|
||||
layers:
|
||||
- map: ["enum.DamageStateVisualLayers.Base"]
|
||||
state: alive
|
||||
- type: DamageStateVisuals
|
||||
states:
|
||||
Alive:
|
||||
Base: alive
|
||||
Dead:
|
||||
Base: dead
|
||||
- type: Bloodstream
|
||||
bloodMaxVolume: 500
|
||||
bloodReagent: Blood
|
||||
- type: InputMover
|
||||
- type: MobMover
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 3.5
|
||||
baseSprintSpeed: 4.5
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
250: Dead
|
||||
- type: MobState
|
||||
allowedStates:
|
||||
- Alive
|
||||
- Dead
|
||||
- type: MeleeWeapon
|
||||
altDisarm: false
|
||||
hidden: true
|
||||
soundHit:
|
||||
path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg
|
||||
animation: WeaponArcSmash
|
||||
damage:
|
||||
types:
|
||||
Slash: 10
|
||||
Blunt: 20
|
||||
Structural: 300
|
||||
- type: GhostRole
|
||||
allowMovement: true
|
||||
allowSpeech: true
|
||||
makeSentient: true
|
||||
name: mob-flesh-pudge-ghost-role-name
|
||||
description: mob-flesh-pudge-ghost-role-name
|
||||
rules: Не атакуйте культистов плоти, не ломайте ДАМы, сервера, консоли и прочее. Не делайте разгерметизацию.
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.40
|
||||
density: 800
|
||||
mask:
|
||||
- MobMask
|
||||
layer:
|
||||
- MobLayer
|
||||
- type: Puller
|
||||
needsHands: false
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: BaseMobFleshCult
|
||||
id: MobFleshBall
|
||||
components:
|
||||
- type: FleshMob
|
||||
soundDeath: "/Audio/_Sunrise/FleshCult/flesh_pudge_dead.ogg"
|
||||
deathMobSpawnId: "MobFleshWorm"
|
||||
deathMobSpawnCount: 0
|
||||
- type: Sprite
|
||||
layers:
|
||||
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
state: ball
|
||||
- type: MeleeWeapon
|
||||
hidden: true
|
||||
soundHit:
|
||||
path: /Audio/Effects/bite.ogg
|
||||
angle: 0
|
||||
animation: WeaponArcSmash
|
||||
damage:
|
||||
types:
|
||||
Piercing: 3
|
||||
- type: DamageStateVisuals
|
||||
states:
|
||||
Alive:
|
||||
Base: ball
|
||||
Dead:
|
||||
Base: ball_dead
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.25
|
||||
density: 10
|
||||
mask:
|
||||
- FlyingMobMask
|
||||
layer:
|
||||
- FlyingMobLayer
|
||||
- type: GhostRole
|
||||
allowMovement: true
|
||||
allowSpeech: true
|
||||
makeSentient: true
|
||||
name: mob-flesh-ball-ghost-role-name
|
||||
description: mob-flesh-ball-ghost-role-name
|
||||
rules: Не атакуйте культистов плоти, не ломайте ДАМы, сервера, консоли и прочее. Не делайте разгерметизацию.
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
25: Dead
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 5
|
||||
baseSprintSpeed: 6
|
||||
- type: TriggerOnMobstateChange
|
||||
mobState:
|
||||
- Dead
|
||||
- type: TriggerImplantAction
|
||||
- type: ExplodeOnTrigger
|
||||
- type: Explosive
|
||||
explosionType: Flesh
|
||||
totalIntensity: 50
|
||||
intensitySlope: 3
|
||||
maxIntensity: 100
|
||||
canCreateVacuum: false
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: BaseMobFleshCult
|
||||
id: MobFleshBat
|
||||
components:
|
||||
- type: HTN
|
||||
rootTask:
|
||||
task: XenoCompound
|
||||
blackboard:
|
||||
NavInteract: !type:Bool
|
||||
true
|
||||
NavPry: !type:Bool
|
||||
false
|
||||
NavSmash: !type:Bool
|
||||
true
|
||||
- type: FleshMob
|
||||
soundDeath: "/Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg"
|
||||
deathMobSpawnId: "MobFleshWorm"
|
||||
deathMobSpawnCount: 0
|
||||
- type: Sprite
|
||||
layers:
|
||||
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
state: bat
|
||||
- type: DamageStateVisuals
|
||||
states:
|
||||
Alive:
|
||||
Base: bat
|
||||
Dead:
|
||||
Base: bat_dead
|
||||
- type: Bloodstream
|
||||
bloodMaxVolume: 50
|
||||
bloodReagent: Blood
|
||||
- type: Vocal
|
||||
sounds:
|
||||
Unsexed: FleshWormEmote
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.25
|
||||
density: 10
|
||||
mask:
|
||||
- FlyingMobMask
|
||||
layer:
|
||||
- FlyingMobLayer
|
||||
- type: GhostRole
|
||||
allowMovement: true
|
||||
allowSpeech: true
|
||||
makeSentient: true
|
||||
name: mob-flesh-bat-ghost-role-name
|
||||
description: mob-flesh-bat-ghost-role-name
|
||||
rules: Не атакуйте культистов плоти, не ломайте ДАМы, сервера, консоли и прочее. Не делайте разгерметизацию.
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: MeleeWeapon
|
||||
hidden: true
|
||||
soundHit:
|
||||
path: /Audio/Effects/bite.ogg
|
||||
angle: 0
|
||||
animation: WeaponArcBite
|
||||
damage:
|
||||
types:
|
||||
Piercing: 5
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
75: Dead
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 5
|
||||
baseSprintSpeed: 6
|
||||
- type: Puller
|
||||
needsHands: false
|
||||
|
||||
- type: entity
|
||||
parent: BaseMobFleshCult
|
||||
id: MobFleshHugger
|
||||
components:
|
||||
# - type: VentCrawler
|
||||
- type: FleshMob
|
||||
soundDeath: "/Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg"
|
||||
deathMobSpawnId: "MobFleshWorm"
|
||||
deathMobSpawnCount: 1
|
||||
- type: FleshHugger
|
||||
paralyzeTime: 5
|
||||
chansePounce: 33
|
||||
damage:
|
||||
types:
|
||||
Piercing: 2
|
||||
actionJump: FleshHuggerJump
|
||||
actionGetOff: FleshHuggerGetOff
|
||||
- type: Sprite
|
||||
drawdepth: SmallMobs
|
||||
noRot: true
|
||||
layers:
|
||||
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
state: fleshhugger
|
||||
- type: DamageStateVisuals
|
||||
states:
|
||||
Alive:
|
||||
Base: fleshhugger
|
||||
Dead:
|
||||
Base: fleshhugger_dead
|
||||
- type: Vocal
|
||||
sounds:
|
||||
Unsexed: FleshWormEmote
|
||||
- type: Clothing
|
||||
quickEquip: false
|
||||
sprite: _Sunrise/FleshCult/flesh_cult_mobs.rsi
|
||||
equippedPrefix: fleshhugger
|
||||
slots:
|
||||
- MASK
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.2
|
||||
density: 100
|
||||
mask:
|
||||
- SmallMobMask
|
||||
layer:
|
||||
- SmallMobLayer
|
||||
- type: Speech
|
||||
- type: Bloodstream
|
||||
bloodMaxVolume: 10
|
||||
bloodReagent: Blood
|
||||
- type: GhostRole
|
||||
allowMovement: true
|
||||
allowSpeech: true
|
||||
makeSentient: true
|
||||
name: mob-flesh-hugger-ghost-role-name
|
||||
description: mob-flesh-hugger-ghost-role-name
|
||||
rules: Не атакуйте культистов плоти, не ломайте ДАМы, сервера, стены и окна если за ними нету людей, консоли и прочее.
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: MeleeWeapon
|
||||
hidden: true
|
||||
soundHit:
|
||||
path: /Audio/Effects/bite.ogg
|
||||
angle: 0
|
||||
animation: WeaponArcBite
|
||||
damage:
|
||||
types:
|
||||
Piercing: 2
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
25: Dead
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 3.5
|
||||
baseSprintSpeed: 4.5
|
||||
- type: Tag
|
||||
tags:
|
||||
- Flesh
|
||||
- CannotSuicide
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: BaseMobFleshCult
|
||||
id: MobFleshWorm
|
||||
components:
|
||||
- type: FleshMob
|
||||
soundDeath: /Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg
|
||||
deathMobSpawnId: MobSmallFleshWorm
|
||||
deathMobSpawnCount: 2
|
||||
- type: Sprite
|
||||
drawdepth: SmallMobs
|
||||
noRot: true
|
||||
layers:
|
||||
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
state: worm
|
||||
- type: DamageStateVisuals
|
||||
states:
|
||||
Alive:
|
||||
Base: worm
|
||||
Dead:
|
||||
Base: worm_dead
|
||||
- type: Vocal
|
||||
sounds:
|
||||
Unsexed: FleshWormEmote
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.2
|
||||
density: 25
|
||||
mask:
|
||||
- SmallMobMask
|
||||
layer:
|
||||
- SmallMobLayer
|
||||
- type: Speech
|
||||
- type: Bloodstream
|
||||
bloodMaxVolume: 10
|
||||
bloodReagent: Blood
|
||||
- type: MeleeWeapon
|
||||
hidden: true
|
||||
soundHit:
|
||||
path: /Audio/Effects/bite.ogg
|
||||
angle: 0
|
||||
animation: WeaponArcBite
|
||||
damage:
|
||||
types:
|
||||
Piercing: 1
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
15: Dead
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 4
|
||||
baseSprintSpeed: 5
|
||||
- type: Tag
|
||||
tags:
|
||||
- Flesh
|
||||
- CannotSuicide
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 25
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: [ "Destruction" ]
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: MobFleshWorm
|
||||
id: MobSmallFleshWorm
|
||||
components:
|
||||
- type: FleshMob
|
||||
soundDeath: /Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg
|
||||
deathMobSpawnId: MobSmallFleshWorm
|
||||
deathMobSpawnCount: 0
|
||||
- type: Sprite
|
||||
drawdepth: SmallMobs
|
||||
noRot: true
|
||||
layers:
|
||||
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
state: small_worm
|
||||
- type: DamageStateVisuals
|
||||
states:
|
||||
Alive:
|
||||
Base: small_worm
|
||||
Dead:
|
||||
Base: small_worm_dead
|
||||
- type: MobThresholds
|
||||
thresholds:
|
||||
0: Alive
|
||||
5: Dead
|
||||
- type: MeleeWeapon
|
||||
hidden: true
|
||||
soundHit:
|
||||
path: /Audio/Effects/bite.ogg
|
||||
angle: 0
|
||||
animation: WeaponArcBite
|
||||
damage:
|
||||
types:
|
||||
Piercing: 0.5
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 15
|
||||
behaviors:
|
||||
- !type:SpawnEntitiesBehavior
|
||||
spawn:
|
||||
FoodMeat:
|
||||
min: 1
|
||||
max: 1
|
||||
- !type:DoActsBehavior
|
||||
acts: [ "Destruction" ]
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
- type: damageModifierSet
|
||||
id: FleshMob
|
||||
coefficients:
|
||||
Heat: 1.50
|
||||
|
||||
- type: damageModifierSet
|
||||
id: FleshHeart
|
||||
coefficients:
|
||||
Heat: 2.00
|
||||
38
Resources/Prototypes/_Sunrise/FleshCult/objectives.yml
Normal file
38
Resources/Prototypes/_Sunrise/FleshCult/objectives.yml
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
- type: entity
|
||||
abstract: true
|
||||
parent: BaseObjective
|
||||
id: BaseFleshCultObjective
|
||||
components:
|
||||
- type: Objective
|
||||
difficulty: 1.5
|
||||
issuer: flesh-cult
|
||||
- type: RoleRequirement
|
||||
roles:
|
||||
components:
|
||||
- FleshCultistRole
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
parent: BaseFleshCultObjective
|
||||
id: CreateFleshHeartObjective
|
||||
name: Создать и пробудить сердце плоти.
|
||||
description: Вам необходимо развить необходимый навык для создания сердца.
|
||||
Для пробуждения оно должно поглотить нужное количество тел развитых существ.
|
||||
После пробуждения будьте готовы его защищать, ведь оно начнет превращать всю станцию в плоть.
|
||||
components:
|
||||
- type: Objective
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistFleshHeart.png
|
||||
- type: NumberObjective
|
||||
min: 1
|
||||
max: 1
|
||||
- type: CreateFleshHeartCondition
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu ]
|
||||
parent: [BaseFleshCultObjective, BaseSurviveObjective]
|
||||
id: FleshCultSurviveObjective
|
||||
name: Выжить и сохранить человеческий облик.
|
||||
description: Не допустите голодания паразита, чтобы избежать непредвиденных обстоятельств.
|
||||
components:
|
||||
- type: Objective
|
||||
icon: _Sunrise/FleshCult/Interface/Actions/fleshCultistSurvivalObjective.png
|
||||
40
Resources/Prototypes/_Sunrise/FleshCult/projectiles.yml
Normal file
40
Resources/Prototypes/_Sunrise/FleshCult/projectiles.yml
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
- type: entity
|
||||
id: BulletSplashAcid
|
||||
name: flesh acid spit
|
||||
parent: BaseBulletTrigger
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/flesh_toxic.rsi
|
||||
layers:
|
||||
- state: flesh_toxic
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Caustic: 1
|
||||
- type: SplashOnTrigger
|
||||
splashReagents:
|
||||
reagents:
|
||||
- ReagentId: FleshAcid
|
||||
Quantity: 30
|
||||
|
||||
- type: entity
|
||||
id: BulletSpike
|
||||
name: spike
|
||||
parent: BaseBullet
|
||||
categories: [ HideSpawnMenu ]
|
||||
description:
|
||||
components:
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
noRot: false
|
||||
sprite: _Sunrise/FleshCult/flesh_projectiles.rsi
|
||||
layers:
|
||||
- state: spike
|
||||
shader: unshaded
|
||||
- type: Projectile
|
||||
impactEffect: BulletImpactEffectKinetic
|
||||
damage:
|
||||
types:
|
||||
Piercing: 13
|
||||
|
||||
48
Resources/Prototypes/_Sunrise/FleshCult/roundstart.yml
Normal file
48
Resources/Prototypes/_Sunrise/FleshCult/roundstart.yml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
- type: entity
|
||||
id: FleshCult
|
||||
parent: BaseGameRule
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: GameRule
|
||||
minPlayers: 20
|
||||
- type: FleshCultRule
|
||||
faction: Flesh
|
||||
- type: AntagObjectives
|
||||
objectives:
|
||||
- CreateFleshHeartObjective
|
||||
- FleshCultSurviveObjective
|
||||
- type: AntagSelection
|
||||
agentName: flesh-cult-round-end-agent-name
|
||||
definitions:
|
||||
- prefRoles: [ FleshCultistLeader ]
|
||||
fallbackRoles: [ FleshCultist ]
|
||||
max: 1
|
||||
startingGear: FleshCultistLeaderGear
|
||||
components:
|
||||
- type: FleshCultist
|
||||
- type: NpcFactionMember
|
||||
factions:
|
||||
- FleshHuman
|
||||
blacklist:
|
||||
components:
|
||||
- AntagImmune
|
||||
- Synth
|
||||
- BibleUser
|
||||
mindRoles:
|
||||
- MindRoleFleshCultistLeader
|
||||
- prefRoles: [ FleshCultist ]
|
||||
fallbackRoles: [ FleshCultistLeader ]
|
||||
max: 3
|
||||
playerRatio: 15
|
||||
components:
|
||||
- type: FleshCultist
|
||||
- type: NpcFactionMember
|
||||
factions:
|
||||
- FleshHuman
|
||||
blacklist:
|
||||
components:
|
||||
- AntagImmune
|
||||
- Synth
|
||||
- BibleUser
|
||||
mindRoles:
|
||||
- MindRoleFleshCultist
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
- type: emoteSounds
|
||||
id: FleshPudgeEmote
|
||||
sound:
|
||||
path: /Audio/_Sunrise/FleshCult/flesh_pudge_dead.ogg
|
||||
params:
|
||||
variation: 0.125
|
||||
|
||||
- type: emoteSounds
|
||||
id: FleshWormEmote
|
||||
sound:
|
||||
path: /Audio/_Sunrise/FleshCult/flesh_worm_scream.ogg
|
||||
params:
|
||||
variation: 0.125
|
||||
28
Resources/Prototypes/_Sunrise/FleshCult/spider_web.yml
Normal file
28
Resources/Prototypes/_Sunrise/FleshCult/spider_web.yml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
- type: entity
|
||||
parent: SpiderWeb
|
||||
id: FleshSpiderWeb
|
||||
name: spider web
|
||||
description: It's stringy and sticky.
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
snap:
|
||||
- Wall
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/FleshCult/fleshspiderweb.rsi
|
||||
layers:
|
||||
- state: spider_web_1
|
||||
map: [ "spiderWebLayer" ]
|
||||
drawdepth: WallMountedItems
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
enum.SpiderWebVisuals.Variant:
|
||||
spiderWebLayer:
|
||||
1: {state: spider_web_1}
|
||||
2: {state: spider_web_2}
|
||||
- type: SpeedModifierContacts
|
||||
walkSpeedModifier: 0.3
|
||||
sprintSpeedModifier: 0.3
|
||||
ignoreWhitelist:
|
||||
components:
|
||||
- IgnoreFleshSpiderWeb
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
- type: startingGear
|
||||
id: FleshCultistLeaderGear
|
||||
storage:
|
||||
back:
|
||||
- SyringeCarolNT
|
||||
- SyringeCarolNT
|
||||
- SyringeCarolNT
|
||||
11
Resources/Prototypes/_Sunrise/FleshCult/status_icon.yml
Normal file
11
Resources/Prototypes/_Sunrise/FleshCult/status_icon.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
- type: factionIcon
|
||||
id: FleshFaction
|
||||
priority: 12
|
||||
showTo:
|
||||
components:
|
||||
- ShowAntagIcons
|
||||
- FleshCultist
|
||||
- FleshMob
|
||||
icon:
|
||||
sprite: /Textures/_Sunrise/FleshCult/Interface/flesh_icon.rsi
|
||||
state: Flesh
|
||||
5
Resources/Prototypes/_Sunrise/FleshCult/tags.yml
Normal file
5
Resources/Prototypes/_Sunrise/FleshCult/tags.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
- type: Tag
|
||||
id: FullBodyOuter
|
||||
|
||||
- type: Tag
|
||||
id: Directional
|
||||
94
Resources/Prototypes/_Sunrise/FleshCult/toxins.yml
Normal file
94
Resources/Prototypes/_Sunrise/FleshCult/toxins.yml
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
- type: reagent
|
||||
id: FleshAcid
|
||||
name: reagent-name-flesh-acid
|
||||
group: Toxins
|
||||
desc: reagent-desc-flesh-acid
|
||||
physicalDesc: reagent-physical-desc-strong-smelling
|
||||
flavor: acid
|
||||
color: "#c9000e"
|
||||
boilingPoint: 0.0
|
||||
meltingPoint: 0.0
|
||||
reactiveEffects:
|
||||
Acidic:
|
||||
methods: [ Touch ]
|
||||
effects:
|
||||
- !type:HealthChange
|
||||
conditions:
|
||||
- !type:HasTag
|
||||
tag: "Flesh"
|
||||
invert: true
|
||||
scaleByQuantity: false
|
||||
ignoreResistances: true
|
||||
damage:
|
||||
types:
|
||||
Caustic: 10
|
||||
- !type:Emote
|
||||
conditions:
|
||||
- !type:HasTag
|
||||
tag: "Flesh"
|
||||
invert: true
|
||||
emote: Scream
|
||||
probability: 0.9
|
||||
- !type:PopupMessage
|
||||
conditions:
|
||||
- !type:HasTag
|
||||
tag: "Flesh"
|
||||
invert: true
|
||||
type: Local
|
||||
visualType: Large
|
||||
messages: [ "generic-reagent-effect-burning-insides" ]
|
||||
probability: 0.9
|
||||
|
||||
|
||||
- type: reagent
|
||||
id: Carol
|
||||
name: reagent-name-carol
|
||||
group: Toxins
|
||||
desc: reagent-desc-carol
|
||||
physicalDesc: reagent-physical-desc-necrotic
|
||||
flavor: bitter
|
||||
color: "#c9000e"
|
||||
metabolisms:
|
||||
Medicine:
|
||||
effects:
|
||||
- !type:CauseFleshCultInfection
|
||||
conditions:
|
||||
- !type:HasTag
|
||||
tag: "Flesh"
|
||||
invert: true
|
||||
- !type:ReagentThreshold
|
||||
min: 5
|
||||
- !type:ModifyBloodLevel
|
||||
conditions:
|
||||
- !type:HasTag
|
||||
tag: "Flesh"
|
||||
amount: 5
|
||||
- !type:SatiateThirst
|
||||
conditions:
|
||||
- !type:HasTag
|
||||
tag: "Flesh"
|
||||
factor: 2.5
|
||||
- !type:SatiateHunger
|
||||
conditions:
|
||||
- !type:HasTag
|
||||
tag: "Flesh"
|
||||
factor: 2.5
|
||||
- !type:HealthChange
|
||||
conditions:
|
||||
- !type:HasTag
|
||||
tag: "Flesh"
|
||||
damage:
|
||||
groups:
|
||||
Airloss: -4
|
||||
types:
|
||||
Heat: -1
|
||||
Shock: -2
|
||||
Cold: -2
|
||||
Poison: -2
|
||||
Piercing: -2
|
||||
Blunt: -2
|
||||
Caustic: -2
|
||||
Slash: -2
|
||||
|
||||
|
||||
|
||||
|
|
@ -116,3 +116,4 @@
|
|||
- Saboteurs
|
||||
- Furs
|
||||
- Crew
|
||||
- VirusFlesh
|
||||
|
|
|
|||
|
|
@ -115,3 +115,4 @@
|
|||
- Saboteurs
|
||||
- Furs
|
||||
- Crew
|
||||
- VirusFlesh
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue