diff --git a/Content.Client/_Sunrise/FleshCult/FleshCultistSystem.cs b/Content.Client/_Sunrise/FleshCult/FleshCultistSystem.cs new file mode 100644 index 0000000000..c2407090e7 --- /dev/null +++ b/Content.Client/_Sunrise/FleshCult/FleshCultistSystem.cs @@ -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(GetFleshCultistIcon); + SubscribeLocalEvent(GetFleshMobIcon); + } + + private void GetFleshCultistIcon(Entity ent, ref GetStatusIconsEvent args) + { + var iconPrototype = _prototype.Index(ent.Comp.StatusIcon); + args.StatusIcons.Add(iconPrototype); + } + + private void GetFleshMobIcon(Entity ent, ref GetStatusIconsEvent args) + { + if (HasComp(ent)) + return; + + var iconPrototype = _prototype.Index(ent.Comp.StatusIcon); + args.StatusIcons.Add(iconPrototype); + } +} diff --git a/Content.Client/_Sunrise/FleshCult/FleshHeartVisualSystem.cs b/Content.Client/_Sunrise/FleshCult/FleshHeartVisualSystem.cs new file mode 100644 index 0000000000..33487ffdb0 --- /dev/null +++ b/Content.Client/_Sunrise/FleshCult/FleshHeartVisualSystem.cs @@ -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 +{ + protected override void OnAppearanceChange(EntityUid uid, FleshHeartComponent component, ref AppearanceChangeEvent args) + { + if (args.Sprite == null) + return; + + if (!AppearanceSystem.TryGetData(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); + } + } +} diff --git a/Content.Client/_Sunrise/FleshCult/FleshHuggerSystem.cs b/Content.Client/_Sunrise/FleshCult/FleshHuggerSystem.cs new file mode 100644 index 0000000000..a79fe76221 --- /dev/null +++ b/Content.Client/_Sunrise/FleshCult/FleshHuggerSystem.cs @@ -0,0 +1,11 @@ +using Content.Server.Flesh; + +namespace Content.Client._Sunrise.FleshCult; + +public sealed class FleshHuggerSystem: SharedFleshHuggerSystem +{ + + public override void Initialize() + { + } +} diff --git a/Content.Client/_Sunrise/FleshCult/FleshMobSystem.cs b/Content.Client/_Sunrise/FleshCult/FleshMobSystem.cs new file mode 100644 index 0000000000..64466b6eed --- /dev/null +++ b/Content.Client/_Sunrise/FleshCult/FleshMobSystem.cs @@ -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(); + } +} diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs index 8a66a63e51..bdb8b8662c 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs @@ -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(targetPlayer, "FleshCult"); + }, + Impact = LogImpact.High, + Message = Loc.GetString("admin-verb-make-flesh-cultist"), + }; + args.Verbs.Add(fleshCultist); } } diff --git a/Content.Server/Destructible/Thresholds/DamageThreshold.cs b/Content.Server/Destructible/Thresholds/DamageThreshold.cs index e180f5c45c..640ed61a8d 100644 --- a/Content.Server/Destructible/Thresholds/DamageThreshold.cs +++ b/Content.Server/Destructible/Thresholds/DamageThreshold.cs @@ -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 } } diff --git a/Content.Server/_Sunrise/FleshCult/CauseFleshCultInfection.cs b/Content.Server/_Sunrise/FleshCult/CauseFleshCultInfection.cs new file mode 100644 index 0000000000..5c8cbc0f2c --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/CauseFleshCultInfection.cs @@ -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(args.TargetEntity); + } +} + diff --git a/Content.Server/_Sunrise/FleshCult/Events/VentFleshWormsComponent.cs b/Content.Server/_Sunrise/FleshCult/Events/VentFleshWormsComponent.cs new file mode 100644 index 0000000000..b1d4ab3810 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/Events/VentFleshWormsComponent.cs @@ -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"; +} diff --git a/Content.Server/_Sunrise/FleshCult/Events/VentFleshWormsRule.cs b/Content.Server/_Sunrise/FleshCult/Events/VentFleshWormsRule.cs new file mode 100644 index 0000000000..e767951605 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/Events/VentFleshWormsRule.cs @@ -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 +{ + [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().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); + } + } +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshCultistRoleComponent.cs b/Content.Server/_Sunrise/FleshCult/FleshCultistRoleComponent.cs new file mode 100644 index 0000000000..79133c884a --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshCultistRoleComponent.cs @@ -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; +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshCultistSystem.Abilities.cs b/Content.Server/_Sunrise/FleshCult/FleshCultistSystem.Abilities.cs new file mode 100644 index 0000000000..b3005d5751 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshCultistSystem.Abilities.cs @@ -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(OnBladeActionEvent); + SubscribeLocalEvent(OnClawActionEvent); + SubscribeLocalEvent(OnFistActionEvent); + SubscribeLocalEvent(OnSpikeHandGunActionEvent); + SubscribeLocalEvent(OnArmorActionEvent); + SubscribeLocalEvent(OnHeavyArmorActionEvent); + SubscribeLocalEvent(OnSpiderLegsActionEvent); + SubscribeLocalEvent(OnAdrenalinActionEvent); + SubscribeLocalEvent(OnCreateFleshHeartActionEvent); + SubscribeLocalEvent(OnThrowHugger); + SubscribeLocalEvent(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(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(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(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(uid)) + { + EntityManager.RemoveComponent(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(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(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(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(uid)) + EntityManager.RemoveComponent(uid); + } + else + { + QueueDel(claw); + } + args.Handled = true; + } + + + private void OnFistActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistFistActionEvent args) + { + if (args.Handled) + return; + if (TryComp(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(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(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(uid)) + EntityManager.RemoveComponent(uid); + } + else + { + QueueDel(fist); + } + args.Handled = true; + } + + private void OnSpikeHandGunActionEvent(EntityUid uid, FleshCultistComponent component, FleshCultistSpikeHandGunActionEvent args) + { + if (args.Handled) + return; + if (TryComp(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(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(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(uid)) + RemComp(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(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(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(entity) && entity != uid || // Is it a mob? + Resolve(entity, ref physics, false) && (physics.CollisionLayer & (int) CollisionGroup.Impassable) != 0 || + HasComp(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); + } + +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshCultistSystem.cs b/Content.Server/_Sunrise/FleshCult/FleshCultistSystem.cs new file mode 100644 index 0000000000..b61da05f63 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshCultistSystem.cs @@ -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(OnStartup); + SubscribeLocalEvent(OnShop); + SubscribeLocalEvent(OnInsulatedImmunityMutation); + SubscribeLocalEvent(OnPressureImmunityMutation); + SubscribeLocalEvent(OnFlashImmunityMutation); + SubscribeLocalEvent(OnRespiratorImmunityMutation); + SubscribeLocalEvent(OnColdTempImmunityMutation); + SubscribeLocalEvent(OnDevourAction); + SubscribeLocalEvent(OnDevourDoAfter); + SubscribeLocalEvent(OnBeingEquippedAttempt); + SubscribeLocalEvent(OnMobStateChanged); + SubscribeLocalEvent(OnAbsormBloodPoolActionEvent); + + SubscribeLocalEvent(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(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(uid); + + var collectiveMindComponent = EnsureComp(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(uid); + + if (HasComp(uid)) + RemComp(uid); + + if (HasComp(uid)) + RemComp(uid); + + _tagSystem.AddTag(uid, "Flesh"); + + if (TryComp(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(uid); + } + + + private void OnPressureImmunityMutation(EntityUid uid, FleshCultistComponent component, + FleshCultistPressureImmunityMutationEvent args) + { + EnsureComp(uid); + } + + private void OnFlashImmunityMutation(EntityUid uid, FleshCultistComponent component, + FleshCultistFlashImmunityMutationEvent args) + { + EnsureComp(uid); + } + + private void OnRespiratorImmunityMutation(EntityUid uid, FleshCultistComponent component, + FleshCultistRespiratorImmunityMutationEvent args) + { + EnsureComp(uid); + } + + private void OnColdTempImmunityMutation(EntityUid uid, FleshCultistComponent component, + FleshCultistColdTempImmunityMutationEvent args) + { + if (TryComp(uid, out var tempComponent)) + { + tempComponent.ColdDamageThreshold = 0; + } + } + + private void OnShop(EntityUid uid, FleshCultistComponent component, FleshCultistShopActionEvent args) + { + if (!TryComp(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(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(target, out var targetState)) + return; + if (!TryComp(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(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(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(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(ent)) + { + continue; + } + _containerSystem.Remove(ent, cont, force: true); + Transform(ent).Coordinates = coordinates; + } + } + } + + if (TryComp(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("MobSkeletonSprites"); + foreach (var (key, id) in skeletonSprites.Sprites) + { + if (key != HumanoidVisualLayers.Head) + { + _sharedHuApp.SetBaseLayerId(args.Args.Target.Value, key, id, humanoid: HuAppComponent); + } + } + + if (TryComp(args.Args.Target, out var fixturesComponent)) + { + _physics.SetDensity(args.Args.Target.Value, "fix1", fixturesComponent.Fixtures["fix1"], 50); + } + + if (TryComp(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(args.Args.Target.Value); + + EnsureComp(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 + { {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(ent)) + continue; + if (HasComp(ent)) + continue; + _containerSystem.Remove(ent, cont, force: true); + Transform(ent).Coordinates = coordinates; + } + } + } + + if (TryComp(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(uid, out var dna)) + { + var comp = EnsureComp(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(); + 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(uid, out var targetMindComp)) + return; + + if (HasComp(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()) + { + 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(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; + } +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshGrowth/SpreaderFleshComponent.cs b/Content.Server/_Sunrise/FleshCult/FleshGrowth/SpreaderFleshComponent.cs new file mode 100644 index 0000000000..08bfad19c0 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshGrowth/SpreaderFleshComponent.cs @@ -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; +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshGrowth/SpreaderFleshSystem.cs b/Content.Server/_Sunrise/FleshCult/FleshGrowth/SpreaderFleshSystem.cs new file mode 100644 index 0000000000..fe28b6bcdf --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshGrowth/SpreaderFleshSystem.cs @@ -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!; + + /// + /// Maximum number of edges that can grow out every interval. + /// + private const int GrowthsPerInterval = 5; + + private float _accumulatedFrameTime; + + private readonly HashSet _edgeGrowths = new(); + + public override void Initialize() + { + SubscribeLocalEvent(SpreaderAddHandler); + SubscribeLocalEvent(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(blocker, out var transform)) + return; // how did we get here? + + if (!TryComp(transform.GridUid, out var grid)) + return; + + var spreaderQuery = GetEntityQuery(); + 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(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(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(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 { { 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(ent, out _)) + return true; + + if (!EntityManager.TryGetComponent(ent, out var airtight)) + return false; + + // var oppositeDir = dir.AsDir().GetOpposite().ToAtmosDirection(); + + // return airtight.AirBlocked && airtight.AirBlockedDirection.IsFlagSet(oppositeDir); + + return false; + } +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshHandModComponent.cs b/Content.Server/_Sunrise/FleshCult/FleshHandModComponent.cs new file mode 100644 index 0000000000..9176c064d6 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshHandModComponent.cs @@ -0,0 +1,8 @@ +namespace Content.Server._Sunrise.FleshCult +{ + [RegisterComponent] + public sealed partial class FleshHandModComponent : Component + { + + } +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshHeartSystem.cs b/Content.Server/_Sunrise/FleshCult/FleshHeartSystem.cs new file mode 100644 index 0000000000..bc7f64d12f --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshHeartSystem.cs @@ -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(OnShutdown); + SubscribeLocalEvent(OnDestruction); + SubscribeLocalEvent(HandleDragDropOn); + SubscribeLocalEvent(OnDragFinished); + SubscribeLocalEvent(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(); + while (fleshTilesQuery.MoveNext(out var ent, out var comp)) + { + if (comp.Source != uid) + continue; + if (!TryComp(ent, out var tagComponent)) + continue; + if (_tagSystem.HasAllTags(tagComponent, "Wall", "Flesh")) + _damageableSystem.TryChangeDamage(ent, component.DamageMobsIfHeartDestruct); + else + QueueDel(ent); + + } + var fleshWalls = new List(); + var fleshWallsQuery = EntityQueryEnumerator(); + while (fleshWallsQuery.MoveNext(out var ent, out var comp)) + { + if (!TryComp(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(); + while (fleshHeartQuery.MoveNext(out var ent, out var comp, out var xform)) + { + var fleshCultRule = EntityQuery().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(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(uid, "bodyContainer"); + } + + private void OnDragFinished(EntityUid uid, FleshHeartComponent component, FleshHeartDragFinished args) + { + if (args.Cancelled || args.Handled || args.Args.Target == null) + return; + + if (!TryComp(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(ent)) + { + continue; + } + _containerSystem.Remove(ent, cont, force: true); + Transform(ent).Coordinates = xform.Coordinates; + } + } + } + } + + if (TryComp(args.Args.Target.Value, out var HuAppComponent)) + { + if (TryComp(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("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(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(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(dragged, out var stateComponent)) + return false; + + if (stateComponent.CurrentState != MobState.Dead) + return false; + + if (!Transform(uid).Anchored) + return false; + + if (!TryComp(dragged, out var humanoidAppearance)) + return false; + + if (!(component.SpeciesWhitelist.Contains(humanoidAppearance.Species))) + return false; + + return !TryComp(dragged, out var mindComp) || true; + } + + private void SpawnFleshFloorOnOpenTiles(EntityUid fleshHeart, FleshHeartComponent component, TransformComponent xform, float radius) + { + if (!TryComp(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(fleshTile); + spreaderFleshComponent.Source = fleshHeart; + } + } + } + + private void SpawnMonstersOnOpenTiles(FleshHeartComponent component, TransformComponent xform, int amount, float radius) + { + if (!TryComp(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(); + 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; + } + } +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshHuggerSystem.cs b/Content.Server/_Sunrise/FleshCult/FleshHuggerSystem.cs new file mode 100644 index 0000000000..695aa47007 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshHuggerSystem.cs @@ -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(OnMapInit); + SubscribeLocalEvent(OnMeleeHit); + SubscribeLocalEvent(OnWormDoHit); + SubscribeLocalEvent(OnGotEquipped); + SubscribeLocalEvent(OnGotUnequipped); + SubscribeLocalEvent(OnGotEquippedHand); + SubscribeLocalEvent(OnMobStateChanged); + SubscribeLocalEvent(OnJump); + SubscribeLocalEvent(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(args.Target)) + return; + if (!HasComp(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(headItem)) + return; + + _inventory.TryGetSlotEntity(args.Target, "mask", out var maskItem); + if (HasComp(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(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(args.Equipee); + EntityManager.EnsureComponent(uid); + } + + private void OnGotEquippedHand(EntityUid uid, FleshHuggerComponent component, GotEquippedHandEvent args) + { + if (HasComp<_Sunrise.FleshCult.FleshPudgeComponent>(args.User)) + return; + if (HasComp(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(uid)) + EntityManager.RemoveComponent(uid); + if (HasComp(component.EquipedOn)) + EntityManager.RemoveComponent(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(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(headItem)) + return; + + _inventory.TryGetSlotEntity(entity, "mask", out var maskItem); + if (HasComp(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(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()) + { + comp.Accumulator += frameTime; + + if (comp.Accumulator <= comp.DamageFrequency) + continue; + + comp.Accumulator = 0; + + if (comp.EquipedOn is not { Valid: true } targetId) + continue; + if (HasComp(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); + } + } + } +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshMobSystem.cs b/Content.Server/_Sunrise/FleshCult/FleshMobSystem.cs new file mode 100644 index 0000000000..65a614cfa7 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshMobSystem.cs @@ -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(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); + } + } + } +} + diff --git a/Content.Server/_Sunrise/FleshCult/FleshPudgeComponent.cs b/Content.Server/_Sunrise/FleshCult/FleshPudgeComponent.cs new file mode 100644 index 0000000000..1429612f05 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshPudgeComponent.cs @@ -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))] + public string ActionThrowWormId = "FleshThrowWorm"; + + [DataField("actionAcidSpit", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string ActionAcidSpitId = "FleshAcidSpit"; + + [DataField("actionAbsorbBloodPool", customTypeSerializer: typeof(PrototypeIdSerializer))] + 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))] + public string FaceHuggerMobSpawnId = "MobFleshHugger"; + + [ViewVariables(VVAccess.ReadWrite), + DataField("bulletAcidSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer))] + 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 BloodWhitelist = new() + { + "Blood", + "CopperBlood", + "InsectBlood", + "AmmoniaBlood", + "ZombieBlood" + }; + + [DataField("bloodAbsorbSound")] + public SoundSpecifier BloodAbsorbSound = new SoundPathSpecifier("/Audio/Effects/Fluids/splat.ogg"); + } +} diff --git a/Content.Server/_Sunrise/FleshCult/FleshPudgeSystem.cs b/Content.Server/_Sunrise/FleshCult/FleshPudgeSystem.cs new file mode 100644 index 0000000000..82e5630894 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/FleshPudgeSystem.cs @@ -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(OnStartup); + SubscribeLocalEvent(OnThrowFaceHugger); + SubscribeLocalEvent(OnAbsorbBloodPoolActionEvent); + SubscribeLocalEvent(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(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); + } + } +} diff --git a/Content.Server/_Sunrise/FleshCult/GameRule/FleshCultRuleComponent.cs b/Content.Server/_Sunrise/FleshCult/GameRule/FleshCultRuleComponent.cs new file mode 100644 index 0000000000..2c0bc540c2 --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/GameRule/FleshCultRuleComponent.cs @@ -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 Cultists = new(); + + [DataField("fleshCultistPrototypeId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string FleshCultistPrototypeId = "FleshCultist"; + + [DataField("fleshCultistLeaderPrototypeID", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string FleshCultistLeaderPrototypeId = "FleshCultistLeader"; + + [DataField("faction", customTypeSerializer: typeof(PrototypeIdSerializer), required: true)] + public string Faction = default!; + + public int TotalCultists => Cultists.Count; + + public readonly List CultistsNames = new(); + + public WinTypes WinType = WinTypes.Fail; + + public bool FleshHeartActive = false; + + public Dictionary FleshHearts = new(); + + public EntityUid? TargetStation; + + [DataField] + public List StarterItems = new() { "SyringeCarolNT", "SyringeCarolNT", "SyringeCarolNT" }; + + public List SpeciesWhitelist = new() + { + "Human", + "Reptilian", + "Dwarf", + "Vulpkanin", + "Felinid", + "Moth", + "Swine", + "Arachnid" + }; + + public enum WinTypes + { + FleshHeartFinal, + AllCultistsDead, + Fail + } + + public TimeSpan AnnounceAt = TimeSpan.Zero; + public Dictionary StartCandidates = new(); +} diff --git a/Content.Server/_Sunrise/FleshCult/GameRule/FleshCultRuleSystem.cs b/Content.Server/_Sunrise/FleshCult/GameRule/FleshCultRuleSystem.cs new file mode 100644 index 0000000000..5fb2233b0f --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/GameRule/FleshCultRuleSystem.cs @@ -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 +{ + [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(AfterEntitySelected); + + SubscribeLocalEvent(OnFleshHeartActivate); + SubscribeLocalEvent(OnFleshHeartDestruction); + SubscribeLocalEvent(OnFleshHeartFinal); + + SubscribeLocalEvent(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(); + 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(); + 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(); + 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 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().FirstOrDefault(); + if (comp == null) + { + GameTicker.StartGameRule("FleshCult", out var ruleEntity); + comp = Comp(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(mind.OwnedEntity.Value); + + _store.TryAddCurrency(new Dictionary + { {fleshCultistComponent.StolenCurrencyPrototype, startingPoints} }, mind.OwnedEntity.Value); + + return true; + } + + private void SendCultistBriefing(EntityUid mind, List 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 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); + } +} diff --git a/Content.Server/_Sunrise/FleshCult/Objectives/CreateFleshHeartConditionComponent.cs b/Content.Server/_Sunrise/FleshCult/Objectives/CreateFleshHeartConditionComponent.cs new file mode 100644 index 0000000000..15b399e3af --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/Objectives/CreateFleshHeartConditionComponent.cs @@ -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 +{ +} diff --git a/Content.Server/_Sunrise/FleshCult/Objectives/FleshCultConditionsSystem.cs b/Content.Server/_Sunrise/FleshCult/Objectives/FleshCultConditionsSystem.cs new file mode 100644 index 0000000000..280283d16f --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/Objectives/FleshCultConditionsSystem.cs @@ -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(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(mindId, out var role)) + return 0f; + + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var fleshCult, out var gameRule)) + { + return fleshCult.FleshHeartActive ? 1f : 0f; + } + + return 0f; + } +} diff --git a/Content.Server/_Sunrise/FleshCult/PendingFleshCultistComponent.cs b/Content.Server/_Sunrise/FleshCult/PendingFleshCultistComponent.cs new file mode 100644 index 0000000000..dc3a6d48ec --- /dev/null +++ b/Content.Server/_Sunrise/FleshCult/PendingFleshCultistComponent.cs @@ -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, +} diff --git a/Content.Server/_Sunrise/SplashOnTrigger/SplashOnTriggerComponent.cs b/Content.Server/_Sunrise/SplashOnTrigger/SplashOnTriggerComponent.cs new file mode 100644 index 0000000000..ef7f6b28fb --- /dev/null +++ b/Content.Server/_Sunrise/SplashOnTrigger/SplashOnTriggerComponent.cs @@ -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() + { + }; + } +} diff --git a/Content.Server/_Sunrise/SplashOnTrigger/SplashOnTriggerSystem.cs b/Content.Server/_Sunrise/SplashOnTrigger/SplashOnTriggerSystem.cs new file mode 100644 index 0000000000..3921cfb750 --- /dev/null +++ b/Content.Server/_Sunrise/SplashOnTrigger/SplashOnTriggerSystem.cs @@ -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(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); + } +} diff --git a/Content.Shared/_Sunrise/FleshCult/FleshCultistComponent.cs b/Content.Shared/_Sunrise/FleshCult/FleshCultistComponent.cs new file mode 100644 index 0000000000..cf88c79508 --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/FleshCultistComponent.cs @@ -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))] + public string BulletAcidSpawnId = "BulletSplashAcid"; + + [ViewVariables(VVAccess.ReadWrite), DataField("speciesWhitelist")] + public List 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 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))] + public string StolenCurrencyPrototype = "StolenMutationPoint"; + + [ViewVariables(VVAccess.ReadWrite), + DataField("fleshBladeSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string BladeSpawnId = "FleshBlade"; + + [ViewVariables(VVAccess.ReadWrite), + DataField("fleshFistSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string FistSpawnId = "FleshFist"; + + [ViewVariables(VVAccess.ReadWrite), + DataField("clawSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string ClawSpawnId = "FleshClaw"; + + [ViewVariables(VVAccess.ReadWrite), + DataField("spikeHandGunSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string SpikeHandGunSpawnId = "FleshSpikeHandGun"; + + [ViewVariables(VVAccess.ReadWrite), + DataField("armorSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string ArmorSpawnId = "ClothingOuterArmorFlesh"; + + [ViewVariables(VVAccess.ReadWrite), + DataField("heavyArmorSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string HeavyArmorSpawnId = "ClothingOuterHeavyArmorFlesh"; + + [ViewVariables(VVAccess.ReadWrite), + DataField("spiderLegsSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string SpiderLegsSpawnId = "ClothingFleshSpiderLegs"; + + [ViewVariables(VVAccess.ReadWrite), + DataField("fleshMutationMobId", customTypeSerializer: typeof(PrototypeIdSerializer))] + 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)), + 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))] + 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 StatusIcon { get; set; } = "FleshFaction"; + + [DataField] + public ProtoId MutationPointAlert = "MutationPoint"; +} diff --git a/Content.Shared/_Sunrise/FleshCult/FleshHeartComponent.cs b/Content.Shared/_Sunrise/FleshCult/FleshHeartComponent.cs new file mode 100644 index 0000000000..f41bf9202b --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/FleshHeartComponent.cs @@ -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 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)), + ViewVariables(VVAccess.ReadWrite)] + public string FleshTileId = "Flesh"; + + [DataField("spawns"), ViewVariables(VVAccess.ReadWrite)] + public Dictionary 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 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 +} diff --git a/Content.Shared/_Sunrise/FleshCult/FleshHeartVisuals.cs b/Content.Shared/_Sunrise/FleshCult/FleshHeartVisuals.cs new file mode 100644 index 0000000000..179f76097d --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/FleshHeartVisuals.cs @@ -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 +} diff --git a/Content.Shared/_Sunrise/FleshCult/FleshHuggerComponent.cs b/Content.Shared/_Sunrise/FleshCult/FleshHuggerComponent.cs new file mode 100644 index 0000000000..1ae3814763 --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/FleshHuggerComponent.cs @@ -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))] + public string ActionFleshHuggerJumpId = "FleshHuggerJump"; + + [DataField("actionGetOff", customTypeSerializer: typeof(PrototypeIdSerializer))] + 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"); + } +} diff --git a/Content.Shared/_Sunrise/FleshCult/FleshMobComponent.cs b/Content.Shared/_Sunrise/FleshCult/FleshMobComponent.cs new file mode 100644 index 0000000000..530dc041ad --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/FleshMobComponent.cs @@ -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))] + public string DeathMobSpawnId = "MobFleshWorm"; + + [DataField("deathMobSpawnCount"), ViewVariables(VVAccess.ReadWrite)] + public int DeathMobSpawnCount; + + [DataField("fleshStatusIcon")] + public ProtoId 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 +{ + +} diff --git a/Content.Shared/_Sunrise/FleshCult/IgnoreFleshSpiderWebComponent.cs b/Content.Shared/_Sunrise/FleshCult/IgnoreFleshSpiderWebComponent.cs new file mode 100644 index 0000000000..13787f3ecf --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/IgnoreFleshSpiderWebComponent.cs @@ -0,0 +1,9 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._Sunrise.FleshCult; + +[RegisterComponent, NetworkedComponent] +public sealed partial class IgnoreFleshSpiderWebComponent : Component +{ + +} diff --git a/Content.Shared/_Sunrise/FleshCult/SharedFleshCultist.cs b/Content.Shared/_Sunrise/FleshCult/SharedFleshCultist.cs new file mode 100644 index 0000000000..b5119b4d5e --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/SharedFleshCultist.cs @@ -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 +{ + +} + + + diff --git a/Content.Shared/_Sunrise/FleshCult/SharedFleshCultistSystem.cs b/Content.Shared/_Sunrise/FleshCult/SharedFleshCultistSystem.cs new file mode 100644 index 0000000000..fa95472b09 --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/SharedFleshCultistSystem.cs @@ -0,0 +1,11 @@ +namespace Content.Shared._Sunrise.FleshCult; + +public abstract class SharedFleshCultistSystem : EntitySystem +{ + + public override void Initialize() + { + base.Initialize(); + + } +} diff --git a/Content.Shared/_Sunrise/FleshCult/SharedFleshHeartComponent.cs b/Content.Shared/_Sunrise/FleshCult/SharedFleshHeartComponent.cs new file mode 100644 index 0000000000..dfc1a9002d --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/SharedFleshHeartComponent.cs @@ -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 + { + } +} diff --git a/Content.Shared/_Sunrise/FleshCult/SharedFleshHuggerSystem.cs b/Content.Shared/_Sunrise/FleshCult/SharedFleshHuggerSystem.cs new file mode 100644 index 0000000000..f57ebca390 --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/SharedFleshHuggerSystem.cs @@ -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(OnUnequipAttempt); + } + + private void OnUnequipAttempt(EntityUid uid, FleshHuggerComponent component, BeingUnequippedAttemptEvent args) + { + if (args.Slot != "mask") + return; + if (component.EquipedOn != args.Unequipee) + return; + if (HasComp(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 +{ + +}; diff --git a/Content.Shared/_Sunrise/FleshCult/SharedFleshMobSystem.cs b/Content.Shared/_Sunrise/FleshCult/SharedFleshMobSystem.cs new file mode 100644 index 0000000000..bf59ce3507 --- /dev/null +++ b/Content.Shared/_Sunrise/FleshCult/SharedFleshMobSystem.cs @@ -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(OnAttackAttempt); + } + + private void OnAttackAttempt(EntityUid uid, FleshMobComponent component, AttackAttemptEvent args) + { + if (args.Cancelled) + return; + + if (HasComp(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(args.Target)) + { + _popup.PopupCursor(Loc.GetString("flesh-mob-cant-atack-flesh-heart"), uid, + PopupType.LargeCaution); + args.Cancel(); + } + } + +} diff --git a/Resources/Audio/_Sunrise/FleshCult/abom_scream.ogg b/Resources/Audio/_Sunrise/FleshCult/abom_scream.ogg new file mode 100644 index 0000000000..95b5521267 Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/abom_scream.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/devour_flesh_cultist.ogg b/Resources/Audio/_Sunrise/FleshCult/devour_flesh_cultist.ogg new file mode 100644 index 0000000000..bb1e040402 Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/devour_flesh_cultist.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/flesh_blade.ogg b/Resources/Audio/_Sunrise/FleshCult/flesh_blade.ogg new file mode 100644 index 0000000000..f4025fdf49 Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/flesh_blade.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/flesh_culstis_greeting.ogg b/Resources/Audio/_Sunrise/FleshCult/flesh_culstis_greeting.ogg new file mode 100644 index 0000000000..b031da3c05 Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/flesh_culstis_greeting.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/flesh_cultist_buy_succes.ogg b/Resources/Audio/_Sunrise/FleshCult/flesh_cultist_buy_succes.ogg new file mode 100644 index 0000000000..ccee88a209 Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/flesh_cultist_buy_succes.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/flesh_cultist_mutation.ogg b/Resources/Audio/_Sunrise/FleshCult/flesh_cultist_mutation.ogg new file mode 100644 index 0000000000..3676702f61 Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/flesh_cultist_mutation.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/flesh_heart.ogg b/Resources/Audio/_Sunrise/FleshCult/flesh_heart.ogg new file mode 100644 index 0000000000..1301fecfd0 Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/flesh_heart.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/flesh_heart_activate.ogg b/Resources/Audio/_Sunrise/FleshCult/flesh_heart_activate.ogg new file mode 100644 index 0000000000..762c6a0cdc Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/flesh_heart_activate.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/flesh_pudge_dead.ogg b/Resources/Audio/_Sunrise/FleshCult/flesh_pudge_dead.ogg new file mode 100644 index 0000000000..461b6eeb5e Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/flesh_pudge_dead.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg b/Resources/Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg new file mode 100644 index 0000000000..51273d7486 Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/flesh_worm_dead.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/flesh_worm_scream.ogg b/Resources/Audio/_Sunrise/FleshCult/flesh_worm_scream.ogg new file mode 100644 index 0000000000..a69e96b02e Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/flesh_worm_scream.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/spike_gun_reload.ogg b/Resources/Audio/_Sunrise/FleshCult/spike_gun_reload.ogg new file mode 100644 index 0000000000..77a48236dd Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/spike_gun_reload.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/spike_gun_shot.ogg b/Resources/Audio/_Sunrise/FleshCult/spike_gun_shot.ogg new file mode 100644 index 0000000000..f8a618b95d Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/spike_gun_shot.ogg differ diff --git a/Resources/Audio/_Sunrise/FleshCult/throw_worm.ogg b/Resources/Audio/_Sunrise/FleshCult/throw_worm.ogg new file mode 100644 index 0000000000..447ccf7c7b Binary files /dev/null and b/Resources/Audio/_Sunrise/FleshCult/throw_worm.ogg differ diff --git a/Resources/Locale/ru-RU/_prototypes/_sunrise/entities/objects/specific/medical/viruses.ftl b/Resources/Locale/ru-RU/_prototypes/_sunrise/entities/objects/specific/medical/viruses.ftl index 6d583d5288..3f93b60f01 100644 --- a/Resources/Locale/ru-RU/_prototypes/_sunrise/entities/objects/specific/medical/viruses.ftl +++ b/Resources/Locale/ru-RU/_prototypes/_sunrise/entities/objects/specific/medical/viruses.ftl @@ -1,2 +1,4 @@ ent-SyringeRomerolNT = { ent-BaseSyringe } .desc = { ent-BaseSyringe.desc } +ent-SyringeCarolNT = { ent-BaseSyringe } + .desc = { ent-BaseSyringe.desc } diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/admin-verb.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/admin-verb.ftl new file mode 100644 index 0000000000..5e7be7011c --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/admin-verb.ftl @@ -0,0 +1,2 @@ +admin-verb-text-make-flesh-cultist = Сделать цель культистом плоти. +admin-verb-make-flesh-cultist = Сделать цель культистом плоти. diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/antags.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/antags.ftl new file mode 100644 index 0000000000..ac1daab0f5 --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/antags.ftl @@ -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 = Воплотите цели культа в реальность. Убедитесь что все участники культа выживут. diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/categories.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/categories.ftl new file mode 100644 index 0000000000..c0ead2a154 --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/categories.ftl @@ -0,0 +1,4 @@ +store-category-flesh-passive-skills = Улучшения +store-category-flesh-active-skills = Умения +store-category-flesh-weapon = Модификации рук +store-category-flesh-armor = Модификации тела diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/currency.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/currency.ftl new file mode 100644 index 0000000000..cf0bb7bdea --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/currency.ftl @@ -0,0 +1 @@ +store-currency-display-stolen-mutation-points = Очки Эволюции diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/flesh-hands.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/flesh-hands.ftl new file mode 100644 index 0000000000..e8ee21a195 --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/flesh-hands.ftl @@ -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 = { "" } + + diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/flesh.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/flesh.ftl new file mode 100644 index 0000000000..70369be375 --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/flesh.ftl @@ -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 = Вы не можете прыгать будучи на лице. diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/flesh_heart.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/flesh_heart.ftl new file mode 100644 index 0000000000..c73752ab43 --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/flesh_heart.ftl @@ -0,0 +1,5 @@ +ent-FleshHeart = сердце плоти + .desc = Такой хуйни вы еще не видели. + +flesh-heart-cant-absorb-targer = Сердце не хочет поглощать это. +flesh-heart-activate-warning = Внимание! На станции была замечена аномальная биологическая сигнатура. Всему персоналу отдела службы безопастности начать немедленную ликвидацию цели. diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/fleshcultist.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/fleshcultist.ftl new file mode 100644 index 0000000000..d5fcde5618 --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/fleshcultist.ftl @@ -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 = Вам больше не нужен кислород. diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/mobs.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/mobs.ftl new file mode 100644 index 0000000000..36f31c267f --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/mobs.ftl @@ -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 = Он хочет сесть тебе на лицо diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/preset.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/preset.ftl new file mode 100644 index 0000000000..95c4a0ee9b --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/preset.ftl @@ -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 = Ни одно сердце плоти не было уничтожено. diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/toxins.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/toxins.ftl new file mode 100644 index 0000000000..9c8de2a899 --- /dev/null +++ b/Resources/Locale/ru-RU/_strings/_sunrise/flesh-cult/toxins.ftl @@ -0,0 +1,4 @@ +reagent-name-carol = ?????? +reagent-desc-carol = ?????? +reagent-name-flesh-acid = ?????? +reagent-desc-flesh-acid = ?????? diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/station-goal/station-goal-component.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/station-goal/station-goal-component.ftl index 9b1e06b711..e80de4c500 100644 --- a/Resources/Locale/ru-RU/_strings/_sunrise/station-goal/station-goal-component.ftl +++ b/Resources/Locale/ru-RU/_strings/_sunrise/station-goal/station-goal-component.ftl @@ -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] diff --git a/Resources/Prototypes/Entities/Structures/Windows/window.yml b/Resources/Prototypes/Entities/Structures/Windows/window.yml index 6b404d65ce..1d0b293cd8 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/window.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/window.yml @@ -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 \ No newline at end of file + node: windowDiagonal diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index e0a3e9001e..f7ab98bf63 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -24,6 +24,7 @@ - id: SpiderClownSpawn - id: SpiderSpawn - id: VentClog + - id: VentFleshWorms - type: entityTable id: BasicAntagEventsTable diff --git a/Resources/Prototypes/_Sunrise/Entities/Objects/Specific/Medical/viruses.yml b/Resources/Prototypes/_Sunrise/Entities/Objects/Specific/Medical/viruses.yml index 79a4be7855..b546288fc4 100644 --- a/Resources/Prototypes/_Sunrise/Entities/Objects/Specific/Medical/viruses.yml +++ b/Resources/Prototypes/_Sunrise/Entities/Objects/Specific/Medical/viruses.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_cultist.yml b/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_cultist.yml new file mode 100644 index 0000000000..e6ad8db16b --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_cultist.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_hugger.yml b/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_hugger.yml new file mode 100644 index 0000000000..0cfc0bae5d --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_hugger.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_pudge.yml b/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_pudge.yml new file mode 100644 index 0000000000..52b2710d6b --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_pudge.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_spider.yml b/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_spider.yml new file mode 100644 index 0000000000..22ef509555 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/Actions/flesh_spider.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/Store/catalog.yml b/Resources/Prototypes/_Sunrise/FleshCult/Store/catalog.yml new file mode 100644 index 0000000000..8c8c69b2b0 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/Store/catalog.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/Store/categories.yml b/Resources/Prototypes/_Sunrise/FleshCult/Store/categories.yml new file mode 100644 index 0000000000..bfbefe2a11 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/Store/categories.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/Store/currency.yml b/Resources/Prototypes/_Sunrise/FleshCult/Store/currency.yml new file mode 100644 index 0000000000..39ee95446b --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/Store/currency.yml @@ -0,0 +1,4 @@ +- type: currency + id: StolenMutationPoint + displayName: store-currency-display-stolen-mutation-points + canWithdraw: false diff --git a/Resources/Prototypes/_Sunrise/FleshCult/ai_factions.yml b/Resources/Prototypes/_Sunrise/FleshCult/ai_factions.yml new file mode 100644 index 0000000000..a3f3f33f79 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/ai_factions.yml @@ -0,0 +1,17 @@ +- type: npcFaction + id: Flesh + hostile: + - NanoTrasen + - Syndicate + - Xeno + - SimpleHostile + - Carps + - Zombie + - Revolutionary + - PetsNT + - Vampire + - Changeling + - Thief + +- type: npcFaction + id: FleshHuman diff --git a/Resources/Prototypes/_Sunrise/FleshCult/alerts.yml b/Resources/Prototypes/_Sunrise/FleshCult/alerts.yml new file mode 100644 index 0000000000..cad349a9e7 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/alerts.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/antag.yml b/Resources/Prototypes/_Sunrise/FleshCult/antag.yml new file mode 100644 index 0000000000..fbb8fa20ff --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/antag.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/body_mods.yml b/Resources/Prototypes/_Sunrise/FleshCult/body_mods.yml new file mode 100644 index 0000000000..f6b62cdab5 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/body_mods.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/events.yml b/Resources/Prototypes/_Sunrise/FleshCult/events.yml new file mode 100644 index 0000000000..503539a244 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/events.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/explosion.yml b/Resources/Prototypes/_Sunrise/FleshCult/explosion.yml new file mode 100644 index 0000000000..848ca6a848 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/explosion.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/flesh_heart.yml b/Resources/Prototypes/_Sunrise/FleshCult/flesh_heart.yml new file mode 100644 index 0000000000..394cd310d2 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/flesh_heart.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/flesh_tile.yml b/Resources/Prototypes/_Sunrise/FleshCult/flesh_tile.yml new file mode 100644 index 0000000000..07dbb25ae0 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/flesh_tile.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/flesh_walls.yml b/Resources/Prototypes/_Sunrise/FleshCult/flesh_walls.yml new file mode 100644 index 0000000000..7ba6bea6c2 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/flesh_walls.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/game_preset.yml b/Resources/Prototypes/_Sunrise/FleshCult/game_preset.yml new file mode 100644 index 0000000000..bcdcd0a294 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/game_preset.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/hands_mods.yml b/Resources/Prototypes/_Sunrise/FleshCult/hands_mods.yml new file mode 100644 index 0000000000..e210725f94 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/hands_mods.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/mind_roles.yml b/Resources/Prototypes/_Sunrise/FleshCult/mind_roles.yml new file mode 100644 index 0000000000..3652fbcd7f --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/mind_roles.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/mobs.yml b/Resources/Prototypes/_Sunrise/FleshCult/mobs.yml new file mode 100644 index 0000000000..ccd83f889c --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/mobs.yml @@ -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" ] diff --git a/Resources/Prototypes/_Sunrise/FleshCult/modifier_sets.yml b/Resources/Prototypes/_Sunrise/FleshCult/modifier_sets.yml new file mode 100644 index 0000000000..3c070d55f9 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/modifier_sets.yml @@ -0,0 +1,9 @@ +- type: damageModifierSet + id: FleshMob + coefficients: + Heat: 1.50 + +- type: damageModifierSet + id: FleshHeart + coefficients: + Heat: 2.00 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/objectives.yml b/Resources/Prototypes/_Sunrise/FleshCult/objectives.yml new file mode 100644 index 0000000000..ecae730ee8 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/objectives.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/projectiles.yml b/Resources/Prototypes/_Sunrise/FleshCult/projectiles.yml new file mode 100644 index 0000000000..9bdde01554 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/projectiles.yml @@ -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 + diff --git a/Resources/Prototypes/_Sunrise/FleshCult/roundstart.yml b/Resources/Prototypes/_Sunrise/FleshCult/roundstart.yml new file mode 100644 index 0000000000..db28307c4d --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/roundstart.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/speech_emote_sounds.yml b/Resources/Prototypes/_Sunrise/FleshCult/speech_emote_sounds.yml new file mode 100644 index 0000000000..4fafb7c9ed --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/speech_emote_sounds.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/spider_web.yml b/Resources/Prototypes/_Sunrise/FleshCult/spider_web.yml new file mode 100644 index 0000000000..c8ee389517 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/spider_web.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/starting_gear.yml b/Resources/Prototypes/_Sunrise/FleshCult/starting_gear.yml new file mode 100644 index 0000000000..57fecc1e72 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/starting_gear.yml @@ -0,0 +1,7 @@ +- type: startingGear + id: FleshCultistLeaderGear + storage: + back: + - SyringeCarolNT + - SyringeCarolNT + - SyringeCarolNT diff --git a/Resources/Prototypes/_Sunrise/FleshCult/status_icon.yml b/Resources/Prototypes/_Sunrise/FleshCult/status_icon.yml new file mode 100644 index 0000000000..2a4821f643 --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/status_icon.yml @@ -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 diff --git a/Resources/Prototypes/_Sunrise/FleshCult/tags.yml b/Resources/Prototypes/_Sunrise/FleshCult/tags.yml new file mode 100644 index 0000000000..b8052cd7cf --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/tags.yml @@ -0,0 +1,5 @@ +- type: Tag + id: FullBodyOuter + +- type: Tag + id: Directional diff --git a/Resources/Prototypes/_Sunrise/FleshCult/toxins.yml b/Resources/Prototypes/_Sunrise/FleshCult/toxins.yml new file mode 100644 index 0000000000..d18907e87f --- /dev/null +++ b/Resources/Prototypes/_Sunrise/FleshCult/toxins.yml @@ -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 + + + diff --git a/Resources/Prototypes/_Sunrise/Maps/bagel.yml b/Resources/Prototypes/_Sunrise/Maps/bagel.yml index 280fdfb440..6a1b02fcb4 100644 --- a/Resources/Prototypes/_Sunrise/Maps/bagel.yml +++ b/Resources/Prototypes/_Sunrise/Maps/bagel.yml @@ -116,3 +116,4 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Maps/box.yml b/Resources/Prototypes/_Sunrise/Maps/box.yml index d2c3b46790..4ce592a183 100644 --- a/Resources/Prototypes/_Sunrise/Maps/box.yml +++ b/Resources/Prototypes/_Sunrise/Maps/box.yml @@ -115,3 +115,4 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Maps/cog.yml b/Resources/Prototypes/_Sunrise/Maps/cog.yml index f818acab7c..5134c3ae5e 100644 --- a/Resources/Prototypes/_Sunrise/Maps/cog.yml +++ b/Resources/Prototypes/_Sunrise/Maps/cog.yml @@ -111,3 +111,4 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Maps/delta.yml b/Resources/Prototypes/_Sunrise/Maps/delta.yml index d4bdf23ccd..f166e829c1 100644 --- a/Resources/Prototypes/_Sunrise/Maps/delta.yml +++ b/Resources/Prototypes/_Sunrise/Maps/delta.yml @@ -83,35 +83,3 @@ StationAi: [ 1, 1 ] Borg: [ 22, 22 ] SecurityCombatBorg: [ 2, 2 ] - - type: StationGoal - goals: - - Shuttle - - Singularity - - SolarPanels - - Artifacts - - Bank - - Zoo - - MiningOutpost - - Tesla - - XenobiologyRepair - - VirusologyAmbusol - - Containment - - WeaponsSecurity - - MaintsRepair - - DormsBuild - - BattleShuttle - - Transit - - NukeRoom - - Permabrig - - Farm - - Delegates - - Cyborgs - - Testing - - Anomaly - - Replenishment - - IntelWeapons - - Reports - - Reconnaissance - - Saboteurs - - Furs - - Crew diff --git a/Resources/Prototypes/_Sunrise/Maps/fland.yml b/Resources/Prototypes/_Sunrise/Maps/fland.yml index cd58fb3a10..eebe108620 100644 --- a/Resources/Prototypes/_Sunrise/Maps/fland.yml +++ b/Resources/Prototypes/_Sunrise/Maps/fland.yml @@ -115,3 +115,4 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Maps/gelta.yml b/Resources/Prototypes/_Sunrise/Maps/gelta.yml index b42ec4c105..d47222ced9 100644 --- a/Resources/Prototypes/_Sunrise/Maps/gelta.yml +++ b/Resources/Prototypes/_Sunrise/Maps/gelta.yml @@ -115,3 +115,4 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Maps/marathon.yml b/Resources/Prototypes/_Sunrise/Maps/marathon.yml index 63d2707b6b..f21ede190e 100644 --- a/Resources/Prototypes/_Sunrise/Maps/marathon.yml +++ b/Resources/Prototypes/_Sunrise/Maps/marathon.yml @@ -115,3 +115,4 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Maps/meta.yml b/Resources/Prototypes/_Sunrise/Maps/meta.yml index 10ea033aa8..edb7e068f1 100644 --- a/Resources/Prototypes/_Sunrise/Maps/meta.yml +++ b/Resources/Prototypes/_Sunrise/Maps/meta.yml @@ -115,4 +115,5 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Maps/oasis.yml b/Resources/Prototypes/_Sunrise/Maps/oasis.yml index c0d7c7d70a..e2ed46e8f5 100644 --- a/Resources/Prototypes/_Sunrise/Maps/oasis.yml +++ b/Resources/Prototypes/_Sunrise/Maps/oasis.yml @@ -113,3 +113,4 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Maps/reach.yml b/Resources/Prototypes/_Sunrise/Maps/reach.yml index b822a752a7..bf1005bf69 100644 --- a/Resources/Prototypes/_Sunrise/Maps/reach.yml +++ b/Resources/Prototypes/_Sunrise/Maps/reach.yml @@ -57,3 +57,4 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Maps/train.yml b/Resources/Prototypes/_Sunrise/Maps/train.yml index 1924b758dd..974ce2b1cf 100644 --- a/Resources/Prototypes/_Sunrise/Maps/train.yml +++ b/Resources/Prototypes/_Sunrise/Maps/train.yml @@ -116,3 +116,4 @@ - Saboteurs - Furs - Crew + - VirusFlesh diff --git a/Resources/Prototypes/_Sunrise/Objectives/goals.yml b/Resources/Prototypes/_Sunrise/Objectives/goals.yml index 8150a0d775..8b4d93be03 100644 --- a/Resources/Prototypes/_Sunrise/Objectives/goals.yml +++ b/Resources/Prototypes/_Sunrise/Objectives/goals.yml @@ -152,3 +152,9 @@ text: station-goal-delegates lockBoxPrototypeId: LockboxCaptain +- type: stationGoal + id: VirusFlesh + text: station-goal-virus + lockBoxPrototypeId: Lockbox + extraItems: + - SyringeCarolNT diff --git a/Resources/Prototypes/_Sunrise/secret_weights.yml b/Resources/Prototypes/_Sunrise/secret_weights.yml index ca04a9b40c..35f54f105f 100644 --- a/Resources/Prototypes/_Sunrise/secret_weights.yml +++ b/Resources/Prototypes/_Sunrise/secret_weights.yml @@ -1,11 +1,11 @@ - type: weightedRandom id: SunriseSecret weights: - Traitor: 0.50 + Traitor: 0.40 + FleshCult: 0.15 Nukeops: 0.15 - Extra: 0.20 - Greenshift: 0.10 - Revolutionary: 0.05 + Extra: 0.10 + Revolutionary: 0.10 Survival: 0.05 Zombie: 0.05 diff --git a/Resources/Prototypes/ai_factions.yml b/Resources/Prototypes/ai_factions.yml index d61411ecba..8f54ccc97f 100644 --- a/Resources/Prototypes/ai_factions.yml +++ b/Resources/Prototypes/ai_factions.yml @@ -12,6 +12,7 @@ - Carps - Changeling - Vampire + - Flesh - type: npcFaction id: Mouse @@ -32,6 +33,7 @@ - AllHostile # Sunrise Edit - Carps + - Flesh - type: npcFaction id: SimpleHostile @@ -48,6 +50,8 @@ - Carps - Changeling - Vampire + - FleshHuman + - Flesh - type: npcFaction id: SimpleNeutral @@ -66,6 +70,8 @@ - Carps - Changeling - Vampire + - FleshHuman + - Flesh - type: npcFaction id: Xeno @@ -82,6 +88,8 @@ - Carps - Changeling - Vampire + - FleshHuman + - Flesh - type: npcFaction id: Zombie @@ -99,6 +107,8 @@ - Carps - Changeling - Vampire + - FleshHuman + - Flesh - type: npcFaction id: Revolutionary @@ -111,6 +121,8 @@ - Carps - Changeling - Vampire + - FleshHuman + - Flesh - type: npcFaction id: AllHostile @@ -130,3 +142,5 @@ - Carps - Changeling - Vampire + - FleshHuman + - Flesh diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi/equipped-OUTERCLOTHING.png b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi/equipped-OUTERCLOTHING.png new file mode 100644 index 0000000000..b78406ab86 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi/equipped-OUTERCLOTHING.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi/icon.png b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi/icon.png new file mode 100644 index 0000000000..2e9189a3d3 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi/icon.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi/meta.json new file mode 100644 index 0000000000..d9d6568901 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_armor.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-OUTERCLOTHING", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi/equipped-FEET.png b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi/equipped-FEET.png new file mode 100644 index 0000000000..6b9cba63a6 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi/equipped-FEET.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi/icon.png b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi/icon.png new file mode 100644 index 0000000000..4e968716c2 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi/icon.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi/meta.json new file mode 100644 index 0000000000..7c464eb29c --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/flesh_spider.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-FEET", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi/equipped-OUTERCLOTHING.png b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi/equipped-OUTERCLOTHING.png new file mode 100644 index 0000000000..b7c655e736 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi/equipped-OUTERCLOTHING.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi/icon.png b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi/icon.png new file mode 100644 index 0000000000..32b3da800d Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi/icon.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi/meta.json new file mode 100644 index 0000000000..d9d6568901 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_armor.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-OUTERCLOTHING", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi/equipped-HELMET.png b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi/equipped-HELMET.png new file mode 100644 index 0000000000..5b56bc53c6 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi/equipped-HELMET.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi/icon.png b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi/icon.png new file mode 100644 index 0000000000..445fde78fe Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi/icon.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi/meta.json new file mode 100644 index 0000000000..60c7a0fc84 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/FleshBodyMods/heavy_flesh_helmet.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-HELMET", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/icon.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/icon.png new file mode 100644 index 0000000000..e2d389744c Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/icon.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/inhand-left.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/inhand-left.png new file mode 100644 index 0000000000..d137c1f977 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/inhand-left.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/inhand-right.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/inhand-right.png new file mode 100644 index 0000000000..c37d0cf6b9 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/inhand-right.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/meta.json new file mode 100644 index 0000000000..53d8c224f8 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_blade.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by discord:", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/icon.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/icon.png new file mode 100644 index 0000000000..f959fb40ac Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/icon.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/inhand-left.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/inhand-left.png new file mode 100644 index 0000000000..bd78d882f6 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/inhand-left.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/inhand-right.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/inhand-right.png new file mode 100644 index 0000000000..f2ca824ed1 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/inhand-right.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/meta.json new file mode 100644 index 0000000000..b7008627d4 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_claw.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/icon.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/icon.png new file mode 100644 index 0000000000..7d15d9baf5 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/icon.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/inhand-left.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/inhand-left.png new file mode 100644 index 0000000000..b979907127 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/inhand-left.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/inhand-right.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/inhand-right.png new file mode 100644 index 0000000000..b1e0a079d7 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/inhand-right.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/meta.json new file mode 100644 index 0000000000..53d8c224f8 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_fist.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by discord:", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/icon.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/icon.png new file mode 100644 index 0000000000..8c8ca37f82 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/icon.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/inhand-left.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/inhand-left.png new file mode 100644 index 0000000000..ce27809cfd Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/inhand-left.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/inhand-right.png b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/inhand-right.png new file mode 100644 index 0000000000..586814cb0b Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/inhand-right.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/meta.json new file mode 100644 index 0000000000..c91b424adc --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/FleshHandMods/flesh_spike_hand.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshAcidSpit.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshAcidSpit.png new file mode 100644 index 0000000000..1763ad4b3f Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshAcidSpit.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistAbsorbBloodPool.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistAbsorbBloodPool.png new file mode 100644 index 0000000000..9756e57d66 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistAbsorbBloodPool.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistAdrenalin.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistAdrenalin.png new file mode 100644 index 0000000000..b71cdb180c Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistAdrenalin.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistArmor.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistArmor.png new file mode 100644 index 0000000000..2e9189a3d3 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistArmor.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistBlade.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistBlade.png new file mode 100644 index 0000000000..e2d389744c Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistBlade.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistBreakCuffs.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistBreakCuffs.png new file mode 100644 index 0000000000..39b7e4f0c2 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistBreakCuffs.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistClaw.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistClaw.png new file mode 100644 index 0000000000..f959fb40ac Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistClaw.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistColdTempImmunityMutation.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistColdTempImmunityMutation.png new file mode 100644 index 0000000000..bd4578afd6 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistColdTempImmunityMutation.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistDevour.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistDevour.png new file mode 100644 index 0000000000..a8540e4436 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistDevour.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistFist.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistFist.png new file mode 100644 index 0000000000..7d15d9baf5 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistFist.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistFlashImmunityMutation.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistFlashImmunityMutation.png new file mode 100644 index 0000000000..a0b1585cb4 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistFlashImmunityMutation.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistFleshHeart.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistFleshHeart.png new file mode 100644 index 0000000000..cb6a3fafa6 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistFleshHeart.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistHeavyArmor.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistHeavyArmor.png new file mode 100644 index 0000000000..32b3da800d Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistHeavyArmor.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistInsulatedImmunityMutation.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistInsulatedImmunityMutation.png new file mode 100644 index 0000000000..66900aa57f Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistInsulatedImmunityMutation.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistPressureImmunityMutation.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistPressureImmunityMutation.png new file mode 100644 index 0000000000..cdd1bd40a5 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistPressureImmunityMutation.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistRespiratorImmunityMutation.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistRespiratorImmunityMutation.png new file mode 100644 index 0000000000..af1001757c Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistRespiratorImmunityMutation.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistShop.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistShop.png new file mode 100644 index 0000000000..38683ad8b4 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistShop.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistSpiderLegs.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistSpiderLegs.png new file mode 100644 index 0000000000..b171b227d0 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistSpiderLegs.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistSpikeGun.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistSpikeGun.png new file mode 100644 index 0000000000..8c8ca37f82 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistSpikeGun.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistSurvivalObjective.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistSurvivalObjective.png new file mode 100644 index 0000000000..31501f6deb Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshCultistSurvivalObjective.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshHuggerGetOff.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshHuggerGetOff.png new file mode 100644 index 0000000000..49c93f7f2f Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshHuggerGetOff.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshThrowHugger.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshThrowHugger.png new file mode 100644 index 0000000000..0358086f90 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/fleshThrowHugger.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/flesh_web.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/flesh_web.png new file mode 100644 index 0000000000..889cdc6c3a Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Actions/flesh_web.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point0.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point0.png new file mode 100644 index 0000000000..18b8ee20f2 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point0.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point1.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point1.png new file mode 100644 index 0000000000..62a0c4f154 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point1.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point10.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point10.png new file mode 100644 index 0000000000..55eb96b487 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point10.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point11.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point11.png new file mode 100644 index 0000000000..43b64a9528 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point11.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point12.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point12.png new file mode 100644 index 0000000000..46f3b8afe5 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point12.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point13.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point13.png new file mode 100644 index 0000000000..e2d985042e Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point13.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point14.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point14.png new file mode 100644 index 0000000000..57b15a883f Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point14.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point15.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point15.png new file mode 100644 index 0000000000..6f85d0cedd Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point15.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point16.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point16.png new file mode 100644 index 0000000000..61a99c7595 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point16.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point2.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point2.png new file mode 100644 index 0000000000..2c20939fa1 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point2.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point3.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point3.png new file mode 100644 index 0000000000..175c35269b Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point3.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point4.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point4.png new file mode 100644 index 0000000000..780e30b424 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point4.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point5.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point5.png new file mode 100644 index 0000000000..cec868444b Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point5.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point6.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point6.png new file mode 100644 index 0000000000..e8f8131a7a Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point6.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point7.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point7.png new file mode 100644 index 0000000000..52fb4a9576 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point7.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point8.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point8.png new file mode 100644 index 0000000000..bb73dc7569 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point8.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point9.png b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point9.png new file mode 100644 index 0000000000..f8ca3c7f4f Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/flesh_point9.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/meta.json new file mode 100644 index 0000000000..d888bbcd9b --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/Interface/Alerts/flesh_point.rsi/meta.json @@ -0,0 +1,62 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by ", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "flesh_point0" + }, + { + "name": "flesh_point1" + }, + { + "name": "flesh_point2" + }, + { + "name": "flesh_point3" + }, + { + "name": "flesh_point4" + }, + { + "name": "flesh_point5" + }, + { + "name": "flesh_point6" + }, + { + "name": "flesh_point7" + }, + { + "name": "flesh_point8" + }, + { + "name": "flesh_point9" + }, + { + "name": "flesh_point10" + }, + { + "name": "flesh_point11" + }, + { + "name": "flesh_point12" + }, + { + "name": "flesh_point13" + }, + { + "name": "flesh_point14" + }, + { + "name": "flesh_point15" + }, + { + "name": "flesh_point16" + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/flesh_icon.rsi/Flesh.png b/Resources/Textures/_Sunrise/FleshCult/Interface/flesh_icon.rsi/Flesh.png new file mode 100644 index 0000000000..50a856637d Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/Interface/flesh_icon.rsi/Flesh.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/Interface/flesh_icon.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/Interface/flesh_icon.rsi/meta.json new file mode 100644 index 0000000000..7f9f90c8f1 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/Interface/flesh_icon.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "", + "size": { + "x": 8, + "y": 8 + }, + "states": [ + { + "name": "Flesh" + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/ball.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/ball.png new file mode 100644 index 0000000000..668cb4d9ca Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/ball.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/ball_dead.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/ball_dead.png new file mode 100644 index 0000000000..8682078e88 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/ball_dead.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/bat.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/bat.png new file mode 100644 index 0000000000..730a2675e9 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/bat.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/bat_dead.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/bat_dead.png new file mode 100644 index 0000000000..61d487618d Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/bat_dead.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/fleshhugger-equipped-MASK.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/fleshhugger-equipped-MASK.png new file mode 100644 index 0000000000..ab7ac8c850 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/fleshhugger-equipped-MASK.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/fleshhugger.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/fleshhugger.png new file mode 100644 index 0000000000..5452e11090 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/fleshhugger.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/fleshhugger_dead.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/fleshhugger_dead.png new file mode 100644 index 0000000000..55e4ea4de3 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/fleshhugger_dead.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/meta.json new file mode 100644 index 0000000000..6022a2c4b4 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/meta.json @@ -0,0 +1,83 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Made by brainfood1183 (github) for ss14", + "states": [ + { + "name": "worm", + "directions": 4 + }, + { + "name": "small_worm", + "directions": 4 + }, + { + "name": "fleshhugger", + "directions": 4 + }, + { + "name": "fleshhugger_dead" + }, + { + "name": "ball", + "directions": 4 + }, + { + "name": "ball_dead" + }, + { + "name": "spider_dead" + }, + { + "name": "bat_dead" + }, + { + "name": "worm_dead" + }, + { + "name": "small_worm_dead" + }, + { + "name": "spider", + "directions": 4 + }, + { + "name": "bat", + "directions": 4, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1 + ], + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "fleshhugger-equipped-MASK", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/small_worm.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/small_worm.png new file mode 100644 index 0000000000..d546a1baef Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/small_worm.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/small_worm_dead.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/small_worm_dead.png new file mode 100644 index 0000000000..c2134d8a98 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/small_worm_dead.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/spider.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/spider.png new file mode 100644 index 0000000000..c6ef3778d4 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/spider.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/spider_dead.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/spider_dead.png new file mode 100644 index 0000000000..780cdcc852 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/spider_dead.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/worm.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/worm.png new file mode 100644 index 0000000000..c18afd0095 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/worm.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/worm_dead.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/worm_dead.png new file mode 100644 index 0000000000..5a6777f396 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_mobs.rsi/worm_dead.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_pudge.rsi/alive.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_pudge.rsi/alive.png new file mode 100644 index 0000000000..5497a620f7 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_pudge.rsi/alive.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_pudge.rsi/dead.png b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_pudge.rsi/dead.png new file mode 100644 index 0000000000..e57ea6ed58 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_pudge.rsi/dead.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_cult_pudge.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_pudge.rsi/meta.json new file mode 100644 index 0000000000..e2e08adbc0 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/flesh_cult_pudge.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Made by brainfood1183 (github) for ss14", + "size": { + "x": 64, + "y": 64 + }, + "states": [ + { + "name": "alive", + "directions": 4 + }, + { + "name": "dead" + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_heart.rsi/base_heart.png b/Resources/Textures/_Sunrise/FleshCult/flesh_heart.rsi/base_heart.png new file mode 100644 index 0000000000..4ef650ee8c Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_heart.rsi/base_heart.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_heart.rsi/final_heart.png b/Resources/Textures/_Sunrise/FleshCult/flesh_heart.rsi/final_heart.png new file mode 100644 index 0000000000..130de2eff0 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_heart.rsi/final_heart.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_heart.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/flesh_heart.rsi/meta.json new file mode 100644 index 0000000000..678f792799 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/flesh_heart.rsi/meta.json @@ -0,0 +1,33 @@ +{ + "version":1, + "size":{ + "x":96, + "y":128 + }, + "license":"CC-BY-SA-3.0", + "copyright":"Made by brainfood1183 (github) for ss14", + "states":[ + { + "name":"base_heart", + "delays": [ + [ + 0.3, + 0.3, + 0.3, + 0.3 + ] + ] + }, + { + "name": "final_heart", + "delays": [ + [ + 0.3, + 0.3, + 0.3, + 0.3 + ] + ] + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_projectiles.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/flesh_projectiles.rsi/meta.json new file mode 100644 index 0000000000..473241f171 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/flesh_projectiles.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "spike" + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_projectiles.rsi/spike.png b/Resources/Textures/_Sunrise/FleshCult/flesh_projectiles.rsi/spike.png new file mode 100644 index 0000000000..0ce0ef0567 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_projectiles.rsi/spike.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/flesh_11.png b/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/flesh_11.png new file mode 100644 index 0000000000..baf033dcda Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/flesh_11.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/flesh_12.png b/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/flesh_12.png new file mode 100644 index 0000000000..b940e30eee Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/flesh_12.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/flesh_13.png b/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/flesh_13.png new file mode 100644 index 0000000000..28b6f5ac7a Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/flesh_13.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/meta.json new file mode 100644 index 0000000000..6343a9a95b --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/flesh_tile.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "flesh_13" + }, + { + "name": "flesh_12" + }, + { + "name": "flesh_11" + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_toxic.rsi/flesh_toxic.png b/Resources/Textures/_Sunrise/FleshCult/flesh_toxic.rsi/flesh_toxic.png new file mode 100644 index 0000000000..1763ad4b3f Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_toxic.rsi/flesh_toxic.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_toxic.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/flesh_toxic.rsi/meta.json new file mode 100644 index 0000000000..48d5ea1bed --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/flesh_toxic.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-NC-4.0", + "copyright": "https://github.com/tgstation/TerraGov-Marine-Corps/blob/f90afeb849db243c8613dbc4defd040aff689b72/icons/obj/items/projectiles.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "flesh_toxic" + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh0.png b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh0.png new file mode 100644 index 0000000000..4e6d8b5ee4 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh0.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh1.png b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh1.png new file mode 100644 index 0000000000..f4517ede4a Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh1.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh2.png b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh2.png new file mode 100644 index 0000000000..4e6d8b5ee4 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh2.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh3.png b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh3.png new file mode 100644 index 0000000000..f4517ede4a Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh3.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh4.png b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh4.png new file mode 100644 index 0000000000..1cabb528db Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh4.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh5.png b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh5.png new file mode 100644 index 0000000000..0ef78e79ac Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh5.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh6.png b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh6.png new file mode 100644 index 0000000000..1cabb528db Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh6.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh7.png b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh7.png new file mode 100644 index 0000000000..120787e309 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/flesh7.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/full.png b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/full.png new file mode 100644 index 0000000000..3deb3e3d5e Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/full.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/meta.json new file mode 100644 index 0000000000..fa2240ad23 --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/flesh_wall.rsi/meta.json @@ -0,0 +1,46 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "", + "states": [ + { + "name": "full" + }, + { + "name": "flesh0", + "directions": 4 + }, + { + "name": "flesh1", + "directions": 4 + }, + { + "name": "flesh2", + "directions": 4 + }, + { + "name": "flesh3", + "directions": 4 + }, + { + "name": "flesh4", + "directions": 4 + }, + { + "name": "flesh5", + "directions": 4 + }, + { + "name": "flesh6", + "directions": 4 + }, + { + "name": "flesh7", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_Sunrise/FleshCult/fleshspiderweb.rsi/meta.json b/Resources/Textures/_Sunrise/FleshCult/fleshspiderweb.rsi/meta.json new file mode 100644 index 0000000000..fbb29bcf3b --- /dev/null +++ b/Resources/Textures/_Sunrise/FleshCult/fleshspiderweb.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/tgstation/tgstation/commit/788b2576cd9511ced86e74222b6395fd3ef9affe", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "spider_web_1" + }, + { + "name": "spider_web_2" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_Sunrise/FleshCult/fleshspiderweb.rsi/spider_web_1.png b/Resources/Textures/_Sunrise/FleshCult/fleshspiderweb.rsi/spider_web_1.png new file mode 100644 index 0000000000..86e836b74f Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/fleshspiderweb.rsi/spider_web_1.png differ diff --git a/Resources/Textures/_Sunrise/FleshCult/fleshspiderweb.rsi/spider_web_2.png b/Resources/Textures/_Sunrise/FleshCult/fleshspiderweb.rsi/spider_web_2.png new file mode 100644 index 0000000000..b50f556cb9 Binary files /dev/null and b/Resources/Textures/_Sunrise/FleshCult/fleshspiderweb.rsi/spider_web_2.png differ