Xenomorphs: Part 3 (#815)
* this is definitely one of the commits * 1 * new facehuggers * suffix * Burst egg * some fix * Update Content.Server/_White/Xenomorphs/Queen/XenomorphQueenSystem.cs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update Content.Server/_White/Xenomorphs/Queen/XenomorphQueenSystem.cs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update Resources/Locale/en-US/_white/objectives/conditions/steal-target-groups.ftl Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update Content.Server/_White/Xenomorphs/FaceHugger/FaceHuggerSystem.cs * Update Content.Server/_White/Xenomorphs/FaceHugger/FaceHuggerSystem.cs * Update Resources/Locale/ru-RU/_white/prototypes/entities/mobs/player/pets.ftl * Update Resources/Locale/ru-RU/WWDP_TRANSLATION/_white/prototypes/entities/structures/storage/glass_box.ftl * Update Resources/Locale/ru-RU/_white/objectives/conditions/steal-target-groups.ftl * Update Content.Server/_White/Xenomorphs/FaceHugger/FaceHuggerSystem.cs * some fix * SelfUnBuckleDelay * Neurotoxin now stun * PlasmaAmmoProvider * some fix * fix * some number --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@@ -1,3 +1,4 @@
|
||||
using Content.Client.Alerts;
|
||||
using Content.Shared.Pinpointer;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
@@ -8,6 +9,32 @@ public sealed class PinpointerSystem : SharedPinpointerSystem
|
||||
{
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
|
||||
// WD EDIT START
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PinpointerComponent, UpdateAlertSpriteEvent>(OnUpdateAlertSprite);
|
||||
}
|
||||
|
||||
private void OnUpdateAlertSprite(EntityUid uid, PinpointerComponent component, ref UpdateAlertSpriteEvent args)
|
||||
{
|
||||
if (args.Alert.ID != component.Alert)
|
||||
return;
|
||||
|
||||
var sprite = args.SpriteViewEnt.Comp;
|
||||
var eye = _eyeManager.CurrentEye;
|
||||
var angle = component.DistanceToTarget switch
|
||||
{
|
||||
Distance.Close or Distance.Medium or Distance.Far => component.ArrowAngle + eye.Rotation,
|
||||
_ => Angle.Zero
|
||||
};
|
||||
|
||||
sprite.LayerSetRotation(PinpointerLayers.Screen, angle);
|
||||
sprite.LayerSetState(PinpointerLayers.Screen, component.DistanceToTarget.ToString().ToLower());
|
||||
}
|
||||
// WD EDIT END
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
@@ -20,7 +47,7 @@ public sealed class PinpointerSystem : SharedPinpointerSystem
|
||||
var query = EntityQueryEnumerator<PinpointerComponent, SpriteComponent>();
|
||||
while (query.MoveNext(out var _, out var pinpointer, out var sprite))
|
||||
{
|
||||
if (!pinpointer.HasTarget)
|
||||
if (!pinpointer.HasTarget || !sprite.LayerExists(PinpointerLayers.Screen)) // WD EDIT
|
||||
continue;
|
||||
var eye = _eyeManager.CurrentEye;
|
||||
var angle = pinpointer.ArrowAngle + eye.Rotation;
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
using Content.Shared._White.Inventory;
|
||||
|
||||
namespace Content.Client._White.Inventory;
|
||||
|
||||
public sealed class WhiteInventorySystem : SharedWhiteInventorySystem;
|
||||
@@ -68,6 +68,9 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
|
||||
|
||||
private void OnTakeGhostRole(Entity<GhostRoleAntagSpawnerComponent> ent, ref TakeGhostRoleEvent args)
|
||||
{
|
||||
if (args.TookRole)
|
||||
return;
|
||||
|
||||
if (ent.Comp.Rule is not { } rule || ent.Comp.Definition is not { } def)
|
||||
return;
|
||||
|
||||
|
||||
@@ -4,12 +4,14 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Server.Shuttles.Events;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.IdentityManagement;
|
||||
|
||||
namespace Content.Server.Pinpointer;
|
||||
|
||||
public sealed class PinpointerSystem : SharedPinpointerSystem
|
||||
{
|
||||
[Dependency] private readonly AlertsSystem _alerts = default!; // WD EDIT
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
|
||||
@@ -20,10 +22,28 @@ public sealed class PinpointerSystem : SharedPinpointerSystem
|
||||
base.Initialize();
|
||||
_xformQuery = GetEntityQuery<TransformComponent>();
|
||||
|
||||
// WD EDIT START
|
||||
SubscribeLocalEvent<PinpointerComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<PinpointerComponent, ComponentShutdown>(OnShutdown);
|
||||
// WD EDIT END
|
||||
SubscribeLocalEvent<PinpointerComponent, ActivateInWorldEvent>(OnActivate);
|
||||
SubscribeLocalEvent<FTLCompletedEvent>(OnLocateTarget);
|
||||
}
|
||||
|
||||
// WD EDIT START
|
||||
private void OnMapInit(EntityUid uid, PinpointerComponent component, MapInitEvent args)
|
||||
{
|
||||
if (component.Alert.HasValue)
|
||||
_alerts.ShowAlert(uid, component.Alert.Value);
|
||||
}
|
||||
|
||||
private void OnShutdown(EntityUid uid, PinpointerComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (component.Alert.HasValue)
|
||||
_alerts.ClearAlert(uid, component.Alert.Value);
|
||||
}
|
||||
// WD EDIT END
|
||||
|
||||
public override bool TogglePinpointer(EntityUid uid, PinpointerComponent? pinpointer = null)
|
||||
{
|
||||
if (!Resolve(uid, ref pinpointer))
|
||||
@@ -48,7 +68,8 @@ public sealed class PinpointerSystem : SharedPinpointerSystem
|
||||
if (args.Handled || !args.Complex)
|
||||
return;
|
||||
|
||||
TogglePinpointer(uid, component);
|
||||
if (component.CanToggle) // WD EDIT
|
||||
TogglePinpointer(uid, component);
|
||||
|
||||
if (!component.CanRetarget)
|
||||
LocateTarget(uid, component);
|
||||
@@ -147,6 +168,7 @@ public sealed class PinpointerSystem : SharedPinpointerSystem
|
||||
if (target == null || !EntityManager.EntityExists(target.Value))
|
||||
{
|
||||
SetDistance(uid, Distance.Unknown, pinpointer);
|
||||
LocateTarget(uid, pinpointer); // WD EDIT
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Shared._White.Actions.Events;
|
||||
using Content.Shared.Construction.EntitySystems;
|
||||
using Content.Shared.Coordinates;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Server.GameObjects;
|
||||
@@ -16,15 +15,14 @@ namespace Content.Server._White.Actions;
|
||||
|
||||
public sealed class ActionsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly ITileDefinitionManager _tileDef = default!;
|
||||
|
||||
[Dependency] private readonly AnchorableSystem _anchorable = default!;
|
||||
[Dependency] private readonly AudioSystem _audio = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
||||
[Dependency] private readonly MapSystem _mapSystem = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly TurfSystem _turf = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -36,7 +34,7 @@ public sealed class ActionsSystem : EntitySystem
|
||||
|
||||
private void OnSpawnTileEntityAction(SpawnTileEntityActionEvent args)
|
||||
{
|
||||
if (args.Handled || !CreationTileEntity(args.Performer, args.Performer.ToCoordinates(), args.TileId, args.Entity, args.Audio, args.BlockedCollision))
|
||||
if (args.Handled || !CreationTileEntity(args.Performer, args.Performer.ToCoordinates(), args.TileId, args.Entity, args.Audio, args.BlockedCollisionLayer, args.BlockedCollisionMask))
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
@@ -49,7 +47,7 @@ public sealed class ActionsSystem : EntitySystem
|
||||
|
||||
if (args.Length != 0)
|
||||
{
|
||||
if (CheckTileBlocked(args.Target, args.BlockedCollision))
|
||||
if (CheckTileBlocked(args.Target, args.BlockedCollisionLayer, args.BlockedCollisionMask))
|
||||
return;
|
||||
|
||||
var ev = new PlaceTileEntityDoAfterEvent
|
||||
@@ -57,7 +55,9 @@ public sealed class ActionsSystem : EntitySystem
|
||||
Target = GetNetCoordinates(args.Target),
|
||||
Entity = args.Entity,
|
||||
TileId = args.TileId,
|
||||
Audio = args.Audio
|
||||
Audio = args.Audio,
|
||||
BlockedCollisionLayer = args.BlockedCollisionLayer,
|
||||
BlockedCollisionMask = args.BlockedCollisionMask
|
||||
};
|
||||
|
||||
var doAfter = new DoAfterArgs(EntityManager, args.Performer, args.Length, ev, null)
|
||||
@@ -73,7 +73,7 @@ public sealed class ActionsSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CreationTileEntity(args.Performer, args.Target, args.TileId, args.Entity, args.Audio, args.BlockedCollision))
|
||||
if (!CreationTileEntity(args.Performer, args.Target, args.TileId, args.Entity, args.Audio, args.BlockedCollisionLayer, args.BlockedCollisionMask))
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
@@ -81,7 +81,7 @@ public sealed class ActionsSystem : EntitySystem
|
||||
|
||||
private void OnPlaceTileEntityDoAfter(PlaceTileEntityDoAfterEvent args)
|
||||
{
|
||||
if (args.Handled || !CreationTileEntity(args.User, GetCoordinates(args.Target), args.TileId, args.Entity, args.Audio, null))
|
||||
if (args.Handled || !CreationTileEntity(args.User, GetCoordinates(args.Target), args.TileId, args.Entity, args.Audio, args.BlockedCollisionLayer, args.BlockedCollisionMask))
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
@@ -89,7 +89,7 @@ public sealed class ActionsSystem : EntitySystem
|
||||
|
||||
#region Helpers
|
||||
|
||||
private bool CreationTileEntity(EntityUid user, EntityCoordinates coordinates, string? tileId, EntProtoId? entProtoId, SoundSpecifier? audio, CollisionGroup? blockedCollision)
|
||||
private bool CreationTileEntity(EntityUid user, EntityCoordinates coordinates, string? tileId, EntProtoId? entProtoId, SoundSpecifier? audio, int collisionLayer = 0, int collisionMask = 0)
|
||||
{
|
||||
if (_container.IsEntityOrParentInContainer(user))
|
||||
return false;
|
||||
@@ -107,7 +107,7 @@ public sealed class ActionsSystem : EntitySystem
|
||||
|
||||
_audio.PlayPvs(audio, coordinates);
|
||||
|
||||
if (entProtoId == null || CheckTileBlocked(coordinates, blockedCollision))
|
||||
if (entProtoId == null || CheckTileBlocked(coordinates, collisionLayer, collisionMask))
|
||||
return false;
|
||||
|
||||
Spawn(entProtoId, coordinates);
|
||||
@@ -115,11 +115,13 @@ public sealed class ActionsSystem : EntitySystem
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CheckTileBlocked(EntityCoordinates coordinates, CollisionGroup? blockedCollision)
|
||||
private bool CheckTileBlocked(EntityCoordinates coordinates, int collisionLayer = 0, int collisionMask = 0)
|
||||
{
|
||||
var tileRef = coordinates.GetTileRef(EntityManager, _mapManager);
|
||||
if (_transform.GetGrid(coordinates) is not { } grid || !TryComp(grid, out MapGridComponent? mapGrid))
|
||||
return true;
|
||||
|
||||
return !tileRef.HasValue || blockedCollision.HasValue && _turf.IsTileBlocked(tileRef.Value, blockedCollision.Value);
|
||||
var tileIndices = _mapSystem.TileIndicesFor(grid, mapGrid, coordinates);
|
||||
return !_anchorable.TileFree(mapGrid, tileIndices, collisionLayer, collisionMask);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using Content.Shared.EntityEffects;
|
||||
using Content.Shared.Whitelist;
|
||||
|
||||
namespace Content.Server._White.Inventory.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class EffectsOnEquipComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public string Slot;
|
||||
|
||||
[DataField]
|
||||
public List<EntityEffect> Effects = new ();
|
||||
|
||||
[DataField]
|
||||
public EntityWhitelist? Blacklist;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using Content.Server._White.Inventory.Components;
|
||||
using Content.Shared.EntityEffects;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Whitelist;
|
||||
|
||||
namespace Content.Server._White.Inventory;
|
||||
|
||||
public sealed partial class WhiteInventorySystem
|
||||
{
|
||||
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
|
||||
private void InitializeEquip()
|
||||
{
|
||||
SubscribeLocalEvent<EffectsOnEquipComponent, GotEquippedEvent>(OnGotEquipped);
|
||||
}
|
||||
|
||||
private void OnGotEquipped(EntityUid uid, EffectsOnEquipComponent component, GotEquippedEvent args)
|
||||
{
|
||||
if (args.Slot != component.Slot
|
||||
|| !_mobState.IsAlive(uid)
|
||||
|| _entityWhitelist.IsBlacklistPass(component.Blacklist, args.Equipee))
|
||||
return;
|
||||
|
||||
var effectsArgs = new EntityEffectBaseArgs(args.Equipee, EntityManager);
|
||||
foreach (var effect in component.Effects)
|
||||
effect.Effect(effectsArgs);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using Content.Shared._White.Inventory;
|
||||
|
||||
namespace Content.Server._White.Inventory;
|
||||
|
||||
public sealed partial class WhiteInventorySystem : SharedWhiteInventorySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
InitializeEquip();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Server._White.Inventory;
|
||||
using Content.Server._White.Xenomorphs.FaceHugger;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared._White.Inventory.Components;
|
||||
using Content.Shared._White.Xenomorphs.Egg;
|
||||
@@ -22,8 +22,8 @@ public sealed class XenomorphEggSystem : EntitySystem
|
||||
[Dependency] private readonly AppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly AudioSystem _audio = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
|
||||
[Dependency] private readonly FaceHuggerSystem _faceHugger = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly WhiteInventorySystem _whiteInventory = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -114,12 +114,12 @@ public sealed class XenomorphEggSystem : EntitySystem
|
||||
var coordinates = Transform(uid).Coordinates;
|
||||
var spawned = Spawn(component.FaceHuggerPrototype, coordinates);
|
||||
|
||||
if (!TryComp<EquipOnMeleeHitComponent>(spawned, out var equipOn))
|
||||
if (!TryComp<FaceHuggerComponent>(spawned, out var equipOn))
|
||||
return;
|
||||
|
||||
foreach (var entity in _entityLookup.GetEntitiesInRange<InventoryComponent>(coordinates, component.BurstRange))
|
||||
{
|
||||
if (_whiteInventory.TryEquip(spawned, entity, equipOn))
|
||||
if (_faceHugger.TryEquipFaceHugger(spawned, entity, equipOn))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using Content.Shared.DoAfter;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.RadialSelector;
|
||||
using Content.Shared.Standing;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -28,6 +29,7 @@ public sealed class XenomorphEvolutionSystem : EntitySystem
|
||||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||
|
||||
[Dependency] private readonly ActionsSystem _actions = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfter = default!;
|
||||
[Dependency] private readonly JitteringSystem _jitter = default!;
|
||||
[Dependency] private readonly MindSystem _mind = default!;
|
||||
@@ -57,21 +59,33 @@ public sealed class XenomorphEvolutionSystem : EntitySystem
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
if (component.EvolvesTo.Count == 1)
|
||||
{
|
||||
StartEvolutionDuAfter(uid, component, component.EvolvesTo.First().Prototype);
|
||||
if (component.Points < component.Max)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-evolution-not-enough-points", ("seconds", (component.Max - component.Points) / component.PointsPerSecond)), uid, uid);
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = Evolve(uid, component.EvolvesTo.First().Prototype, component.EvolutionDelay);
|
||||
return;
|
||||
}
|
||||
|
||||
_ui.TryToggleUi(uid, RadialSelectorUiKey.Key, uid);
|
||||
_ui.SetUiState(uid, RadialSelectorUiKey.Key, new TrackedRadialSelectorState(component.EvolvesTo));
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnEvolutionRecieved(EntityUid uid, XenomorphEvolutionComponent component, RadialSelectorSelectedMessage args)
|
||||
{
|
||||
if (StartEvolutionDuAfter(uid, component, args.SelectedItem))
|
||||
if (component.Points < component.Max)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-evolution-not-enough-points", ("seconds", (component.Max - component.Points) / component.PointsPerSecond)), uid, uid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Evolve(uid, args.SelectedItem, component.EvolutionDelay))
|
||||
return;
|
||||
|
||||
var actor = args.Actor;
|
||||
@@ -116,7 +130,7 @@ public sealed class XenomorphEvolutionSystem : EntitySystem
|
||||
var query = EntityQueryEnumerator<XenomorphEvolutionComponent>();
|
||||
while (query.MoveNext(out var uid, out var alienEvolution))
|
||||
{
|
||||
if (alienEvolution.Points == alienEvolution.Max || time < alienEvolution.NextPointsAt)
|
||||
if (alienEvolution.Points == alienEvolution.Max || time < alienEvolution.NextPointsAt || _container.IsEntityInContainer(uid))
|
||||
continue;
|
||||
|
||||
alienEvolution.NextPointsAt = time + TimeSpan.FromSeconds(1);
|
||||
@@ -129,32 +143,27 @@ public sealed class XenomorphEvolutionSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private bool StartEvolutionDuAfter(EntityUid uid, XenomorphEvolutionComponent component, string? selectedItem)
|
||||
public bool Evolve(EntityUid uid, string? evolveTo, TimeSpan evolutionDelay, bool checkNeedCasteDeath = true)
|
||||
{
|
||||
if (component.Points < component.Max)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-evolution-not-enough-points", ("seconds", (component.Max - component.Points) / component.PointsPerSecond)), uid, uid);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedItem == null
|
||||
|| !_protoManager.TryIndex(selectedItem, out var xenomorphPrototype)
|
||||
|| !xenomorphPrototype.TryGetComponent<XenomorphComponent>(out var xenomorph, _componentFactory))
|
||||
if (evolveTo == null
|
||||
|| !_protoManager.TryIndex(evolveTo, out var xenomorphPrototype)
|
||||
|| !xenomorphPrototype.TryGetComponent<XenomorphComponent>(out var xenomorph, _componentFactory)
|
||||
|| !_mind.TryGetMind(uid, out _, out _))
|
||||
return false;
|
||||
|
||||
var ev = new BeforeXenomorphEvolutionEvent(xenomorph.Caste);
|
||||
var ev = new BeforeXenomorphEvolutionEvent(xenomorph.Caste, checkNeedCasteDeath);
|
||||
RaiseLocalEvent(uid, ev);
|
||||
|
||||
if (ev.Cancelled)
|
||||
return false;
|
||||
|
||||
var doAfterEvent = new XenomorphEvolutionDoAfterEvent(selectedItem, xenomorph.Caste);
|
||||
var doAfter = new DoAfterArgs(EntityManager, uid, component.EvolutionDelay, doAfterEvent, uid);
|
||||
var doAfterEvent = new XenomorphEvolutionDoAfterEvent(evolveTo, xenomorph.Caste, checkNeedCasteDeath);
|
||||
var doAfter = new DoAfterArgs(EntityManager, uid, evolutionDelay, doAfterEvent, uid);
|
||||
|
||||
if (!_doAfter.TryStartDoAfter(doAfter))
|
||||
return false;
|
||||
|
||||
_jitter.DoJitter(uid, component.EvolutionDelay, true, 80, 8, true);
|
||||
_jitter.DoJitter(uid, evolutionDelay, true, 80, 8, true);
|
||||
|
||||
var popupOthers = Loc.GetString("xenomorphs-evolution-start-others", ("uid", uid));
|
||||
_popup.PopupEntity(popupOthers, uid, Filter.PvsExcept(uid), true, PopupType.Medium);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._White.Xenomorphs.FaceHugger;
|
||||
@@ -8,24 +8,51 @@ namespace Content.Server._White.Xenomorphs.FaceHugger;
|
||||
[RegisterComponent]
|
||||
public sealed partial class FaceHuggerComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public string Slot;
|
||||
[DataField]
|
||||
public DamageSpecifier DamageOnImpact = new();
|
||||
|
||||
[DataField]
|
||||
public DamageSpecifier DamageOnInfect = new();
|
||||
|
||||
[DataField]
|
||||
public EntityWhitelist? Blacklist;
|
||||
|
||||
[DataField]
|
||||
public EntProtoId? InfectionPrototype = "XenomorphInfection";
|
||||
|
||||
[DataField]
|
||||
public string BlockingSlot = "head";
|
||||
|
||||
[DataField]
|
||||
public string InfectionSlotId = "xenomorph_larva";
|
||||
|
||||
[DataField]
|
||||
public EntProtoId InfectionPrototype = "XenomorphInfection";
|
||||
public string Slot = "mask";
|
||||
|
||||
[DataField]
|
||||
public int LarvaEmbryoCount = 1;
|
||||
public SoundSpecifier SoundOnImpact = new SoundCollectionSpecifier("MetalThud");
|
||||
|
||||
[DataField]
|
||||
public List<MobState> AllowedPassiveDamageStates = new();
|
||||
public TimeSpan KnockdownTime = TimeSpan.FromSeconds(5);
|
||||
|
||||
[DataField]
|
||||
public DamageSpecifier PassiveDamage = new();
|
||||
public TimeSpan MaxInfectTime = TimeSpan.FromSeconds(20);
|
||||
|
||||
[DataField]
|
||||
public TimeSpan MaxRestTime = TimeSpan.FromSeconds(20);
|
||||
|
||||
[DataField]
|
||||
public TimeSpan MinInfectTime = TimeSpan.FromSeconds(10);
|
||||
|
||||
[DataField]
|
||||
public TimeSpan MinRestTime = TimeSpan.FromSeconds(10);
|
||||
|
||||
[ViewVariables]
|
||||
public bool Active = true;
|
||||
|
||||
[ViewVariables]
|
||||
public TimeSpan InfectIn = TimeSpan.Zero;
|
||||
|
||||
[ViewVariables]
|
||||
public TimeSpan RestIn = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
@@ -1,32 +1,125 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Nutrition.Components;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server._White.Xenomorphs.FaceHugger;
|
||||
|
||||
public sealed class FaceHuggerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
[Dependency] private readonly AudioSystem _audio = default!;
|
||||
[Dependency] private readonly BodySystem _body = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly StunSystem _stun = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FaceHuggerComponent, StartCollideEvent>(OnCollideEvent);
|
||||
SubscribeLocalEvent<FaceHuggerComponent, MeleeHitEvent>(OnMeleeHit);
|
||||
SubscribeLocalEvent<FaceHuggerComponent, GotEquippedHandEvent>(OnPickedUp);
|
||||
|
||||
SubscribeLocalEvent<FaceHuggerComponent, GotEquippedEvent>(OnGotEquipped);
|
||||
SubscribeLocalEvent<FaceHuggerComponent, GotUnequippedEvent>(OnGotUnequipped);
|
||||
SubscribeLocalEvent<FaceHuggerComponent, BeingUnequippedAttemptEvent>(OnBeingUnequippedAttempt);
|
||||
}
|
||||
|
||||
private void OnCollideEvent(EntityUid uid, FaceHuggerComponent component, StartCollideEvent args)
|
||||
{
|
||||
TryEquipFaceHugger(uid, args.OtherEntity, component);
|
||||
}
|
||||
|
||||
private void OnMeleeHit(EntityUid uid, FaceHuggerComponent component, MeleeHitEvent args)
|
||||
{
|
||||
if (args.HitEntities.FirstOrNull() is not {} target)
|
||||
return;
|
||||
|
||||
TryEquipFaceHugger(uid, target, component);
|
||||
}
|
||||
|
||||
private void OnPickedUp(EntityUid uid, FaceHuggerComponent component, GotEquippedHandEvent args)
|
||||
{
|
||||
TryEquipFaceHugger(uid, args.User, component);
|
||||
}
|
||||
|
||||
private void OnGotEquipped(EntityUid uid, FaceHuggerComponent component, GotEquippedEvent args)
|
||||
{
|
||||
if (args.Slot != component.Slot
|
||||
|| component.LarvaEmbryoCount <= 0
|
||||
|| !_mobState.IsAlive(uid)
|
||||
|| _entityWhitelist.IsBlacklistPass(component.Blacklist, args.Equipee)
|
||||
|| _body.GetRootPartOrNull(args.Equipee) is not {} rootPart)
|
||||
|| _mobState.IsDead(uid)
|
||||
|| _entityWhitelist.IsBlacklistPass(component.Blacklist, args.Equipee))
|
||||
return;
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-face-hugger-equip", ("equipment", uid)), uid, args.Equipee);
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-face-hugger-equip-other", ("equipment", uid), ("target", Identity.Entity(args.Equipee, EntityManager))), uid, Filter.PvsExcept(args.Equipee), true);
|
||||
|
||||
_stun.TryKnockdown(args.Equipee, component.KnockdownTime, true);
|
||||
|
||||
if (!component.InfectionPrototype.HasValue)
|
||||
return;
|
||||
|
||||
component.InfectIn = _timing.CurTime + _random.Next(component.MinInfectTime, component.MaxInfectTime);
|
||||
}
|
||||
|
||||
private void OnBeingUnequippedAttempt(EntityUid uid, FaceHuggerComponent component, BeingUnequippedAttemptEvent args)
|
||||
{
|
||||
if (_mobState.IsDead(uid) || !component.InfectionPrototype.HasValue || args.Unequipee != args.UnEquipTarget)
|
||||
return;
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-face-hugger-unequip", ("equipment", Identity.Entity(uid, EntityManager))), uid, args.Unequipee);
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var time = _timing.CurTime;
|
||||
|
||||
var query = EntityQueryEnumerator<FaceHuggerComponent>();
|
||||
while (query.MoveNext(out var uid, out var faceHugger))
|
||||
{
|
||||
if (!faceHugger.Active && time > faceHugger.RestIn)
|
||||
faceHugger.Active = true;
|
||||
|
||||
if (faceHugger.InfectIn != TimeSpan.Zero && time > faceHugger.InfectIn)
|
||||
{
|
||||
faceHugger.InfectIn = TimeSpan.Zero;
|
||||
Infect(uid, faceHugger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Infect(EntityUid uid, FaceHuggerComponent component)
|
||||
{
|
||||
if (!component.InfectionPrototype.HasValue
|
||||
|| !TryComp<ClothingComponent>(uid, out var clothing)
|
||||
|| clothing.InSlot != component.Slot
|
||||
|| !_container.TryGetContainingContainer((uid, null, null), out var target)
|
||||
|| _body.GetRootPartOrNull(target.Owner) is not {} rootPart)
|
||||
return;
|
||||
|
||||
var organ = Spawn(component.InfectionPrototype);
|
||||
@@ -38,16 +131,42 @@ public sealed class FaceHuggerSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
component.LarvaEmbryoCount--;
|
||||
_damageable.TryChangeDamage(uid, component.DamageOnInfect, true);
|
||||
}
|
||||
|
||||
private void OnGotUnequipped(EntityUid uid, FaceHuggerComponent component, GotUnequippedEvent args)
|
||||
public bool TryEquipFaceHugger(EntityUid uid, EntityUid target, FaceHuggerComponent component)
|
||||
{
|
||||
if (component.LarvaEmbryoCount > 0 || HasComp<PassiveDamageComponent>(uid))
|
||||
return;
|
||||
if (!component.Active || _mobState.IsDead(uid) || _entityWhitelist.IsBlacklistPass(component.Blacklist, target))
|
||||
return false;
|
||||
|
||||
var passiveDamage = EnsureComp<PassiveDamageComponent>(uid);
|
||||
passiveDamage.AllowedStates = component.AllowedPassiveDamageStates;
|
||||
passiveDamage.Damage = component.PassiveDamage;
|
||||
component.RestIn = _timing.CurTime + _random.Next(component.MinRestTime, component.MaxRestTime);
|
||||
component.Active = false;
|
||||
|
||||
EntityUid? blocker = null;
|
||||
|
||||
if (_inventory.TryGetSlotEntity(target, "head", out var headUid)
|
||||
&& TryComp<IngestionBlockerComponent>(headUid, out var headBlocker)
|
||||
&& headBlocker.Enabled)
|
||||
blocker = headUid;
|
||||
|
||||
if (!blocker.HasValue && _inventory.TryGetSlotEntity(target, "mask", out var maskUid))
|
||||
{
|
||||
if (TryComp<IngestionBlockerComponent>(maskUid, out var maskBlocker) && maskBlocker.Enabled)
|
||||
blocker = maskUid;
|
||||
else
|
||||
_inventory.TryUnequip(target, component.Slot, true);
|
||||
}
|
||||
|
||||
if (!blocker.HasValue)
|
||||
return _inventory.TryEquip(target, uid, component.Slot, true, true);
|
||||
|
||||
_audio.PlayPvs(component.SoundOnImpact, uid);
|
||||
|
||||
_damageable.TryChangeDamage(uid, component.DamageOnImpact);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-face-hugger-try-equip", ("equipment", uid), ("equipmentBlocker", blocker.Value)), uid);
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-face-hugger-try-equip-other", ("equipment", uid), ("equipmentBlocker", blocker.Value), ("target", Identity.Entity(target, EntityManager))), uid, Filter.PvsExcept(target), true);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using Content.Shared._White.Xenomorphs.Caste;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._White.Xenomorphs.Queen;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class XenomorphPromotionComponent : Component
|
||||
{
|
||||
[ViewVariables]
|
||||
public EntProtoId PromoteTo = "MobXenomorphPraetorian";
|
||||
|
||||
[ViewVariables]
|
||||
public FixedPoint2 PlasmaCost = 0;
|
||||
|
||||
[ViewVariables]
|
||||
public List<ProtoId<XenomorphCastePrototype>> CasteWhitelist = new();
|
||||
|
||||
[ViewVariables]
|
||||
public TimeSpan EvolutionDelay = TimeSpan.FromSeconds(3);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using Content.Server._White.Xenomorphs.Evolution;
|
||||
using Content.Server._White.Xenomorphs.Plasma;
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Hands.Systems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared._White.Actions;
|
||||
using Content.Shared._White.Xenomorphs;
|
||||
using Content.Shared._White.Xenomorphs.Queen;
|
||||
using Content.Shared._White.Xenomorphs.Xenomorph;
|
||||
using Content.Shared.Interaction;
|
||||
|
||||
namespace Content.Server._White.Xenomorphs.Queen;
|
||||
|
||||
public sealed class XenomorphQueenSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ActionsSystem _actions = default!;
|
||||
[Dependency] private readonly HandsSystem _hands = default!;
|
||||
[Dependency] private readonly PlasmaSystem _plasma = default!;
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly XenomorphEvolutionSystem _xenomorphEvolution = default!;
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<XenomorphQueenComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<XenomorphQueenComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<XenomorphQueenComponent, PromotionActionEvent>(OnPromotionAction);
|
||||
|
||||
SubscribeLocalEvent<XenomorphPromotionComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, XenomorphQueenComponent component, MapInitEvent args) =>
|
||||
_actions.AddAction(uid, ref component.PromotionAction, component.PromotionActionId);
|
||||
|
||||
private void OnShutdown(EntityUid uid, XenomorphQueenComponent component, ComponentShutdown args) =>
|
||||
_actions.RemoveAction(uid, component.PromotionAction);
|
||||
|
||||
private void OnPromotionAction(EntityUid uid, XenomorphQueenComponent component, PromotionActionEvent args)
|
||||
{
|
||||
if (Exists(component.Promotion))
|
||||
{
|
||||
QueueDel(component.Promotion);
|
||||
component.Promotion = null;
|
||||
return;
|
||||
}
|
||||
|
||||
component.Promotion = Spawn(component.PromotionId);
|
||||
var promotion = EnsureComp<XenomorphPromotionComponent>(component.Promotion.Value);
|
||||
promotion.CasteWhitelist = component.CasteWhitelist;
|
||||
promotion.PromoteTo = component.PromoteTo;
|
||||
promotion.EvolutionDelay = component.EvolutionDelay;
|
||||
|
||||
if (TryComp<PlasmaCostActionComponent>(component.PromotionAction, out var plasmaCostAction))
|
||||
promotion.PlasmaCost = plasmaCostAction.PlasmaCost;
|
||||
|
||||
if (!_hands.TryForcePickupAnyHand(uid, component.Promotion.Value))
|
||||
{
|
||||
QueueDel(component.Promotion);
|
||||
component.Promotion = null;
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnAfterInteract(EntityUid uid, XenomorphPromotionComponent component, AfterInteractEvent args)
|
||||
{
|
||||
if (!args.CanReach
|
||||
|| args.Target is not { } target
|
||||
|| target == args.User
|
||||
|| !TryComp<XenomorphComponent>(target, out var xenomorph))
|
||||
return;
|
||||
|
||||
if (!component.CasteWhitelist.Contains(xenomorph.Caste))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-queen-promotion-didnt-pass-whitelist"), args.User);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_xenomorphEvolution.Evolve(target, component.PromoteTo, component.EvolutionDelay))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("xenomorphs-queen-promotion-no-mind"), args.User);
|
||||
return;
|
||||
}
|
||||
|
||||
if (component.PlasmaCost != 0)
|
||||
_plasma.ChangePlasmaAmount(args.User, component.PlasmaCost);
|
||||
|
||||
QueueDel(uid);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
@@ -150,6 +151,11 @@ public readonly record struct UnstrappedEvent(Entity<StrapComponent> Strap, Enti
|
||||
[ByRefEvent]
|
||||
public readonly record struct UnbuckledEvent(Entity<StrapComponent> Strap, Entity<BuckleComponent> Buckle);
|
||||
|
||||
// WD EDIT START
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class UnbuckleDoAfterEvent : SimpleDoAfterEvent;
|
||||
// WD EDIT END
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum BuckleVisuals
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
@@ -84,6 +85,14 @@ public sealed partial class StrapComponent : Component
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool BuckleOnInteractHand = true;
|
||||
|
||||
// WD EDIT START
|
||||
/// <summary>
|
||||
/// Delay, that must occur, before user can unbuckle
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public TimeSpan SelfUnBuckleDelay = TimeSpan.Zero;
|
||||
// WD EDIT END
|
||||
}
|
||||
|
||||
public enum StrapPosition
|
||||
|
||||
@@ -32,6 +32,7 @@ public abstract partial class SharedBuckleSystem
|
||||
{
|
||||
public static ProtoId<AlertCategoryPrototype> BuckledAlertCategory = "Buckled";
|
||||
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!; // WD EDIT
|
||||
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
|
||||
|
||||
private void InitializeBuckle()
|
||||
@@ -53,6 +54,8 @@ public abstract partial class SharedBuckleSystem
|
||||
SubscribeLocalEvent<BuckleComponent, StandAttemptEvent>(OnBuckleStandAttempt);
|
||||
SubscribeLocalEvent<BuckleComponent, ThrowPushbackAttemptEvent>(OnBuckleThrowPushbackAttempt);
|
||||
SubscribeLocalEvent<BuckleComponent, UpdateCanMoveEvent>(OnBuckleUpdateCanMove);
|
||||
|
||||
SubscribeLocalEvent<BuckleComponent, UnbuckleDoAfterEvent>(OnUnbuckleDoAfter); // WD EDIT
|
||||
}
|
||||
|
||||
private void OnBuckleComponentShutdown(Entity<BuckleComponent> ent, ref ComponentShutdown args)
|
||||
@@ -174,6 +177,16 @@ public abstract partial class SharedBuckleSystem
|
||||
args.Cancel();
|
||||
}
|
||||
|
||||
// WD EDIT START
|
||||
private void OnUnbuckleDoAfter(EntityUid uid, BuckleComponent component, UnbuckleDoAfterEvent args)
|
||||
{
|
||||
if (args.Cancelled || !CanUnbuckle((uid, component), uid, true, out var strap))
|
||||
return;
|
||||
|
||||
Unbuckle((uid, component), strap, uid);
|
||||
}
|
||||
// WD EDIT END
|
||||
|
||||
public bool IsBuckled(EntityUid uid, BuckleComponent? component = null)
|
||||
{
|
||||
return Resolve(uid, ref component, false) && component.Buckled;
|
||||
@@ -419,6 +432,14 @@ public abstract partial class SharedBuckleSystem
|
||||
if (!CanUnbuckle(buckle, user, popup, out var strap))
|
||||
return false;
|
||||
|
||||
// WD EDIT START
|
||||
if (buckle.Owner == user && strap.Comp.SelfUnBuckleDelay != TimeSpan.Zero)
|
||||
{
|
||||
var doAfter = new DoAfterArgs(EntityManager, buckle.Owner, strap.Comp.SelfUnBuckleDelay, new UnbuckleDoAfterEvent(), buckle.Owner);
|
||||
return _doAfter.TryStartDoAfter(doAfter);
|
||||
}
|
||||
// WD EDIT END
|
||||
|
||||
Unbuckle(buckle!, strap, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Content.Shared.Alert;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Pinpointer;
|
||||
@@ -48,10 +50,24 @@ public sealed partial class PinpointerComponent : Component
|
||||
[DataField("canRetarget"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool CanRetarget;
|
||||
|
||||
// WD EDIT START
|
||||
[DataField]
|
||||
public ProtoId<AlertPrototype>? Alert;
|
||||
|
||||
[DataField]
|
||||
public bool CanToggle = true;
|
||||
|
||||
[DataField]
|
||||
public bool CanEmag = true;
|
||||
|
||||
[DataField]
|
||||
public bool CanExamine = true;
|
||||
// WD EDIT END
|
||||
|
||||
[ViewVariables]
|
||||
public EntityUid? Target = null;
|
||||
|
||||
[ViewVariables, AutoNetworkedField]
|
||||
[DataField, AutoNetworkedField] // WD EDIT: ViewVariables -> DataField
|
||||
public bool IsActive = false;
|
||||
|
||||
[ViewVariables, AutoNetworkedField]
|
||||
|
||||
@@ -66,7 +66,7 @@ public abstract class SharedPinpointerSystem : EntitySystem
|
||||
|
||||
private void OnExamined(EntityUid uid, PinpointerComponent component, ExaminedEvent args)
|
||||
{
|
||||
if (!args.IsInDetailsRange || component.TargetName == null)
|
||||
if (!component.CanExamine || !args.IsInDetailsRange || component.TargetName == null) // WD EDIT
|
||||
return;
|
||||
|
||||
args.PushMarkup(Loc.GetString("examine-pinpointer-linked", ("target", component.TargetName)));
|
||||
@@ -137,6 +137,11 @@ public abstract class SharedPinpointerSystem : EntitySystem
|
||||
|
||||
private void OnEmagged(EntityUid uid, PinpointerComponent component, ref GotEmaggedEvent args)
|
||||
{
|
||||
// WD EDIT START
|
||||
if (!component.CanEmag)
|
||||
return;
|
||||
// WD EDIT END
|
||||
|
||||
args.Handled = true;
|
||||
component.CanRetarget = true;
|
||||
}
|
||||
|
||||
@@ -598,7 +598,7 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
protected IShootable EnsureShootable(EntityUid uid)
|
||||
public IShootable EnsureShootable(EntityUid uid) // WD EDIT: protected -> public
|
||||
{
|
||||
if (TryComp<CartridgeAmmoComponent>(uid, out var cartridge))
|
||||
return cartridge;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared._White.Actions.Events;
|
||||
|
||||
@@ -31,8 +32,11 @@ public sealed partial class SpawnTileEntityActionEvent : InstantActionEvent
|
||||
[DataField]
|
||||
public SoundSpecifier? Audio;
|
||||
|
||||
[DataField]
|
||||
public CollisionGroup? BlockedCollision;
|
||||
[DataField(customTypeSerializer: typeof(FlagSerializer<CollisionMask>))]
|
||||
public int BlockedCollisionMask;
|
||||
|
||||
[DataField(customTypeSerializer: typeof(FlagSerializer<CollisionLayer>))]
|
||||
public int BlockedCollisionLayer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,8 +62,11 @@ public sealed partial class PlaceTileEntityEvent : WorldTargetActionEvent
|
||||
[DataField]
|
||||
public SoundSpecifier? Audio;
|
||||
|
||||
[DataField]
|
||||
public CollisionGroup? BlockedCollision;
|
||||
[DataField(customTypeSerializer: typeof(FlagSerializer<CollisionMask>))]
|
||||
public int BlockedCollisionMask;
|
||||
|
||||
[DataField(customTypeSerializer: typeof(FlagSerializer<CollisionLayer>))]
|
||||
public int BlockedCollisionLayer;
|
||||
|
||||
/// <summary>
|
||||
/// The duration of the action in seconds
|
||||
@@ -79,5 +86,9 @@ public sealed partial class PlaceTileEntityDoAfterEvent : DoAfterEvent
|
||||
|
||||
public SoundSpecifier? Audio;
|
||||
|
||||
public int BlockedCollisionMask;
|
||||
|
||||
public int BlockedCollisionLayer;
|
||||
|
||||
public override DoAfterEvent Clone() => this;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ namespace Content.Shared._White.Actions;
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class PlasmaCostActionComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public bool ShouldChangePlasma = true;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public FixedPoint2 PlasmaCost = 50;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public sealed class PlasmaCostActionSystem : EntitySystem
|
||||
|
||||
private void OnActionPerformed(EntityUid uid, PlasmaCostActionComponent component, ActionPerformedEvent args)
|
||||
{
|
||||
_plasma.ChangePlasmaAmount(args.Performer, -component.PlasmaCost);
|
||||
if (component.ShouldChangePlasma)
|
||||
_plasma.ChangePlasmaAmount(args.Performer, -component.PlasmaCost);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._White.Inventory;
|
||||
|
||||
public abstract partial class SharedWhiteInventorySystem
|
||||
public sealed partial class WhiteInventorySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
@@ -21,6 +21,7 @@ public abstract partial class SharedWhiteInventorySystem
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||
|
||||
|
||||
private void InitializeEquip()
|
||||
{
|
||||
SubscribeLocalEvent<EquipOnCollideComponent, StartCollideEvent>(OnCollideEvent);
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Content.Shared._White.Inventory;
|
||||
|
||||
public abstract partial class SharedWhiteInventorySystem : EntitySystem
|
||||
public sealed partial class WhiteInventorySystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -0,0 +1,15 @@
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Weapons.Ranged.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._White.Weapons.Ranged.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class PlasmaAmmoProviderComponent : AmmoProviderComponent
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public EntProtoId Proto;
|
||||
|
||||
[DataField]
|
||||
public FixedPoint2 FireCost = 55f;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Content.Shared._White.Weapons.Ranged.Components;
|
||||
using Content.Shared._White.Xenomorphs.Plasma;
|
||||
using Content.Shared._White.Xenomorphs.Plasma.Components;
|
||||
using Content.Shared.Weapons.Ranged.Events;
|
||||
using Content.Shared.Weapons.Ranged.Systems;
|
||||
|
||||
namespace Content.Shared._White.Weapons.Ranged.Systems;
|
||||
|
||||
public sealed class PlasmaAmmoProviderSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedGunSystem _gun = default!;
|
||||
[Dependency] private readonly SharedPlasmaSystem _plasma = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PlasmaAmmoProviderComponent, TakeAmmoEvent>(OnTakeAmmo);
|
||||
SubscribeLocalEvent<PlasmaAmmoProviderComponent, GetAmmoCountEvent>(OnGetAmmoCount);
|
||||
}
|
||||
|
||||
private void OnTakeAmmo(EntityUid uid, PlasmaAmmoProviderComponent component, ref TakeAmmoEvent args)
|
||||
{
|
||||
if (!TryComp<PlasmaVesselComponent>(uid, out var plasmaVessel))
|
||||
return;
|
||||
|
||||
for (var i = 0; i < args.Shots; i++)
|
||||
{
|
||||
if (!_plasma.ChangePlasmaAmount(uid, -component.FireCost, plasmaVessel))
|
||||
return;
|
||||
|
||||
var shot = Spawn(component.Proto, args.Coordinates);
|
||||
args.Ammo.Add((shot, _gun.EnsureShootable(shot)));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGetAmmoCount(EntityUid uid, PlasmaAmmoProviderComponent component, ref GetAmmoCountEvent args)
|
||||
{
|
||||
if (!TryComp<PlasmaVesselComponent>(uid, out var plasmaVessel))
|
||||
return;
|
||||
|
||||
args.Capacity = (int) (plasmaVessel.MaxPlasma / component.FireCost);
|
||||
args.Count = (int) (plasmaVessel.Plasma / component.FireCost);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace Content.Shared._White.Xenomorphs.Egg;
|
||||
public sealed partial class XenomorphEggComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public EntProtoId FaceHuggerPrototype = "MobXenomorphFaceHugger";
|
||||
public EntProtoId? FaceHuggerPrototype = "MobXenomorphFaceHugger";
|
||||
|
||||
[DataField]
|
||||
public float BurstRange = 1f;
|
||||
@@ -28,6 +28,9 @@ public sealed partial class XenomorphEggComponent : Component
|
||||
[DataField]
|
||||
public TimeSpan MinGrowthTime = TimeSpan.FromSeconds(90);
|
||||
|
||||
[DataField]
|
||||
public XenomorphEggStatus Status = XenomorphEggStatus.Growning;
|
||||
|
||||
[ViewVariables]
|
||||
public TimeSpan BurstAt = TimeSpan.Zero;
|
||||
|
||||
@@ -36,9 +39,6 @@ public sealed partial class XenomorphEggComponent : Component
|
||||
|
||||
[ViewVariables]
|
||||
public TimeSpan GrownAt = TimeSpan.Zero;
|
||||
|
||||
[ViewVariables]
|
||||
public XenomorphEggStatus Status = XenomorphEggStatus.Growning;
|
||||
}
|
||||
|
||||
public enum XenomorphEggStatus : byte
|
||||
|
||||
@@ -16,10 +16,14 @@ public sealed partial class XenomorphEvolutionDoAfterEvent : DoAfterEvent
|
||||
[DataField]
|
||||
public ProtoId<XenomorphCastePrototype> Caste;
|
||||
|
||||
public XenomorphEvolutionDoAfterEvent(EntProtoId choice, ProtoId<XenomorphCastePrototype> caste)
|
||||
[DataField]
|
||||
public bool CheckNeedCasteDeath;
|
||||
|
||||
public XenomorphEvolutionDoAfterEvent(EntProtoId choice, ProtoId<XenomorphCastePrototype> caste, bool checkNeedCasteDeath = true)
|
||||
{
|
||||
Choice = choice;
|
||||
Caste = caste;
|
||||
CheckNeedCasteDeath = checkNeedCasteDeath;
|
||||
}
|
||||
|
||||
public override DoAfterEvent Clone() => this;
|
||||
@@ -36,6 +40,8 @@ public sealed partial class TransferPlasmaActionEvent : EntityTargetActionEvent
|
||||
|
||||
public sealed partial class EvolutionsActionEvent : InstantActionEvent;
|
||||
|
||||
public sealed partial class PromotionActionEvent : InstantActionEvent;
|
||||
|
||||
public sealed partial class TailLashActionEvent : WorldTargetActionEvent;
|
||||
|
||||
public sealed partial class AcidActionEvent : EntityTargetActionEvent;
|
||||
@@ -47,9 +53,10 @@ public sealed partial class AfterXenomorphEvolutionEvent(EntityUid evolvedInto,
|
||||
public ProtoId<XenomorphCastePrototype> Caste = caste;
|
||||
}
|
||||
|
||||
public sealed partial class BeforeXenomorphEvolutionEvent(ProtoId<XenomorphCastePrototype> caste) : CancellableEntityEventArgs
|
||||
public sealed partial class BeforeXenomorphEvolutionEvent(ProtoId<XenomorphCastePrototype> caste, bool checkNeedCasteDeath = true) : CancellableEntityEventArgs
|
||||
{
|
||||
public ProtoId<XenomorphCastePrototype> Caste = caste;
|
||||
public bool CheckNeedCasteDeath = checkNeedCasteDeath;
|
||||
}
|
||||
|
||||
public sealed partial class PlasmaAmountChangeEvent(FixedPoint2 amount) : EntityEventArgs
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using Content.Shared._White.Xenomorphs.Caste;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._White.Xenomorphs.Queen;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class XenomorphQueenComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public EntProtoId PromotionActionId = "ActionXenomorphPromotion";
|
||||
|
||||
[DataField]
|
||||
public EntProtoId PromotionId = "XenomorphPromotion";
|
||||
|
||||
[DataField]
|
||||
public EntProtoId PromoteTo = "MobXenomorphPraetorian";
|
||||
|
||||
[DataField]
|
||||
public List<ProtoId<XenomorphCastePrototype>> CasteWhitelist = new() { "Drone", "Hunter", "Sentinel", };
|
||||
|
||||
[DataField]
|
||||
public TimeSpan EvolutionDelay = TimeSpan.FromSeconds(3);
|
||||
|
||||
[ViewVariables]
|
||||
public EntityUid? Promotion;
|
||||
|
||||
[ViewVariables]
|
||||
public EntityUid? PromotionAction;
|
||||
}
|
||||
@@ -4,5 +4,8 @@ alerts-blocked-desc = I can't block for a while!
|
||||
alerts-knockdown-name = [color=yellow]Knocked down[/color]
|
||||
alerts-knockdown-desc = You're [color=yellow]knocked down[/color]! Something is impairing your ability to get up.
|
||||
|
||||
alerts-plasma-name = [color='#ff2da4']Plasma[/color]
|
||||
alerts-plasma-desc = The amount of [color='#ff2da4']plasma[/color] you have to use your abilities.
|
||||
alerts-plasma-name = [color=#ff2da4]Plasma[/color]
|
||||
alerts-plasma-desc = The amount of [color=#ff2da4]plasma[/color] you have to use your abilities.
|
||||
|
||||
alerts-queen-finder-name = Queen sense
|
||||
alerts-queen-finder-desc = Allows you to sense the general direction of your Queen.
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
steal-target-groups-animal-lamarr = Lamarr
|
||||
@@ -1,2 +0,0 @@
|
||||
ent-MiniSyringe = mini syringe
|
||||
ent-MiniSyringe-desc = A regular syringe, reshaped to fit inside of a gun.
|
||||
7
Resources/Locale/en-US/_white/xenomorphs/face-hugger.ftl
Normal file
@@ -0,0 +1,7 @@
|
||||
xenomorphs-face-hugger-equip = { $equipment } leaps at your face!
|
||||
xenomorphs-face-hugger-equip-other = { $equipment } leaps at { $target }'s face!
|
||||
|
||||
xenomorphs-face-hugger-unequip = { $equipment } is latched on too tight!
|
||||
|
||||
xenomorphs-face-hugger-try-equip = { $equipment } smashes against your { $equipmentBlocker }
|
||||
xenomorphs-face-hugger-try-equip-other = { $equipment } smashes against { $target }'s { $equipmentBlocker }
|
||||
2
Resources/Locale/en-US/_white/xenomorphs/queen.ftl
Normal file
@@ -0,0 +1,2 @@
|
||||
xenomorphs-queen-promotion-didnt-pass-whitelist = You may only use this with your adult, non-royal children!
|
||||
xenomorphs-queen-promotion-no-mind = Her mind can't support the promotion!
|
||||
@@ -16631,10 +16631,6 @@ ent-SmallExplosionInstant = мгновенный взрыв (малый)
|
||||
ent-MediumExplosionInstant = мгновенный взрыв (средний)
|
||||
|
||||
|
||||
ent-PlushieSanabi = плюшевая игрушка бригадира
|
||||
.desc = Маленькая мягкая копия сурового бригадного генерала. Ужасно милая.
|
||||
|
||||
|
||||
ent-ItemSnowballMaker = снежколеп
|
||||
.desc = Лепит снежки. Весело и опасно.
|
||||
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
ent-XenomorphEgg = яйцо ксеноморфа
|
||||
.desc = Большое пятнистое яйцо.
|
||||
|
||||
ent-XenomorphEggBurst = { ent-XenomorphEgg }
|
||||
.desc = { ent-XenomorphEgg.desc }
|
||||
.suffix = Открытое
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
ent-GlassBoxLamarrFilled = { ent-GlassBox }
|
||||
.desc = { ent-GlassBox.desc }
|
||||
.suffix = Ламарр, Заполненная
|
||||
@@ -4,5 +4,8 @@ alerts-blocked-desc = Невозможно блокировать некотор
|
||||
alerts-knockdown-name = [color=yellow]Сбиты с ног[/color]
|
||||
alerts-knockdown-desc = Вы [color=yellow]сбиты с ног[/color]! Что-то мешает вам встать.
|
||||
|
||||
alerts-plasma-name = [color='#ff2da4']Плазма[/color]
|
||||
alerts-plasma-desc = Количество [color='#ff2da4']плазмы[/color] которое у тебя есть для использования своих способностей.
|
||||
alerts-plasma-name = [color=#ff2da4]Плазма[/color]
|
||||
alerts-plasma-desc = Количество [color=#ff2da4]плазмы[/color] которое у тебя есть для использования своих способностей.
|
||||
|
||||
alerts-queen-finder-name = Чувство королевы
|
||||
alerts-queen-finder-desc = Позволяет вам чувствовать общее направление движения вашей королевы.
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
steal-target-groups-animal-lamarr = Ламарр
|
||||
@@ -1,51 +1,44 @@
|
||||
ent-ActionCombatModeToggleXenomorph = { ent-ActionCombatModeToggle }
|
||||
.desc = { ent-ActionCombatModeToggle.desc }
|
||||
|
||||
|
||||
ent-ToggleThermalVisionXenomorph = { ent-ActionCombatModeToggle }
|
||||
.desc = { ent-ActionCombatModeToggle.desc }
|
||||
|
||||
|
||||
ent-ActionEvolution = Эволюционировать
|
||||
.desc = Эволюционирует в высшую касту ксеноморфов.
|
||||
|
||||
ent-ActionEvolutionPraetorian = Эволюционировать в преторианца (500)
|
||||
.desc = Эволюционирует в главного защитника улья.
|
||||
|
||||
|
||||
ent-ActionEvolutionQueen = Эволюционировать в королеву (500)
|
||||
.desc = Формирует внутренний яйцевой мешок, способный производить потомство. Одновременно может существовать только одна королева.
|
||||
|
||||
|
||||
ent-ActionSpawnResinWeedNode = Посадить траву (50)
|
||||
.desc = Сажает траву ксеноморфов.
|
||||
|
||||
ent-ActionSpawnXenomorphEgg = Отложить яйцо (75)
|
||||
.desc = Отложить яйцо, чтобы произвести на свет лицехватов, с помощью которых можно оплодотворить добычу.
|
||||
|
||||
ent-ActionSpawnWallResin = Выделить смолу (50)
|
||||
ent-ActionSpawnWallResin = Построить смоляную стену (50)
|
||||
.desc = Выделяют вязкую, пластичную смолу.
|
||||
|
||||
|
||||
ent-ActionSpawnResinMembrane = Выделить смолу (50)
|
||||
ent-ActionSpawnResinMembrane = Построить смоляную мембрану (50)
|
||||
.desc = Выделяют вязкую, пластичную смолу.
|
||||
|
||||
|
||||
ent-ActionSpawnResinNest = Выделить смолу (50)
|
||||
ent-ActionSpawnResinNest = Построить смоляное гнездо (50)
|
||||
.desc = Выделяют вязкую, пластичную смолу.
|
||||
|
||||
|
||||
ent-ActionTailLash = Удар хвостом
|
||||
.desc = Ударь противника хвостом.
|
||||
|
||||
|
||||
ent-ActionAcid = Едкая кислота (200)
|
||||
.desc = Покройте предмет кислотой, которая со временем его разрушит.
|
||||
|
||||
|
||||
ent-ActionJumpXenomorph = Прыжок
|
||||
.desc = Оглушите врагов быстрым прыжком.
|
||||
|
||||
|
||||
ent-ActionTransferPlasma = Передача плазмы (50)
|
||||
.desc = Передаёт плазму вашему другу.
|
||||
|
||||
ent-ActionXenomorphPromotion = Создать королевского паразита (500)
|
||||
.desc = Создает королевского паразита, чтобы предоставить одному из ваших детей честь стать вашим преторианцем.
|
||||
@@ -0,0 +1,6 @@
|
||||
ent-PlushieSanabi = плюшевая игрушка бригадира
|
||||
.desc = Маленькая мягкая копия сурового генерала бригадира. Ужасно милая.
|
||||
|
||||
ent-FaceHuggerToys = ксеноморф лицехват
|
||||
.desc = Игрушка, которую часто используют, чтобы подшутить над другими членами экипажа, подкладывая её им в кровати. После того, как она зацепится за что-нибудь, ей требуется некоторое время для перезарядки.
|
||||
.suffix = Игрушка
|
||||
@@ -0,0 +1,3 @@
|
||||
ent-MobXenomorphFaceHuggerLamarr = Ламарр
|
||||
.desc = бывший кандидат в кошмар, а ныне – примерный питомец.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
ent-XenomorphPromotion = королевский паразит
|
||||
.desc = Введите это в одну из своих взрослых дочерей, чтобы повысить её до преторианца!
|
||||
.suffix = { ent-BaseItem.suffix }
|
||||
7
Resources/Locale/ru-RU/_white/xenomorphs/face-hugger.ftl
Normal file
@@ -0,0 +1,7 @@
|
||||
xenomorphs-face-hugger-equip = { $equipment } прыгает тебе на лицо!
|
||||
xenomorphs-face-hugger-equip-other = { $equipment } прыгает на лицо { $target }!
|
||||
|
||||
xenomorphs-face-hugger-unequip = { $equipment } прицепился слишком крепко!
|
||||
|
||||
xenomorphs-face-hugger-try-equip = { $equipment } врезается в твой { $equipmentBlocker }
|
||||
xenomorphs-face-hugger-try-equip-other = { $equipment } врезается в { $equipmentBlocker } { $target }
|
||||
2
Resources/Locale/ru-RU/_white/xenomorphs/queen.ftl
Normal file
@@ -0,0 +1,2 @@
|
||||
xenomorphs-queen-promotion-didnt-pass-whitelist = Вы можете использовать это только с вашими взрослыми детьми, не являющимися королевскими!
|
||||
xenomorphs-queen-promotion-no-mind = Её разум не может выдержать повышение!
|
||||
@@ -771,8 +771,6 @@
|
||||
orGroup: Plushie
|
||||
- id: PlushieMothRandom
|
||||
orGroup: Plushie
|
||||
- id: PlushieSanabi # WWDP edit
|
||||
orGroup: Plushie
|
||||
- id: PlushieMoth
|
||||
prob: 0.5
|
||||
orGroup: Plushie
|
||||
@@ -785,6 +783,12 @@
|
||||
- id: PlushieShadowkin
|
||||
prob: 0.5
|
||||
orGroup: Plushie
|
||||
# WD EDIT START
|
||||
- id: PlushieSanabi
|
||||
orGroup: Plushie
|
||||
- id: FaceHuggerToys
|
||||
orGroup: Plushie
|
||||
# WD EDIT END
|
||||
|
||||
# Random snacks, replaces MailChocolate (lousy animal organs)
|
||||
- type: entity
|
||||
|
||||
@@ -71,8 +71,11 @@
|
||||
- PlushieJester
|
||||
- PlushieHarpy
|
||||
- PlushieMort
|
||||
- PlushieSanabi #WWDP edit
|
||||
- PlushieShadowkin
|
||||
# WD EDIT START
|
||||
- PlushieSanabi
|
||||
- FaceHuggerToys
|
||||
# WD EDIT END
|
||||
chance: 0.5
|
||||
offset: 0.2
|
||||
|
||||
|
||||
@@ -84,8 +84,6 @@
|
||||
orGroup: GiftPool
|
||||
- id: PlushieRatvar
|
||||
orGroup: GiftPool
|
||||
- id: PlushieSanabi #WWDP edit
|
||||
orGroup: GiftPool
|
||||
- id: PlushieSpaceLizard
|
||||
orGroup: GiftPool
|
||||
- id: PlushieSharkBlue
|
||||
@@ -386,6 +384,12 @@
|
||||
orGroup: GiftPool
|
||||
- id: ToySiobhan # DeltaV Toy, see Resources/Prototypes/DeltaV/Entities/Objects/Fun/toys.yml
|
||||
orGroup: GiftPool
|
||||
# WD EDIT START
|
||||
- id: PlushieSanabi
|
||||
orGroup: GiftPool
|
||||
- id: FaceHuggerToys
|
||||
orGroup: GiftPool
|
||||
# WD EDIT END
|
||||
sound:
|
||||
path: /Audio/Effects/unwrap.ogg
|
||||
|
||||
|
||||
@@ -910,7 +910,7 @@
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Caustic: 15 # WD EDIT: 5 -> 15
|
||||
Caustic: 5
|
||||
- type: Sprite
|
||||
sprite: Objects/Weapons/Guns/Projectiles/xeno_toxic.rsi
|
||||
layers:
|
||||
|
||||
@@ -1911,6 +1911,7 @@
|
||||
- ToySword
|
||||
- BwoinkHammer
|
||||
- ThronglerToy
|
||||
- FaceHuggerToys # WD EDIT
|
||||
- type: MaterialStorage
|
||||
whitelist:
|
||||
tags:
|
||||
|
||||
@@ -62,7 +62,12 @@
|
||||
icon: { sprite: _White/Interface/Actions/xenomorph.rsi, state: plant_seed }
|
||||
event: !type:SpawnTileEntityActionEvent
|
||||
entity: ResinWeedNode
|
||||
blockedCollision: SlipLayer
|
||||
blockedCollisionMask:
|
||||
- SlipLayer
|
||||
blockedCollisionLayer:
|
||||
- Impassable
|
||||
- MidImpassable
|
||||
- LowImpassable
|
||||
- type: PlasmaCostAction
|
||||
|
||||
- type: entity
|
||||
@@ -77,62 +82,73 @@
|
||||
icon: { sprite: _White/Interface/Actions/xenomorph.rsi, state: egg }
|
||||
event: !type:SpawnTileEntityActionEvent
|
||||
entity: XenomorphEgg
|
||||
blockedCollision: TableMask
|
||||
blockedCollisionMask:
|
||||
- TableMask
|
||||
blockedCollisionLayer:
|
||||
- TableLayer
|
||||
- BulletImpassable
|
||||
- type: PlasmaCostAction
|
||||
plasmaCost: 75
|
||||
|
||||
# TODO: delete it
|
||||
- type: entity
|
||||
id: ActionSpawnWallResin
|
||||
name: Secrete resin (50)
|
||||
name: Build a resin wall (50)
|
||||
description: Secrete tough malleable resin.
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
useDelay: 1
|
||||
range: 2
|
||||
itemIconStyle: BigAction
|
||||
checkCanAccess: false
|
||||
icon: { sprite: _White/Structures/Walls/resin.rsi, state: full }
|
||||
event: !type:PlaceTileEntityEvent
|
||||
entity: WallResin
|
||||
length: 0.5
|
||||
blockedCollision: FullTileMask
|
||||
blockedCollisionMask:
|
||||
- FullTileMask
|
||||
blockedCollisionLayer:
|
||||
- WallLayer
|
||||
- type: PlasmaCostAction
|
||||
|
||||
# TODO: delete it
|
||||
- type: entity
|
||||
id: ActionSpawnResinMembrane
|
||||
name: Secrete resin (50)
|
||||
name: Build a resin membrane (50)
|
||||
description: Secrete tough malleable resin.
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
useDelay: 1
|
||||
range: 2
|
||||
itemIconStyle: BigAction
|
||||
checkCanAccess: false
|
||||
icon: { sprite : _White/Structures/Windows/resin_membrane.rsi, state: full }
|
||||
event: !type:PlaceTileEntityEvent
|
||||
entity: ResinMembrane
|
||||
length: 0.5
|
||||
blockedCollision: GlassLayer
|
||||
blockedCollisionMask:
|
||||
- FullTileMask
|
||||
blockedCollisionLayer:
|
||||
- GlassLayer
|
||||
- type: PlasmaCostAction
|
||||
|
||||
# TODO: delete it
|
||||
- type: entity
|
||||
id: ActionSpawnResinNest
|
||||
name: Secrete resin (50)
|
||||
name: Build a resin nest (50)
|
||||
description: Secrete tough malleable resin.
|
||||
components:
|
||||
- type: WorldTargetAction
|
||||
useDelay: 1
|
||||
range: 2
|
||||
itemIconStyle: BigAction
|
||||
checkCanAccess: false
|
||||
icon: { sprite : _White/Structures/Windows/resin_membrane.rsi, state: full }
|
||||
event: !type:PlaceTileEntityEvent
|
||||
entity: ResinNest
|
||||
length: 0.5
|
||||
blockedCollision: TableMask
|
||||
blockedCollisionMask:
|
||||
- TableMask
|
||||
blockedCollisionLayer:
|
||||
- TableLayer
|
||||
- BulletImpassable
|
||||
- type: PlasmaCostAction
|
||||
|
||||
# Tail lash action
|
||||
@@ -145,7 +161,6 @@
|
||||
useDelay: 11
|
||||
range: 10
|
||||
itemIconStyle: BigAction
|
||||
checkCanAccess: false
|
||||
icon: { sprite : _White/Interface/Actions/xenomorph.rsi, state: tail_attack }
|
||||
event: !type:TailLashActionEvent
|
||||
|
||||
@@ -188,3 +203,18 @@
|
||||
icon: { sprite : _White/Interface/Actions/xenomorph.rsi, state: plasma_transfer_off }
|
||||
iconOn: { sprite : _White/Interface/Actions/xenomorph.rsi, state: plasma_transfer_on }
|
||||
event: !type:TransferPlasmaActionEvent
|
||||
|
||||
# Promotion action
|
||||
- type: entity
|
||||
id: ActionXenomorphPromotion
|
||||
name: Create royal parasite (500)
|
||||
description: Produce a royal parasite to grant one of your children the honor of being your Praetorian.
|
||||
components:
|
||||
- type: InstantAction
|
||||
checkCanInteract: false
|
||||
itemIconStyle: BigAction
|
||||
useDelay: 0
|
||||
icon: { sprite : _White/Interface/Actions/xenomorph.rsi, state: promote }
|
||||
event: !type:PromotionActionEvent
|
||||
- type: PlasmaCostAction
|
||||
plasmaCost: 500
|
||||
|
||||
@@ -63,3 +63,23 @@
|
||||
offset: 0.175, 0
|
||||
- map: [ "enum.PlasmaVisualLayers.Digit3" ]
|
||||
offset: 0.35, 0
|
||||
|
||||
# Queen Finder Alert
|
||||
- type: alert
|
||||
id: QueenFinder
|
||||
icons:
|
||||
- sprite: /Textures/_White/Interface/Alerts/queen_finder.rsi
|
||||
state: queen_finder
|
||||
alertViewEntity: AlertQueenFinderSpriteView
|
||||
name: alerts-queen-finder-name
|
||||
description: alerts-queen-finder-desc
|
||||
|
||||
- type: entity
|
||||
id: AlertQueenFinderSpriteView
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: /Textures/_White/Interface/Alerts/queen_finder.rsi
|
||||
layers:
|
||||
- map: [ "enum.AlertVisualLayers.Base" ]
|
||||
- map: [ "enum.PinpointerLayers.Screen" ]
|
||||
|
||||
@@ -107,12 +107,11 @@
|
||||
onAdd:
|
||||
- type: RechargeBasicEntityAmmo
|
||||
rechargeCooldown: 0.75
|
||||
- type: BasicEntityAmmoProvider
|
||||
proto: BulletAcidLarge
|
||||
capacity: 1
|
||||
count: 1
|
||||
- type: PlasmaAmmoProvider
|
||||
fireCost: 55
|
||||
proto: BulletNeurotoxin
|
||||
- type: Gun
|
||||
fireRate: 0.25
|
||||
fireRate: 0.75
|
||||
useKey: false
|
||||
selectedMode: FullAuto
|
||||
availableModes:
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
- type: entity
|
||||
parent: BasePlushie
|
||||
id: PlushieSanabi
|
||||
name: brigadier plushie
|
||||
description: A small stuffed doll of the brigadier general.
|
||||
components:
|
||||
- type: Item
|
||||
size: Normal
|
||||
inhandVisuals:
|
||||
left:
|
||||
- state: sanabi-inhand-left
|
||||
right:
|
||||
- state: sanabi-inhand-right
|
||||
- type: Sprite
|
||||
sprite: _White/Objects/Fun/sanabi.rsi
|
||||
state: sanabi
|
||||
|
||||
@@ -15,6 +15,3 @@
|
||||
rules: ghost-role-information-rules-default-team-antagonist
|
||||
mindRoles:
|
||||
- MindRoleGhostRoleTeamAntagonist
|
||||
- type: GhostRoleMobSpawner
|
||||
prototype: MobXenomorphLarva
|
||||
- type: GhostRoleAntagSpawner
|
||||
|
||||
16
Resources/Prototypes/_White/Entities/Mobs/Player/pets.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
- type: entity
|
||||
id: MobXenomorphFaceHuggerLamarr
|
||||
parent: MobXenomorphFaceHugger
|
||||
name: Lamarr
|
||||
description: A former nightmare candidate, now an exemplary pet.
|
||||
components:
|
||||
- type: FaceHugger
|
||||
knockdownTime: 0
|
||||
infectionPrototype: null
|
||||
damageOnImpact:
|
||||
types:
|
||||
Blunt: 2
|
||||
- type: UseDelay
|
||||
delay: 7
|
||||
- type: StealTarget
|
||||
stealGroup: AnimalLamarr
|
||||
@@ -1,6 +1,8 @@
|
||||
- type: entity
|
||||
parent:
|
||||
- BaseSimpleMob
|
||||
- BaseMob
|
||||
- MobDamageable
|
||||
- MobPolymorphable
|
||||
- MobCombat
|
||||
- MobBloodstream
|
||||
- MobFlammable
|
||||
@@ -14,10 +16,20 @@
|
||||
Toxin: -5
|
||||
Airloss: -10
|
||||
Brute: -5
|
||||
- type: Pinpointer
|
||||
component: XenomorphQueen
|
||||
alert: QueenFinder
|
||||
isActive: true
|
||||
canToggle: false
|
||||
canEmag: false
|
||||
canExamine: false
|
||||
- type: ThermalVision
|
||||
toggleAction: ToggleThermalVisionXenomorph
|
||||
color: "#7d0cc9"
|
||||
lightRadius: 10
|
||||
strength: 0
|
||||
noise: 0
|
||||
tint: 3, 3, 3
|
||||
- type: NameIdentifier
|
||||
group: GenericNumber
|
||||
- type: CombatMode
|
||||
|
||||
@@ -46,53 +46,23 @@
|
||||
heatDamageThreshold: 360
|
||||
coldDamageThreshold: -150
|
||||
currentTemperature: 310.15
|
||||
- type: EquipOnCollide
|
||||
slot: mask
|
||||
blockingSlot: head
|
||||
blacklist:
|
||||
components:
|
||||
- XenomorphInfected
|
||||
- XenomorphLarvaVictim
|
||||
- Ghost
|
||||
- type: EquipOnPickUp
|
||||
slot: mask
|
||||
blockingSlot: head
|
||||
blacklist:
|
||||
components:
|
||||
- XenomorphInfected
|
||||
- XenomorphLarvaVictim
|
||||
- Ghost
|
||||
- type: EquipOnMeleeHit
|
||||
slot: mask
|
||||
blockingSlot: head
|
||||
blacklist:
|
||||
components:
|
||||
- XenomorphInfected
|
||||
- XenomorphLarvaVictim
|
||||
- Ghost
|
||||
- type: EffectsOnEquip
|
||||
slot: mask
|
||||
blacklist:
|
||||
components:
|
||||
- XenomorphInfected
|
||||
- XenomorphLarvaVictim
|
||||
- Ghost
|
||||
effects:
|
||||
- !type:Paralyze
|
||||
paralyzeTime: 5
|
||||
- type: Butcherable
|
||||
spawned:
|
||||
- id: FoodMeatXeno
|
||||
amount: 1
|
||||
- type: FaceHugger
|
||||
slot: mask
|
||||
blacklist:
|
||||
components:
|
||||
- XenomorphInfected
|
||||
- XenomorphLarvaVictim
|
||||
- Silicon
|
||||
- Ghost
|
||||
allowedPassiveDamageStates:
|
||||
- Alive
|
||||
passiveDamage:
|
||||
damageOnImpact:
|
||||
types:
|
||||
Blunt: 15
|
||||
damageOnInfect:
|
||||
groups:
|
||||
Genetic: 1
|
||||
Genetic: 100
|
||||
- type: NameIdentifier
|
||||
group: GenericNumber
|
||||
- type: NpcFactionMember
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
- map: [ "pocket2" ]
|
||||
- type: Xenomorph
|
||||
caste: Queen
|
||||
- type: XenomorphQueen
|
||||
- type: TailLash
|
||||
tailDamage:
|
||||
groups:
|
||||
@@ -54,6 +55,9 @@
|
||||
600: 0.9
|
||||
645: 0.7
|
||||
690: 0.6
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 2
|
||||
baseSprintSpeed: 2.5
|
||||
- type: MeleeWeapon
|
||||
damage:
|
||||
groups:
|
||||
|
||||
81
Resources/Prototypes/_White/Entities/Objects/Fun/toys.yml
Normal file
@@ -0,0 +1,81 @@
|
||||
## Plushies
|
||||
|
||||
- type: entity
|
||||
parent: BasePlushie
|
||||
id: PlushieSanabi
|
||||
name: brigadier plushie
|
||||
description: A small stuffed doll of the brigadier general.
|
||||
components:
|
||||
- type: Item
|
||||
size: Normal
|
||||
inhandVisuals:
|
||||
left:
|
||||
- state: sanabi-inhand-left
|
||||
right:
|
||||
- state: sanabi-inhand-right
|
||||
- type: Sprite
|
||||
sprite: _White/Objects/Fun/sanabi.rsi
|
||||
state: sanabi
|
||||
|
||||
# MISC
|
||||
|
||||
- type: entity
|
||||
parent: ClothingMaskBase
|
||||
id: FaceHuggerToys
|
||||
name: xenomorph facehugger
|
||||
description: A toy often used to play pranks on other crew members by putting it in their beds. It takes a bit to recharge after latching onto something.
|
||||
suffix: Toys
|
||||
components:
|
||||
- type: Sprite
|
||||
noRot: true
|
||||
sprite: _White/Mobs/Aliens/Xenomorphs/facehugger.rsi
|
||||
layers:
|
||||
- map: ["enum.DamageStateVisualLayers.Base"]
|
||||
state: facehugger
|
||||
- type: Clothing
|
||||
sprite: _White/Mobs/Aliens/Xenomorphs/facehugger.rsi
|
||||
slots: [mask]
|
||||
- type: IngestionBlocker
|
||||
- type: Blindfold
|
||||
- type: AddAccentClothing
|
||||
accent: ReplacementAccent
|
||||
replacement: mumble
|
||||
- type: FaceHugger
|
||||
blacklist:
|
||||
components:
|
||||
- Ghost
|
||||
knockdownTime: 0
|
||||
infectionPrototype: null
|
||||
damageOnImpact:
|
||||
types:
|
||||
Blunt: 0
|
||||
- type: MeleeWeapon
|
||||
hidden: true
|
||||
canHeavyAttack: false
|
||||
angle: 0
|
||||
damage:
|
||||
types:
|
||||
Blunt: 0
|
||||
- type: Physics
|
||||
bodyType: Dynamic
|
||||
- type: CollisionWake
|
||||
enabled: false
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
slips:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.35
|
||||
layer:
|
||||
- SlipLayer
|
||||
hard: false
|
||||
fix1:
|
||||
shape:
|
||||
!type:PhysShapeCircle
|
||||
radius: 0.35
|
||||
density: 10
|
||||
mask:
|
||||
- ItemMask
|
||||
- type: Tag
|
||||
tags:
|
||||
- XenomorphItem
|
||||
@@ -0,0 +1,19 @@
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
id: XenomorphPromotion
|
||||
name: royal parasite
|
||||
description: Inject this into one of your grown children to promote her to a Praetorian!
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _White/Objects/Misc/xenomorph_promotion.rsi
|
||||
state: icon
|
||||
- type: Item
|
||||
size: Ginormous
|
||||
- type: Unremoveable
|
||||
deleteOnDrop: true
|
||||
- type: DeleteOnDrop
|
||||
- type: XenomorphPromotion
|
||||
- type: Tag
|
||||
tags:
|
||||
- XenomorphItem
|
||||
@@ -1,9 +1,12 @@
|
||||
- type: entity
|
||||
id: BulletAcidLarge
|
||||
id: BulletNeurotoxin
|
||||
parent: BulletAcid
|
||||
name: neurotoxin spit
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: StaminaDamageOnCollide
|
||||
damage: 65
|
||||
- type: Projectile
|
||||
damage:
|
||||
types:
|
||||
Caustic: 35
|
||||
Caustic: 1
|
||||
|
||||
@@ -21,10 +21,7 @@
|
||||
!type:PhysShapeAabb
|
||||
bounds: "-0.45,-0.45,0.45,0.05"
|
||||
density: 190
|
||||
mask:
|
||||
- TableMask
|
||||
layer:
|
||||
- TableLayer
|
||||
- BulletImpassable
|
||||
- type: RequireProjectileTarget
|
||||
- type: Damageable
|
||||
@@ -63,6 +60,7 @@
|
||||
- type: Strap
|
||||
position: Down
|
||||
rotation: -90
|
||||
selfUnBuckleDelay: 100
|
||||
- type: Transform
|
||||
anchored: true
|
||||
noRot: true
|
||||
|
||||
@@ -63,8 +63,23 @@
|
||||
!type:PhysShapeAabb
|
||||
bounds: "-0.45,-0.45,0.45,0.05"
|
||||
density: 190
|
||||
mask:
|
||||
- TableMask
|
||||
layer:
|
||||
- TableLayer
|
||||
- BulletImpassable
|
||||
|
||||
- type: entity
|
||||
parent: XenomorphEgg
|
||||
id: XenomorphEggBurst
|
||||
suffix: Burst
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _White/Structures/Furniture/xenomorph_egg.rsi
|
||||
noRot: true
|
||||
layers:
|
||||
- state: egg_burst
|
||||
map: [ "status" ]
|
||||
- type: Icon
|
||||
sprite: _White/Structures/Furniture/xenomorph_egg.rsi
|
||||
state: egg_burst
|
||||
- type: XenomorphEgg
|
||||
faceHuggerPrototype: null
|
||||
status: Burst
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
- type: entity
|
||||
parent: GlassBox
|
||||
id: GlassBoxLamarrFilled
|
||||
suffix: Lamarr, Filled
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Structures/Storage/glassbox.rsi
|
||||
layers:
|
||||
- state: base
|
||||
- sprite: _White/Mobs/Aliens/Xenomorphs/facehugger.rsi
|
||||
state: facehugger
|
||||
map: ["enum.ItemCabinetVisuals.Layer"]
|
||||
visible: true
|
||||
- state: glass
|
||||
map: ["enum.OpenableVisuals.Layer"]
|
||||
- state: locked
|
||||
shader: unshaded
|
||||
map: ["enum.LockVisualLayers.Lock"]
|
||||
- type: AccessReader
|
||||
access: [["ResearchDirector"]]
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
ItemCabinet:
|
||||
startingItem: MobXenomorphFaceHuggerLamarr
|
||||
ejectOnInteract: true
|
||||
whitelist:
|
||||
components:
|
||||
- FaceHugger
|
||||
@@ -53,6 +53,8 @@
|
||||
earliestStart: 35
|
||||
reoccurrenceDelay: 50
|
||||
- type: VentSpawnRule
|
||||
- type: AntagSpawner
|
||||
prototype: MobXenomorphLarva
|
||||
- type: XenomorphsRule
|
||||
- type: AntagObjectives
|
||||
objectives:
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Thief Animal
|
||||
|
||||
- type: stealTargetGroup
|
||||
id: AnimalLamarr
|
||||
name: steal-target-groups-animal-lamarr
|
||||
sprite:
|
||||
sprite: _White/Mobs/Aliens/Xenomorphs/facehugger.rsi
|
||||
state: facehugger
|
||||
10
Resources/Prototypes/_White/Objective/thief.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
- type: entity
|
||||
parent: BaseThiefStealAnimalObjective
|
||||
id: LamarrStealObjective
|
||||
components:
|
||||
- type: NotJobRequirement
|
||||
job: ResearchDirector
|
||||
- type: StealCondition
|
||||
stealGroup: AnimalLamarr
|
||||
- type: Objective
|
||||
difficulty: 2
|
||||
@@ -5,3 +5,11 @@
|
||||
completetime: 0.1
|
||||
materials:
|
||||
PrizeTicket: 50
|
||||
|
||||
- type: latheRecipe
|
||||
id: FaceHuggerToys
|
||||
result: FaceHuggerToys
|
||||
applyMaterialDiscount: false
|
||||
completetime: 0.1
|
||||
materials:
|
||||
PrizeTicket: 100
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
- type: xenomorphCaste
|
||||
id: Praetorian
|
||||
name: xenomorph-caste-praetorian
|
||||
# needCasteDeath: Queen - TODO: Royal larva
|
||||
needCasteDeath: Queen
|
||||
maxCount: 1
|
||||
|
||||
- type: xenomorphCaste
|
||||
|
||||
@@ -28,11 +28,14 @@
|
||||
{
|
||||
"name": "tail_attack"
|
||||
},
|
||||
{
|
||||
"name": "plasma_transfer_off"
|
||||
},
|
||||
{
|
||||
"name": "plasma_transfer_on"
|
||||
},
|
||||
{
|
||||
"name": "plasma_transfer_off"
|
||||
"name": "promote"
|
||||
},
|
||||
{
|
||||
"name": "acid"
|
||||
|
||||
|
After Width: | Height: | Size: 388 B |
|
After Width: | Height: | Size: 603 B |
|
After Width: | Height: | Size: 215 B |
|
After Width: | Height: | Size: 603 B |
@@ -7,8 +7,47 @@
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "close",
|
||||
"delays": [
|
||||
[
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "far",
|
||||
"delays": [
|
||||
[
|
||||
4.0,
|
||||
4.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "medium",
|
||||
"delays": [
|
||||
[
|
||||
2.0,
|
||||
2.0
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "queen_finder"
|
||||
},
|
||||
{
|
||||
"name": "reached",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "unknown"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 96 B |
|
After Width: | Height: | Size: 239 B |
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "from https://github.com/tgstation/tgstation/blob/icons/mob/actions/actions_xeno.dmi",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
}
|
||||
]
|
||||
}
|
||||