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 f99d17694e17da..966c62e05b476d 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 5d4b09f72ea59f..f466481eb290c5 100644 --- a/Resources/Prototypes/SS220/Damage/modifier_sets.yml +++ b/Resources/Prototypes/SS220/Damage/modifier_sets.yml @@ -18,3 +18,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 00000000000000..8ee906eab3e28b Binary files /dev/null and b/Resources/Textures/SS220/Effects/wallwebspawn.rsi/webwall.png differ 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 00000000000000..ab0e3043a9430f Binary files /dev/null and b/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/cocoon.png differ diff --git a/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/crystal_spawn.png b/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/crystal_spawn.png new file mode 100644 index 00000000000000..66a589efceff08 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/crystal_spawn.png differ 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 00000000000000..688e4054ddef42 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Actions/action_spider.rsi/wall_spawn.png differ diff --git a/Resources/Textures/SS220/Interface/Actions/meta.json b/Resources/Textures/SS220/Interface/Actions/meta.json new file mode 100644 index 00000000000000..8e397e4477fda6 --- /dev/null +++ b/Resources/Textures/SS220/Interface/Actions/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/tgstation/tgstation/blob/HEAD/icons/effects/web.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "web" + } + ] +} diff --git a/Resources/Textures/SS220/Interface/Actions/web.png b/Resources/Textures/SS220/Interface/Actions/web.png new file mode 100644 index 00000000000000..3cb5b2ad62872c Binary files /dev/null and b/Resources/Textures/SS220/Interface/Actions/web.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood0.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood0.png new file mode 100644 index 00000000000000..fa8fcd3dbfc7e6 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood0.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood1.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood1.png new file mode 100644 index 00000000000000..04103bfed57bdb Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood1.png differ 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 00000000000000..333d7da22d9eaa Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood10.png differ 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 00000000000000..55f7125ade0a21 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood11.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood12.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood12.png new file mode 100644 index 00000000000000..2113f2f5cbe061 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood12.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood13.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood13.png new file mode 100644 index 00000000000000..5f50193ff3d745 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood13.png differ 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 00000000000000..80249d7a8e2242 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood14.png differ 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 00000000000000..0e02b06dd275e9 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood15.png differ 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 00000000000000..5712ed8c85f275 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood16.png differ 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 00000000000000..ba5d664c0a41aa Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood17.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood18.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood18.png new file mode 100644 index 00000000000000..fbe9e11e1b4e4d Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood18.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood19.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood19.png new file mode 100644 index 00000000000000..89a562aba0892c Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood19.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood2.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood2.png new file mode 100644 index 00000000000000..62e345a240726d Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood2.png differ 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 00000000000000..6844b5065764d9 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood20.png differ 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 00000000000000..50dbc6473408db Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood21.png differ 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 00000000000000..2bd5789c826c7f Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood22.png differ 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 00000000000000..41bf4794de1d6a Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood23.png differ 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 00000000000000..c0cc200ad4b77d Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood3.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood4.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood4.png new file mode 100644 index 00000000000000..c0757533a95b85 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood4.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood5.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood5.png new file mode 100644 index 00000000000000..ee4c30cccfd43c Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood5.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood6.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood6.png new file mode 100644 index 00000000000000..c5fbb9d79b96aa Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood6.png differ 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 00000000000000..40f7abf0e08ed4 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood7.png differ 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 00000000000000..50ec9b673ab0f8 Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood8.png differ diff --git a/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood9.png b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood9.png new file mode 100644 index 00000000000000..0c970a98f7b68b Binary files /dev/null and b/Resources/Textures/SS220/Interface/Alerts/blood_counter.rsi/blood9.png differ 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 00000000000000..c416be97995b5d Binary files /dev/null and b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/cocoon1.png differ 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 00000000000000..b04b1f6e8e49c4 Binary files /dev/null and b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/cocoon2.png differ 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 00000000000000..078b07ec6de886 Binary files /dev/null and b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/destroyed_cocoon1.png differ diff --git a/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/destroyed_cocoon2.png b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/destroyed_cocoon2.png new file mode 100644 index 00000000000000..f4f592ca494cc1 Binary files /dev/null and b/Resources/Textures/SS220/Structures/Specific/cocoon.rsi/destroyed_cocoon2.png differ 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" + } + ] +}