From e6fb001e1752d305da0330b239077541aff2e008 Mon Sep 17 00:00:00 2001 From: Kirus59 <145689588+Kirus59@users.noreply.github.com> Date: Thu, 10 Oct 2024 19:59:10 +0300 Subject: [PATCH] Spider queen antag v0.2 (#1789) * Spider queen antag v0.2 * move actions to unique component * add mana system * Add cocooning action * Actions optimization and delete needless implants * some optimization * add mana generation bonus from cocoons * Add game rule and some fixes * add cocoons sprites and some changes * some fixes... * Game Rule fixes * Add cocoons objective * Add survive objective and fixes * Add mana information into character briefing * Add station announcement * fix greentext * Balance changes and some fixes * Create cocoons conditoin fixes * yaml fixes * Add bonus to MaxMana from cocoons * Review fixes * Add doAfter to SpiderWorldSpawnEvent, add wallspawn animation and some fixes * ops... * Cocoons bonus change * Some fixes * Some fixes 2 * Rename mana and some changes * Some fixes * Tag fix * Add hunger conversion * Mother of balance * some fixes * change actions description and some changes * some changes * yaml fixes * fix cocoons damage per second * balance changes * add alert for blood points and some fixes * add alert name and desc * post-review fixes * forgot add to BasicAntagEventsTable * some optimization * post-tests fixes * delete needless usings * delete needless using and dependency * delete needless comment --- Content.Server/Roles/RoleSystem.cs | 3 + .../Markers/AntagSpawnMarkerComponent.cs | 7 + .../CreateCocoonsConditionComponent.cs | 7 + .../Systems/CreateCocoonsConditionSystem.cs | 49 +++ .../SS220/Roles/SpiderQueenRoleComponent.cs | 11 + .../Components/SpiderQueenRuleComponent.cs | 15 + .../SpiderQueen/Systems/SpiderCocoonSystem.cs | 172 +++++++++++ .../Systems/SpiderQueenRuleSystem.cs | 95 ++++++ .../SpiderQueen/Systems/SpiderQueenSystem.cs | 231 +++++++++++++++ .../Components/DamageContactsComponent.cs | 16 + .../Components/DamagedByContactComponent.cs | 9 + .../Damage/Systems/DamageContactsSystem.cs | 23 +- .../Components/SpiderCocoonComponent.cs | 64 ++++ .../Components/SpiderQueenComponent.cs | 89 ++++++ .../SpiderQueen/SharedSpiderQueenEvents.cs | 110 +++++++ .../Systems/SharedSpiderQueenSystem.cs | 149 ++++++++++ .../ru-RU/ss220/actions/spider-actions.ftl | 30 +- .../Locale/ru-RU/ss220/alerts/alerts.ftl | 2 + .../ru-RU/ss220/misc/spider-implants.ftl | 34 --- .../Locale/ru-RU/ss220/mobs/spider-queen.ftl | 36 +-- .../ru-RU/ss220/objectives/spider-queen.ftl | 19 ++ .../prototypes/entities/markings/markers.ftl | 3 + .../ru-RU/ss220/spider-queen/spider-queen.ftl | 19 ++ .../ss220/strucrure/spider-structures.ftl | 25 ++ Resources/Prototypes/Actions/spider.yml | 4 +- Resources/Prototypes/Alerts/alerts.yml | 1 + Resources/Prototypes/GameRules/events.yml | 1 + .../SS220/Actions/Spider_actions.yml | 137 ++++++--- .../Prototypes/SS220/Alerts/spider_queen.yml | 55 ++++ .../Prototypes/SS220/Antags/spider_queen.yml | 5 + .../Prototypes/SS220/Damage/modifier_sets.yml | 55 ++++ .../SS220/Entities/Mobs/NPCs/spider_queen.yml | 226 ++++++++------ .../Entities/Objects/Misc/spider_eggs.yml | 8 +- .../Entities/Objects/Misc/spider_implants.yml | 141 --------- .../Entities/Objects/Misc/spider_web.yml | 31 +- .../Structures/Specific/spider_structures.yml | 279 ++++++++++++------ .../markers/Spawners/antag-markers.yml | 16 + .../Entities/markers/Spawners/ghost_roles.yml | 5 +- .../SS220/GameRules/midround_antags.yml | 32 ++ .../SS220/Objectives/spider_queen.yml | 38 +++ .../Graphs/structures/spider_structures.yml | 54 ++++ Resources/Prototypes/SS220/tags.yml | 16 + .../SS220/Effects/wallwebspawn.rsi/meta.json | 31 ++ .../Effects/wallwebspawn.rsi/webwall.png | Bin 0 -> 10176 bytes .../Actions/action_spider.rsi/cocoon.png | Bin 0 -> 1370 bytes .../action_spider.rsi/crystal_spawn.png | Bin 0 -> 1362 bytes .../Actions/action_spider.rsi/meta.json | 9 + .../Actions/action_spider.rsi/wall_spawn.png | Bin 0 -> 1299 bytes .../SS220/Interface/Actions/meta.json | 14 + .../Textures/SS220/Interface/Actions/web.png | Bin 0 -> 755 bytes .../Alerts/blood_counter.rsi/blood0.png | Bin 0 -> 1206 bytes .../Alerts/blood_counter.rsi/blood1.png | Bin 0 -> 1402 bytes .../Alerts/blood_counter.rsi/blood10.png | Bin 0 -> 1347 bytes .../Alerts/blood_counter.rsi/blood11.png | Bin 0 -> 1351 bytes .../Alerts/blood_counter.rsi/blood12.png | Bin 0 -> 1314 bytes .../Alerts/blood_counter.rsi/blood13.png | Bin 0 -> 1317 bytes .../Alerts/blood_counter.rsi/blood14.png | Bin 0 -> 1281 bytes .../Alerts/blood_counter.rsi/blood15.png | Bin 0 -> 1299 bytes .../Alerts/blood_counter.rsi/blood16.png | Bin 0 -> 1263 bytes .../Alerts/blood_counter.rsi/blood17.png | Bin 0 -> 1243 bytes .../Alerts/blood_counter.rsi/blood18.png | Bin 0 -> 1232 bytes .../Alerts/blood_counter.rsi/blood19.png | Bin 0 -> 1224 bytes .../Alerts/blood_counter.rsi/blood2.png | Bin 0 -> 1352 bytes .../Alerts/blood_counter.rsi/blood20.png | Bin 0 -> 1199 bytes .../Alerts/blood_counter.rsi/blood21.png | Bin 0 -> 1196 bytes .../Alerts/blood_counter.rsi/blood22.png | Bin 0 -> 1187 bytes .../Alerts/blood_counter.rsi/blood23.png | Bin 0 -> 1177 bytes .../Alerts/blood_counter.rsi/blood3.png | Bin 0 -> 1423 bytes .../Alerts/blood_counter.rsi/blood4.png | Bin 0 -> 1428 bytes .../Alerts/blood_counter.rsi/blood5.png | Bin 0 -> 1440 bytes .../Alerts/blood_counter.rsi/blood6.png | Bin 0 -> 1403 bytes .../Alerts/blood_counter.rsi/blood7.png | Bin 0 -> 1381 bytes .../Alerts/blood_counter.rsi/blood8.png | Bin 0 -> 1370 bytes .../Alerts/blood_counter.rsi/blood9.png | Bin 0 -> 1337 bytes .../Alerts/blood_counter.rsi/meta.json | 83 ++++++ .../Specific/cocoon.rsi/cocoon1.png | Bin 0 -> 1622 bytes .../Specific/cocoon.rsi/cocoon2.png | Bin 0 -> 1281 bytes .../Specific/cocoon.rsi/destroyed_cocoon1.png | Bin 0 -> 1576 bytes .../Specific/cocoon.rsi/destroyed_cocoon2.png | Bin 0 -> 1138 bytes .../Structures/Specific/cocoon.rsi/meta.json | 23 ++ 80 files changed, 2048 insertions(+), 434 deletions(-) create mode 100644 Content.Server/SS220/Markers/AntagSpawnMarkerComponent.cs create mode 100644 Content.Server/SS220/Objectives/Components/CreateCocoonsConditionComponent.cs create mode 100644 Content.Server/SS220/Objectives/Systems/CreateCocoonsConditionSystem.cs create mode 100644 Content.Server/SS220/Roles/SpiderQueenRoleComponent.cs create mode 100644 Content.Server/SS220/SpiderQueen/Components/SpiderQueenRuleComponent.cs create mode 100644 Content.Server/SS220/SpiderQueen/Systems/SpiderCocoonSystem.cs create mode 100644 Content.Server/SS220/SpiderQueen/Systems/SpiderQueenRuleSystem.cs create mode 100644 Content.Server/SS220/SpiderQueen/Systems/SpiderQueenSystem.cs create mode 100644 Content.Shared/SS220/SpiderQueen/Components/SpiderCocoonComponent.cs create mode 100644 Content.Shared/SS220/SpiderQueen/Components/SpiderQueenComponent.cs create mode 100644 Content.Shared/SS220/SpiderQueen/SharedSpiderQueenEvents.cs create mode 100644 Content.Shared/SS220/SpiderQueen/Systems/SharedSpiderQueenSystem.cs create mode 100644 Resources/Locale/ru-RU/ss220/alerts/alerts.ftl delete mode 100644 Resources/Locale/ru-RU/ss220/misc/spider-implants.ftl create mode 100644 Resources/Locale/ru-RU/ss220/objectives/spider-queen.ftl create mode 100644 Resources/Locale/ru-RU/ss220/prototypes/entities/markings/markers.ftl create mode 100644 Resources/Locale/ru-RU/ss220/spider-queen/spider-queen.ftl create mode 100644 Resources/Prototypes/SS220/Alerts/spider_queen.yml create mode 100644 Resources/Prototypes/SS220/Antags/spider_queen.yml delete mode 100644 Resources/Prototypes/SS220/Entities/Objects/Misc/spider_implants.yml create mode 100644 Resources/Prototypes/SS220/Entities/markers/Spawners/antag-markers.yml create mode 100644 Resources/Prototypes/SS220/Objectives/spider_queen.yml create mode 100644 Resources/Prototypes/SS220/Recipes/Construction/Graphs/structures/spider_structures.yml create mode 100644 Resources/Textures/SS220/Effects/wallwebspawn.rsi/meta.json create mode 100644 Resources/Textures/SS220/Effects/wallwebspawn.rsi/webwall.png create mode 100644 Resources/Textures/SS220/Interface/Actions/action_spider.rsi/cocoon.png create mode 100644 Resources/Textures/SS220/Interface/Actions/action_spider.rsi/crystal_spawn.png create mode 100644 Resources/Textures/SS220/Interface/Actions/action_spider.rsi/wall_spawn.png create mode 100644 Resources/Textures/SS220/Interface/Actions/meta.json create mode 100644 Resources/Textures/SS220/Interface/Actions/web.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood0.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood1.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood10.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood11.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood12.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood13.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood14.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood15.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood16.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood17.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood18.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood19.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood2.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood20.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood21.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood22.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood23.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood3.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood4.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood5.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood6.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood7.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood8.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood9.png create mode 100644 Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/meta.json create mode 100644 Resources/Textures/SS220/Structures/Specific/cocoon.rsi/cocoon1.png create mode 100644 Resources/Textures/SS220/Structures/Specific/cocoon.rsi/cocoon2.png create mode 100644 Resources/Textures/SS220/Structures/Specific/cocoon.rsi/destroyed_cocoon1.png create mode 100644 Resources/Textures/SS220/Structures/Specific/cocoon.rsi/destroyed_cocoon2.png create mode 100644 Resources/Textures/SS220/Structures/Specific/cocoon.rsi/meta.json diff --git a/Content.Server/Roles/RoleSystem.cs b/Content.Server/Roles/RoleSystem.cs index 03513d205f57a9..e87b6fdccbd2bc 100644 --- a/Content.Server/Roles/RoleSystem.cs +++ b/Content.Server/Roles/RoleSystem.cs @@ -1,3 +1,4 @@ +using Content.Server.SS220.Roles; using Content.Shared.Roles; using Content.Shared.SS220.DarkReaper; using Content.Shared.SS220.MindSlave; @@ -24,6 +25,8 @@ public override void Initialize() SubscribeAntagEvents(); //SS220 DarkReaper SubscribeAntagEvents(); + //SS220 Spider queen + SubscribeAntagEvents(); } public string? MindGetBriefing(EntityUid? mindId) diff --git a/Content.Server/SS220/Markers/AntagSpawnMarkerComponent.cs b/Content.Server/SS220/Markers/AntagSpawnMarkerComponent.cs new file mode 100644 index 00000000000000..20ae229c053899 --- /dev/null +++ b/Content.Server/SS220/Markers/AntagSpawnMarkerComponent.cs @@ -0,0 +1,7 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +namespace Content.Server.SS220.Markers; + +[RegisterComponent] +public sealed partial class AntagSpawnMarkerComponent : Component +{ +} diff --git a/Content.Server/SS220/Objectives/Components/CreateCocoonsConditionComponent.cs b/Content.Server/SS220/Objectives/Components/CreateCocoonsConditionComponent.cs new file mode 100644 index 00000000000000..bd348a1608c059 --- /dev/null +++ b/Content.Server/SS220/Objectives/Components/CreateCocoonsConditionComponent.cs @@ -0,0 +1,7 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +namespace Content.Server.SS220.Objectives.Components; + +[RegisterComponent] +public sealed partial class CreateCocoonsConditionComponent : Component +{ +} diff --git a/Content.Server/SS220/Objectives/Systems/CreateCocoonsConditionSystem.cs b/Content.Server/SS220/Objectives/Systems/CreateCocoonsConditionSystem.cs new file mode 100644 index 00000000000000..3ed262ca6452b3 --- /dev/null +++ b/Content.Server/SS220/Objectives/Systems/CreateCocoonsConditionSystem.cs @@ -0,0 +1,49 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Server.Objectives.Systems; +using Content.Server.SS220.Objectives.Components; +using Content.Server.SS220.Roles; +using Content.Shared.Mind; +using Content.Shared.Objectives.Components; +using Content.Shared.SS220.SpiderQueen.Components; + +namespace Content.Server.SS220.Objectives.Systems; + +public sealed partial class CreateCocoonsConditionSystem : EntitySystem +{ + [Dependency] private readonly NumberObjectiveSystem _number = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetProgress); + } + + private void OnGetProgress(Entity ent, ref ObjectiveGetProgressEvent args) + { + args.Progress = GetProgress(args.MindId, args.Mind, _number.GetTarget(ent.Owner)); + } + + private float GetProgress(EntityUid mindId, MindComponent mind, int target) + { + if (!TryComp(mindId, out var spiderQueenRole)) + return 0f; + + if (spiderQueenRole.IsCreateCocoonsCompletedOnce) + return 1f; + + var mobUid = mind.CurrentEntity; + if (mobUid is null || + !TryComp(mobUid, out var spiderQueen)) + return 0f; + + var progress = spiderQueen.CocoonsList.Count >= target + ? 1f + : (float)spiderQueen.CocoonsList.Count / (float)target; + + if (progress == 1f) + spiderQueenRole.IsCreateCocoonsCompletedOnce = true; + + return progress; + } +} diff --git a/Content.Server/SS220/Roles/SpiderQueenRoleComponent.cs b/Content.Server/SS220/Roles/SpiderQueenRoleComponent.cs new file mode 100644 index 00000000000000..d133981679a767 --- /dev/null +++ b/Content.Server/SS220/Roles/SpiderQueenRoleComponent.cs @@ -0,0 +1,11 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Shared.Roles; + +namespace Content.Server.SS220.Roles; + +[RegisterComponent, ExclusiveAntagonist] +public sealed partial class SpiderQueenRoleComponent : AntagonistRoleComponent +{ + [ViewVariables] + public bool IsCreateCocoonsCompletedOnce = false; +} diff --git a/Content.Server/SS220/SpiderQueen/Components/SpiderQueenRuleComponent.cs b/Content.Server/SS220/SpiderQueen/Components/SpiderQueenRuleComponent.cs new file mode 100644 index 00000000000000..80a87e122735be --- /dev/null +++ b/Content.Server/SS220/SpiderQueen/Components/SpiderQueenRuleComponent.cs @@ -0,0 +1,15 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Shared.Whitelist; + +namespace Content.Server.SS220.SpiderQueen.Components; + +[RegisterComponent] +public sealed partial class SpiderQueenRuleComponent : Component +{ + /// + /// Spawn on a random entity that passed whitelist. + /// If null - spawn on a random tile. + /// + [DataField] + public EntityWhitelist? MarkersWhitelist; +} diff --git a/Content.Server/SS220/SpiderQueen/Systems/SpiderCocoonSystem.cs b/Content.Server/SS220/SpiderQueen/Systems/SpiderCocoonSystem.cs new file mode 100644 index 00000000000000..49d85cca36cafc --- /dev/null +++ b/Content.Server/SS220/SpiderQueen/Systems/SpiderCocoonSystem.cs @@ -0,0 +1,172 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Server.Body.Components; +using Content.Server.Body.Systems; +using Content.Server.DoAfter; +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Damage; +using Content.Shared.DoAfter; +using Content.Shared.Examine; +using Content.Shared.FixedPoint; +using Content.Shared.Nutrition.EntitySystems; +using Content.Shared.SS220.SpiderQueen; +using Content.Shared.SS220.SpiderQueen.Components; +using Content.Shared.Verbs; +using Robust.Shared.Containers; +using Robust.Shared.Timing; + +namespace Content.Server.SS220.SpiderQueen.Systems; + +public sealed partial class SpiderCocoonSystem : EntitySystem +{ + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; + [Dependency] private readonly SpiderQueenSystem _spiderQueen = default!; + [Dependency] private readonly BloodstreamSystem _bloodstream = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly HungerSystem _hunger = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent>(OnAlternativeVerb); + SubscribeLocalEvent(OnExtractBloodPoints); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var component)) + { + if (_gameTiming.CurTime < component.NextSecond) + continue; + + component.NextSecond = _gameTiming.CurTime + TimeSpan.FromSeconds(1); + if (!_container.TryGetContainer(uid, component.CocoonContainerId, out var container) || + container.ContainedEntities is not { } entities || + entities.Count <= 0) + continue; + + foreach (var entity in entities) + { + ConvertBloodIntoBloodPoints(uid, component, entity, component.BloodConversionPerSecond); + CauseCocoonDamage(uid, component, entity); + } + } + } + + private void OnShutdown(Entity entity, ref ComponentShutdown args) + { + var (uid, comp) = entity; + if (comp.CocoonOwner is null || + !TryComp(comp.CocoonOwner, out var queenComponent)) + return; + + queenComponent.CocoonsList.Remove(uid); + queenComponent.MaxBloodPoints -= entity.Comp.BloodPointsBonus; + } + + private void OnExamine(Entity entity, ref ExaminedEvent args) + { + if (HasComp(args.Examiner)) + { + args.PushMarkup(Loc.GetString("spider-cocoon-blood-points-amount", ("amount", entity.Comp.BloodPointsAmount))); + } + } + + private void OnAlternativeVerb(EntityUid uid, SpiderCocoonComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || + !TryComp(args.User, out var spiderQueen)) + return; + + var extractVerb = new AlternativeVerb + { + Text = Loc.GetString("spider-cocoon-extract-blood-points-verb"), + Act = () => + { + var doAfterEventArgs = new DoAfterArgs(EntityManager, + args.User, + spiderQueen.CocoonExtractTime, + new CocoonExtractBloodPointsEvent(), + uid, + uid) + { + Broadcast = false, + BreakOnDamage = false, + BreakOnMove = true, + NeedHand = false + }; + + _doAfter.TryStartDoAfter(doAfterEventArgs); + } + }; + + args.Verbs.Add(extractVerb); + } + + private void OnExtractBloodPoints(Entity entity, ref CocoonExtractBloodPointsEvent args) + { + if (args.Cancelled || + !TryComp(args.User, out var spiderQueen)) + return; + + var amountToMax = spiderQueen.MaxBloodPoints - spiderQueen.CurrentBloodPoints; + var extractedValue = MathF.Min((float)amountToMax, (float)entity.Comp.BloodPointsAmount); + entity.Comp.BloodPointsAmount -= extractedValue; + spiderQueen.CurrentBloodPoints += extractedValue; + + _hunger.ModifyHunger(args.User, extractedValue * spiderQueen.HungerExtractCoefficient); + + Dirty(args.User, spiderQueen); + Dirty(entity); + _spiderQueen.UpdateAlert((args.User, spiderQueen)); + } + + /// + /// Converts entity blood into blood points based on the + /// + private void ConvertBloodIntoBloodPoints(EntityUid uid, SpiderCocoonComponent component, EntityUid target, FixedPoint2 amount) + { + if (!TryComp(target, out var bloodstream) || + !_solutionContainer.ResolveSolution(target, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution)) + return; + + var solutionEnt = bloodstream.BloodSolution.Value; + if (solutionEnt.Comp.Solution.Volume <= FixedPoint2.Zero) + return; + + _bloodstream.TryModifyBleedAmount(target, -1f, bloodstream); + _solutionContainer.SplitSolution(solutionEnt, amount); + component.BloodPointsAmount += amount * component.BloodConversionCoefficient; + Dirty(uid, component); + } + + private void CauseCocoonDamage(EntityUid uid, SpiderCocoonComponent component, EntityUid target) + { + if (!TryComp(target, out var damageable) || + component.DamagePerSecond is not { } damagePerSecond) + return; + + DamageSpecifier causedDamage = new(); + foreach (var damage in damagePerSecond.DamageDict) + { + var (type, value) = damage; + if (component.DamageCap.TryGetValue(type, out var cap) && + damageable.Damage.DamageDict.TryGetValue(type, out var total) && + total >= cap) + continue; + + causedDamage.DamageDict.Add(type, value); + } + + _damageable.TryChangeDamage(target, causedDamage, true); + Dirty(uid, component); + } +} diff --git a/Content.Server/SS220/SpiderQueen/Systems/SpiderQueenRuleSystem.cs b/Content.Server/SS220/SpiderQueen/Systems/SpiderQueenRuleSystem.cs new file mode 100644 index 00000000000000..ccca05908276ae --- /dev/null +++ b/Content.Server/SS220/SpiderQueen/Systems/SpiderQueenRuleSystem.cs @@ -0,0 +1,95 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Server.Antag; +using Content.Server.GameTicking.Rules; +using Content.Server.Mind; +using Content.Server.Respawn; +using Content.Server.Roles; +using Content.Server.SS220.Markers; +using Content.Server.SS220.Roles; +using Content.Server.SS220.SpiderQueen.Components; +using Content.Server.Station.Components; +using Content.Server.Station.Systems; +using Content.Shared.Whitelist; +using Robust.Shared.Map; + +namespace Content.Server.SS220.SpiderQueen.Systems; + +public sealed class SpiderQueenRuleSystem : GameRuleSystem +{ + [Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly StationSystem _station = default!; + [Dependency] private readonly SpecialRespawnSystem _specialRespawn = default!; + [Dependency] private readonly MindSystem _mind = default!; + [Dependency] private readonly AntagSelectionSystem _antag = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAntagSelectLocation); + SubscribeLocalEvent(AfterEntitySelected); + + SubscribeLocalEvent(OnGetBriefing); + } + + private void OnAntagSelectLocation(Entity ent, ref AntagSelectLocationEvent args) + { + if (args.Handled) + return; + + List validCoordinates = new(); + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out _)) + { + if (_entityWhitelist.IsWhitelistFail(ent.Comp.MarkersWhitelist, uid) || + !TryComp(uid, out var transform)) + continue; + + validCoordinates.Add(_transform.ToMapCoordinates(transform.Coordinates)); + } + + if (validCoordinates.Count > 0) + args.Coordinates = validCoordinates; + else + { + EntityUid? grid = null; + EntityUid? map = null; + foreach (var station in _station.GetStationsSet()) + { + if (!TryComp(station, out var data)) + continue; + + grid = _station.GetLargestGrid(data); + if (!grid.HasValue) + continue; + + map = Transform(grid.Value).MapUid; + if (!map.HasValue) + continue; + + break; + } + + if (grid.HasValue && map.HasValue && + _specialRespawn.TryFindRandomTile(grid.Value, map.Value, 30, out var randomCoords)) + args.Coordinates.Add(_transform.ToMapCoordinates(randomCoords)); + } + } + + private void AfterEntitySelected(Entity ent, ref AfterAntagEntitySelectedEvent args) + { + var spider = args.EntityUid; + if (!_mind.TryGetMind(spider, out var mindId, out var mind)) + return; + + var briefing = Loc.GetString("spider-queen-role-greeting"); + _antag.SendBriefing(spider, briefing, null, null); + } + + private void OnGetBriefing(Entity ent, ref GetBriefingEvent args) + { + var briefing = Loc.GetString("spider-queen-role-greeting"); + args.Append(briefing); + } +} diff --git a/Content.Server/SS220/SpiderQueen/Systems/SpiderQueenSystem.cs b/Content.Server/SS220/SpiderQueen/Systems/SpiderQueenSystem.cs new file mode 100644 index 00000000000000..36a45b0277d86d --- /dev/null +++ b/Content.Server/SS220/SpiderQueen/Systems/SpiderQueenSystem.cs @@ -0,0 +1,231 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Server.Chat.Systems; +using Content.Server.Pinpointer; +using Content.Shared.Coordinates.Helpers; +using Content.Shared.DoAfter; +using Content.Shared.FixedPoint; +using Content.Shared.Mobs.Systems; +using Content.Shared.Nutrition.Components; +using Content.Shared.Nutrition.EntitySystems; +using Content.Shared.SS220.SpiderQueen; +using Content.Shared.SS220.SpiderQueen.Components; +using Content.Shared.SS220.SpiderQueen.Systems; +using Content.Shared.Storage; +using Robust.Server.GameObjects; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Containers; +using Robust.Shared.Map; +using Robust.Shared.Player; +using Robust.Shared.Random; +using Robust.Shared.Timing; +using Robust.Shared.Utility; +using System.Numerics; + +namespace Content.Server.SS220.SpiderQueen.Systems; + +public sealed partial class SpiderQueenSystem : SharedSpiderQueenSystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly NavMapSystem _navMap = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly HungerSystem _hunger = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAfterCocooning); + SubscribeLocalEvent(OnTargetSpawn); + SubscribeLocalEvent(OnSpawnDoAfter); + SubscribeLocalEvent(OnNearbySpawn); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) + { + if (_timing.CurTime < comp.NextSecond) + continue; + + comp.NextSecond = _timing.CurTime + TimeSpan.FromSeconds(1); + + if (!_hunger.IsHungerBelowState(uid, HungerThreshold.Okay)) + ConvertHungerIntoBloodPoints(uid, comp, comp.HungerConversionPerSecond); + } + } + + private void OnTargetSpawn(Entity entity, ref SpiderTargetSpawnEvent args) + { + var spider = entity.Owner; + if (args.Handled || + spider != args.Performer || + !CheckEnoughBloodPoints(spider, args.Cost, entity.Comp)) + return; + + if (TryStartSpiderSpawnDoAfter(spider, args.DoAfter, args.Target, args.Prototypes, args.Offset, args.Cost)) + { + args.Handled = true; + } + else + { + Log.Error($"Failed to start DoAfter by {spider}"); + return; + } + } + + private void OnNearbySpawn(Entity entity, ref SpiderNearbySpawnEvent args) + { + var spider = entity.Owner; + if (args.Handled || + spider != args.Performer || + !TryComp(entity.Owner, out var transform) || + !CheckEnoughBloodPoints(spider, args.Cost, entity.Comp)) + return; + + if (TryStartSpiderSpawnDoAfter(spider, args.DoAfter, transform.Coordinates, args.Prototypes, args.Offset, args.Cost)) + { + args.Handled = true; + } + else + { + Log.Error($"Failed to start DoAfter by {spider}"); + return; + } + } + + private void OnSpawnDoAfter(Entity entity, ref SpiderSpawnDoAfterEvent args) + { + if (args.Cancelled || + !CheckEnoughBloodPoints(entity, args.Cost, entity.Comp)) + return; + + entity.Comp.CurrentBloodPoints -= args.Cost; + Dirty(entity); + UpdateAlert(entity); + + var getProtos = EntitySpawnCollection.GetSpawns(args.Prototypes, _random); + var targetMapCords = GetCoordinates(args.TargetCoordinates); + foreach (var proto in getProtos) + { + Spawn(proto, targetMapCords.SnapToGrid(EntityManager, _mapManager)); + targetMapCords = targetMapCords.Offset(args.Offset); + } + } + + private void OnAfterCocooning(Entity entity, ref AfterCocooningEvent args) + { + if (args.Cancelled || args.Target is not EntityUid target) + return; + + if (!TryComp(target, out var transform) || !_mobState.IsDead(target)) + return; + + var targetCords = _transform.GetMoverCoordinates(target, transform); + var cocoonPrototypeID = _random.Pick(entity.Comp.CocoonPrototypes); + var cocoonUid = Spawn(cocoonPrototypeID, targetCords); + + if (!TryComp(cocoonUid, out var spiderCocoon) || + !_container.TryGetContainer(cocoonUid, spiderCocoon.CocoonContainerId, out var container)) + { + Log.Error($"{cocoonUid} doesn't have required components to cocooning target"); + return; + } + + _container.Insert(target, container); + entity.Comp.CocoonsList.Add(cocoonUid); + entity.Comp.MaxBloodPoints += spiderCocoon.BloodPointsBonus; + Dirty(entity); + UpdateAlert(entity); + + spiderCocoon.CocoonOwner = entity.Owner; + Dirty(cocoonUid, spiderCocoon); + + if (entity.Comp.CocoonsCountToAnnouncement is { } value && + entity.Comp.CocoonsList.Count >= value) + DoStationAnnouncement(entity); + } + + /// + /// Do a station announcement if all conditions are met + /// + private void DoStationAnnouncement(EntityUid uid, SpiderQueenComponent? component = null) + { + if (!Resolve(uid, ref component) || + component.IsAnnouncedOnce || + !TryComp(uid, out var xform)) + return; + + var msg = Loc.GetString("spider-queen-warning", + ("location", FormattedMessage.RemoveMarkupOrThrow(_navMap.GetNearestBeaconString((uid, xform))))); + _chat.DispatchGlobalAnnouncement(msg, playSound: false, colorOverride: Color.Red); + _audio.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast(), true); + component.IsAnnouncedOnce = true; + } + + /// + /// Converts hunger into blood points based on the + /// + private void ConvertHungerIntoBloodPoints(EntityUid uid, SpiderQueenComponent component, float amount, HungerComponent? hunger = null) + { + if (!Resolve(uid, ref hunger)) + return; + + var amountToMax = component.MaxBloodPoints - component.CurrentBloodPoints; + if (amountToMax <= FixedPoint2.Zero) + return; + + var value = amount * component.HungerConvertCoefficient; + value = MathF.Min(value, (float)amountToMax); + + var hungerDecreaseValue = -(value / component.HungerConvertCoefficient); + _hunger.ModifyHunger(uid, hungerDecreaseValue, hunger); + component.CurrentBloodPoints += value; + Dirty(uid, component); + UpdateAlert((uid, component)); + } + + private bool TryStartSpiderSpawnDoAfter(EntityUid spider, + TimeSpan doAfter, + EntityCoordinates coordinates, + List prototypes, + Vector2 offset, + FixedPoint2 cost) + { + var netCoordinates = GetNetCoordinates(coordinates); + var doAfterArgs = new DoAfterArgs( + EntityManager, + spider, + doAfter, + new SpiderSpawnDoAfterEvent() + { + TargetCoordinates = netCoordinates, + Prototypes = prototypes, + Offset = offset, + Cost = cost, + }, + spider + ) + { + Broadcast = false, + BreakOnDamage = false, + BreakOnMove = true, + NeedHand = false, + BlockDuplicate = true, + CancelDuplicate = true, + DuplicateCondition = DuplicateConditions.SameEvent + }; + + var started = _doAfter.TryStartDoAfter(doAfterArgs); + return started; + } +} diff --git a/Content.Shared/Damage/Components/DamageContactsComponent.cs b/Content.Shared/Damage/Components/DamageContactsComponent.cs index 4ae88db8d72bea..e3895de2534eb2 100644 --- a/Content.Shared/Damage/Components/DamageContactsComponent.cs +++ b/Content.Shared/Damage/Components/DamageContactsComponent.cs @@ -17,4 +17,20 @@ public sealed partial class DamageContactsComponent : Component /// [DataField("ignoreWhitelist")] public EntityWhitelist? IgnoreWhitelist; + + //SS220 Add ignore blacklist begin + /// + /// Entities that damaged by this entity + /// + [DataField] + public EntityWhitelist? IgnoreBlacklist; + //SS220 Add ignore blacklist end + + //SS220 Add stand still time begin + /// + /// How many seconds does a entity need to stand still to start taking damage + /// + [DataField] + public TimeSpan StandStillTime = TimeSpan.Zero; + //SS220 Add stand still time end } diff --git a/Content.Shared/Damage/Components/DamagedByContactComponent.cs b/Content.Shared/Damage/Components/DamagedByContactComponent.cs index bc86f1f5e2a158..937101f0a30fb3 100644 --- a/Content.Shared/Damage/Components/DamagedByContactComponent.cs +++ b/Content.Shared/Damage/Components/DamagedByContactComponent.cs @@ -4,6 +4,7 @@ namespace Content.Shared.Damage.Components; [NetworkedComponent, RegisterComponent] +[AutoGenerateComponentState] //SS220 Add stand still time public sealed partial class DamagedByContactComponent : Component { [DataField("nextSecond", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] @@ -11,4 +12,12 @@ public sealed partial class DamagedByContactComponent : Component [ViewVariables] public DamageSpecifier? Damage; + + //SS220 Add stand still time begin + [ViewVariables, AutoNetworkedField] + public TimeSpan LastMovement = TimeSpan.Zero; + + [DataField, ViewVariables, AutoNetworkedField] + public TimeSpan StandStillTime = TimeSpan.Zero; + //SS220 Add stand still time end } diff --git a/Content.Shared/Damage/Systems/DamageContactsSystem.cs b/Content.Shared/Damage/Systems/DamageContactsSystem.cs index 7516f9574d1714..5bcdb4472e8888 100644 --- a/Content.Shared/Damage/Systems/DamageContactsSystem.cs +++ b/Content.Shared/Damage/Systems/DamageContactsSystem.cs @@ -21,6 +21,9 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnEntityEnter); SubscribeLocalEvent(OnEntityExit); + + //SS220 Add stand still time + SubscribeLocalEvent(OnMove); } public override void Update(float frameTime) @@ -31,7 +34,8 @@ public override void Update(float frameTime) while (query.MoveNext(out var ent, out var damaged)) { - if (_timing.CurTime < damaged.NextSecond) + if (_timing.CurTime < damaged.NextSecond || + _timing.CurTime < damaged.LastMovement + damaged.StandStillTime) //SS220 Add stand still time continue; damaged.NextSecond = _timing.CurTime + TimeSpan.FromSeconds(1); @@ -91,10 +95,25 @@ private void OnEntityEnter(EntityUid uid, DamageContactsComponent component, ref if (HasComp(otherUid)) return; - if (_whitelistSystem.IsWhitelistPass(component.IgnoreWhitelist, otherUid)) + if (_whitelistSystem.IsWhitelistPass(component.IgnoreWhitelist, otherUid) || + _whitelistSystem.IsBlacklistFail(component.IgnoreBlacklist, otherUid)) //SS220 Add ignore blacklist return; var damagedByContact = EnsureComp(otherUid); damagedByContact.Damage = component.Damage; + + //SS220 Add stand still time begin + damagedByContact.StandStillTime = component.StandStillTime; + Dirty(otherUid, damagedByContact); + //SS220 Add stand still time end + } + + //SS220 Add stand still time begin + private void OnMove(Entity ent, ref MoveEvent args) + { + var (uid, component) = ent; + component.LastMovement = _timing.CurTime; + Dirty(uid, component); } + //SS220 Add stand still time end } diff --git a/Content.Shared/SS220/SpiderQueen/Components/SpiderCocoonComponent.cs b/Content.Shared/SS220/SpiderQueen/Components/SpiderCocoonComponent.cs new file mode 100644 index 00000000000000..b34e339867ddd0 --- /dev/null +++ b/Content.Shared/SS220/SpiderQueen/Components/SpiderCocoonComponent.cs @@ -0,0 +1,64 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Shared.Damage; +using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; + +namespace Content.Shared.SS220.SpiderQueen.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SpiderCocoonComponent : Component +{ + /// + /// The time at which the next every-second action will occur (for example ). + /// + [ViewVariables] + public TimeSpan NextSecond = TimeSpan.Zero; + + /// + /// The entity that created this cocoon + /// + [ViewVariables, AutoNetworkedField] + public EntityUid? CocoonOwner; + + /// + /// ID of the container in which the entities placed in the cocoon are stored + /// + [DataField("container", required: true)] + public string CocoonContainerId = "cocoon"; + + /// + /// Bonus to max blood points from this cocoon + /// + [DataField] + public FixedPoint2 BloodPointsBonus = FixedPoint2.Zero; + + /// + /// The amount of blood points that can be extracted from the cocoon + /// + [DataField, AutoNetworkedField] + public FixedPoint2 BloodPointsAmount = FixedPoint2.Zero; + + /// + /// How much blood points is given for each unit of blood + /// + [DataField, AutoNetworkedField] + public float BloodConversionCoefficient = 1f; + + /// + /// How much blood is converted into blood points per second + /// + [DataField("bloodConversion"), AutoNetworkedField] + public FixedPoint2 BloodConversionPerSecond = FixedPoint2.New(0.5); + + /// + /// How much damage does the entity receive inside the cocoon + /// + [DataField("damage")] + public DamageSpecifier? DamagePerSecond; + + /// + /// The cap of the damage of the entity, above which the cocoon cannot cause damage. + /// + [DataField] + public Dictionary DamageCap = new(); +} diff --git a/Content.Shared/SS220/SpiderQueen/Components/SpiderQueenComponent.cs b/Content.Shared/SS220/SpiderQueen/Components/SpiderQueenComponent.cs new file mode 100644 index 00000000000000..2a1802fd40e90a --- /dev/null +++ b/Content.Shared/SS220/SpiderQueen/Components/SpiderQueenComponent.cs @@ -0,0 +1,89 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Shared.Alert; +using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.SS220.SpiderQueen.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SpiderQueenComponent : Component +{ + /// + /// The time at which the next every-second action will occur (for example + /// + [ViewVariables] + public TimeSpan NextSecond = TimeSpan.Zero; + + /// + /// Current amount of blood points + /// + [DataField, AutoNetworkedField] + public FixedPoint2 CurrentBloodPoints = FixedPoint2.Zero; + + /// + /// Maximum amount of blood points + /// + [DataField, AutoNetworkedField] + public FixedPoint2 MaxBloodPoints = FixedPoint2.New(200); + + /// + /// How much hunger converts into blood points per second + /// + [DataField("hungerConversion")] + public float HungerConversionPerSecond = 0.25f; + + /// + /// How much blood points is given for each unit of hunger + /// + [DataField("convertCoefficient")] + public float HungerConvertCoefficient = 2f; + + /// + /// How much hunger is given for each unit of extracted blood points + /// + [DataField] + public float HungerExtractCoefficient = 0.2f; + + /// + /// Id of the cocoon prototype + /// + [DataField] + public List CocoonPrototypes = new(); + + /// + /// List of cocoons created by this entity + /// + [ViewVariables, AutoNetworkedField] + public List CocoonsList = new(); + + /// + /// The time it takes to extract blood points from the cocoon + /// + [DataField] + public TimeSpan CocoonExtractTime = TimeSpan.FromSeconds(5); + + /// + /// The minimum distance between cocoons for their spawn + /// + [DataField] + public float CocoonsMinDistance = 0.5f; + + /// + /// How many cocoons need to station announcement + /// + [DataField] + public int? CocoonsCountToAnnouncement; + + /// + /// Has there been a special announcement about this entity yet + /// + [ViewVariables] + public bool IsAnnouncedOnce = false; + + /// + /// The prototype of alert that displays the current amount of blood points + /// + [DataField] + public ProtoId BloodPointsAlert = "BloodPoints"; +} diff --git a/Content.Shared/SS220/SpiderQueen/SharedSpiderQueenEvents.cs b/Content.Shared/SS220/SpiderQueen/SharedSpiderQueenEvents.cs new file mode 100644 index 00000000000000..8ed870b62f991a --- /dev/null +++ b/Content.Shared/SS220/SpiderQueen/SharedSpiderQueenEvents.cs @@ -0,0 +1,110 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Shared.Actions; +using Content.Shared.DoAfter; +using Content.Shared.FixedPoint; +using Content.Shared.Storage; +using Robust.Shared.Map; +using Robust.Shared.Serialization; +using System.Numerics; + +namespace Content.Shared.SS220.SpiderQueen; + +public sealed partial class SpiderTargetSpawnEvent : WorldTargetActionEvent +{ + /// + /// The list of prototypes will spawn + /// + [DataField] + public List Prototypes = new(); + + /// + /// The offset the prototypes will spawn in on relative to the one prior. + /// Set to 0,0 to have them spawn on the same tile. + /// + [DataField] + public Vector2 Offset; + + /// + /// The cost of blood points to use this action + /// + [DataField] + public FixedPoint2 Cost = FixedPoint2.Zero; + + /// + /// The time it takes before spawn entities + /// + [DataField] + public TimeSpan DoAfter = TimeSpan.Zero; +} + +public sealed partial class SpiderCocooningActionEvent : EntityTargetActionEvent +{ + /// + /// The time it takes to create a cocoon on the target + /// + [DataField] + public TimeSpan CocooningTime = TimeSpan.Zero; +} + +public sealed partial class SpiderNearbySpawnEvent : InstantActionEvent +{ + /// + /// The list of prototypes will spawn + /// + [DataField] + public List Prototypes = new(); + + /// + /// The offset the prototypes will spawn in on relative to the one prior. + /// Set to 0,0 to have them spawn on the same tile. + /// + [DataField] + public Vector2 Offset; + + /// + /// The cost of blood points to use this action + /// + [DataField] + public FixedPoint2 Cost = FixedPoint2.Zero; + + /// + /// The time it takes before spawn entities + /// + [DataField] + public TimeSpan DoAfter = TimeSpan.Zero; +} + +[Serializable, NetSerializable] +public sealed partial class AfterCocooningEvent : SimpleDoAfterEvent +{ +} + +[Serializable, NetSerializable] +public sealed partial class SpiderSpawnDoAfterEvent : SimpleDoAfterEvent +{ + /// + /// The coordinates of the location that the user targeted. + /// + public NetCoordinates TargetCoordinates; + + /// + /// List of prototypes to spawn + /// + public List Prototypes = new(); + + /// + /// The offset the prototypes will spawn in on relative to the one prior. + /// Set to 0,0 to have them spawn on the same tile. + /// + public Vector2 Offset; + + /// + /// The cost of blood points to use this action + /// + public FixedPoint2 Cost = FixedPoint2.Zero; +} + +[Serializable, NetSerializable] +public sealed partial class CocoonExtractBloodPointsEvent : SimpleDoAfterEvent +{ +} diff --git a/Content.Shared/SS220/SpiderQueen/Systems/SharedSpiderQueenSystem.cs b/Content.Shared/SS220/SpiderQueen/Systems/SharedSpiderQueenSystem.cs new file mode 100644 index 00000000000000..41d4b05bc10414 --- /dev/null +++ b/Content.Shared/SS220/SpiderQueen/Systems/SharedSpiderQueenSystem.cs @@ -0,0 +1,149 @@ +// © SS220, An EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt +using Content.Shared.Alert; +using Content.Shared.DoAfter; +using Content.Shared.Examine; +using Content.Shared.FixedPoint; +using Content.Shared.Humanoid; +using Content.Shared.Mobs.Systems; +using Content.Shared.Popups; +using Content.Shared.Rounding; +using Content.Shared.SS220.SpiderQueen.Components; +using Robust.Shared.Network; +using Robust.Shared.Prototypes; + +namespace Content.Shared.SS220.SpiderQueen.Systems; + +public abstract class SharedSpiderQueenSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly EntityLookupSystem _entityLookup = default!; + [Dependency] private readonly AlertsSystem _alerts = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(OnCocooningAction); + } + + private void OnStartup(Entity entity, ref ComponentStartup args) + { + UpdateAlert(entity); + } + + private void OnExamine(Entity entity, ref ExaminedEvent args) + { + if (args.Examined == args.Examiner) + { + args.PushMarkup(Loc.GetString("spider-queen-blood-points-amount", + ("current", entity.Comp.CurrentBloodPoints.Int()), ("max", entity.Comp.MaxBloodPoints.Int()))); + } + } + + private void OnCocooningAction(Entity entity, ref SpiderCocooningActionEvent args) + { + if (args.Handled) + return; + + var performer = args.Performer; + var target = args.Target; + + foreach (var entityInRange in _entityLookup.GetEntitiesInRange(target, entity.Comp.CocoonsMinDistance)) + { + if (!HasComp(entityInRange)) + continue; + + _popup.PopupEntity(Loc.GetString("cocooning-too-close"), performer, performer); + return; + } + + if (!_mobState.IsDead(target)) + { + _popup.PopupEntity(Loc.GetString("cocooning-target-not-dead"), performer, performer); + return; + } + + if (!HasComp(target)) + { + _popup.PopupEntity(Loc.GetString("cocooning-target-not-humanoid"), performer, performer); + return; + } + + var doAfterArgs = new DoAfterArgs( + EntityManager, + performer, + args.CocooningTime, + new AfterCocooningEvent(), + performer, + target + ) + { + Broadcast = false, + BreakOnDamage = false, + BreakOnMove = true, + NeedHand = false, + BlockDuplicate = true, + CancelDuplicate = true, + DuplicateCondition = DuplicateConditions.SameEvent + }; + + var started = _doAfter.TryStartDoAfter(doAfterArgs); + if (started) + { + args.Handled = true; + } + else + { + if (_net.IsClient) + Log.Error($"Failed to start DoAfter by {performer}"); + + return; + } + } + + /// + /// Checks if the spider has enough blood points for any action + /// + public bool CheckEnoughBloodPoints(EntityUid uid, FixedPoint2 cost, SpiderQueenComponent? component = null) + { + if (!Resolve(uid, ref component)) + { + if (_net.IsServer) + Log.Error($"{uid} doesn't have SpiderQueenComponent to CheckEnoughBloodPoints"); + + return false; + } + + if (component.CurrentBloodPoints < cost) + { + _popup.PopupEntity(Loc.GetString("spider-queen-not-enough-blood-points"), uid, uid); + return false; + } + else + return true; + } + + /// + /// Updates the alert that displays the current amount of blood points + /// + public void UpdateAlert(Entity entity) + { + var (uid, comp) = entity; + if (comp.Deleted || + comp.MaxBloodPoints <= FixedPoint2.Zero) + { + _alerts.ClearAlert(uid, comp.BloodPointsAlert); + return; + } + + var alertProto = _prototypeManager.Index(comp.BloodPointsAlert); + var severity = ContentHelpers.RoundToLevels(comp.CurrentBloodPoints.Double(), comp.MaxBloodPoints.Double(), alertProto.MaxSeverity); + _alerts.ShowAlert(uid, alertProto, (short)severity); + } +} diff --git a/Resources/Locale/ru-RU/ss220/actions/spider-actions.ftl b/Resources/Locale/ru-RU/ss220/actions/spider-actions.ftl index 57540b7e401e83..c83a865d21cc44 100644 --- a/Resources/Locale/ru-RU/ss220/actions/spider-actions.ftl +++ b/Resources/Locale/ru-RU/ss220/actions/spider-actions.ftl @@ -1,26 +1,28 @@ action-speech-spell-spider = Кссс...!?? -ent-ActionSpawnSpiderEggDrone = Яйцо паука рыцаря - .desc = Он же трутень, может строить кристаллы и стены. +ent-ActionSpawnSpiderEggDroneBloodPoints = Яйцо паука рыцаря + .desc = Он же трутень, может строить кристаллы и стены. Стоимость [color=#800000]40 крови[/color]. -ent-ActionSpawnSpiderEggHunter = Яйцо паучьего охотника - .desc = Создает яйцо паучьего охотника. Главный добытчик пищи. Во имя королевы! +ent-ActionSpawnSpiderEggHunterBloodPoints = Яйцо паучьего охотника + .desc = Создает яйцо паучьего охотника. Главный добытчик пищи. Во имя королевы! Стоимость [color=#800000]60 крови[/color]. -ent-ActionSpawnSpiderEggGhost = Яйцо паучьего призрака - .desc = Создает яйцо паучьего призрака. Ваш невидимый слуга. Уничтожит всех ваших врагов скрытым способом. +ent-ActionSpawnSpiderEggGhostBloodPoints = Яйцо паучьего призрака + .desc = Создает яйцо паучьего призрака. Ваш невидимый слуга. Уничтожит всех ваших врагов скрытым способом. Стоимость [color=#800000]60 крови[/color]. -ent-ActionSpawnSpiderEggShooter = Яйцо паучьего стрелка - .desc = Создает яйцо паучьего стрелка Дальнобойные враги не проблема. Стрелок сможет защитить вас от них. +ent-ActionSpawnSpiderEggShooterBloodPoints = Яйцо паучьего стрелка + .desc = Создает яйцо паучьего стрелка Дальнобойные враги не проблема. Стрелок сможет защитить вас от них. Стоимость [color=#800000]50 крови[/color]. -ent-ActionSpawnSpiderLittle = Выпустить паучат - .desc = Выпускает трёх маленьких паучков, которые атакуют вашу добычу. Пауки исчезают через 20 секунд. +ent-ActionSpawnSpiderLittleBloodPoints = Выпустить паучат + .desc = Выпускает трёх маленьких паучков, которые атакуют вашу добычу. Пауки исчезают через 20 секунд. Стоимость [color=#800000]20 крови[/color]. ent-ActionSpawnSpiderCrystal = Создать осколок кристалла .desc = Осколок, который служит подсветкой для пауков. +ent-ActionSpawnSpiderCrystalBloodPoints = { ent-ActionSpawnSpiderCrystal } + .desc = Осколок, который служит подсветкой для пауков. Стоимость [color=#800000]5 крови[/color]. ent-ActionSpawnSpiderWallWeb = Создать стену .desc = Наматывает огромную стену из паутины. @@ -28,6 +30,8 @@ ent-ActionSpawnSpiderWallWeb = Создать стену ent-ActionSpawnSpiderWallWebDurable = Создать прочную стену .desc = Создаёт прочную стену из... Паутины?!?!? +ent-ActionSpawnSpiderWallWebDurableBloodPoints = { ent-ActionSpawnSpiderWallWebDurable } + .desc = Создаёт прочную стену из... Паутины?!?!? Стоимость [color=#800000]10 крови[/color]. ent-ActionSpawnSingleSpiderWebShortDelay = Пустить паутину .desc = Создаёт паутину, которая замедляет вашу добычу. @@ -38,5 +42,11 @@ ent-ActionSpawnSingleSpiderWebLongDelay = { ent-ActionSpawnSingleSpiderWebShortD ent-ActionSpawnSingleSpiderWebDurable = Пустить прочную паутину .desc = { ent-ActionSpawnSingleSpiderWebShortDelay.desc } +ent-ActionSpawnSingleSpiderWebDurableBloodPoints = { ent-ActionSpawnSingleSpiderWebDurable } + .desc = Создаёт паутину, которая замедляет вашу добычу. Стоимость [color=#800000]2 крови[/color]. + ent-ActionSpawnSingleSpiderWebClown = Пустить клоунскую паутину .desc = { ent-ActionSpawnSingleSpiderWebShortDelay.desc } + +ent-ActionSpiderCoconning = Сплести кокон + .desc = Заматывает жертву в паутину! После полного облачения в шёлк из неё можно пить кровь. diff --git a/Resources/Locale/ru-RU/ss220/alerts/alerts.ftl b/Resources/Locale/ru-RU/ss220/alerts/alerts.ftl new file mode 100644 index 00000000000000..36319f6f12773a --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/alerts/alerts.ftl @@ -0,0 +1,2 @@ +alerts-spider-blood-points-name = Очки крови +alerts-spider-blood-points-desc = Это ваше брюшко. Брюшко хочет крови! БОЛЬШЕ КРОВИ!!!! diff --git a/Resources/Locale/ru-RU/ss220/misc/spider-implants.ftl b/Resources/Locale/ru-RU/ss220/misc/spider-implants.ftl deleted file mode 100644 index 43b6e542e5eb84..00000000000000 --- a/Resources/Locale/ru-RU/ss220/misc/spider-implants.ftl +++ /dev/null @@ -1,34 +0,0 @@ -ent-LightImplantSpiderEggDrone = Яйцо охранного паука - .desc = Он же трутень, может строить кристаллы и стены. - -ent-LightImplantSpiderEggHunter = Яйцо паука охотника - -ent-LightImplantSpiderEggGhost = Яйцо паука призрака - -ent-LightImplantSpiderEggShooter = Яйцо паука стрелка - - -ent-LightImplantSpiderLittle = Выпустить паучат - .desc = Выпускает трёх маленьких пауков, которые атакуют вашу добычу. Пауки исчезают через 20 секунд. - - -ent-LightImplantSpiderCrystal = Создать осколок кристалла - .desc = Осколок, который служит подсветкой для пауков. - - -ent-LightImplantSpiderWallWeb = Создать стену - -ent-LightImplantSpiderWallWebDurable = Создать прочную стену - - -ent-LightImplantSingleSpiderWebShortDelay = Пустить паутину - .desc = Создаёт паутину, которая замедляет вашу добычу. - -ent-LightImplantSingleSpiderWebLongDelay = { ent-LightImplantSingleSpiderWebShortDelay } - .desc = { ent-LightImplantSingleSpiderWebShortDelay.desc } - -ent-LightImplantSingleSpiderWebDurable = Пустить прочную паутину - .desc = { ent-LightImplantSingleSpiderWebShortDelay.desc } - -ent-LightImplantSingleSpiderWebClown = Пустить клоунскую паутину - .desc = { ent-LightImplantSingleSpiderWebShortDelay.desc } diff --git a/Resources/Locale/ru-RU/ss220/mobs/spider-queen.ftl b/Resources/Locale/ru-RU/ss220/mobs/spider-queen.ftl index c5c13bfe8efd74..7e7e22325de11b 100644 --- a/Resources/Locale/ru-RU/ss220/mobs/spider-queen.ftl +++ b/Resources/Locale/ru-RU/ss220/mobs/spider-queen.ftl @@ -1,7 +1,7 @@ spider-royQueen-name = Королева пауков -spider-royQueen-desc = Ваша задача — построить максимально большой улей. Не позволяйте причинить вред потомству. Экипаж - ваша пища, устройте большой пир. +spider-royQueen-desc = Ваша задача — построить максимально большой улей. Не позволяйте причинить вред потомству. Экипаж - ваша пища, устройте большой пир! -spider-royDrone-name = Рыцарь королевы пауков +spider-royDrone-name = Трутень королевы пауков spider-royDrone-desc = Ваша задача — защищать свою королеву всеми возможными способами. Вы её охрана и щит, не позволяйте причинять вред вашему потомству. Во имя паучей королевы! spider-royHunter-name = Паучий охотник @@ -16,26 +16,26 @@ spider-royShooter-desc = Ваша задача — Защищать свою к spider-royLittle-name = Маленький паучок spider-royLittle-desc = Ваша задача — Защищать свою королеву всеми возможными способами. Ваш размер не должен пугать вас, это ваше преимущество. Не позволяйте причинить вред потомству. Экипаж - ваша пища. -ent-MobSpiderSpaceQueen = королева пауков +ent-MobSpiderQueen = королева пауков .desc = Он так светится, что выглядит опасным. .suffix = Улей пауков -ent-MobSpiderSpaceDrone = рыцарь королевы пауков - .desc = { ent-MobSpiderSpaceQueen.desc } - .suffix = { ent-MobSpiderSpaceQueen.suffix } +ent-MobSpiderDrone = трутень королевы пауков + .desc = { ent-MobSpiderQueen.desc } + .suffix = { ent-MobSpiderQueen.suffix } -ent-MobSpiderSpaceHunter = паучий охотник - .desc = { ent-MobSpiderSpaceQueen.desc } - .suffix = { ent-MobSpiderSpaceQueen.suffix } +ent-MobSpiderHunter = паучий охотник + .desc = { ent-MobSpiderQueen.desc } + .suffix = { ent-MobSpiderQueen.suffix } -ent-MobSpiderSpaceGhost = паучий призрак - .desc = { ent-MobSpiderSpaceQueen.desc } - .suffix = { ent-MobSpiderSpaceQueen.suffix } +ent-MobSpiderGhost = паучий призрак + .desc = { ent-MobSpiderQueen.desc } + .suffix = { ent-MobSpiderQueen.suffix } -ent-MobSpiderSpaceShooter = паучий стрелок - .desc = { ent-MobSpiderSpaceQueen.desc } - .suffix = { ent-MobSpiderSpaceQueen.suffix } +ent-MobSpiderShooter = паучий стрелок + .desc = { ent-MobSpiderQueen.desc } + .suffix = { ent-MobSpiderQueen.suffix } -ent-MobSpiderSpaceLittle = маленький паучок - .desc = { ent-MobSpiderSpaceQueen.desc } - .suffix = { ent-MobSpiderSpaceQueen.suffix } +ent-MobSpiderLittle = маленький паучок + .desc = { ent-MobSpiderQueen.desc } + .suffix = { ent-MobSpiderQueenn.suffix } diff --git a/Resources/Locale/ru-RU/ss220/objectives/spider-queen.ftl b/Resources/Locale/ru-RU/ss220/objectives/spider-queen.ftl new file mode 100644 index 00000000000000..46934e3f60fdb6 --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/objectives/spider-queen.ftl @@ -0,0 +1,19 @@ +ent-BaseSpiderQueenObjective = { ent-BaseObjective } + .desc = { ent-BaseObjective.desc } +ent-CreateCocoonsObjective= { ent-BaseSpiderQueenObjective } + .desc = { ent-BaseSpiderQueenObjective.desc } +ent-SpiderQueenSurviveObjective = Выжить + .desc = Вы должны оставаться в живых, чтобы сохранять контроль. + +objective-create-cocoons-title = + Создать { $count } { $count -> + [one] кокон + [few] кокона + *[other] коконов + }. +objective-create-cocoons-description = + Используйте действие «Сплести кокон» чтобы создать { $count } { $count -> + [one] кокон + [few] кокона + *[other] коконов + }. diff --git a/Resources/Locale/ru-RU/ss220/prototypes/entities/markings/markers.ftl b/Resources/Locale/ru-RU/ss220/prototypes/entities/markings/markers.ftl new file mode 100644 index 00000000000000..d3153d3d573e84 --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/prototypes/entities/markings/markers.ftl @@ -0,0 +1,3 @@ +ent-SpiderQueenSpawnMarker = маркер спавна королевы пауков + .desc = Маркер, обозначающий координату, в которой возможен спавн королевы пауков + .suffix = Улей пауков diff --git a/Resources/Locale/ru-RU/ss220/spider-queen/spider-queen.ftl b/Resources/Locale/ru-RU/ss220/spider-queen/spider-queen.ftl new file mode 100644 index 00000000000000..550b329ee96626 --- /dev/null +++ b/Resources/Locale/ru-RU/ss220/spider-queen/spider-queen.ftl @@ -0,0 +1,19 @@ +spider-queen-blood-points-amount = У вас [color=#800000]{ $current } крови[/color]. Ваш максимум — [color=#800000]{ $max } крови[/color]. +spider-queen-not-enough-blood-points = Недостаточно крови +spider-queen-warning = Замечена аномальная биологическая активность в { $location }. Служба Безопасности должна ликвидировать угрозу до того как активу будет нанесен непоправимый ущерб! + +spider-queen-role-greeting = Ваша задача — построить максимально большой улей, не позволяйте причинять вред вашему потомству. Экипаж - ваша пища, устройте большой пир! + +spider-cocoon-blood-points-amount = В коконе содержится [color=#800000]{ $amount } крови[/color]. +spider-cocoon-extract-blood-points-verb = Извлечь ману + +cocooning-too-close = Слишком близко к другому кокону +cocooning-target-not-dead = Цель должна быть мертва +cocooning-target-not-humanoid = Цель должна быть гуманоидом + +objective-issuer-spider-queen = [color=#c8a2c8]Королева пауков[/color] + +spider-queen-round-end-agent-name = [color=#c8a2c8]королева пауков[/color] + +roles-antag-spider-queen-name = Королева пауков +roles-antag-spider-queen-objective = Постройте максимально большой улей и не позволяйте причинять вред вашему потомству. Экипаж - ваша пища, устройте большой пир! diff --git a/Resources/Locale/ru-RU/ss220/strucrure/spider-structures.ftl b/Resources/Locale/ru-RU/ss220/strucrure/spider-structures.ftl index 0439b9e7682d49..9749606c672523 100644 --- a/Resources/Locale/ru-RU/ss220/strucrure/spider-structures.ftl +++ b/Resources/Locale/ru-RU/ss220/strucrure/spider-structures.ftl @@ -17,3 +17,28 @@ ent-TableWebSpidersDurable = каркас стены из паутины ent-WallWebDurable = прочная паутинная стена .desc = Удерживает паучат внутри, а ассистентов снаружи. .suffix = { ent-TableWebSpiders.suffix } + +ent-BaseSpiderCocoon = кокон из паутины + .desc = Большая куча паучьего шёлка оплетающее... + Что-то массивное. Кажется, или это похоже на туловище? + .suffix = Улей пауков + +ent-SpiderCocoonHorizontal = { ent-BaseSpiderCocoon } + .desc = { ent-BaseSpiderCocoon.desc } + .suffix = { ent-BaseSpiderCocoon.suffix } + +ent-SpiderCocoonVertical = { ent-BaseSpiderCocoon } + .desc = { ent-BaseSpiderCocoon.desc } + .suffix = { ent-BaseSpiderCocoon.suffix } + +ent-BaseSpiderCocoonDestroyed = разрушенный кокон + .desc = { ent-BaseSpiderCocoon.desc } + .suffix = { ent-BaseSpiderCocoon.suffix } + +ent-SpiderCocoonHorizontalDestroyed = { ent-BaseSpiderCocoonDestroyed } + .desc = { ent-BaseSpiderCocoonDestroyed.desc } + .suffix = { ent-BaseSpiderCocoonDestroyed.suffix } + +ent-SpiderCocoonVerticalDestroyed = { ent-BaseSpiderCocoonDestroyed } + .desc = { ent-BaseSpiderCocoonDestroyed.desc } + .suffix = { ent-BaseSpiderCocoonDestroyed.suffix } diff --git a/Resources/Prototypes/Actions/spider.yml b/Resources/Prototypes/Actions/spider.yml index fe37085ecabc54..1907a6c97ef6db 100644 --- a/Resources/Prototypes/Actions/spider.yml +++ b/Resources/Prototypes/Actions/spider.yml @@ -4,7 +4,7 @@ description: Spawns a web that slows your prey down. components: - type: InstantAction - icon: Interface/Actions/web.png + icon: SS220/Interface/Actions/web.png #SS220 new web action sprite event: !type:SpiderWebActionEvent useDelay: 25 @@ -14,6 +14,6 @@ description: Weave a bit of silk for use in arts and crafts. components: - type: InstantAction - icon: Interface/Actions/web.png + icon: SS220/Interface/Actions/web.png #SS220 new web action sprite event: !type:SericultureActionEvent useDelay: 1 diff --git a/Resources/Prototypes/Alerts/alerts.yml b/Resources/Prototypes/Alerts/alerts.yml index 80fcc44a559e02..75b3b54fd76d2c 100644 --- a/Resources/Prototypes/Alerts/alerts.yml +++ b/Resources/Prototypes/Alerts/alerts.yml @@ -4,6 +4,7 @@ # If item is not in list it will go at the bottom (ties broken by alert type enum value) id: BaseAlertOrder order: + - alertType: BloodPoints #SS220 Spider queen antag - category: Health - category: Stamina - alertType: SuitPower diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 7b192e03200533..8e829371b1387d 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -36,6 +36,7 @@ - id: SleeperAgents - id: ZombieOutbreak - id: DarkReaperSpawn #ss220 darkreaper middle event + # - id: SpiderQueenSpawn #SS220 spider queen midround event - type: entity id: BaseStationEvent diff --git a/Resources/Prototypes/SS220/Actions/Spider_actions.yml b/Resources/Prototypes/SS220/Actions/Spider_actions.yml index cc3911422c00de..f3a9868c90b070 100644 --- a/Resources/Prototypes/SS220/Actions/Spider_actions.yml +++ b/Resources/Prototypes/SS220/Actions/Spider_actions.yml @@ -3,14 +3,13 @@ id: BaseActionSpawnSpiderEgg abstract: true components: - - type: WorldTargetAction - useDelay: 200 - range: 1 + - type: InstantAction + useDelay: 2 itemIconStyle: BigAction icon: sprite: SS220/Interface/Actions/action_spider.rsi state: guard_spawn - event: !type:WorldSpawnSpellEvent + event: !type:SpiderNearbySpawnEvent prototypes: - id: SpiderEggDrone amount: 1 @@ -40,93 +39,93 @@ #Egg - type: entity parent: BaseActionSpawnSpiderEgg - id: ActionSpawnSpiderEggDrone + id: ActionSpawnSpiderEggDroneBloodPoints name: guard spider egg description: He is also a drone and can build crystals and walls. categories: [ HideSpawnMenu ] components: - - type: WorldTargetAction - event: !type:WorldSpawnSpellEvent + - type: InstantAction + event: !type:SpiderNearbySpawnEvent prototypes: - id: SpiderEggDrone amount: 1 offset: 0, 1 - speech: action-speech-spell-spider + cost: 40 + doAfter: 5 - type: entity parent: BaseActionSpawnSpiderEgg - id: ActionSpawnSpiderEggHunter + id: ActionSpawnSpiderEggHunterBloodPoints name: hunter spider egg categories: [ HideSpawnMenu ] components: - - type: WorldTargetAction + - type: InstantAction icon: sprite: SS220/Interface/Actions/action_spider.rsi state: hunter_spawn - useDelay: 300 #КД - event: !type:WorldSpawnSpellEvent + event: !type:SpiderNearbySpawnEvent prototypes: - id: SpiderEggHunter amount: 1 offset: 0, 1 - speech: action-speech-spell-spider + cost: 60 + doAfter: 5 - type: entity parent: BaseActionSpawnSpiderEgg - id: ActionSpawnSpiderEggGhost + id: ActionSpawnSpiderEggGhostBloodPoints name: ghost spider egg categories: [ HideSpawnMenu ] components: - - type: WorldTargetAction + - type: InstantAction icon: sprite: SS220/Interface/Actions/action_spider.rsi state: nurse_spawn - useDelay: 350 - event: !type:WorldSpawnSpellEvent + event: !type:SpiderNearbySpawnEvent prototypes: - id: SpiderEggGhost amount: 1 offset: 0, 1 - speech: action-speech-spell-spider + cost: 60 + doAfter: 5 - type: entity parent: BaseActionSpawnSpiderEgg - id: ActionSpawnSpiderEggShooter + id: ActionSpawnSpiderEggShooterBloodPoints name: shooter spider egg categories: [ HideSpawnMenu ] components: - - type: WorldTargetAction + - type: InstantAction icon: sprite: SS220/Interface/Actions/action_spider.rsi state: viper_spawn - useDelay: 380 - event: !type:WorldSpawnSpellEvent + event: !type:SpiderNearbySpawnEvent prototypes: - id: SpiderEggShooter amount: 1 offset: 0, 1 - speech: action-speech-spell-spider + cost: 50 + doAfter: 5 #Spider - type: entity - id: ActionSpawnSpiderLittle + id: ActionSpawnSpiderLittleBloodPoints name: release the spiderlings description: Releases three small spiders that attack your prey. The spiders disappear after 20 seconds. categories: [ HideSpawnMenu ] components: - - type: WorldTargetAction + - type: InstantAction useDelay: 40 - range: 2 itemIconStyle: BigAction icon: sprite: SS220/Interface/Actions/action_spider.rsi state: little_spider_spawn - event: !type:WorldSpawnSpellEvent + event: !type:SpiderNearbySpawnEvent prototypes: - - id: MobSpiderSpaceLittle + - id: MobSpiderLittle amount: 3 - offset: 0, 1 - speech: action-speech-spell-spider + offset: 0, 0.5 + cost: 20 #Cryctal - type: entity @@ -140,8 +139,8 @@ range: 1 itemIconStyle: BigAction icon: - sprite: Structures/Decoration/crystal.rsi - state: crystal1 + sprite: SS220/Interface/Actions/action_spider.rsi + state: crystal_spawn event: !type:WorldSpawnSpellEvent prototypes: - id: ShardCrystalBlueXeno @@ -149,6 +148,26 @@ offset: 0, 1 speech: action-speech-spell-spider +- type: entity + id: ActionSpawnSpiderCrystalBloodPoints + name: create a crystal shard + description: A shard that serves as a backlight for spiders. + categories: [ HideSpawnMenu ] + components: + - type: WorldTargetAction + useDelay: 5 + range: 1 + itemIconStyle: BigAction + icon: + sprite: SS220/Interface/Actions/action_spider.rsi + state: crystal_spawn + event: !type:SpiderTargetSpawnEvent + prototypes: + - id: ShardCrystalBlueXeno + amount: 1 + offset: 0, 1 + cost: 5 + #Wall - type: entity id: ActionSpawnSpiderWallWeb @@ -160,11 +179,11 @@ range: 1.5 itemIconStyle: BigAction icon: - sprite: SS220/Structures/Walls/web.rsi #SS220-Walss-Sprite-Update-V4 - state: full + sprite: SS220/Interface/Actions/action_spider.rsi #SS220-Walss-Sprite-Update-V4 + state: wall_spawn event: !type:WorldSpawnSpellEvent prototypes: - - id: TableWebSpiders + - id: WallWebSpawn amount: 1 offset: 0, 1 speech: action-speech-spell-spider @@ -179,8 +198,25 @@ useDelay: 16 event: !type:WorldSpawnSpellEvent prototypes: - - id: TableWebSpidersDurable + - id: WallWebDurableSpawn + amount: 1 + offset: 0, 1 + speech: action-speech-spell-spider + +- type: entity + parent: ActionSpawnSpiderWallWeb + id: ActionSpawnSpiderWallWebDurableBloodPoints + name: create a durable wall + categories: [ HideSpawnMenu ] + components: + - type: WorldTargetAction + useDelay: 6 + event: !type:SpiderTargetSpawnEvent + prototypes: + - id: WallWebDurableSpawn amount: 1 + offset: 0, 1 + cost: 10 #Web - type: entity @@ -214,6 +250,21 @@ offset: 0, 1 speech: action-speech-spell-spider +- type: entity + parent: BaseActionSpawnSingleSpiderWeb + id: ActionSpawnSingleSpiderWebDurableBloodPoints + name: spin a durable web + categories: [ HideSpawnMenu ] + components: + - type: WorldTargetAction + useDelay: 2 + event: !type:SpiderTargetSpawnEvent + prototypes: + - id: SpiderWebDurable + amount: 1 + offset: 0, 1 + cost: 2 + #Clown web - type: entity id: ActionSpawnSingleSpiderWebClown @@ -234,3 +285,17 @@ amount: 1 offset: 0, 1 speech: action-speech-spell-spider + +#Cocooning +- type: entity + id: ActionSpiderCoconning + name: weave a cocoon + description: Wraps the victim in a web! After fully clothed in silk, you can drink blood from it. + categories: [ HideSpawnMenu ] + components: + - type: EntityTargetAction + event: !type:SpiderCocooningActionEvent + cocooningTime: 15 + itemIconStyle: NoItem + icon: { sprite: SS220/Interface/Actions/action_spider.rsi, state: cocoon } + useDelay: 10 diff --git a/Resources/Prototypes/SS220/Alerts/spider_queen.yml b/Resources/Prototypes/SS220/Alerts/spider_queen.yml new file mode 100644 index 00000000000000..2e34f337a526b5 --- /dev/null +++ b/Resources/Prototypes/SS220/Alerts/spider_queen.yml @@ -0,0 +1,55 @@ +- type: alert + id: BloodPoints + icons: + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood0 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood1 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood2 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood3 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood4 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood5 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood6 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood7 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood8 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood9 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood10 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood11 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood12 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood13 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood14 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood15 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood16 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood17 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood18 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood19 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood20 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood21 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood22 + - sprite: /Textures/SS220/Interface/Alerts/blood_counter.rsi + state: blood23 + name: alerts-spider-blood-points-name + description: alerts-spider-blood-points-desc + minSeverity: 0 + maxSeverity: 24 diff --git a/Resources/Prototypes/SS220/Antags/spider_queen.yml b/Resources/Prototypes/SS220/Antags/spider_queen.yml new file mode 100644 index 00000000000000..3e8fae3a6c3677 --- /dev/null +++ b/Resources/Prototypes/SS220/Antags/spider_queen.yml @@ -0,0 +1,5 @@ +- type: antag + id: SpiderQueen + name: roles-antag-spider-queen-name + antagonist: true + objective: roles-antag-spider-queen-objective diff --git a/Resources/Prototypes/SS220/Damage/modifier_sets.yml b/Resources/Prototypes/SS220/Damage/modifier_sets.yml index a244961c923aef..4eb2b4e3732c1e 100644 --- a/Resources/Prototypes/SS220/Damage/modifier_sets.yml +++ b/Resources/Prototypes/SS220/Damage/modifier_sets.yml @@ -24,3 +24,58 @@ Poison: 0.6 Cellular: 1 Radiation: 0.5 + +# Spider queen antag +- type: damageModifierSet + id: SpiderQueen + coefficients: + Piercing: 0.6 + Blunt: 0.5 + Slash: 0.6 + Heat: 0.6 + Poison: 0.2 + +- type: damageModifierSet + id: SpiderDrone + coefficients: + Piercing: 0.6 + Blunt: 0.7 + Slash: 0.7 + Heat: 0.6 + Poison: 0.2 + +- type: damageModifierSet + id: SpiderHunter + coefficients: + Piercing: 0.6 + Blunt: 0.4 + Slash: 0.4 + Heat: 0.6 + Poison: 0.2 + +- type: damageModifierSet + id: SpiderGhost + coefficients: + Piercing: 0.7 + Blunt: 0.5 + Slash: 0.6 + Heat: 0.7 + Poison: 0.2 + +- type: damageModifierSet + id: SpiderShooter + coefficients: + Piercing: 0.5 + Blunt: 0.7 + Slash: 0.7 + Heat: 0.5 + Poison: 0.2 + +- type: damageModifierSet + id: SpiderLittle + coefficients: + Piercing: 0.8 + Blunt: 0.8 + Slash: 0.8 + Heat: 0.8 + Poison: 0.2 diff --git a/Resources/Prototypes/SS220/Entities/Mobs/NPCs/spider_queen.yml b/Resources/Prototypes/SS220/Entities/Mobs/NPCs/spider_queen.yml index 0598402e6e8408..b8bbcf6fe8cf72 100644 --- a/Resources/Prototypes/SS220/Entities/Mobs/NPCs/spider_queen.yml +++ b/Resources/Prototypes/SS220/Entities/Mobs/NPCs/spider_queen.yml @@ -6,9 +6,12 @@ - MobCombat id: BaseMobSpiderQueen abstract: true - name: Probca + name: Spider queen description: spider dance components: + - type: AutoImplant + implants: + - ThermalVisionImplant - type: NpcFactionMember factions: - SpiderQueen @@ -17,6 +20,8 @@ - type: InputMover - type: MobMover - type: HTN + rootTask: + task: SimpleHostileCompound - type: Sprite drawdepth: Mobs sprite: Mobs/Animals/spider.rsi @@ -57,17 +62,6 @@ - MobMask layer: - MobLayer - - type: MeleeWeapon - hidden: true - soundHit: - path: /Audio/Effects/bite.ogg - angle: 0. - animation: WeaponArcBite - damage: - types: - Piercing: 12 #Damage - Poison: 4 - Structural: 15 - type: MeleeChemicalInjector solution: melee transferAmount: 3 @@ -77,22 +71,11 @@ interactFailureString: petting-failure-generic - type: NoSlip - type: IgnoreSpiderWeb - - type: PassiveDamage # Slight passive regen. Assuming one damage type, comes out to about 4 damage a minute.Самолечение - allowedStates: - - Alive - damageCap: 300 - damage: - types: - Heat: -2.5 - groups: - Brute: -3 - Toxin: -5 - Airloss: -2.5 - Burn: -2.5 - type: Tag tags: - CannotSuicide - DoorBumpOpener + - SpiderQueen - type: Tool # Open door from xeno.yml. speedModifier: 1.5 qualities: @@ -143,31 +126,57 @@ channels: - HiveRadio +- type: entity + parent: BaseMobSpiderQueen + id: BaseMobSpiderServant + abstract: true + components: + - type: Tag + tags: + - CannotSuicide + - DoorBumpOpener + - SpiderServant + - type: Puller + needsHands: false + #Spider queen - type: entity parent: - BaseMobSpiderQueen - MobSpiderQueenGhostRole - id: MobSpiderSpaceQueen + id: MobSpiderQueen name: Spider queen description: spider dance components: - - type: AutoImplant - implants: - - LightImplantSpiderEggHunter - - LightImplantSpiderWallWebDurable - - LightImplantSpiderEggDrone - - LightImplantSpiderEggGhost - - LightImplantSpiderCrystal - - LightImplantSpiderLittle - - LightImplantSingleSpiderWebDurable - - LightImplantSpiderEggShooter - - ThermalVisionImplant + - type: SpiderQueen + currentBloodPoints: 100 + cocoonsCountToAnnouncement: 10 + cocoonPrototypes: + - SpiderCocoonHorizontal + - SpiderCocoonVertical + - type: ActionGrant + actions: + - ActionSpawnSpiderEggDroneBloodPoints + - ActionSpawnSpiderEggHunterBloodPoints + - ActionSpawnSpiderEggGhostBloodPoints + - ActionSpawnSpiderEggShooterBloodPoints + - ActionSpawnSpiderLittleBloodPoints + - ActionSpawnSpiderCrystalBloodPoints + - ActionSpawnSingleSpiderWebDurableBloodPoints + - ActionSpawnSpiderWallWebDurableBloodPoints + - ActionSpiderCoconning + - type: Hunger + thresholds: # only animals and rats are derived from this prototype so let's override it here and in rats' proto + Overfed: 150 + Okay: 75 + Peckish: 35 + Starving: 15 + Dead: 0 - type: Butcherable spawned: - id: FoodMeatSpider amount: 3 - - id: MobSpiderSpaceLittle + - id: MobSpiderLittle amount: 7 - type: Spider webPrototype: SpiderWebDespawned @@ -177,6 +186,17 @@ proto: PoisonousAcid capacity: 2 count: 2 + - type: MeleeWeapon + hidden: true + soundHit: + path: /Audio/Effects/bite.ogg + angle: 0. + animation: WeaponArcBite + damage: + types: + Piercing: 25 #Damage + Poison: 5 + Structural: 25 - type: Gun fireRate: 1 useKey: false @@ -184,6 +204,9 @@ availableModes: - FullAuto soundGunshot: /Audio/Weapons/Xeno/alien_spitacid.ogg + - type: Damageable + damageContainer: Biological + damageModifierSet: SpiderQueen - type: SolutionContainerManager solutions: melee: @@ -194,14 +217,28 @@ baseWalkSpeed : 3.5 baseSprintSpeed : 4 - type: LizardAccent + - type: Puller + needsHands: false + - type: PassiveDamage # Slight passive regen. Assuming one damage type, comes out to about 4 damage a minute.Самолечение + allowedStates: + - Alive + damageCap: 300 + damage: + types: + Bloodloss: -1 + groups: + Brute: -2 + Toxin: -5 + Airloss: -2.5 + Burn: -2.5 #Spiders-servants - type: entity parent: - MobSpiderDroneGhostRole - - BaseMobSpiderQueen - id: MobSpiderSpaceDrone - name: spider guard + - BaseMobSpiderServant + id: MobSpiderDrone + name: spider drone description: spider dance components: - type: Sprite #Спрайт @@ -214,7 +251,7 @@ - type: MobThresholds thresholds: 0: Alive - 85: Dead #HP + 60: Dead #HP - type: DamageStateVisuals states: Alive: @@ -224,13 +261,12 @@ - type: PassiveDamage # Slight passive regen. Assuming one damage type, comes out to about 4 damage a minute. Самолечение allowedStates: - Alive - damageCap: 85 + damageCap: 60 damage: types: - Heat: -3 + Bloodloss: -3 groups: Brute: -2 - Toxin: -5 Airloss: -2 Burn: -2 - type: MeleeWeapon #Damage @@ -242,12 +278,15 @@ damage: types: Piercing: 5 #Damage - Structural: 10 - - type: AutoImplant - implants: - - LightImplantSpiderWallWebDurable - - LightImplantSpiderCrystal - - LightImplantSingleSpiderWebShortDelay + Structural: 20 + - type: Damageable + damageContainer: Biological + damageModifierSet: SpiderDrone + - type: ActionGrant + actions: + - ActionSpawnSpiderWallWebDurable + - ActionSpawnSpiderCrystal + - ActionSpawnSingleSpiderWebShortDelay - type: Spider webPrototype: SpiderWebDespawned - type: MovementSpeedModifier @@ -257,8 +296,8 @@ - type: entity parent: - MobSpiderHunterGhostRole - - BaseMobSpiderQueen - id: MobSpiderSpaceHunter + - BaseMobSpiderServant + id: MobSpiderHunter name: spider hunt description: spider dance components: @@ -285,9 +324,9 @@ damageCap: 110 damage: types: - Heat: -2.5 + Bloodloss: -1.5 groups: - Brute: -3 + Brute: -1.5 Toxin: -5 Airloss: -2 Burn: -1 @@ -299,22 +338,26 @@ animation: WeaponArcBite damage: types: - Piercing: 15 - Structural: 15 + Piercing: 20 + Poison: 5 + Structural: 10 + - type: Damageable + damageContainer: Biological + damageModifierSet: SpiderHunter - type: Spider webPrototype: SpiderWebDespawned - type: MovementSpeedModifier baseWalkSpeed : 3 baseSprintSpeed : 3.9 - - type: AutoImplant - implants: - - LightImplantSingleSpiderWebLongDelay + - type: ActionGrant + actions: + - ActionSpawnSingleSpiderWebLongDelay - type: entity parent: - MobSpiderGhostGhostRole - - BaseMobSpiderQueen - id: MobSpiderSpaceGhost + - BaseMobSpiderServant + id: MobSpiderGhost name: spider ghost description: spider dance components: @@ -328,7 +371,7 @@ - type: MobThresholds thresholds: 0: Alive - 100: Dead + 90: Dead - type: DamageStateVisuals states: Alive: @@ -338,12 +381,12 @@ - type: PassiveDamage allowedStates: - Alive - damageCap: 100 + damageCap: 90 damage: types: - Heat: -2 + Bloodloss: -1 groups: - Brute: -3 + Brute: -1.5 Toxin: -5 Airloss: -2 Burn: -1 @@ -355,9 +398,12 @@ animation: WeaponArcBite damage: types: - Piercing: 3 - Poison: 4 - Structural: 10 + Piercing: 5 + Poison: 10 + Structural: 5 + - type: Damageable + damageContainer: Biological + damageModifierSet: SpiderGhost - type: SolutionContainerManager solutions: melee: @@ -384,15 +430,15 @@ - type: MovementSpeedModifier baseWalkSpeed : 1.5 baseSprintSpeed : 3.9 - - type: AutoImplant - implants: - - LightImplantSingleSpiderWebLongDelay + - type: ActionGrant + actions: + - ActionSpawnSingleSpiderWebLongDelay - type: entity parent: - MobSpiderShooterGhostRole - - BaseMobSpiderQueen - id: MobSpiderSpaceShooter + - BaseMobSpiderServant + id: MobSpiderShooter name: spider shooter description: spider dance components: @@ -406,7 +452,7 @@ - type: MobThresholds thresholds: 0: Alive - 80: Dead + 70: Dead - type: DamageStateVisuals states: Alive: @@ -416,10 +462,10 @@ - type: PassiveDamage allowedStates: - Alive - damageCap: 80 + damageCap: 70 damage: types: - Heat: -3 + Bloodloss: -0.5 groups: Brute: -1 Toxin: -5 @@ -434,8 +480,11 @@ damage: types: Poison: 5 - Piercing: 2 + Piercing: 5 Structural: 5 + - type: Damageable + damageContainer: Biological + damageModifierSet: SpiderShooter - type: SolutionContainerManager solutions: melee: @@ -455,9 +504,9 @@ availableModes: - FullAuto soundGunshot: /Audio/Weapons/Xeno/alien_spitacid.ogg - - type: AutoImplant - implants: - - LightImplantSingleSpiderWebClown + - type: ActionGrant + actions: + - ActionSpawnSingleSpiderWebClown - type: MovementSpeedModifier baseWalkSpeed : 3 baseSprintSpeed : 3.7 @@ -466,7 +515,7 @@ parent: - BaseMobSpiderQueen - MobSpiderLittleGhostRole - id: MobSpiderSpaceLittle + id: MobSpiderLittle name: small spider description: spider dance components: @@ -480,7 +529,7 @@ - type: MobThresholds thresholds: 0: Alive - 15: Dead + 30: Dead - type: DamageStateVisuals states: Alive: @@ -490,10 +539,8 @@ - type: PassiveDamage allowedStates: - Alive - damageCap: 15 + damageCap: 30 damage: - types: - Heat: -0.5 groups: Brute: -0.5 Toxin: -0.5 @@ -508,11 +555,20 @@ damage: types: Piercing: 5 + Structural: 10 + - type: Damageable + damageContainer: Biological + damageModifierSet: SpiderLittle - type: TimedDespawn lifetime: 20 - type: MovementSpeedModifier baseWalkSpeed : 3.5 baseSprintSpeed : 4.5 + - type: Tag + tags: + - CannotSuicide + - DoorBumpOpener + - SpiderLittle # GHOST ROLES diff --git a/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_eggs.yml b/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_eggs.yml index a3bdd513c5a8a2..d579ad18166ff9 100644 --- a/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_eggs.yml +++ b/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_eggs.yml @@ -119,7 +119,7 @@ - type: TimedDespawn lifetime: 55 - type: SpawnOnDespawn - prototype: MobSpiderSpaceDrone + prototype: MobSpiderDrone - type: entity parent: BaseSpiderEgg @@ -131,7 +131,7 @@ - type: TimedDespawn #Система цикла lifetime: 80 - type: SpawnOnDespawn - prototype: MobSpiderSpaceHunter #Система цикла + prototype: MobSpiderHunter #Система цикла - type: entity parent: BaseSpiderEgg @@ -143,7 +143,7 @@ - type: TimedDespawn lifetime: 80 - type: SpawnOnDespawn - prototype: MobSpiderSpaceGhost + prototype: MobSpiderGhost - type: entity parent: BaseSpiderEgg @@ -155,4 +155,4 @@ - type: TimedDespawn lifetime: 80 - type: SpawnOnDespawn - prototype: MobSpiderSpaceShooter + prototype: MobSpiderShooter diff --git a/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_implants.yml b/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_implants.yml deleted file mode 100644 index 76bd984418077f..00000000000000 --- a/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_implants.yml +++ /dev/null @@ -1,141 +0,0 @@ -#Base -- type: entity - parent: BaseSubdermalImplant - id: BaseLightImplantSpider - abstract: true - components: - - type: SubdermalImplant - - type: PointLight - enabled: false - radius: 2.5 - softness: 5 - mask: /Textures/Effects/LightMasks/cone.png - autoRot: true - - type: Tag - tags: - - SubdermalImplant - - HideContextMenu - - Flashlight - - type: UnpoweredFlashlight - -# #Egg -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSpiderEggDrone - name: guard spider egg - description: He is also a drone and can build crystals and walls. - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSpiderEggDrone - -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSpiderEggHunter - name: hunter spider egg - description: - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSpiderEggHunter - -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSpiderEggGhost - name: ghost spider egg - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSpiderEggGhost - -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSpiderEggShooter - name: shooter spider egg - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSpiderEggShooter - -#Spider -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSpiderLittle - name: release the spiderlings - description: Releases three small spiders that attack your prey. The spiders disappear after 20 seconds. - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSpiderLittle - -# #Cristal -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSpiderCrystal - name: create a crystal shard - description: A shard that serves as a backlight for spiders. - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSpiderCrystal - -#Wall -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSpiderWallWeb - name: create a wall - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSpiderWallWeb - -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSpiderWallWebDurable - name: create a durable wall - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSpiderWallWebDurable - -#Web -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSingleSpiderWebShortDelay - name: spin a web - description: Creates a web that slows down your prey. - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSingleSpiderWebShortDelay - -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSingleSpiderWebLongDelay - name: spin a web - description: Creates a web that slows down your prey. - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSingleSpiderWebLongDelay - -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSingleSpiderWebDurable - name: spin a durable web - description: Creates a web that slows down your prey. - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSingleSpiderWebDurable - -#Clown web -- type: entity - parent: BaseLightImplantSpider - id: LightImplantSingleSpiderWebClown - name: spin a clown web - description: Creates a web that slows down your prey. - categories: [ HideSpawnMenu ] - components: - - type: SubdermalImplant - implantAction: ActionSpawnSingleSpiderWebClown diff --git a/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_web.yml b/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_web.yml index 6ca78cc18d2d9b..29f9b1437cc2cd 100644 --- a/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_web.yml +++ b/Resources/Prototypes/SS220/Entities/Objects/Misc/spider_web.yml @@ -89,6 +89,20 @@ - type: SpeedModifierContacts walkSpeedModifier: 0.25 sprintSpeedModifier: 0.25 + - type: DamageContacts + standStillTime: 3 + damage: + types: + Bloodloss: -1 + groups: + Brute: -0.5 + Toxin: -0.5 + Burn: -0.5 + ignoreBlacklist: + tags: + - SpiderQueen + - SpiderServant + - SpiderLittle - type: entity parent: BaseSpiderWeb @@ -99,7 +113,7 @@ snap: - Wall components: - + - type: Sprite - type: Destructible thresholds: - trigger: @@ -111,6 +125,21 @@ - type: SpeedModifierContacts walkSpeedModifier: 0.15 sprintSpeedModifier: 0.15 + - type: DamageContacts + standStillTime: 3 + damage: + types: + Bloodloss: -1.5 + groups: + Brute: -1 + Toxin: -0.5 + Airloss: -1 + Burn: -1 + ignoreBlacklist: + tags: + - SpiderQueen + - SpiderServant + - SpiderLittle - type: entity parent: BaseSpiderWeb diff --git a/Resources/Prototypes/SS220/Entities/Structures/Specific/spider_structures.yml b/Resources/Prototypes/SS220/Entities/Structures/Specific/spider_structures.yml index 211caf838ec311..f9c7c9184a23cc 100644 --- a/Resources/Prototypes/SS220/Entities/Structures/Specific/spider_structures.yml +++ b/Resources/Prototypes/SS220/Entities/Structures/Specific/spider_structures.yml @@ -1,135 +1,126 @@ # AT THE BOTTOM IS A TILE MADE OF COBWEBS. -#TODO: Сделать нормальную анимацию спавна стены без использования костыля в виде спавна тайлов и столов #Base - type: entity - parent: BaseItemSpider - id: BaseFloorTileItemSpiders - description: These could work as a pretty decent throwing weapon. + id: BaseSpiderCocoon + name: spider cocoon + description: description + suffix: Spider hive abstract: true components: + - type: Icon + sprite: SS220/Structures/Specific/cocoon.rsi - type: Sprite - sprite: Objects/Tiles/web.rsi - state: icon - - type: FloorTile - outputs: - - FloorWebTile - - type: DamageOtherOnHit + sprite: SS220/Structures/Specific/cocoon.rsi + drawdepth: Items + - type: Transform + - type: Physics + bodyType: Static + canCollide: false + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb {} + - type: Clickable + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Wood + - type: Destructible + - type: ContainerContainer + containers: + cocoon: !type:Container + - type: Tag + tags: + - SpiderCocoon + - type: SpiderCocoon + container: cocoon + bloodPointsBonus: 20 damage: types: - Blunt: 5 + Caustic: 0.5 + Blunt: 1 + damageCap: + Caustic: 40 + Blunt: 80 + +- type: entity + id: BaseSpiderCocoonDestroyed + name: spider cocoon destroyed + description: description + suffix: Spider hive + abstract: true + components: + - type: Icon + sprite: SS220/Structures/Specific/cocoon.rsi + - type: Sprite + sprite: SS220/Structures/Specific/cocoon.rsi + drawdepth: Items + - type: Transform + - type: Physics + bodyType: Static + canCollide: false + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb {} + - type: Clickable - type: Damageable damageContainer: Inorganic - - type: Construction - graph: WebObjects - node: tile - - type: TimedDespawn - - type: SpawnOnDespawn + damageModifierSet: Wood - type: Destructible thresholds: - trigger: !type:DamageTrigger - damage: 1 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - trigger: - !type:DamageTrigger - damage: 20 + damage: 75 behaviors: - !type:PlaySoundBehavior sound: - collection: MetalBreak - params: - volume: -8 + path: /Audio/Effects/poster_broken.ogg - !type:DoActsBehavior acts: [ "Destruction" ] - - type: DamageOnLand - damage: - types: - Blunt: 5 -#Tile (used to spawn walls) -# - type: entity -# parent: BaseFloorTileItemSpiders -# id: FloorTileItemWebSpiders -# name: web construction -# description: Very smooth and surprisingly durable. -# categories: [ HideSpawnMenu ] -# components: -# - type: TimedDespawn -# lifetime: 5 -# - type: SpawnOnDespawn -# prototype: TableWebSpiders - -# - type: entity -# name: web -# description: Web -# parent: BaseFloorTileItemSpiders -# id: FloorTileItemWebSpidersDurable -# categories: [ HideSpawnMenu ] -# components: -# - type: TimedDespawn -# lifetime: 6 -# - type: SpawnOnDespawn -# prototype: TableWebSpidersDurable -# - type: Sprite -# shader: unshaded -# color: gray - -#Table (заглушка типо как анимация) +#WallSpawnWeb - type: entity - parent: TableBase - id: TableWebSpiders - name: web - description: web + id: WallWebSpawn categories: [ HideSpawnMenu ] components: - - type: Damageable - damageModifierSet: Web + - type: Transform + anchored: True + - type: InteractionOutline + - type: Physics + bodyType: Static - type: Sprite - sprite: Structures/Furniture/Tables/web.rsi - - type: Icon - sprite: Structures/Furniture/Tables/web.rsi - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 10 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - type: MeleeSound - soundGroups: - Brute: - path: - "/Audio/Weapons/slash.ogg" - - type: Construction - graph: WebStructures - node: table - - type: FootstepModifier - footstepSoundCollection: - collection: FootstepCarpet + sprite: SS220/Effects/wallwebspawn.rsi + state: webwall + - type: Fixtures + fixtures: + portalFixture: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.48,0.25,0.48" + mask: + - FullTileMask + layer: + - WallLayer + hard: false - type: TimedDespawn - lifetime: 5 + lifetime: 2.4 - type: SpawnOnDespawn prototype: WallWeb - type: entity - parent: TableWebSpiders - id: TableWebSpidersDurable - name: web - description: web + parent: WallWebSpawn + id: WallWebDurableSpawn categories: [ HideSpawnMenu ] components: - - type: TimedDespawn - lifetime: 8 - - type: SpawnOnDespawn - prototype: WallWebDurable - type: Sprite - sprite: Structures/Furniture/Tables/web.rsi - shader: unshaded + sprite: SS220/Effects/wallwebspawn.rsi + state: webwall color: gray + - type: SpawnOnDespawn + prototype: WallWebDurable #Wall - type: entity @@ -177,3 +168,95 @@ - type: Construction graph: WebStructures node: wall + +# Cocoon +- type: entity + parent: BaseSpiderCocoon + id: SpiderCocoonHorizontal + suffix: Spider hive + components: + - type: Icon + sprite: SS220/Structures/Specific/cocoon.rsi + state: cocoon1 + - type: Sprite + sprite: SS220/Structures/Specific/cocoon.rsi + layers: + - state: cocoon1 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:EmptyContainersBehaviour + containers: + - cocoon + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/poster_broken.ogg + - !type:ChangeConstructionNodeBehavior + node: cocoonHorizontalDestroyed + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Construction + graph: SpiderCocoon + node: cocoonHorizontal + +- type: entity + parent: BaseSpiderCocoon + id: SpiderCocoonVertical + suffix: Spider hive + components: + - type: Icon + state: cocoon2 + - type: Sprite + layers: + - state: cocoon2 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:EmptyContainersBehaviour + containers: + - cocoon + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/poster_broken.ogg + - !type:ChangeConstructionNodeBehavior + node: cocoonVerticalDestroyed + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Construction + graph: SpiderCocoon + node: cocoonVertical + +# Destroyed cocoon +- type: entity + parent: BaseSpiderCocoonDestroyed + id: SpiderCocoonHorizontalDestroyed + suffix: Spider hive + components: + - type: Icon + state: destroyed_cocoon1 + - type: Sprite + layers: + - state: destroyed_cocoon1 + - type: Construction + graph: SpiderCocoon + node: cocoonHorizontalDestroyed + +- type: entity + parent: BaseSpiderCocoonDestroyed + id: SpiderCocoonVerticalDestroyed + suffix: Spider hive + components: + - type: Icon + state: destroyed_cocoon2 + - type: Sprite + layers: + - state: destroyed_cocoon2 + - type: Construction + graph: SpiderCocoon + node: cocoonVerticalDestroyed diff --git a/Resources/Prototypes/SS220/Entities/markers/Spawners/antag-markers.yml b/Resources/Prototypes/SS220/Entities/markers/Spawners/antag-markers.yml new file mode 100644 index 00000000000000..f1cc905066d692 --- /dev/null +++ b/Resources/Prototypes/SS220/Entities/markers/Spawners/antag-markers.yml @@ -0,0 +1,16 @@ +- type: entity + parent: MarkerBase + id: SpiderQueenSpawnMarker + name: spider queen spawn marker + description: A marker indicating the coordinate at which the spider queen can spawn. + suffix: Spiders hive + components: + - type: Sprite + layers: + - state: pink + - sprite: Mobs/Animals/spider.rsi + state: midwife + - type: Tag + tags: + - SpiderQueenSpawnMarker + - type: AntagSpawnMarker diff --git a/Resources/Prototypes/SS220/Entities/markers/Spawners/ghost_roles.yml b/Resources/Prototypes/SS220/Entities/markers/Spawners/ghost_roles.yml index 4761f7a83c337c..84058f8cb3f879 100644 --- a/Resources/Prototypes/SS220/Entities/markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/SS220/Entities/markers/Spawners/ghost_roles.yml @@ -1,9 +1,10 @@ #Used by gamerule - type: entity + categories: [ HideSpawnMenu, Spawner ] + parent: BaseAntagSpawner id: SpawnPointGhostSpaceQueen name: спавнер роли королевы-пауков suffix: паук-королева - parent: MarkerBase components: - type: GhostRole name: spider-royQueen-name @@ -17,8 +18,6 @@ time: 18000 # 5h raffle: settings: default - - type: GhostRoleMobSpawner - prototype: MobSpiderSpaceQueen - type: Sprite sprite: Markers/jobs.rsi layers: diff --git a/Resources/Prototypes/SS220/GameRules/midround_antags.yml b/Resources/Prototypes/SS220/GameRules/midround_antags.yml index a4ea755e37f97b..0e5ee1a7b06ea8 100644 --- a/Resources/Prototypes/SS220/GameRules/midround_antags.yml +++ b/Resources/Prototypes/SS220/GameRules/midround_antags.yml @@ -37,3 +37,35 @@ - type: DarkReaperRole prototype: DarkReaper - type: DarkReaperMajorRule + + # Spider queen +- type: entity + parent: BaseGameRule + id: SpiderQueenSpawn + categories: [ GameRules ] + components: + - type: StationEvent + weight: 5.5 + duration: 1 + earliestStart: 30 + minimumPlayers: 40 + - type: AntagSpawner + prototype: MobSpiderQueen + - type: AntagObjectives + objectives: + - CreateCocoonsObjective + - SpiderQueenSurviveObjective + - type: AntagSelection + agentName: spider-queen-round-end-agent-name + definitions: + - prefRoles: [ SpiderQueen ] + spawnerPrototype: SpawnPointGhostSpaceQueen + max: 1 + playerRatio: 10 + mindComponents: + - type: SpiderQueenRole + prototype: SpiderQueen + - type: SpiderQueenRule + markersWhitelist: + tags: + - SpiderQueenSpawnMarker diff --git a/Resources/Prototypes/SS220/Objectives/spider_queen.yml b/Resources/Prototypes/SS220/Objectives/spider_queen.yml new file mode 100644 index 00000000000000..fb29735a4465a9 --- /dev/null +++ b/Resources/Prototypes/SS220/Objectives/spider_queen.yml @@ -0,0 +1,38 @@ +- type: entity + abstract: true + parent: BaseObjective + id: BaseSpiderQueenObjective + components: + - type: Objective + difficulty: 1.5 + issuer: objective-issuer-spider-queen + - type: RoleRequirement + roles: + components: + - SpiderQueenRole + +- type: entity + parent: BaseSpiderQueenObjective + id: CreateCocoonsObjective + components: + - type: Objective + icon: + sprite: SS220/Structures/Specific/cocoon.rsi + state: cocoon2 + - type: NumberObjective + min: 10 + max: 10 + title: objective-create-cocoons-title + description: objective-create-cocoons-description + - type: CreateCocoonsCondition + +- type: entity + parent: [BaseSpiderQueenObjective, BaseSurviveObjective] + id: SpiderQueenSurviveObjective + name: Survive + description: You have to stay alive to maintain control. + components: + - type: Objective + icon: + sprite: Mobs/Animals/spider.rsi + state: midwife diff --git a/Resources/Prototypes/SS220/Recipes/Construction/Graphs/structures/spider_structures.yml b/Resources/Prototypes/SS220/Recipes/Construction/Graphs/structures/spider_structures.yml new file mode 100644 index 00000000000000..6472cf35c9bcf5 --- /dev/null +++ b/Resources/Prototypes/SS220/Recipes/Construction/Graphs/structures/spider_structures.yml @@ -0,0 +1,54 @@ +- type: constructionGraph + id: SpiderCocoon + start: start + graph: + - node: start + actions: + - !type:SpawnPrototype + prototype: MaterialWebSilk1 + amount: 4 + - !type:DeleteEntity + + - node: cocoonHorizontal + entity: SpiderCocoonHorizontal + edges: + - to: cocoonHorizontalDestroyed + completed: + - !type:EmptyContainer + container: cocoon + - !type:SpawnPrototype + prototype: MaterialWebSilk1 + amount: 2 + steps: + - tool: Slicing + doAfter: 10 + + - node: cocoonVertical + entity: SpiderCocoonVertical + edges: + - to: cocoonVerticalDestroyed + completed: + - !type:EmptyContainer + container: cocoon + - !type:SpawnPrototype + prototype: MaterialWebSilk1 + amount: 2 + steps: + - tool: Slicing + doAfter: 10 + + - node: cocoonHorizontalDestroyed + entity: SpiderCocoonHorizontalDestroyed + edges: + - to: start + steps: + - tool: Slicing + doAfter: 4 + + - node: cocoonVerticalDestroyed + entity: SpiderCocoonVerticalDestroyed + edges: + - to: start + steps: + - tool: Slicing + doAfter: 4 diff --git a/Resources/Prototypes/SS220/tags.yml b/Resources/Prototypes/SS220/tags.yml index 707d2fe899cf26..643316022474c7 100644 --- a/Resources/Prototypes/SS220/tags.yml +++ b/Resources/Prototypes/SS220/tags.yml @@ -114,3 +114,19 @@ # SS220 to put lighter in a cigarette pack - type: Tag id: Lighter + +# Spider queen antag +- type: Tag + id: SpiderQueen + +- type: Tag + id: SpiderServant + +- type: Tag + id: SpiderCocoon + +- type: Tag + id: SpiderQueenSpawnMarker + +- type: Tag + id: SpiderLittle diff --git a/Resources/Textures/SS220/Effects/wallwebspawn.rsi/meta.json b/Resources/Textures/SS220/Effects/wallwebspawn.rsi/meta.json new file mode 100644 index 00000000000000..81e18e99f4cf14 --- /dev/null +++ b/Resources/Textures/SS220/Effects/wallwebspawn.rsi/meta.json @@ -0,0 +1,31 @@ +{ + "version": 1, + "license": "EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt", + "copyright": "Made by Estkemran (Github) for SS220", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "webwall", + "directions": 1, + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + } + ] +} diff --git a/Resources/Textures/SS220/Effects/wallwebspawn.rsi/webwall.png b/Resources/Textures/SS220/Effects/wallwebspawn.rsi/webwall.png new file mode 100644 index 0000000000000000000000000000000000000000..8ee906eab3e28b49631de1493a0e93435443cd55 GIT binary patch literal 10176 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/cocoon.png b/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/cocoon.png new file mode 100644 index 0000000000000000000000000000000000000000..ab0e3043a9430f662b8bd1992674e0b326011409 GIT binary patch literal 1370 zcmV-g1*Q6lP)Px(`bk7VR9J<@m%oqPL=?wAIf5M}vILAJ4qv#lDKgc%a&;>%TGDLA6=;Q&l_C_7 zf|Mrz0)GSr1(BdYiXcJ}%{94IF1k>#qVN`pDX_VONeVm7=%UyNL9v>-{dJd1n!L)M zU+??g`_7y9;5Ew$^YQ+BAN~jM(c0$#th^}!`1_x1YQrDuN=dKR!*Lv{szSHso)d;4-EQ~LGiJGUYyd`i z6h%0WLs^zIO#@*6rIbi1SzlkD;>V;+lG*~8W$GdkLJ$N2LI|XkxUP%VnxZJIHvpQZ zvA~Wa$MV31^DW{y#&un)s&q$S*REZo*Xt36A+GBZh9Ll2YnrB^EK7tCXss;)o2FrVdz-Jn z`SD1_hHr;*AdX|ClqjVLf`GCtfiW4&vb1ims*1X&B3W}lt4tQeT z2pAK!*X!A|Z)6TYS(XGrfbaXbuFG&ZB+D{{5Uj7SQ`a?FmeJ{SEHTqGB~4T74W$%P zN}C^&B(ZPDtSr2SgTa6x2=F|Q<>h5gojS#EIJ9ZDsw$LHD5c2r9N+heqKL9ANz)YH z_sO!1wY4>y9gSz;jiUkFzB9u2eMX}ZNs_R%v}BV}5CnFeQVP%W=ytm_O@mU3IF8X; zlcp(A6tTa*Z7GJTU)@}M~7fi ze*R?_fLph2v9hva$CD(%aU7y3!uNfYQiNe>Q?&_?xeZyCvAw;`?K>k|lr98t?o0<( znJSwN2!1c-0N%TI?;p4j} zUVCdc*POz*Pk?D_W~*5vi`unGQk%18=S*|@+U0-ksPx(@<~KNR9J<@mtANSR}{y8yGeX7KGgjnhPo4+!X^+AUxKvIun|cgYHMF4NG%El zDTF??kQaT>=Za8hzz30Pp=xc=#9c&_hx2i zHVy5Ae^{8=x#yh!`MBra1Me6C@ephO*aq0y@ihSNw{!xqSekJOJbtao=h2%#@cGW~ z*JNnnue|Gh{#hm<2?*oMZx+_f{OFNE4jeeZix)5G`S8;<%K?PeZs3iesrOwaKbNlvf z3Wb6%3BxdCxGR;4FF{37$Y!%1<9_f&AQp>xl%M z&aiEpYPBlAClU$v@83^zb2F7n#X~?CANcZHU&Ep^dLpoQpSy`@nkGrq7v1vmGDAZ{ z*tU&jSso)I4Rf;-@^}2oZr2*$6aaL0ccZE*i;IhrfN7dQ&HJgTDFAd`=kVdf9&*uW zl*!3Sl9x}T>pHrw``U345QVXK-ypGAOp;hyS^~f{O%z3O)xyS&8_{*0fq?<}UpyY? z&Ye3veE1N6NF+iu8s*rrW1g+qFam;vfNk5d(nXID2!%rOSyff8UcE|FQxk^{9U>Bm zFf}#B$&)AP@9+26X}ApqiQj(xiQ(a43WWk)U0pyew{2~06pKXyfdDfzGcv^ae4ZUU zc5warb!KO0rLO+|ek{vkY;4R+zX15Q?+5k2A7UqyLM457D*MJC zsaC55gEdu&M1t}0aa6T-!uIy|Vp$f+WReRbY1#H&5pd$%#hci+&7M7bWCLo1P$)#9 zP;fOXaYzZ+woNLP;=)MUtH6(dfKzEBynXu?(=;iSO0GU2yzlAhS=D$$0_T6%Fin$i zIJ_!>VzJ1B2M;)S@E`!4ot^Tm*t&HqH*VbE;-%GZSgsmy79-S-RRQ6Z6PZkg6DLl{ z_lb!Kxi*u@_!_Ub(G1=@JHVwYe*j=v7VFlnBODIofwGRjq0AK9>2yjQG9^$;vb=@VqW&-inK2Y$z89Nm^3-12?`v5$7@`Qzj1uV<* z9NPlU`Qhf=DZnuqIR}&ay(&;Yq}1nAI^jV58sS`M{buH$Wdi?sH2Xhrj%J?W6jtU0 zr#JPtSpny`Cg3b;=gi^!CWg~@j=upRM0VNhl`Ccd000hUSV?A0O#mtY000O800000 U007cclK=n!07*qoM6N<$f}sA5V*mgE literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/meta.json b/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/meta.json index e53770b396e3e6..00cc38b18ea15c 100644 --- a/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/meta.json +++ b/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/meta.json @@ -27,6 +27,15 @@ }, { "name": "clown_web_spawn" + }, + { + "name": "wall_spawn" + }, + { + "name": "cocoon" + }, + { + "name": "crystal_spawn" } ] } diff --git a/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/wall_spawn.png b/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/wall_spawn.png new file mode 100644 index 0000000000000000000000000000000000000000..688e4054ddef427aae8911d324c07ccbf13e208a GIT binary patch literal 1299 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 UU32090000*FP)Px)G)Y83R9JF4`Tv zdEX!NW@cktGVU(k2~&y8)VMcn^V_>;vCG!`#}n=@-U)j_mmA4>Ip!D^08PIGz@LK; zq;>OBL_V1q1r~riewl4!gB`yt^R|r*N#-&{;-3PyHII^&RlsM37L^+X}GH4n$I*zwB>a8lQ4`W-fLNb0&A6GV3WGLB(kYaZ)~!rzjZX^~Jazy-kV zAj_WKnpx;}kmV^&lDf_y2!QdjH2n_lD0Sg-%ygg^bmg;9IS7Ia!2$O4mULkghfSQB z^(I4MCF~Lnx8s**D!-CU(jN@uZ#0B@fYT9tb9F;DCcw+#fr2R=SWgtfv~B_@;6j}M zzLHE%k%&f8*X6u94OtH$t(#LlAqk{)lScAD+2_%irFPcXtoZ3|nH$M@8p#8MNQJ<9 zq7denHpu64QvD{5V&^Qi(HI1Q%pU{+NnK|XN7R2Qj@ zzDIKfiKjF<9i5Mf`cW6+Fz(X!$sw-m()2rQ8ykwE$@T6J1{bcsP!A~J0IuuOJ~>o& zh3o-u*v7VP;QVZ#R4RaHIWQ|k6N;T++cw^?t>h@@fa|&d?2eigu#`jPQxVM*&jl<> znj-~?`q7YkGHaS4j8C-PQB$%Pc1Eq8d=`1)`E)c^FP5OBIl%dLZgsm7Hy#Dg=W^`n zElQdrCx0GXRk}N>G727zD7c6{y+uBkQ^W$y0jvxP^nxz6dVSmnt#j5-X-+vILa3gl ze3FE1+tliHOy44{o3wa#?m#c-a?`#?G2BwD+8v#5BLNgW=_dO_fUaqlybDU2BkL8z zEpFQPrgwqZmzjlST-U|6ZI0;6BtfEpr6`{KU;OTmI_!>`lr)DU`q;LO>$+qXmWkp? z0+X?nO3}~Gv!+>6#U>8>BXxTguoSyRzKA3G^t1CUrBbtCR08djLupg3UY{bdJ8DXm zr=u~rAQV+z(i}>f!|KV&(R!AqP{ z8yt}jud^Pvc@@5;q&X}y&#UmQEL74QR^nGVqR+nGVLp?R;HGaW^?N~=xh1~yPfos% z6<1e7*L7ug_JS^H-6WOBP>DSOkZTCAGCbo8-{4Eew*HRCABGP=BN3mk literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood10.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood10.png new file mode 100644 index 0000000000000000000000000000000000000000..333d7da22d9eaaed9928435a9416ffc646fc68dc GIT binary patch literal 1347 zcmV-J1-$x+P)Px({YgYYR9J9QZ7i++J@y6eJ)u2R}8Le>tnAz3IOLa~I22Mn=Mc%I;D#x_zW@pLhHPxI_iQm4He zOHcRSbI$$qW}M-Sc4Ojtl+Tq;o%{U`e;oXoIcvUu9dKjfdejX)E}7@lS;Z;>upR6H z@Vxh$f?=PD$Oj#hz!GpRXs~K6uog6w->S8s$ee{p_Cw&#h|fx~tbwPQJg-MVt|z`P}S#Nu-uY zDwp6A;A&XriLslS=xSKzA={XSK`#t}xGmek9^!3&Xgg9X&<#EHS*q-X;ZSgZC&sR- z!V(phsHEmQX&Nh8E;(>(K_gZ9xM_0O>#4sXRTVLHo2fxAuH7b?EAh- zm>jBMYLnlSzLLa4wt4e*a3=F7tB{3wN;^k82qD-G_E@zRG({)-ec0;_?Y~qHXy5=s z2s%eQ+E%C;@cSJc#{mX+`$?q|IIRL{CWlaNg5x;&{f_Q)lHp=^oNMIyl27?!A`2%} zyw5KFa2tSo-~FncKRS4humXh0VsSzHEer8(x@H@I4J!bM!Ovh4{N?w*X|a#+H9yyE zYj;5wplsU_K&@KE&1HFn&*OvRj{*ly#co&uZZ1o$S|y1G?`}f*$n~taPm8TX0Ircg zb0w1CQvHS%5KLc02!S0GwMVtuf-BBV>d`U)_wB>fgdYp;=3)``XqhX{O>GNCVX&8_ zu_>Bj9mjFl=)Z&@u7XUQR*f`*NpJwiaS%fA`PdW+ub&`r(kAnH_NQUv#el>xur%N# zcrbmD$$TCmL~4v8&^g+nG&V&&TBfPqi!(h ziQn&FhebBGwiJo`LNL=mRz!xG1a@;-9LG`Mc2LAOIx2rR^eEeQwCj19QO9u*2$j4W zdK3(s>F6@et#u&op(_M#?l2|-d=^-#z|vm`fe?avw2W_b)ZitzZP)V{oy^B&l_Uy= zO>HuM!{ul>X6$;{6uD3@0Pw2W<#8_d?S>w_9^*p2K<(Xc$3eu5F-tyIqBJ%|X>5wk z{e}iEaYy%kpJuC-sn5+t0>N~2St%>Mo7#M?gx~M5@4w>MjdYU0=6-`$O^@tMhJs-u z|8bG=GKXunaU4hC0c4x4RtDn9mk*2Npp?d@RNo|cK37scoueJ{xe^7#=Gcwsh8}*u zqk(shcGSa8Dwnuw3uGnAwjJ3)oJ1;@b0Pcq^S3`@{W8w2V3pskHG;1X`RdLsV9=J$ z{e~9rS$piZJf&RPsaNIt+*~BDOlh9A$FApPVDRE9D6)eaYFS1bSk002ovPDHLk FV1hSjmTUk3 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood11.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood11.png new file mode 100644 index 0000000000000000000000000000000000000000..55f7125ade0a21260a241d8f857d60fc52bc6797 GIT binary patch literal 1351 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 bKBvyV!(g*VQG;GK00000NkvXXu0mjfhc0@# literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood14.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood14.png new file mode 100644 index 0000000000000000000000000000000000000000..80249d7a8e22425d0470c8d32013ebaad12bb6b9 GIT binary patch literal 1281 zcmV+c1^)VpP)Px(yGcYrR9JXuc%?d74H2?IU7BskJUtle0=y|v73);+4jAY*i7gIi~#c~3kCN*BMi>wyQ zh$)||GgrcQHgMit48@dB#V)cIG!kITFxU=uxkd%cF!Y!*vKBO`*hR#Y&v|q4jV4k{ zq%v1<1-LXS^U&y|2D&sV^DEm}hQa=51Vr1i9qb}s<|l4PY6bcuPk&cg?vF+j;Q$Yf zj;_KrDqN$I8t-)_T&Z%Y1Gg45QZqkkS?ula>(97U_5lCBgwH>?pbsX%<6%3&)D<{y zE`|le0Z71Ab_#sbvc^orWf_KEH$8=p2T(Aau`{6!6buK~YA5uil$)a|*AYUn zF?}jhbAV$(!gfs8_t#xYEYQh8@8kq#01mE1+(%ah|>?9489VhGuhkN1=yEvmFn_FAj z#9b*_7#?UNlcd0|nMDYp;Z9J*H@Z50f8avI*lu~X^@0)_>&61we9qf=dOB4);12?2U^6-b<1iU-g(U+adTyb?5 zs7jO_Cv<`+h{{}@3$>5mfAKB$4=1@1+~Q|@jo{NgKKbSbaJVg-y+&faXYbN!c{+2Y zu~+5#(o(1%nM$6$OULu{+miyt0dV-j86}ZiuS)+qZ|u?5Y_&4AYL)ClhR4HpCc6-= zQ5VSLVLP*0EOXO7#gpfMannAr&O1mcsbo_io<_-StNy rfV=)Eym$M~#JTbB?^SUF$BFYFGT@<5Sj55%00000NkvXXu0mjfNmghP literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood15.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood15.png new file mode 100644 index 0000000000000000000000000000000000000000..0e02b06dd275e951ef99b08109a69e6b3a2afd5e GIT binary patch literal 1299 zcmV+u1?>8XP)Px(%}GQ-R9JC**QceZQg8efO=d%m+yN$upf==Aj7 z@ALirdGDPvoYHQLT@MRpd0^b@cld4h_snVi{qF@g#;%9Gz~!_2CwgqkDgm(RcLDhG z;0;B?K9!L7PK<*UaM^Eg*P3V9Z|HeWtCVeRS+W{ zH^#1qXBIGL&V*vbW6CPA>^BnNykW5Ece%+FdBf0SO31R`V9F{XMm*-snRkjvO_7RR z!4=?IP~n-eo$BaXP~lfL$r}a-K>$Q$+4Q@}w}qkQNXss2t{LX}FFYPe;;ksA5Ae4f371N|8{6+OVeZ{h1t=XGNOyy&+ROr3!_b0#br zHb4TdqEp~=`TT&0xaAE)ugi^~{Q(pWd!Q$B>Y-@ZIQcf;@0MBkyUTa?zXjmcy@#>z z7__vpBYV1g2)(~p#iMBXIA)h=W}tsUz??Y~*2d?_RRR_c{uu2 zl5df_RAzd6o?hUFsuWp>q6gUVyfZ^jT3P_gzv5{Dy}+fjzlD@iEB@GU04XJ%{jJ2V z&`s#|I|v~@7_QO}B!XG9e1s5q{Z3+j;vA4tvWj=+EX3hyCZ!x0%R;m_oqSs>{SdfH zzY1cNWM4V?cH%6^0#s}}1gKT3IA-?LSr`Uawr2S_W|msDN}LBrC!xA>U8{=_f~&1P z0KTBW!q_`6%mItTRrG6?k3V@4DJ8aFN?g@?7hDmysE3OHJht~z9iA2Lm{Ab*aFHwG zR$>?A;CNq_M<-~?6@(D1^WkESk%SM{OI2=F-fs~TZM<>v{eoVkg8!r^tnS`~M z$0CNo(!g=JKY5YyLLqerBm{K!wlYhTDD#&**6Xy}+en+u^qBW^zIZ zBvL!?1ujLyW-`1?b7KXFYUoIbW9~&lh%T2ju$nKWL`q3LT*Navy7A(>ZQFIpjTfS{ zDiKA)rZyhE;j+INDRx|JN?fQH0eIc)@zjjw_5v5)jB=q~q;~Y%p&v4B%uq1Plt(8h zk4~_@(@4M-H@D+?G+V7qeRejKNG8L}IsK`}cs5<`i&5u|=pX0WFmtU-9{IB--@`u~N zaaq=P8j1C;)n&Wo>d2K1yeijcXG3*lDs!za+pe2|;}=(z2?c=T7tSb%YK06!6zdw2KD0EhyhXBsX^YF=oM?>evpFgU_1$>B~{{Yp#tqPMG3IhND002ov JPDHLkV1oTYczOT; literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood16.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood16.png new file mode 100644 index 0000000000000000000000000000000000000000..5712ed8c85f275122606ae70a9063cbae05a59d8 GIT binary patch literal 1263 zcmVPx(sYygZR9J<|! zKR}N?^b7RTy9+%9+8jd8F0>^%C?Gu$j@Wy^3Qy@5R!1 z=6!zeznxWv6WXomn_6_soaQQ6%iC(K&WdOGPT>$>x ze?!TzPbB2njd8F7uKF$RTT86^Exqr)wWP(IL`e2HxR~--DOVHlG*jy}tISHdikR}a zHGMNYwSX(;LMWy@YF3$5zm)*z4TCLzm)q3H8-`v}LRS42HLHx6^0;CyyjMhOid5tZ zt^n7ADo>4_R7cl?D!;Ks-Z0n?0w5~OmcNU9Tbx*q)C>#)SASMf?gzm{IKWe5M`z(S zHEvT&^>^43s#LmE!>#(Q)X2}}^X%>K>%VbR(F6SV7QX&;NjE0I^HDd!)L*Wc3t`Ey z83Zohj&j_X&T{eld%XPamx=0+vnQ_)0QeJ+CuRZVKQ2O-pk&xM`ECM!R=Y7hu5js- ze{k|$N`{@-lY=Pw#>^7AYQT;Ce*w-Exe_1uamlyHU8*p@v&0~9LzRUrpjGuf@6^!4 zmKK2WAJ0M-qAu+Xw~Sv?L`sS6mlIdDo`S35 z4$W{GfJgRTs>9R59Wx4|87^~G+(}G94#sm?Da_KAYX~7&AH4)W%7Sv7mW?!laX5ew z0x2b*7iQ7CQB1&Ln<*CQ&%yeOv4}~qG;kd5&s}7uSWKOOgn-^~n@VApX1GjybB#v5 zo)7_JA(Nn!;2WEpy1c#Nc2Ypqw!?uxu8BA5VFzV4HaE41M^Z9BI?zHUnF2dz79oU& z+kP3(=xP6hz@=*2;g0KOazY3sQac|6E+xZeF1$>8a}9`U=tzlU?nOd~E|)a0+ApO< zN=Y+Z#xr`l@#53A~H`n2FwS87@bP9T%H27n&siUbP22G12!sZwg#! zmT0{D-+>=8Z!AzWD^v=zR0^|f^jitI;^z9EN4wL>G#3{`iDWLktRt(u>)N7O!5j7H zd#^Zf!lX!Gqu=6H+a)`np=8*oA1>;=^5NvW2q82NAlvSAG7xpXx-8<2QYp;px+!?k ztmr+x;WkCHLdmc>a6$%wi#O^e;Jx9tzU)-wimRtUWuj`^q3uUbROG5JR2_f%=0~ib z&vDnk&#%@h{#Sc^`NLgcT$YV~D{B;I&x)4UX`1Ri=ldCDs!z}c3d|D;}=(z z2?c=h3uhEW^1Mp@VcwBPTf5WAH0pJ-^BJCxx|!^JbVgku&qv+NO1a8C>pU-B|HVD) zJS*jD0uCh3H|q6N_n+BKc3=Hg-)|Ni*F!_ZlK76LeH&%(zK9!}gF|NK!cF5oPF Z{s;4BrV{CpXfpr+002ovPDHLkV1jJcYAyf( literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood17.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood17.png new file mode 100644 index 0000000000000000000000000000000000000000..ba5d664c0a41aa7374d42e0af0aab78a9fcadc1d GIT binary patch literal 1243 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 KMNUMnLSTZ5+K?as literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood20.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood20.png new file mode 100644 index 0000000000000000000000000000000000000000..6844b5065764d92e33727ef94823ff67cbeeb063 GIT binary patch literal 1199 zcmV;g1W@~lP)Px(X-PyuR9J?|wpLtKC98UBJcvAg>;Ima*55}jSSzlo-q7dsnagJEx?KU_uka9nKi|Hi zoOh-Ya^}P&SOXu0+dQyWcoc4%c@OLrBW4;Q*|Xr{Qou%~mV%EnJ$~J;uu-WYE(NR= zSJhbpCMsOE7S+Qj$DLxV@!I$IQ@_9d?w1cb-s&IooPaH>z{{vJk&_!YxK>Afi0A#--y}<^TDBGyKr;1O#I$g2$x;BP z%3&zW)}kus9iv=>Vfx4?Svl{RAWsP>=N;Uc4iBST3jV3AeEDzOnGQNgZ8?aeZ_KWc zs|~sH_Fv#)QIE^qjnF1{qsqd;3caDPbSbicQPmBCb3;$sxB#^OWEQdzcd0knM@q?7 z|M-7_14t?H2K%X9VR|5lJcJMzh9`R`8O)9yB7`7_ywv>EQ7om5x6C=Sa8~0=DNl`M zA>NzrOvfm_2wbOM2l1SAU%4}#)LD=Ps5y=TXw>VtR(9$vOoD6Mu|r%dOQT*V$%FSN zp}ul``w$@nx7$Ymd`T&FB7Te|;X3*qJ0zUHhLjQ~tfa1LvkPvCyEN5008gExu@27* zcda;xrdsEgxSQGqIT-EBYGIC++(Zb$PV^eWI1AeGxNM9Qn1lleA&^q?MPUxZixL7( z+H9#rcOG_LjYLd>jRPm);rumbOQo?pASJ*X>{Bhw(NycS_BLtM>nRa15;6%o3BJ3x zXUgjh_R|7tj-z_vs3t+=;S4M6?(G>7Po-obIyOQknFhO779oUzJ7I+&?-~ESp-;_m z)Pe73azY3s(m3x8ead-EyZcoBFcG(#%%n;Ww0JAc6}TwTy2&Cc+={!WyN!QLm%E1xY{h!c>mjRs94A^ zQnIR43v*NpbL@7vQ*h1Ab%TIbyPat+Eh&j)Ufnd2Ro{1Q$*K}W9^K##$F53?1a`aI zylMGl7c!Ld4*HLaUax()GaZBwh6j*swc8npJ6~TG$wsLb=1ko*yku3)9B;5s$*NM$ zI~==;-q0tAycFCU?3>F@N3OYM7wAmX97j1}>_kVd`$E_8r*D76{`oWRg%9}Eenj~7 z5nugq4;YnYx4WHM@7sqQw0#q~wo^~#=F*bVN2WI4KIFjnGcbC%>P%<=j2@hE5b5_exlsX7Ye}Le4(B_ell@x^7ALPq=1X~`42(Oe2{^w$5sFU N002ovPDHLkV1mdqKGy&M literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood21.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood21.png new file mode 100644 index 0000000000000000000000000000000000000000..50dbc6473408db79c3c0e40eb97eb6d0414fdb48 GIT binary patch literal 1196 zcmV;d1XKHoP)Px(W=TXrR9J4G04{h+p0bz4Z}%gpNU%oA=EHe`3;^ZDE*{q8fX48Wh^F#vzO zc}pp0&m`o71Cw9{d>HO<-&*BixTDA2w^p^7S%kcIz^%fD{HFI0>jgu|pWccb=H5fcTBMm`FEU-V-l zqJUCiLr%-YL;>A_&wAm~82l{YQ4!C3vA=1SQgy>zmH-c;?AW@`3RkA;VcX0DFuEL? za>HDfrJSvmD=^F+`7|r#Y#rp7fKtxJoon+T%BJ8S%SxC2#+_@Uf>f4;IQshhD%t9Q z^*8?l7mIpQ=B|Yn*=rS+j#lXoeBBuapjCB(;M~wrn-qZZpUi>*ag}=gLxd1)_fG#8 zIDilWuYZ{83S9$1mO3dFVK*iG!M3@*J>#dFcdNkIt{*maG;mh z>mQ~CRBc;!!{M3)k%v7fvwv`)MLZRPrRY=(nPv*?ng)*JXt*7g338tH-yQf=ZCf7s zekSWU4g#T_cLzSDoXw)VPV-<3h}X~+0@pl=g%BSulfY`c5CS0t4Y^5>^K{`QyY0yL z$<7z!v?>v$oK1Z`zTwi}j1{{+Hf63fN&viWcG))LvE6|WZ}VJfl&HV^b{a~Sa?2FW z3YGiwb!3%yRa-PG1d&H4c+IIR(;|WW&JM4e zKE_gpQqD&GaZ&S?4|lGO<2afJU^H8;48)bM4vS==RPqaY-4wiNR`eLJe@M}+P|Dey zx{~g|Cy2Zh-0L6e!%ju6xVj5eCaShA?J#ztB3E^x*72urf5iIv6Yhrh`Neuj`1J{2 z{csl;F3WyrCpF)Hyh|+L_zsD)+3*yzKqXJ?k>J%hePdNX@U;Y7^n_ zwav9PovOylicCH~d-O!QTQ4MlyY)god-P=L*yQhzYDobX@$(-SJ%0%>(6cQ70000< KMNUMnLSTYI8blEQ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood22.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood22.png new file mode 100644 index 0000000000000000000000000000000000000000..2bd5789c826c7f312caec9616df39f9b691b93e1 GIT binary patch literal 1187 zcmV;U1YG-xP)Px(T}ebiR9J>4?Pw7 z2jtj8j=l8KdkZ-Q+8jd8KC~g11Vkv7F!e%dY&IQlP_-+o*{FDW*vx2GKl~%kJ4vfI z@AG|c-kVuvIHTPxtgDh;op>HZ9>4Z~%bYddsTbTVtgGJ8=hL|h=GiC33IKnG2LSx> z<}Kx%b0#4tI%@FUD9c*GI@b4T{|JEZ?Eg+J1YalBcUQgzi{QNTpQE!^8YGhCbQho^QPfbs1xl&kiND(4)d zT!Z24na{Fv&M`?&2q@KI!SF=h_i3ZUn5%^vi9a*;Cxw6 ztK8+VNcM7-<^5~)hQ65$3oxp>LGa$tahsNaj-RZ81#y>pgFU2_<}~}zZ~!SK-e4~^ z6{ZJ*$U_KmZg{eHlF4irLxd0nk(csM9qv-fcx2wQ3MVzLlyc&k1@UaUa~-4fJaAop zox~H;edW$|QfGk$P;(pw(5TmOZR^Zcm<89iT?}z;i$=Xpk_YcjLVe}>#RG&8+-M&H z@HwRuui$Y@!gcoB#gK4m0VyR;SV>*gW(uy0+ceb%0FRu*sR7>??%Ht@O|`*waXU2y zSs2Y_HNQwpZXtwVJ9-6STm>C?S~aE#Ou_+#5J)NcEWe21MF|1pHeV{yU4reGBN4M; z)4)l1xU|50sWf#0QUbie9@YFJO|?O5cZ){7o)Q5gA+w;f;5)m!W_!KCURprSaa1oH z?MV=MIKv7%ySqljBPm&qj*O65ropalA%rk+C#(?UJQKe+^r<m zPdVqXq^{7~-2&o0bfv_#4`U(3m&-J;_Lov3rKG7g2y&ijyyUd)`##zEQe0LoqMUPR z%wLNm4>n@Ou8%{7OU*I>uUkEy+OcnM=)>DQmzrf7?|wT970bC5N_LfMevxW^k)7_d z6kKz&-5{XVZfBaSt4bnSQddl7)puQ6va1AlxQk*m@oft~I%UblR#wGp9$5eY002ovPDHLkV1mVT BKH2~P literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood23.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood23.png new file mode 100644 index 0000000000000000000000000000000000000000..41bf4794de1d6a6cba4ff7f67fa1b9571b816ce8 GIT binary patch literal 1177 zcmV;K1ZMk*P)Px(Q%OWYR9J~8BdCKhbqt={(XOm^tK#WlJ*!>)u&vndB&}xN z=lkBgH*b|UeFvXVx)k<$Oqw^Q7;WSU6sx z-E*VPFn~x^%NxGoKGjAAp#8_QU_e-{vxG_9l zJMm!l^FBfdyueAUPh9R&%CKcVF$-4}u9R}4pwi5gTuo} z#2YDD2+kuR<4l8X(?AFj!7YCVFXKf1+dY@EWvOG=O{IkpNMz)^-E%2sEaue%>W5oE zc!su=*ydR%gmAcw0_*isN~Dz3)COM0i3%^?ZO5)ldb$v%Rf{NQEUMEhq37;KsMvO~ znBiWn2*7E*&5jwaZTDRGH_N?Rk?O^7=e}Ygvq-@#QOeFy%Fc1n+D*VUH{J3)>WxOK zwzQ-ql6mzYimY@|wFR?;7dW)MQ_gLb6bT%(b~&xP7z-(i84LZ#Meo->?5QR~h=>PZ z)EkWygq5#{MZ8c-*}3T4G`wJzqBTzUh=N(7n6Wsw744pj7dQ#H(>;oYosL{{qb|^y zC|j1Y{LqPxT-Sv@$DhCbk^C>8@zno@U-LiVe|^SRKRgBc$8ylxP3(8`Cmc82C~|E> zugbNhC8e)SZEpUAW7kbV|HV~jLIa@x!WjmU+^WxOKTB%?xq}U6ZDPtkr zqX)=d&`dp^DYKcs%lpnBZ07Isc&40y1Bw0BN@XPcQrlQvjZ#%xT2k@vZ(qJv_SQQE rU~j!sZ(qJ1yEgv$RxK{zCVu`0*tmOJ&pxiE00000NkvXXu0mjficvy( literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood3.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood3.png new file mode 100644 index 0000000000000000000000000000000000000000..c0cc200ad4b77da30fc8c09964516e2fd3b6d6f9 GIT binary patch literal 1423 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 JPDHLkV1i<7nsERC literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood7.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood7.png new file mode 100644 index 0000000000000000000000000000000000000000..40f7abf0e08ed431930c3ba817653a3449f6f2f6 GIT binary patch literal 1381 zcmV-r1)BPaP)Px)A4x<(R9J zdg+JAAzz@E-g}0TJ5Bm|7r+h0^f`SG%#1vaz>^&5U;JRb01y zFItV>d7tNb|IDlsoYAgNTnlpP;)!*4(B-F>KPS!_?;mftK5;GR`3{#d=hRx+ECA5< zb^-XK|BAd}or%b)j!|FpZh z5_Zbv`oy*1UlUkJ&johMrEC^h^XeLK#xQ7myDU*AV;E{p5?S-=l+6Nm%4H!v_f`_I zDU!-1xCFTBm)I~mv4O7oB_7fyV;J;(9|+6R_I446xsm0F%|Oq0)U#CC_x+LJ02@X} zWnqajOO#{d9XE}YOqXo9HLo74d_0q3zu#A%QIqNcULV32=NDCD0z4UPYM3em3+cHa zZ&&~txKt;B$1|A|B%+ov47G18g^CA|H>?vqp$Oy+i&kb+oAao}sf}BUvv2;Yb18F< zR%R0^QX{aCo(rmzi&QHWrGAOBmd-e}QS1A@^6&dT8N*m=qLziER1dJ{ zx+-9_sYa=devkS}5)Wzf`f#`=<43cQgs@Ay2RjHMXnVWdG#52R$Lqb{?~km%R1aw2 z073}52RqtSs2*?!U2NM1hG+Y6r4l$U192vsP)>qv+qi?S=A)ehLI?mJ9JZOGpdBiw zS=3KH&rx6{RaSyz{HUp!ELm0n;feO(u&vn3bVgHq{8{?R=hug!dRc;%R2dkKbH{NM zZZZm9tyI`BI;^D1YV*7Pd9AynDx=_0i-JqrFgjE#6-}(lfV^@YGpy5<<~{%)lT!gc znh2{kb$gZPx9&1^dli7^x9$S)=;aZ|?H9tXe`yENir@1cN|qIL949em+cpBBg7E3m$8i{&%!O%{B=UwubuxUz%8GBgHkU5q4!Z2QFF0xiI!Rz_ug;5xLvl7j-ms8=T;zTkqm|jjwrzz6kZd%Y z2?#r1UKY_tDQ2ft-6VJ}T~t2ZgB^0|B6-8&s1?xj9o#`z1MeQ}sLM_&m$+&QWF|_M z6e_zC+@;fWlyYe&UX^R} z^MO1vr8(xVxgC_>*aQ-2)q#L?DhHWSrKh2(64CxgvIayHx}FOVmL z&BRKf#Hx9LXD@$a)x5w;p`?KW+Wu;#5)1xTTfTBdrK&bRA4I?3zjH5Wtv?O`TI-L4 n`*-e*^o>6MuNEcnU*h}?8K(6@`Zt&400000NkvXXu0mjf(&mx6 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood8.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood8.png new file mode 100644 index 0000000000000000000000000000000000000000..50ec9b673ab0f85d39812fa1a40a0f8b91c1d9ca GIT binary patch literal 1370 zcmV-g1*Q6lP)Px)6iGxuR9JqDyh@H z7q4dDd7tNb|IDltoY8Jh-Uza(!l`w4(B-!`zbDQb?_Y1YIe8=K`3@J;=hRxs%mdKz z_5k>+|CXF#or%at9izY!aNVo3W-hYs)s^3xxv0pTg-G&a;P#lyO1`Lp$C+F&nR!<7 zMeH$`o0B(!PbRRCss{F$OUcZ$?$tHmv|-Tk_E@4s+A!3bB(m<+DVcffF_(o@^@Aj0 zQzVs3a0zhLFY?UTjSY0wFY<&AX~UrJ`#@Nhj<<(6%8o2YYzBJ1qn@S8zVD9&2Y6=e zsw^x~Vu@00ypyJ}lIfBSx9-(rl~1J89Q6C@Z`7oEfOkjm&1Z|MF#%o-wlqwYfrV5x z$Qc%Z1}@b};E8nl6p5&%4MXi4A4A0h$QjnDo=^mGhDAHQrOkQN;?%~i#o3R4*SVNJ zM?1ZR6sZwdNL7Q%)FPE~S*c&5q@^=XZPfa{ul)PIPueh8qNI&yrCg>mwWwtwDb)k) zyRHftZK_dfqraoRlEf1_ygM4M$@tMMBq8k5?%@tX2s+*#Yv!V+=w!VQ`u&mhm+Aox z96$&`_i#s>3e^Mdpo?wW!0>E8sZ;{TWgyOE6Us@jZ5wyc)qJ#bKnMZA&-C3@UfsE`-ph9nzWe2r!as1?G(Fm> zq>3LUk$~Zq>zHAkt~3t-xK5U9lOMb=PubHq#~L`mrs?6$P9ucC^77hMt)}3zeT!PK z48TL{AU5Eqg11wlh+44BW&4&k1>-QB%R**`hShgWu8QCD9g3C}>^e?j+_r55LIv;n4mrbOHn>EiwE=`RYzsjX)xf)lJL+n$P4SmU@NhbFS2T$=jEF} zSvAkIk}qoDfVRIPx(^GQTOR9JA1cl71JsJ>{`hENkFNCf6%wk+otO zd&=Yb%(d`?2`pvmp*`hMF^g>YO$|6}7WuJfKU~Fc<~_5S69t?;{TL6U&j9fqvksXQ^@+1QWpl9vOQo z3oBGup^_NyxM{3px@5y`_{~J+XR}!jhC}rkH>n=r^&x!u(XwhxfG49Z4O3-cDN_#% zh6SL3OLY?XY&Ls>MBK85q4rHrq2d7)4C_QsC;|n;qLbay<~(jmYLnKI?1z7vT+E)K zlifm!)CeqP>S1kmnOe1~)UQy{(wU?-Zo?o@{=*<3YZ$Ch(Z;h@tx}s^*0PY6>H&J5 zrvk>CYLeRc_qeYl@qjL`565dVemo0lh`Q7n>>`Aq>+iE}E^CU8*ZW{NoLGOU9?-x6 zgb+A`U2Q5<4|pR7+qQx6*?wH91Ww98lF25NlVIC6-pJ8>v~xfR0l;sEUFsCIL*-o- z_mj_cimXjllpq;DZfYjWmK6dljE?xqFDr*nXWn{UD7*08EdcI*^Ru@8CsEy>nm(OO z6l>3Q6>d5XUaMB=WYTKWX~Ca=`%B^;30|vKiQ~bW49F|jHKRIRX&(Ua8Tt1nA?@MI zBlR3t@6TUA2!Z7nwX0f9!Dagfjc^r!d)7f>zz+qNsc(dxaYd5Y1_6D2o<~^xD*VF`S230 zolPLBVMho$nS+Q3@Ud?u0!x1(1VRWJ;VPctsK$#=+n(z(J)4ixDoGR!i`s1ThRa|z zV%%}DD00400N_Qd&%;dQ+YelLmE(M)K<&+MM}EkHQ74}%QOeCx%FVIeYii&Uce>|! zwA$@dV{tJQ23q-!n$V^B87{72vBJ}+-^~do}9Br+3J5{SzNiU>$GTKU| z7ot7#0(mmpO05;k+%nJc?B!qFGS9JAENkF^w!c=bCW61!RgSxu00000NkvXXu0mjfnsAAs literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/meta.json b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/meta.json new file mode 100644 index 00000000000000..912c64a3ae7228 --- /dev/null +++ b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/meta.json @@ -0,0 +1,83 @@ +{ + "version": 1, + "license": "EULA/CLA with a hosting restriction, full text: https://raw.githubusercontent.com/SerbiaStrong-220/space-station-14/master/CLA.txt", + "copyright": "Made for SS220 by DaGo7393 (Discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "blood0" + }, + { + "name": "blood1" + }, + { + "name": "blood2" + }, + { + "name": "blood3" + }, + { + "name": "blood4" + }, + { + "name": "blood5" + }, + { + "name": "blood6" + }, + { + "name": "blood7" + }, + { + "name": "blood8" + }, + { + "name": "blood9" + }, + { + "name": "blood10" + }, + { + "name": "blood11" + }, + { + "name": "blood12" + }, + { + "name": "blood13" + }, + { + "name": "blood14" + }, + { + "name": "blood15" + }, + { + "name": "blood16" + }, + { + "name": "blood17" + }, + { + "name": "blood18" + }, + { + "name": "blood19" + }, + { + "name": "blood20" + }, + { + "name": "blood21" + }, + { + "name": "blood22" + }, + { + "name": "blood23" + } + ] +} diff --git a/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/cocoon1.png b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/cocoon1.png new file mode 100644 index 0000000000000000000000000000000000000000..c416be97995b5df5b77405db6d7e33addf9bdb6d GIT binary patch literal 1622 zcmV-c2C4apP)Px*5J^NqR9Ju* zVa}ZMoag&}p7We@o`EjndEOQEM8|yJU-^~3UUs8>v2KdGuCGPOoMc$jwBJu7(Xnyy z7=d0B!z4lmP9>q99%}zNM&Km&x~{KuSX^bQBrLw#6plt+&qF*Y^^NAv2Ul=7AkBEPt}cnti;jT;E%u@Isl zrMxvWGjl9d^Yim7%46HM<>SYXsn_ddG8q8gy?e*CYuCu-a&(A^xw*M3z{T0w*@av# zw*oLTGZREGpU>m_{z{($oS&b+P_NfN#9}eh=`>*vzkU10nKNg8`o6!COeS$%mrN!@ zv)RNj3=)Y19ROawe96+%k_7%imu;s+C4b-E-X6(hQhxmSk;%zP?%ur{825cY@Um1Y z#eu)2QYq^7I*CLA-}f;L1Jg7qm&;g|MK*hw60@_j|I{=M&+`Cwfq_n&g@pxjx!fTW z+qR{YQts^R$YQZ5rIhm1r%zH!DckL~{PN|CRIpQYnUphUo9_Cy_`{uh&^!U1elsgmSqY*sv@MfXT^807gegxq9^~$z*a6xTGQ# z+=i~}GBGiM>$>Q=POVm>(P#vObX~`B95R^? z?cm@5fJ&tTz`(#jK&o6W2RY?=9?fR+NHPWyNT<_`j*g=1I-cjz-`@{_=Xp4eL$leW zR;!W8WLRBY#j-4FwHlUXvA@3$fUfH_o6W#;&+~$%*xue|a&i*Kac~^xC;``XF${xB zrGjain5KzkSyZc4CMG5@P4mchQ*)F!j)UvE0ocL80j}%f`#!H;y#nC<`}YB{LZJYi z154PpE$`g9!^Xx2rfJe>G#DKnWoT#!$8peg9n&;%94FX*x~^kc7Nt^&Mx(*?>(?oj zN=N$6o;@3oQ%TrpG?<>A-fg$rQ=N#d#Q^c-$rG~KEUi`xAONgZtHBZ|_QS)&n5Ido zR3e+r2JK3vLVtfhjYb2@vUv064TVC1<>h6TmzR0__AS%X(?x*U+1cQ<6}BB**OG`l zc<_Mx_wNVa-t)_P!U30`1$kafEqUpqiZc0mCv6)|G(XC|2H0wUl<%5 z{M4;DjdcSLzonG7G)+sY@pwG`?_U8|cH{B*1%Om4l~p#wm`8R&ugVn;y^hD@`zQUd zL}hSr@b3WU&z}z*h?0m!2ci=0*EB78%D>;SxyfYmk6t!UOY##HP9hQgqdrOZPdo<1 U*5D|l$^ZZW07*qoM6N<$f}zkU+W-In literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/cocoon2.png b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/cocoon2.png new file mode 100644 index 0000000000000000000000000000000000000000..b04b1f6e8e49c43308e53108918fe916dca0b87e GIT binary patch literal 1281 zcmV+c1^)VpP)Px(yGcYrR9J=WmceTiTNK8BF?GVzToagC&1NR6c_0arS6;J`x3sJN0k6_R+}J1- zT?A5e;i9BP(2b~2=t9sxARFsSTm&kNU1TV{;3COpRvAc~K3--P&Rdu}q_NQ!7j8VO z;hwqYeD{3ke&@n3`(?lECtKoM&cR^t-2k;(EjmriXV0FUxPR_P0Bmn>N9A%ERaF7- zJdfSo-DnnwGXvP#+M4N0Boa}%T*k62+U+)`Y2r8z<#PEsH#d3 z1myF1Y};mjejY_p&IIDr0BW_`zWffukYqB6rfCF0K)c-r!1sMj)5Nl@Qy=EsS(4Z5 z^-{fFFZKI&&0@rm>6om^HE&%-gLjcCfFDH}9ivU|&TSb5GgVX+3(%E=cLo=`q=f)%F4=z`}gn1oQGiud@23QmoMYE zPo6x9DadBC2d4%wPJX%7Y6*Zsp|B6oYPCu`J3CReT1C?|02D>R^E^784gh<5d&lBF zdi1FHEdaA9xC|V=e*K!OSFaW&|2sQ7(Ty8705DAx(=^d_9bMO1T3Vt|D6qD+1`w;` z-Me>BO#D3n7=}@j-y0hn2LP8YUBa>~3WWl;ZPV>`@jMSzRq1xSn5K!MC^M4{27|w+ z*Je@R8-^hUgFz9XQmGtdGMQ*`aq-wa55o}Gbpa4U0MKkUu`G+xXvD(8LZVu&vazu- zlZLN^Xw3g_y#RlX&(3wI0Sh0>Q(9E$B)ta`g(l&Mx%kQ>u8!5>wp|e-ENoN-Ccmhty{NZ z1)ZezL;$^BZ-4Tq!C+7v4u?<26)aO|#hqNXYWb zIMX1`$wZRxX_FhypFbbpd&hCGZ5vfpSz21++O=!s^ZA$x%d+r&pGg6daVBU1U`{3; z4u?;tPY+P3RLEp9mEmysE)2u8>~;X#wh=<$c^-E!bI0X%r{ARUGw%gf93`+Y3S!m_Nm`{hvbJdZbT-k|Gx9IsZZ&D4U#1fqGv zFye}2v)O}6rNU@5iU8Ku)=*WIMxz0Mypr-7>bj2Wy7<12=XnSrP!xsd&z}P%-oT;toEE#x#4j5ZtVO^qWkpeQ?$Omj-n{&x{l*G+`M@+9zcyoBW}Pj3<-h&UDvTJ z3&(K~Lh$(UWA5C!6HOfU@K^;Vn{Sc|!!SynPABU3`|+4nRTUvbJo{Bujhk(<(}EXQiL>3!*yL;*Nq2K zE|-fNwcT!W<;oROsnn5S7((v<3c#dHN)X9p@?tujUX|;&Z{Pl)C<a({1p2iYg}Ef?FRsd00000NkvXXu0mjfyxDVk literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/destroyed_cocoon1.png b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/destroyed_cocoon1.png new file mode 100644 index 0000000000000000000000000000000000000000..078b07ec6de88602e5889ab9f559a57af5b085d0 GIT binary patch literal 1576 zcmV+@2G{wCP)Px);z>k7R9J`qDuoM7>P34 zP=Jt-ZAC(Y!WNWi60SfLDN;doMPglCI6mp{>XfsWV%HSAo?PxiBs^E(S#8$qgeO_v znR)Zx_kMQv8z4q}-=CMi=o;sI_ebW&*^SOAaf*zwMik6>hAE{>7l9bsxIO}4+{Q47 zkbw(9$ln;XKSuzZhn_Lk2m|T&`v-%;pm-jL;o~gl{OCtYGZ98V#@L9+Y(%p(v@si+ znhoh+M@$CDI47L*-7pB>_vZ;A8`*5O5H5!V5e`7^hYTMh}BhGK%z6~NHCWLGVA?}){Ig+aN z_4OkFa2zN7^5sjsc<}tcO<9h#=Wwrx}@l|7l2At(`DGfgwdV69dI=X_T&O|xN| zW8YtHRI63Et_xk)p=lcO`8+gDla6OO=SR|s zX_{DGUWRF!KSzU-%|CH`e2h#cBR+llgc~<*V0CpBx~{|XJaEpT>pB3S*=)*E!F63E zlgYr?!-o&|*4EZQDb1{`tcY^CEKJixr_%|SXx8_Ayng-q%z2|^G8s{=R$&+h>h(Hw zT}P+WfvT#QnVEs(H~@gTxw!xUV+@Qj*tU&Ut0f}}BENU<9){(>ty{NnczB4z!^5<6 zPAOfwfB*gxF#H&Ko(EM`15}h!0D$Ydn4X?SyWNK8c_4bV=%NZf+s~005m%2aAh~=yW<@jKOgn^m@Gj5MvCM zWkJ_2gh-s>pJT7I&!%j9LK@V&Q9D#NTCJkpZo@DPG@DJNQYn1=_z`Ps zYq8%QMW$a>Rdl;u7={7EFp$gTVB0np7Z+g|22@o&)A=$JLz$HzDwPUyxf}rCa9tOtr>C-PyPWe~-}mQBrP90vKwiCig+if#e!mX@Fbo5hWx=-X zpain3r>Ccb^cD&Qpjjx8l}Z>421R*TJ%0Q+IBkhc z1ppDP&$DOG@bu}^V7#!f5R@pHOybR(HvoWqK98F>Z~j9m&6LY!VcRyAmzS}#vja`j z@ZiCNg<;woo12?wctV(z5&)!BDlL>sr3C;anN02t&v62P?Cz!(~xt1bZ~HhN~N;L z7$fqutkr5^_5{XQ_<58gMDGL_5z8nGj*c&~HxZo(bGVDBcpRMz)AR5eW2_OUKM_Yf zBYuvf8zty*Tr!Sj_xt?=0LM{X5*I0BtPv(Egph0BzI~gN>#C~8a>=NC{`~ph!C>%L zB9XY3PN)BlBd1E7^YFhA;x45$Bi9p&#P2`iT-r?}64wAAo6Q!a&9KiiZ^1a`3Ve?` zkx2Y^-i0M9>2&%R0JwVfY7jsagc4ndN_d`9nz`WaH?lXA$^0?S=0#0@uEKdBqBrXE abpHpH>UV%N;Rloe0000Px(EJ;K`R9J=WmN97CSQy8DZi>|*asu{b50)kuiaMl%WGNjJ2&hvsTucv?K&95w{qaFLK5r?il^Oa9Y) z-xKfu|Nh_i-Vx7!3kfGCP=Z*P;yWI}+)j~_EW zKAx)8YF`y_;VM3_zY6?2G&E$_YBdGm)~#D%tyV*lB#w`dQ4|FL*L4v^k!G_=yWK{X zWkgZLFbtkPefl@_y4jCQO8{_ocJ`%SuOCKaolXY;MNxS7?j5FS5(EL3Wg*Klnx@6V z05&%_C!(aHQ`L{260};a!=zfz^TvGN-}?0FQ|LGjf*@eqHj*TvX&SEU^5Me=1VI3Z zOJP}7yl2$FzVC1K?;ktxwFjqIEKWF%!|v`b$r6~RNj95B(=;Y0Cs7n7E=8$SA_xM4 zAn4gAO0vg+h}if2t^Vu*G))T|jRvM^QZAR7otEdc3s8h}crf+R^y zO-*rda1a9bk|Hh$h{%({h)f1SU84*+ys4|QEfRaJr@z;PU0 z*Zp6qsJl_`bjO z=+UE(4Z+1%V5fAi+eg^MpW=x?XhY8|evt&Jx?tk>)Jo;`c^F`Z7+ z?RMkL9LJ$hC;%XeV(L5=zX^`xkjZ4|e=#GT{@72)e{^CCPzYKeI{*Lx07*qoM6N<$ Eg0H|ChX4Qo literal 0 HcmV?d00001 diff --git a/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/meta.json b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/meta.json new file mode 100644 index 00000000000000..3f1b42638204a7 --- /dev/null +++ b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/meta.json @@ -0,0 +1,23 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Paradise at https://github.com/ss220club/Paradise-SS220/blob/master/icons/effects/effects.dmi, modified by Estkemran (Github) for SS220", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "cocoon1" + }, + { + "name": "destroyed_cocoon1" + }, + { + "name": "cocoon2" + }, + { + "name": "destroyed_cocoon2" + } + ] +}