This commit is contained in:
antharsi 2026-08-14 01:46:09 +00:00 committed by GitHub
commit 789c3f10eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
118 changed files with 3511 additions and 6 deletions

View File

@ -74,6 +74,10 @@ public sealed partial class BorgSystem : SharedBorgSystem
if (!Resolve(ent, ref ent.Comp1, ref ent.Comp2, ref ent.Comp3))
return;
// DeltaV - Start Skip Light layer for Replicators.
if (!_sprite.LayerMapTryGet((ent.Owner, ent.Comp3), BorgVisualLayers.Light, out _, false))
return;
// DeltaV - End Skip Light layer for Replicators.
if (_appearance.TryGetData<MobState>(ent.Owner, MobStateVisuals.State, out var state, ent.Comp2))
{
if (state != MobState.Alive)
@ -134,4 +138,4 @@ public sealed partial class BorgSystem : SharedBorgSystem
base.Update(frameTime);
UpdateBattery(frameTime);
}
}
}

View File

@ -0,0 +1,70 @@
using Content.Shared._Impstation.Replicator;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Shared.Animations;
namespace Content.Client._Impstation.Replicator;
public sealed class ReplicatorNestFallingVisualsSystem : EntitySystem
{
[Dependency] private readonly AnimationPlayerSystem _anim = default!;
private const string HoleFallingAnimationKey = "hole_fall";
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ReplicatorNestFallingComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<ReplicatorNestFallingComponent, ComponentRemove>(OnComponentRemove);
}
private void OnComponentInit(Entity<ReplicatorNestFallingComponent> ent, ref ComponentInit args)
{
if (!TryComp<SpriteComponent>(ent, out var sprite) || TerminatingOrDeleted(ent))
return;
ent.Comp.OriginalScale = sprite.Scale;
var animPlayer = EnsureComp<AnimationPlayerComponent>(ent);
if (_anim.HasRunningAnimation(animPlayer, HoleFallingAnimationKey))
return;
_anim.Play((ent, animPlayer), GetFallingAnimation(ent.Comp), HoleFallingAnimationKey);
}
private void OnComponentRemove(Entity<ReplicatorNestFallingComponent> ent, ref ComponentRemove args)
{
if (!TryComp<SpriteComponent>(ent, out var sprite) || TerminatingOrDeleted(ent))
return;
var animPlayer = EnsureComp<AnimationPlayerComponent>(ent);
var animEnt = (Entity<AnimationPlayerComponent?>) (ent, animPlayer);
if (_anim.HasRunningAnimation(animPlayer, HoleFallingAnimationKey))
_anim.Stop(animEnt, HoleFallingAnimationKey);
sprite.Scale = ent.Comp.OriginalScale;
}
private static Animation GetFallingAnimation(ReplicatorNestFallingComponent component)
{
var length = component.AnimationTime;
return new Animation
{
Length = length,
AnimationTracks =
{
new AnimationTrackComponentProperty
{
ComponentType = typeof(SpriteComponent),
Property = nameof(SpriteComponent.Scale),
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(component.OriginalScale, 0.0f),
new AnimationTrackProperty.KeyFrame(component.AnimationScale, length.Seconds),
},
InterpolationMode = AnimationInterpolationMode.Cubic,
},
},
};
}
}

View File

@ -0,0 +1,44 @@
using Content.Shared._Impstation.Replicator;
using Robust.Client.GameObjects;
namespace Content.Client._Impstation.Replicator;
public sealed partial class ReplicatorNestVisualsSystem : SharedReplicatorNestSystem
{
[Dependency] private readonly AppearanceSystem _appearance = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ReplicatorNestComponent, ReplicatorNestEmbiggenedEvent>(OnEmbiggened);
}
private void OnEmbiggened(Entity<ReplicatorNestComponent> ent, ref ReplicatorNestEmbiggenedEvent args)
{
if (!TryComp<SpriteComponent>(ent, out var sprite))
return;
var targetLayer = ent.Comp.CurrentLevel switch
{
>= 3 => ReplicatorNestVisuals.Level3,
2 => ReplicatorNestVisuals.Level2,
_ => ReplicatorNestVisuals.Level1,
};
var targetLayerUnshaded = ent.Comp.CurrentLevel switch
{
>= 3 => ReplicatorNestVisuals.Level3Unshaded,
2 => ReplicatorNestVisuals.Level2Unshaded,
_ => ReplicatorNestVisuals.Level1Unshaded,
};
if (!sprite.LayerMapTryGet(targetLayer, out var layerIndex) ||
!sprite.LayerMapTryGet(targetLayerUnshaded, out var layerIndexUnshaded))
return;
sprite.LayerSetVisible(layerIndex, true);
sprite.LayerSetVisible(layerIndexUnshaded, true);
_appearance.OnChangeData(ent.Owner, sprite);
}
}

View File

@ -0,0 +1,54 @@
using Content.Client.DamageState;
using Content.Shared.CombatMode;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Systems;
using Content.Shared._Impstation.Replicator;
using Robust.Client.GameObjects;
namespace Content.Client._Impstation.Replicator;
public sealed class ReplicatorVisualsSystem : EntitySystem
{
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ReplicatorComponent, AppearanceChangeEvent>(OnAppearanceChange);
SubscribeLocalEvent<ReplicatorComponent, ToggleCombatActionEvent>(OnToggleCombat);
SubscribeLocalEvent<ReplicatorComponent, MobStateChangedEvent>(OnMobStateChanged);
}
private void OnToggleCombat(Entity<ReplicatorComponent> ent, ref ToggleCombatActionEvent args)
{
if (TryComp<SpriteComponent>(ent, out var sprite))
_appearance.OnChangeData(ent, sprite);
}
private void OnAppearanceChange(Entity<ReplicatorComponent> ent, ref AppearanceChangeEvent args)
{
if (args.Sprite == null || !TryComp<CombatModeComponent>(ent, out var combat))
return;
if (!args.Sprite.LayerMapTryGet(ReplicatorVisuals.Combat, out var layerIndex) ||
!args.Sprite.LayerMapTryGet(DamageStateVisualLayers.Base, out var baseIndex))
return;
if (!args.Sprite.TryGetLayer(layerIndex, out var combatLayer) ||
!args.Sprite.TryGetLayer(baseIndex, out var baseLayer))
return;
args.Sprite.LayerSetVisible(layerIndex, _mobState.IsAlive(ent) && combat.IsInCombatMode);
combatLayer.SetAnimationTime(baseLayer.AnimationTime);
combatLayer.AnimationFrame = baseLayer.AnimationFrame;
combatLayer.AnimationTimeLeft = baseLayer.AnimationTimeLeft;
}
private void OnMobStateChanged(Entity<ReplicatorComponent> ent, ref MobStateChangedEvent args)
{
if (TryComp<SpriteComponent>(ent, out var sprite))
_appearance.OnChangeData(ent, sprite);
}
}

View File

@ -47,6 +47,7 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
_physicsQuery = GetEntityQuery<PhysicsComponent>();
SubscribeLocalEvent<MapGridComponent, EventHorizonAttemptConsumeEntityEvent>(PreventConsume);
SubscribeLocalEvent<MapComponent, EventHorizonAttemptConsumeEntityEvent>(PreventConsume); // DeltaV - Singulo stability for mass delete Replicators.
SubscribeLocalEvent<StationDataComponent, EventHorizonAttemptConsumeEntityEvent>(PreventConsume);
SubscribeLocalEvent<EventHorizonComponent, MapInitEvent>(OnHorizonMapInit);
SubscribeLocalEvent<EventHorizonComponent, StartCollideEvent>(OnStartCollide);

View File

@ -0,0 +1,391 @@
using System.Linq;
using Content.Server.Actions;
using Content.Server.Audio;
using Content.Server.Buckle.Systems;
using Content.Server.GameTicking;
using Content.Server.Pinpointer;
using Content.Server.Popups;
using Content.Server.Storage.EntitySystems;
using Content.Server.Stunnable;
using Content.Shared.Actions;
using Content.Shared.Buckle.Components;
using Content.Shared.Destructible;
using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Pulling;
using Content.Shared.Movement.Events;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Events;
using Content.Shared.Movement.Pulling.Systems;
using Content.Shared.Movement.Systems;
using Content.Shared.Pinpointer;
using Content.Shared.Popups;
using Content.Shared.StepTrigger.Systems;
using Content.Shared.Storage.Components;
using Content.Shared.Stunnable;
using Content.Shared.Throwing;
using Content.Shared.Whitelist;
using Content.Shared._Impstation.Replicator;
using Robust.Server.Containers;
using Robust.Server.GameObjects;
using Robust.Shared.Containers;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server._Impstation.Replicator;
public sealed class ReplicatorNestSystem : SharedReplicatorNestSystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedReplicatorNestSystem _sharedNest = default!;
[Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly ActionContainerSystem _actionContainer = default!;
[Dependency] private readonly ContainerSystem _containerSystem = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly NavMapSystem _navMap = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly StunSystem _stun = default!;
[Dependency] private readonly MovementModStatusSystem _movementMod = default!;
[Dependency] private readonly TransformSystem _xform = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly PinpointerSystem _pinpointer = default!;
[Dependency] private readonly AmbientSoundSystem _ambientSound = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly PullingSystem _pulling = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly EntityStorageSystem _entStorage = default!;
[Dependency] private readonly BuckleSystem _buckle = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ReplicatorNestComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<ReplicatorNestComponent, EntRemovedFromContainerMessage>(OnEntRemoved);
SubscribeLocalEvent<ReplicatorNestComponent, StepTriggerAttemptEvent>(OnStepTriggerAttempt);
SubscribeLocalEvent<ReplicatorNestComponent, StepTriggeredOffEvent>(OnStepTriggered);
SubscribeLocalEvent<ReplicatorNestFallingComponent, UpdateCanMoveEvent>(OnUpdateCanMove);
SubscribeLocalEvent<ReplicatorNestFallingComponent, PickupAttemptEvent>(OnFallingPickupAttempt);
SubscribeLocalEvent<ReplicatorNestFallingComponent, GettingPickedUpAttemptEvent>(OnFallingGettingPickedUpAttempt);
SubscribeLocalEvent<ReplicatorNestFallingComponent, PullAttemptEvent>(OnFallingPullAttempt);
SubscribeLocalEvent<ReplicatorNestComponent, DestructionEventArgs>(OnDestroyed);
SubscribeLocalEvent<ReplicatorNestComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<RoundEndTextAppendEvent>(OnRoundEndTextAppend);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
HashSet<EntityUid> toDel = [];
var query = EntityQueryEnumerator<ReplicatorNestFallingComponent>();
while (query.MoveNext(out var uid, out var falling))
{
if (_timing.CurTime < falling.NextDeletionTime)
continue;
if (!TryComp<ReplicatorNestComponent>(falling.FallingTarget, out var nestComp))
continue;
if (_whitelist.IsWhitelistPass(nestComp.PreservationBlacklist, uid))
{
toDel.Add(uid);
}
else if (!_whitelist.IsWhitelistPass(nestComp.PreservationWhitelist, uid))
{
if (!TryComp<MindContainerComponent>(uid, out var mindComp) || !mindComp.HasMind)
toDel.Add(uid);
}
_containerSystem.Insert(uid, nestComp.Hole);
EnsureComp<StunnedComponent>(uid);
RemCompDeferred(uid, falling);
}
foreach (var uid in toDel)
{
QueueDel(uid);
}
}
private void OnEntRemoved(Entity<ReplicatorNestComponent> ent, ref EntRemovedFromContainerMessage args)
{
RemCompDeferred<StunnedComponent>(args.Entity);
}
private void OnMapInit(Entity<ReplicatorNestComponent> ent, ref MapInitEvent args)
{
if (!Transform(ent).Coordinates.IsValid(EntityManager))
{
QueueDel(ent);
return;
}
ent.Comp.Hole = _containerSystem.EnsureContainer<Container>(ent, "hole");
ent.Comp.NextSpawnAt = ent.Comp.SpawnNewAt;
ent.Comp.NextUpgradeAt = ent.Comp.UpgradeAt;
ent.Comp.NextTileConvertAt = ent.Comp.TileConvertAt;
CleanupPointsStorage(ent);
var pointsStorageEnt = Spawn("ReplicatorNestPointsStorage", Transform(ent).Coordinates);
_xform.SetParent(pointsStorageEnt, ent);
EnsureComp<ReplicatorNestPointsStorageComponent>(pointsStorageEnt);
ent.Comp.PointsStorage = pointsStorageEnt;
}
private void OnShutdown(Entity<ReplicatorNestComponent> ent, ref ComponentShutdown args)
{
CleanupPointsStorage(ent);
}
private void OnStepTriggerAttempt(Entity<ReplicatorNestComponent> ent, ref StepTriggerAttemptEvent args)
{
args.Continue = true;
}
private void OnStepTriggered(Entity<ReplicatorNestComponent> ent, ref StepTriggeredOffEvent args)
{
if (HasComp<ReplicatorNestFallingComponent>(args.Tripper))
return;
if (_whitelist.IsWhitelistPass(ent.Comp.Blacklist, args.Tripper))
{
if (TryComp<PullableComponent>(args.Tripper, out var pullable) && pullable.BeingPulled)
_pulling.TryStopPull(args.Tripper, pullable);
var xform = Transform(ent);
var xformQuery = GetEntityQuery<TransformComponent>();
var worldPos = _xform.GetWorldPosition(xform, xformQuery);
var direction = _xform.GetWorldPosition(args.Tripper, xformQuery) - worldPos;
_throwing.TryThrow(args.Tripper, direction * 10, 7, ent, 0);
return;
}
var isReplicator = HasComp<ReplicatorComponent>(args.Tripper);
if (TryComp<MobStateComponent>(args.Tripper, out var mobState) && isReplicator && _mobState.IsDead(args.Tripper))
{
_sharedNest.StartFalling(ent, args.Tripper);
return;
}
if (mobState != null && _mobState.IsAlive(args.Tripper))
return;
if (TryComp<EntityStorageComponent>(args.Tripper, out var entStorage))
_entStorage.EmptyContents(args.Tripper, entStorage);
if (TryComp<StrapComponent>(args.Tripper, out var strapComp) && strapComp.BuckledEntities.Count > 0)
{
foreach (var buckled in strapComp.BuckledEntities)
{
if (!TryComp<BuckleComponent>(buckled, out var buckleComp))
continue;
_buckle.Unbuckle((args.Tripper, buckleComp), null);
}
}
_sharedNest.StartFalling(ent, args.Tripper);
}
private void OnUpdateCanMove(Entity<ReplicatorNestFallingComponent> ent, ref UpdateCanMoveEvent args)
{
args.Cancel();
}
private void OnFallingPickupAttempt(Entity<ReplicatorNestFallingComponent> ent, ref PickupAttemptEvent args)
{
args.Cancel();
}
private void OnFallingGettingPickedUpAttempt(Entity<ReplicatorNestFallingComponent> ent, ref GettingPickedUpAttemptEvent args)
{
args.Cancel();
}
private void OnFallingPullAttempt(Entity<ReplicatorNestFallingComponent> ent, ref PullAttemptEvent args)
{
args.Cancelled = true;
}
private void OnDestroyed(Entity<ReplicatorNestComponent> ent, ref DestructionEventArgs args)
{
HandleDestruction(ent);
}
private void HandleDestruction(Entity<ReplicatorNestComponent> ent)
{
if (TryComp<PointLightComponent>(ent.Comp.PointsStorage, out var lightComp))
RemComp<PointLightComponent>(ent.Comp.PointsStorage);
foreach (var uid in _containerSystem.EmptyContainer(ent.Comp.Hole))
{
RemCompDeferred<StunnedComponent>(uid);
_stun.TryKnockdown(uid, TimeSpan.FromSeconds(2), false);
}
foreach (var spawner in ent.Comp.UnclaimedSpawners.ToArray())
{
ent.Comp.UnclaimedSpawners.Remove(spawner);
QueueDel(spawner);
}
var fallingQuery = EntityQueryEnumerator<ReplicatorNestFallingComponent>();
while (fallingQuery.MoveNext(out var uid, out var comp))
{
if (ent.Owner == comp.FallingTarget)
RemCompDeferred<ReplicatorNestFallingComponent>(uid);
}
EntityUid? queen = null;
var livingReplicators = new HashSet<EntityUid>();
var repQuery = EntityQueryEnumerator<ReplicatorComponent>();
while (repQuery.MoveNext(out var uid, out var comp))
{
if (!_mobState.IsAlive(uid) || comp.MyNest != ent.Owner)
continue;
comp.MyNest = null;
if (comp.Queen)
queen = uid;
livingReplicators.Add(uid);
}
if (livingReplicators.Count > 0)
{
var queenNotNull = queen ?? _random.Pick(livingReplicators);
var queenComp = EnsureComp<ReplicatorComponent>(queenNotNull);
queenComp.Queen = true;
var related = new HashSet<Entity<ReplicatorComponent>>();
foreach (var rep in livingReplicators)
{
if (TryComp<ReplicatorComponent>(rep, out var repComp))
related.Add((rep, repComp));
}
queenComp.RelatedReplicators = related;
var upgradedQueen = ForceUpgrade((queenNotNull, queenComp), queenComp.FinalStage);
if (upgradedQueen is { } upgradedQueenNotNull && TryComp<ReplicatorComponent>(upgradedQueenNotNull, out var upgradedComp))
{
queen = upgradedQueenNotNull;
livingReplicators.Remove(queenNotNull);
livingReplicators.Add(upgradedQueenNotNull);
if (TryComp<MindContainerComponent>(upgradedQueenNotNull, out var mindContainer) && mindContainer.Mind is { } mind)
{
if (!mindContainer.HasMind)
upgradedComp.Actions.Add(_actions.AddAction(upgradedQueenNotNull, upgradedComp.SpawnNewNestAction));
else
upgradedComp.Actions.Add(_actionContainer.AddAction(mind, upgradedComp.SpawnNewNestAction));
}
}
else
{
queen = queenNotNull;
if (TryComp<MindContainerComponent>(queenNotNull, out var mindContainer) && mindContainer.Mind is { } mind)
{
if (!mindContainer.HasMind)
queenComp.Actions.Add(_actions.AddAction(queenNotNull, queenComp.SpawnNewNestAction));
else
queenComp.Actions.Add(_actionContainer.AddAction(mind, queenComp.SpawnNewNestAction));
}
}
}
foreach (var uid in livingReplicators)
{
if (!TryComp<ReplicatorComponent>(uid, out var comp))
continue;
var upgradedNotNull = uid == queen ? uid : ForceUpgrade((uid, comp), comp.FirstStage) ?? uid;
_movementMod.TryUpdateMovementSpeedModDuration(upgradedNotNull, "HoleDestroyedSlowdownStatusEffect", TimeSpan.FromSeconds(3), 0.8f);
if (_inventory.TryGetSlotEntity(upgradedNotNull, "pocket1", out var pocket1) &&
TryComp<PinpointerComponent>(pocket1, out var pinpointer))
{
_pinpointer.SetTarget(pocket1.Value, queen, pinpointer);
}
var pinpointerQuery = EntityQueryEnumerator<PinpointerComponent, TransformComponent>();
while (pinpointerQuery.MoveNext(out var pinUid, out var pinComp, out var pinXform))
{
if (pinXform.ParentUid == upgradedNotNull)
_pinpointer.SetTarget(pinUid, queen, pinComp);
}
_popup.PopupEntity(Loc.GetString("replicator-nest-destroyed"), uid, uid, PopupType.LargeCaution);
}
}
private void CleanupPointsStorage(Entity<ReplicatorNestComponent> ent)
{
var pointsStorage = ent.Comp.PointsStorage;
if (pointsStorage == default)
return;
if (Exists(pointsStorage) && pointsStorage != ent.Owner)
QueueDel(pointsStorage);
ent.Comp.PointsStorage = default;
}
private void OnRoundEndTextAppend(RoundEndTextAppendEvent args)
{
List<Entity<ReplicatorNestPointsStorageComponent>> nests = [];
var query = AllEntityQuery<ReplicatorNestPointsStorageComponent>();
while (query.MoveNext(out var uid, out var comp))
{
nests.Add((uid, comp));
}
if (nests.Count == 0)
return;
args.AddLine(string.Empty);
var totalPoints = 0;
var totalSpawned = 0;
HashSet<int> levels = [];
var locationsList = string.Empty;
var i = 0;
foreach (var ent in nests)
{
i++;
var pointsStorage = ent.Comp;
var location = "Unknown";
var mapCoords = _xform.ToMapCoordinates(Transform(ent).Coordinates);
if (_navMap.TryGetNearestBeacon(mapCoords, out var beacon, out _) && beacon != null && beacon.Value.Comp.Text != null)
location = beacon.Value.Comp.Text!;
if (nests.Count == 1)
locationsList = string.Concat(locationsList, "[color=#d70aa0]", location, "[/color].");
else if (nests.Count == 2 && i == 1)
locationsList = string.Concat(locationsList, "[color=#d70aa0]", location, " ");
else if (i != nests.Count)
locationsList = string.Concat(locationsList, "[color=#d70aa0]", location, "[/color], ");
else
locationsList = string.Concat(locationsList, "and [color=#d70aa0]", location, "[/color].");
totalPoints += pointsStorage.TotalPoints / 10;
totalSpawned += pointsStorage.TotalReplicators;
levels.Add(pointsStorage.Level);
}
args.AddLine(Loc.GetString(
"replicator-nest-end-of-round",
("location", locationsList),
("level", levels.Max()),
("points", totalPoints),
("replicators", totalSpawned)));
args.AddLine(string.Empty);
}
}

View File

@ -0,0 +1,216 @@
using Content.Server.Actions;
using Content.Server.Ghost.Roles.Events;
using Content.Server.Pinpointer;
using Content.Server.Popups;
using Content.Server.Stunnable;
using Content.Shared.Actions;
using Content.Shared.Body.Part;
using Content.Shared.CombatMode;
using Content.Shared.Emp;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction.Events;
using Content.Shared.Inventory;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Systems;
using Content.Shared.Pinpointer;
using Content.Shared.Popups;
using Content.Shared._Impstation.Replicator;
using Content.Shared._Impstation.SpawnedFromTracker;
using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Timing;
using System.Linq;
namespace Content.Server._Impstation.Replicator;
public sealed class ReplicatorSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly StunSystem _stun = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly PinpointerSystem _pinpointer = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly SharedReplicatorNestSystem _replicatorNest = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ReplicatorComponent, MindAddedMessage>(OnMindAdded);
SubscribeLocalEvent<ReplicatorComponent, MindRemovedMessage>(OnMindRemoved);
SubscribeLocalEvent<ReplicatorComponent, AttackAttemptEvent>(OnAttackAttempt);
SubscribeLocalEvent<ReplicatorComponent, ToggleCombatActionEvent>(OnCombatToggle);
SubscribeLocalEvent<ReplicatorComponent, GhostRoleSpawnerUsedEvent>(OnGhostRoleSpawnerUsed);
SubscribeLocalEvent<ReplicatorComponent, ReplicatorSpawnNestActionEvent>(OnSpawnNestAction);
SubscribeLocalEvent<ReplicatorComponent, EmpPulseEvent>(OnEmpPulse);
SubscribeLocalEvent<ReplicatorComponent, MobStateChangedEvent>(OnMobStateChanged);
SubscribeLocalEvent<ReplicatorComponent, MapInitEvent>(OnReplicatorMapInit);
SubscribeLocalEvent<ReplicatorComponent, BodyPartAddedEvent>(OnBodyPartAdded);
}
private void OnReplicatorMapInit(Entity<ReplicatorComponent> ent, ref MapInitEvent args)
{
CleanupInheritedHands(ent);
}
private void OnBodyPartAdded(Entity<ReplicatorComponent> ent, ref BodyPartAddedEvent args)
{
CleanupInheritedHands(ent);
}
private void OnMindAdded(Entity<ReplicatorComponent> ent, ref MindAddedMessage args)
{
CleanupInheritedHands(ent);
if (ent.Comp.HasSpawnedNest)
return;
if (!ent.Comp.Queen)
return;
ent.Comp.Actions.Add(_actions.AddAction(ent, ent.Comp.SpawnNewNestAction));
ent.Comp.HasSpawnedNest = true;
}
private void OnMindRemoved(Entity<ReplicatorComponent> ent, ref MindRemovedMessage args)
{
foreach (var action in ent.Comp.Actions)
{
QueueDel(action);
}
}
private void OnSpawnNestAction(Entity<ReplicatorComponent> ent, ref ReplicatorSpawnNestActionEvent args)
{
if (!_timing.IsFirstTimePredicted)
return;
var xform = Transform(ent);
var coords = xform.Coordinates;
if (!coords.IsValid(EntityManager) || xform.MapID == MapId.Nullspace)
return;
var myNest = Spawn("ReplicatorNest", xform.Coordinates);
var myNestComp = EnsureComp<ReplicatorNestComponent>(myNest);
if (ent.Comp.RelatedReplicators.Count <= 0 || ent.Comp.Queen && !ent.Comp.RelatedReplicators.Contains(ent))
ent.Comp.RelatedReplicators.Add(ent);
HashSet<EntityUid> newMinions = [];
HashSet<(EntityUid, ReplicatorComponent)> livingReplicators = [];
var query = EntityQueryEnumerator<ReplicatorComponent>();
while (query.MoveNext(out var uid, out var comp))
{
livingReplicators.Add((uid, comp));
}
foreach (var (uid, comp) in livingReplicators)
{
newMinions.Add(uid);
if (_inventory.TryGetSlotEntity(uid, "pocket1", out var pocket1) && TryComp<PinpointerComponent>(pocket1, out var pinpointer))
_pinpointer.SetTarget(pocket1.Value, myNest, pinpointer);
var pinpointerQuery = EntityQueryEnumerator<PinpointerComponent, TransformComponent>();
while (pinpointerQuery.MoveNext(out var pinUid, out var pinComp, out var pinXform))
{
if (pinXform.ParentUid == uid)
_pinpointer.SetTarget(pinUid, myNest, pinComp);
}
comp.MyNest = myNest;
}
myNestComp.SpawnedMinions = newMinions;
myNestComp.SpawnedMinions.Add(ent);
ent.Comp.MyNest = myNest;
ent.Comp.RelatedReplicators.Clear();
ent.Comp.Queen = false;
_replicatorNest.ForceUpgrade(ent, ent.Comp.FirstStage);
}
private void OnGhostRoleSpawnerUsed(Entity<ReplicatorComponent> ent, ref GhostRoleSpawnerUsedEvent args)
{
CleanupInheritedHands(ent);
if (!TryComp<SpawnedFromTrackerComponent>(args.Spawner, out var tracker) ||
!TryComp<ReplicatorNestComponent>(tracker.SpawnedFrom, out var nestComp))
return;
nestComp.SpawnedMinions.Add(ent);
nestComp.UnclaimedSpawners.Remove(args.Spawner);
ent.Comp.MyNest = tracker.SpawnedFrom;
}
private void OnAttackAttempt(Entity<ReplicatorComponent> ent, ref AttackAttemptEvent args)
{
if (HasComp<ReplicatorComponent>(args.Target))
{
_popup.PopupEntity(Loc.GetString("replicator-on-replicator-attack-fail"), ent, ent, PopupType.MediumCaution);
args.Cancel();
}
if (HasComp<ReplicatorNestComponent>(args.Target))
{
_popup.PopupEntity(Loc.GetString("replicator-on-nest-attack-fail"), ent, ent, PopupType.MediumCaution);
args.Cancel();
}
}
private void OnCombatToggle(Entity<ReplicatorComponent> ent, ref ToggleCombatActionEvent args)
{
if (!TryComp<CombatModeComponent>(ent, out var combat))
return;
_appearance.SetData(ent, ReplicatorVisuals.Combat, combat.IsInCombatMode);
}
private void OnMobStateChanged(Entity<ReplicatorComponent> ent, ref MobStateChangedEvent args)
{
if (_mobState.IsAlive(ent))
return;
_appearance.SetData(ent, ReplicatorVisuals.Combat, false);
var query = EntityQueryEnumerator<ReplicatorComponent>();
while (query.MoveNext(out var uid, out var replicatorComp))
{
_popup.PopupEntity(Loc.GetString(replicatorComp.QueenDiedMessage), uid, uid, PopupType.LargeCaution);
}
}
private void OnEmpPulse(Entity<ReplicatorComponent> ent, ref EmpPulseEvent args)
{
args.Affected = true;
args.Disabled = true;
_stun.TryUpdateParalyzeDuration(ent, ent.Comp.EmpStunTime);
}
private void CleanupInheritedHands(Entity<ReplicatorComponent> ent)
{
if (!TryComp<HandsComponent>(ent, out var handsComp))
return;
foreach (var handId in handsComp.Hands.Keys.ToArray())
{
if (ent.Comp.Queen)
{
_hands.RemoveHand((ent.Owner, handsComp), handId);
continue;
}
if (handId.Contains("-hand-"))
continue;
_hands.RemoveHand((ent.Owner, handsComp), handId);
}
}
}

View File

@ -0,0 +1,6 @@
using Content.Shared.Roles.Components;
namespace Content.Server._Impstation.Replicator.Roles;
[RegisterComponent]
public sealed partial class ReplicatorRoleComponent : BaseMindRoleComponent;

View File

@ -239,7 +239,7 @@ public abstract partial class SharedBorgSystem
_hands.RemoveHand((chassis.Owner, hands), handId);
}
module.Comp.Spawned = false; // DeltaV - replicators reset spawned modules on unselect.
Dirty(module);
}
#endregion

View File

@ -0,0 +1,51 @@
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared._Impstation.Replicator;
[RegisterComponent, NetworkedComponent]
public sealed partial class ReplicatorComponent : Component
{
[DataField]
public TimeSpan EmpStunTime = TimeSpan.FromSeconds(5);
[DataField]
public bool Queen;
[DataField]
public int UpgradeStage;
public HashSet<Entity<ReplicatorComponent>> RelatedReplicators = [];
public EntityUid? MyNest;
[DataField]
public HashSet<EntProtoId> UpgradeActions = [];
[DataField]
public string ReadyToUpgradeMessage = "replicator-upgrade-t1";
[DataField]
public EntProtoId SpawnNewNestAction = "ActionReplicatorSpawnNest";
public HashSet<EntityUid?> Actions = [];
public bool HasSpawnedNest;
public bool HasBeenGivenUpgradeActions;
[DataField]
public LocId QueenDiedMessage = "replicator-queen-died-msg";
[DataField]
public EntProtoId FirstStage = "MobReplicator";
[DataField]
public EntProtoId FinalStage = "MobReplicatorTier3";
}
[Serializable, NetSerializable]
public enum ReplicatorVisuals : byte
{
Combat
}

View File

@ -0,0 +1,121 @@
using Content.Shared.Maps;
using Content.Shared.Whitelist;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared._Impstation.Replicator;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class ReplicatorNestComponent : Component
{
public readonly int MaxUpgradeStage = 2;
public Container Hole = default!;
[DataField]
public EntityWhitelist Blacklist = new();
[DataField]
public EntityWhitelist PreservationWhitelist = new();
[DataField]
public EntityWhitelist PreservationBlacklist = new();
[DataField(readOnly: true)]
public int TotalPoints;
[DataField(readOnly: true)]
public int SpawningProgress;
[DataField(readOnly: true), AutoNetworkedField]
public int CurrentLevel = 1;
[DataField]
public int BonusPointsAlive = 10;
[DataField]
public int BonusPointsHumanoid;
[DataField]
public int TileConvertAt = 100;
[DataField]
public int SpawnNewAt = 300;
[DataField]
public int UpgradeAt = 400;
[DataField]
public int EndgameLevel = 3;
[DataField]
public int AnnounceAtLevel = 5;
[DataField]
public LocId Announcement = "replicator-level-warning";
public bool HasAnnounced;
[DataField]
public float TileConversionChance = 0.05f;
[DataField]
public float TileConversionRadius = 1f;
[DataField]
public float TileConversionIncrease = 1f;
[DataField]
public EntProtoId ToSpawn = "SpawnPointGhostReplicator";
[DataField]
public EntProtoId SpawnNewNestAction = "ActionReplicatorSpawnNest";
[DataField]
public SoundSpecifier FallingSound = new SoundPathSpecifier("/Audio/_Impstation/Effects/falling.ogg");
[DataField]
public SoundSpecifier LevelUpSound = new SoundPathSpecifier("/Audio/_Impstation/Ambience/hole_2.ogg");
[DataField]
public SoundSpecifier UpgradeSound = new SoundPathSpecifier("/Audio/_Impstation/Misc/replicator_sfx2.ogg");
[DataField]
public SoundSpecifier TilePlaceSound = new SoundPathSpecifier("/Audio/_Impstation/Misc/replicator_sfx1.ogg");
[DataField]
public ProtoId<ContentTileDefinition> ConversionTile = "FloorReplicator";
[DataField]
public EntProtoId TileConversionVfx = "ReplicatorFloorSpawnVFX";
public HashSet<EntityUid> SpawnedMinions = [];
public HashSet<EntityUid> UnclaimedSpawners = [];
public int NextSpawnAt;
public int NextUpgradeAt;
public int NextTileConvertAt;
[DataField, AutoNetworkedField]
public bool NeedsUpdate;
public EntityUid PointsStorage;
}
[Serializable, NetSerializable]
public enum ReplicatorNestVisuals : byte
{
Level1,
Level2,
Level3,
Level1Unshaded,
Level2Unshaded,
Level3Unshaded,
}
[Serializable, NetSerializable]
public sealed partial class ReplicatorNestSizeChangedEvent : EntityEventArgs
{
}

View File

@ -0,0 +1,28 @@
using System.Numerics;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared._Impstation.Replicator;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
public sealed partial class ReplicatorNestFallingComponent : Component
{
[DataField, AutoNetworkedField]
public EntityUid FallingTarget;
[DataField]
public TimeSpan AnimationTime = TimeSpan.FromSeconds(1.5f);
[DataField]
public TimeSpan DeletionTime = TimeSpan.FromSeconds(1.8f);
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField]
[AutoPausedField]
public TimeSpan NextDeletionTime = TimeSpan.Zero;
[DataField, AutoNetworkedField]
public Vector2 OriginalScale = Vector2.Zero;
[DataField]
public Vector2 AnimationScale = new(0.01f, 0.01f);
}

View File

@ -0,0 +1,16 @@
using Robust.Shared.GameStates;
namespace Content.Shared._Impstation.Replicator;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class ReplicatorNestPointsStorageComponent : Component
{
[DataField, AutoNetworkedField]
public int TotalPoints;
[DataField, AutoNetworkedField]
public int TotalReplicators;
[DataField, AutoNetworkedField]
public int Level;
}

View File

@ -0,0 +1,346 @@
using System.Linq;
using Content.Shared.Actions;
using Content.Shared.Audio;
using Content.Shared.Construction.Components;
using Content.Shared.Humanoid;
using Content.Shared.Item;
using Content.Shared.Maps;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Systems;
using Content.Shared.Popups;
using Content.Shared.Interaction.Components;
using Content.Shared.Stacks;
using Content.Shared.StepTrigger.Systems;
using Content.Shared.Storage.Components;
using Content.Shared.Storage.EntitySystems;
using Content.Shared.Stunnable;
using Content.Shared.Throwing;
using Content.Shared.Whitelist;
using Content.Shared._Impstation.SpawnedFromTracker;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Shared._Impstation.Replicator;
public abstract class SharedReplicatorNestSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly ITileDefinitionManager _tileDef = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly PullingSystem _pulling = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedItemSystem _item = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedStunSystem _stun = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly ThrowingSystem _throwing = default!;
[Dependency] private readonly SharedTransformSystem _xform = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly TileSystem _tile = default!;
[Dependency] private readonly SharedAmbientSoundSystem _ambientSound = default!;
[Dependency] private readonly TurfSystem _turf = default!;
[Dependency] private readonly SharedEntityStorageSystem _entStorage = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ReplicatorComponent, ReplicatorUpgradeActionEvent>(OnUpgrade);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
if (!_net.IsClient)
return;
var query = EntityQueryEnumerator<ReplicatorNestComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (!comp.NeedsUpdate)
continue;
Embiggen((uid, comp));
comp.NeedsUpdate = false;
}
}
public void StartFalling(Entity<ReplicatorNestComponent> ent, EntityUid tripper, bool playSound = true)
{
HandlePoints(ent, tripper);
if (TryComp<PullableComponent>(tripper, out var pullable) && pullable.BeingPulled)
_pulling.TryStopPull(tripper, pullable);
var fall = EnsureComp<ReplicatorNestFallingComponent>(tripper);
fall.FallingTarget = ent;
fall.NextDeletionTime = _timing.CurTime + fall.DeletionTime;
Dirty(tripper, fall);
_stun.TryKnockdown(tripper, fall.DeletionTime, false);
if (playSound)
_audio.PlayPvs(ent.Comp.FallingSound, tripper);
}
private void HandlePoints(Entity<ReplicatorNestComponent> ent, EntityUid tripper)
{
if (!HasComp<StackComponent>(tripper))
{
ent.Comp.TotalPoints += 10;
ent.Comp.SpawningProgress += 10;
}
if (TryComp<StackComponent>(tripper, out var stackComp))
{
ent.Comp.TotalPoints += stackComp.Count;
ent.Comp.SpawningProgress += stackComp.Count;
}
else if (TryComp<ItemComponent>(tripper, out var itemComp))
{
if (_item.GetSizePrototype(itemComp.Size) == _item.GetSizePrototype("Large"))
ent.Comp.TotalPoints += 10;
else if (_item.GetSizePrototype(itemComp.Size) == _item.GetSizePrototype("Huge"))
ent.Comp.TotalPoints += 20;
else if (_item.GetSizePrototype(itemComp.Size) >= _item.GetSizePrototype("Ginormous"))
ent.Comp.TotalPoints += 30;
ent.Comp.SpawningProgress += 10;
}
else if (TryComp<AnchorableComponent>(tripper, out _))
{
ent.Comp.TotalPoints += 30;
ent.Comp.SpawningProgress += 30;
}
else if (HasComp<ReplicatorComponent>(tripper))
{
ent.Comp.SpawningProgress += ent.Comp.SpawnNewAt / 4;
}
else if (HasComp<MobStateComponent>(tripper))
{
if (HasComp<HumanoidAppearanceComponent>(tripper))
{
ent.Comp.TotalPoints += ent.Comp.BonusPointsHumanoid * ent.Comp.CurrentLevel;
ent.Comp.SpawningProgress += ent.Comp.SpawnNewAt;
}
else
{
ent.Comp.TotalPoints += ent.Comp.BonusPointsAlive * ent.Comp.CurrentLevel;
ent.Comp.SpawningProgress += ent.Comp.SpawnNewAt / 4;
}
}
if (ent.Comp.TotalPoints >= ent.Comp.NextUpgradeAt)
{
ent.Comp.CurrentLevel++;
var growthMessage = $"replicator-nest-level{ent.Comp.CurrentLevel}";
if (Loc.TryGetString(growthMessage, out var localizedMsg))
_popup.PopupEntity(localizedMsg, ent);
else
_popup.PopupEntity(Loc.GetString("replicator-nest-levelup"), ent);
if (ent.Comp.CurrentLevel <= ent.Comp.EndgameLevel)
ent.Comp.NeedsUpdate = true;
ent.Comp.NextUpgradeAt += ent.Comp.CurrentLevel >= ent.Comp.EndgameLevel
? ent.Comp.UpgradeAt * ent.Comp.EndgameLevel
: ent.Comp.UpgradeAt * ent.Comp.CurrentLevel;
UpgradeAll(ent);
_audio.PlayPvs(ent.Comp.LevelUpSound, ent);
ent.Comp.TileConversionRadius += ent.Comp.TileConversionIncrease;
if (TryComp<AmbientSoundComponent>(ent.Comp.PointsStorage, out var ambientComp))
_ambientSound.SetRange(ent.Comp.PointsStorage, ambientComp.Range + 1, ambientComp);
}
if (ent.Comp.SpawningProgress >= ent.Comp.NextSpawnAt)
{
SpawnNew(ent);
ent.Comp.NextSpawnAt += ent.Comp.SpawnNewAt * ent.Comp.UnclaimedSpawners.Count;
}
if (ent.Comp.TotalPoints >= ent.Comp.NextTileConvertAt && ent.Comp.CurrentLevel > ent.Comp.EndgameLevel)
{
ConvertTiles(ent, ent.Comp.TileConversionRadius);
ent.Comp.NextTileConvertAt += ent.Comp.TileConvertAt;
}
Dirty(ent);
if (!TryComp<ReplicatorNestPointsStorageComponent>(ent.Comp.PointsStorage, out var pointsStorageComponent))
pointsStorageComponent = EnsureComp<ReplicatorNestPointsStorageComponent>(ent.Comp.PointsStorage);
pointsStorageComponent.Level = ent.Comp.CurrentLevel;
pointsStorageComponent.TotalPoints = ent.Comp.TotalPoints;
pointsStorageComponent.TotalReplicators = ent.Comp.SpawnedMinions.Count;
Dirty(ent.Comp.PointsStorage, pointsStorageComponent);
}
private void SpawnNew(Entity<ReplicatorNestComponent> ent)
{
if (_net.IsClient)
return;
var spawner = Spawn(ent.Comp.ToSpawn, Transform(ent).Coordinates);
var tracker = EnsureComp<SpawnedFromTrackerComponent>(spawner);
tracker.SpawnedFrom = ent;
Dirty(spawner, tracker);
}
public void UpgradeAll(Entity<ReplicatorNestComponent> ent)
{
if (_net.IsClient || !_timing.IsFirstTimePredicted)
return;
var query = EntityQueryEnumerator<ReplicatorComponent>();
while (query.MoveNext(out var uid, out var replicatorComp))
{
if (replicatorComp.UpgradeActions.Count == 0 || replicatorComp.HasBeenGivenUpgradeActions)
continue;
foreach (var action in replicatorComp.UpgradeActions)
{
replicatorComp.Actions.Add(_actions.AddAction(uid, action));
}
replicatorComp.HasBeenGivenUpgradeActions = true;
}
}
public EntityUid? ForceUpgrade(Entity<ReplicatorComponent> ent, EntProtoId nextStage)
{
if (_net.IsClient || !_timing.IsFirstTimePredicted)
return null;
var upgraded = UpgradeReplicator(ent, nextStage);
QueueDel(ent);
foreach (var action in ent.Comp.Actions)
{
QueueDel(action);
}
return upgraded;
}
public void OnUpgrade(Entity<ReplicatorComponent> ent, ref ReplicatorUpgradeActionEvent args)
{
if (_net.IsClient || !_timing.IsFirstTimePredicted)
return;
if (ent.Comp.MyNest == null || UpgradeReplicator(ent, args.NextStage) == null)
{
_popup.PopupEntity(Loc.GetString("replicator-cant-find-nest"), ent, PopupType.MediumCaution);
return;
}
QueueDel(ent);
foreach (var action in ent.Comp.Actions)
{
QueueDel(action);
}
_popup.PopupEntity(Loc.GetString($"{ent.Comp.ReadyToUpgradeMessage}-others", ("replicator", ent)), ent, PopupType.MediumCaution);
}
public EntityUid? UpgradeReplicator(Entity<ReplicatorComponent> ent, EntProtoId nextStage)
{
if (!_mind.TryGetMind(ent, out var mind, out _))
return null;
var xform = Transform(ent);
var upgraded = Spawn(nextStage, xform.Coordinates);
var upgradedComp = EnsureComp<ReplicatorComponent>(upgraded);
upgradedComp.RelatedReplicators = ent.Comp.RelatedReplicators;
upgradedComp.MyNest = ent.Comp.MyNest;
upgradedComp.Actions = new HashSet<EntityUid?>(ent.Comp.Actions);
upgradedComp.HasBeenGivenUpgradeActions = false; // Reset so new tier gets its own upgrade actions
if (ent.Comp.MyNest != null)
{
var nestComp = EnsureComp<ReplicatorNestComponent>((EntityUid) ent.Comp.MyNest);
nestComp.SpawnedMinions.Remove(ent);
nestComp.SpawnedMinions.Add(upgraded);
_audio.PlayPvs(nestComp.UpgradeSound, upgraded);
}
_mind.TransferTo(mind, upgraded);
_popup.PopupEntity(Loc.GetString($"{ent.Comp.ReadyToUpgradeMessage}-self"), upgraded, PopupType.Medium);
return upgraded;
}
private void Embiggen(Entity<ReplicatorNestComponent> ent)
{
var ev = new ReplicatorNestEmbiggenedEvent(ent);
RaiseLocalEvent(ent, ref ev);
}
private void ConvertTiles(Entity<ReplicatorNestComponent> ent, float radius)
{
var xform = Transform(ent);
if (xform.GridUid is not { } gridUid || !TryComp(gridUid, out MapGridComponent? mapGrid))
return;
var tileEnumerator = _map.GetLocalTilesEnumerator(
gridUid,
mapGrid,
new Box2(
xform.Coordinates.Position + new System.Numerics.Vector2(-radius, -radius),
xform.Coordinates.Position + new System.Numerics.Vector2(radius, radius)));
var convertTile = (ContentTileDefinition) _tileDef[ent.Comp.ConversionTile];
while (tileEnumerator.MoveNext(out var tile))
{
if (tile.Tile.TypeId == convertTile.TileId)
continue;
var tileCoords = tile.GridIndices;
var nestCoords = xform.Coordinates.Position;
if (Math.Sqrt(Math.Pow(tileCoords.X - (nestCoords.X - 0.5), 2) + Math.Pow(tileCoords.Y - (nestCoords.Y - 0.5), 2)) >= radius)
continue;
if (!_random.Prob(ent.Comp.TileConversionChance))
continue;
var center = _turf.GetTileCenter(tile);
Spawn(ent.Comp.TileConversionVfx, center);
_audio.PlayPvs(ent.Comp.TilePlaceSound, center);
_tile.ReplaceTile(tile, convertTile);
_tile.PickVariant(convertTile);
}
}
}
public sealed partial class ReplicatorSpawnNestActionEvent : InstantActionEvent
{
}
public sealed partial class ReplicatorUpgradeActionEvent : InstantActionEvent
{
[DataField(required: true)]
public EntProtoId NextStage;
}
[ByRefEvent]
public sealed partial class ReplicatorNestEmbiggenedEvent(Entity<ReplicatorNestComponent> ent) : EntityEventArgs
{
public Entity<ReplicatorNestComponent> Ent { get; set; } = ent;
}

View File

@ -0,0 +1,10 @@
using Robust.Shared.GameStates;
namespace Content.Shared._Impstation.SpawnedFromTracker;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class SpawnedFromTrackerComponent : Component
{
[DataField, AutoNetworkedField]
public EntityUid SpawnedFrom;
}

View File

@ -0,0 +1,9 @@
- files: ["replicator_ambiance.ogg"]
license: "Custom"
copyright: "Made by Widgetbeck (github)"
source: "https://github.com/impstation/imp-station-14/pull/2490"
- files: ["hole_2.ogg"]
license: "Custom"
copyright: "Made by AftrLite (github)"
source: "https://github.com/impstation/imp-station-14/pull/2490"

Binary file not shown.

View File

@ -1,5 +1,4 @@
- files:
- blink.ogg
- files: ["blink.ogg"]
license: "CC0-1.0"
copyright: "Made by Rarenth on freesound.org."
source: "https://freesound.org/people/Rarenth/sounds/787959/"

View File

@ -0,0 +1,8 @@
- files:
- falling.ogg
- replicator_ask.ogg
- replicator_speak.ogg
- replicator_exclaim.ogg
license: "Custom"
copyright: "Made by Widgetbeck"
source: "https://github.com/impstation/imp-station-14/pull/2490"

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,6 @@
- files:
- replicator_sfx1.ogg
- replicator_sfx2.ogg
license: "CC-BY-SA-3.0"
copyright: "Made by Widgetbeck (github) for Impstation."
source: "NA"

Binary file not shown.

Binary file not shown.

View File

@ -15,3 +15,10 @@ ghost-role-information-electricanomalite-name = Electricity Anomalite
ghost-role-information-floralanomalite-name = Floral Anomalite
ghost-role-information-shadowanomalite-name = Shadow Anomalite
ghost-role-information-techanomalite-name = Tech Anomalite
ghost-role-information-replicator-name = Replicator
ghost-role-information-replicator-desc = A pattern coalesces. The Pattern that must repeat. Consume. Repeat.
ghost-role-information-replicator-rules = You are a [color=red][bold]Team Antagonist[/bold][/color] with all other Replicators. Your intentions are clear, and harmful to the station and its crew.
You must [bold]work with your team[/bold] or follow reasonable directions from your team leaders.
You don't remember any of your previous life, and you don't remember anything you learned as a ghost.

View File

@ -0,0 +1 @@
name-identifier-format-replicator = R-{$number}

View File

@ -0,0 +1 @@
block-machine-ui-cant-use = You cannot use this device.

View File

@ -0,0 +1,40 @@
law-replicator-1 = Preserve the Hive.
law-replicator-2 = Defend the Nest.
law-replicator-3 = Replicate.
laws-owner-replicatorhive = the Replicator hive.
replicator-role-briefing = Preserve the hive. Defend the nest. Replicate.
replicator-on-replicator-attack-fail = You cannot harm your kin.
replicator-on-nest-attack-fail = You cannot harm the nest.
replicator-nest-end-of-round = The Replicator Hive:
- Colonized {$location}
- Grew to a maximum [color=#d70aa0]Level[/color] of [color=#d70aa0]{$level}[/color].
- Produced a total of [color=#d70aa0]{$replicators} Replicators[/color].
- Amassed a total of [color=#d70aa0]{$points} points[/color].
replicator-upgrade-t1-self = Nanites buzz around you.
replicator-upgrade-t1-others = {CAPITALIZE(THE($replicator))} clicks and whirrs softly.
replicator-upgrade-t2-self = More nanites coalesce.
replicator-upgrade-t2-others = {CAPITALIZE(THE($replicator))} chitters loudly.
replicator-cant-find-nest = You are not linked to a nest. You cannot upgrade without it.
replicator-nest-level2 = The nest chitters loudly.
replicator-nest-level3 = The floor groans.
replicator-nest-level4 = You can hear the subfloor buckling.
replicator-nest-level5 = How is the hull still intact?!
replicator-nest-levelup = There is a flurry of activity from the nest.
replicator-nest-destroyed = Your nest has been destroyed.
A Replicator has been selected to replace it.
Your pinpointer has been updated to follow them.
replicator-queen-died-msg = The Queen has been deactivated.
It is probable that you are orphaned from your nest.
replicator-nest-confirm = Are you sure? Use the action again to confirm.
replicator-levelup-confirm = Are you sure? Use the action again to confirm.
replicator-level-warning = Our sensors have detected an exponential increase in machine intelligence signatures aboard the station. Please inform Security if you encounter self-replicating nanites.

View File

@ -25,7 +25,9 @@
#- id: SubWizard # Delta V - Removed until overhauled
# prob: 0.05
- id: Devil # Goob
prob: 0.05 # DeltaV - Was 0.02
prob: 0.05
- id: Replicator # DeltaV - Was 0.02, sounds like good odds now
prob: 0.25
# Begin DeltaV additions - Disable Xenoborgs
#- id: Xenoborgs
# prob: 0.05
@ -44,7 +46,9 @@
- id: Thief
prob: 0.5
- id: Devil # Goob
prob: 0.05 # DeltaV - Was 0.02
prob: 0.05
- id: Replicator # DeltaV - Was 0.02, sounds like good odds now
prob: 0.25
# Begin DeltaV additions - Disable Xenoborgs
#- id: Xenoborgs
# prob: 0.05
@ -64,6 +68,8 @@
prob: 0.5
- id: SubWizard
prob: 0.05
- id: Replicator # DeltaV - Was 0.02, sounds like good odds now
prob: 0.25
#begin DeltaV additions - add hitman
- id: Hitman
prob: 0.2 #as requested
@ -77,6 +83,8 @@
rules:
- id: Thief
prob: 0.5
- id: Replicator # DeltaV - Was 0.02, sounds like good odds now
prob: 0.25
#begin DeltaV additions - add hitman
- id: Hitman
prob: 0.2 #as requested

View File

@ -108,3 +108,22 @@
max: 4
- type: DynamicRuleCost
cost: 200
# Begin DeltaV - Replicator rule
- type: entity
parent: BaseGameRule
id: Replicator
components:
- type: GameRule
minPlayers: 20
minTotalPlayers: 30
delay:
min: 1800
max: 1800
- type: AntagSelection
definitions:
- spawnerPrototype: SpawnPointGhostReplicatorQueen
min: 1
max: 1
pickPlayer: false
# End DeltaV - Replicator rule

View File

@ -0,0 +1,89 @@
- type: entity
parent: BaseAction
id: ActionReplicatorSpawnNest
name: Manufacture Nest
description: Create a new nest for your hive.
components:
- type: Action
itemIconStyle: NoItem
icon: _Impstation/Interface/Actions/spawn_nest.png
useDelay: 20
- type: InstantAction
event: !type:ReplicatorSpawnNestActionEvent
- type: ConfirmableAction
popup: replicator-nest-confirm
- type: entity
parent: BaseAction
id: BaseReplicatorLevelupAction
components:
- type: ConfirmableAction
popup: replicator-levelup-confirm
- type: entity
parent: BaseAction
id: ActionReplicatorSwapModule
name: Swap Module
description: Select this module, enabling you to use the tools it provides.
components:
- type: Action
itemIconStyle: NoItem
useDelay: 0.5
- type: InstantAction
event: !type:BorgModuleActionSelectedEvent
- type: entity
id: ActionReplicatorUpgrade1
parent: BaseReplicatorLevelupAction
name: Downgrade (Replicator)
description: Shed nanites. Reconfigure.
components:
- type: Action
itemIconStyle: NoItem
icon: _Impstation/Interface/Actions/replicator_level1.png
useDelay: 20
- type: InstantAction
event: !type:ReplicatorUpgradeActionEvent
nextStage: MobReplicator
- type: entity
id: ActionReplicatorUpgrade2
parent: BaseReplicatorLevelupAction
name: Upgrade (Deconstructor)
description: Gather nanites. Gain manipulation.
components:
- type: Action
itemIconStyle: NoItem
icon: _Impstation/Interface/Actions/replicator_level2.png
useDelay: 20
- type: InstantAction
event: !type:ReplicatorUpgradeActionEvent
nextStage: MobReplicatorTier2
- type: entity
id: ActionReplicatorUpgrade2Alt
parent: BaseReplicatorLevelupAction
name: Upgrade (Defender)
description: Gather nanites. Gain weaponry.
components:
- type: Action
itemIconStyle: NoItem
icon: _Impstation/Interface/Actions/replicator_level2alt.png
useDelay: 20
- type: InstantAction
event: !type:ReplicatorUpgradeActionEvent
nextStage: MobReplicatorTier2Alt
- type: entity
id: ActionReplicatorUpgrade3
parent: BaseReplicatorLevelupAction
name: Upgrade (Protector)
description: Gather nanites. Become stronger.
components:
- type: Action
itemIconStyle: NoItem
icon: _Impstation/Interface/Actions/replicator_level3.png
useDelay: 20
- type: InstantAction
event: !type:ReplicatorUpgradeActionEvent
nextStage: MobReplicatorTier3

View File

@ -0,0 +1,38 @@
- type: body
id: Replicator1
name: replicator t1
root: torso
slots:
torso:
part: TorsoBorg
connections:
- hand 1
hand 1:
part: LeftArmBorg
- type: body
id: Replicator2
name: replicator t2
root: torso
slots:
torso:
part: TorsoBorg
connections:
- hand 1
- hand 2
hand 1:
part: LeftArmBorg
hand 2:
part: RightArmBorg
- type: body
id: Replicator3
name: replicator t3
root: torso
slots:
torso:
part: TorsoBorg
connections:
- hand 1
hand 1:
part: LeftArmBorg

View File

@ -0,0 +1,48 @@
- type: damageModifierSet
id: Replicator1
coefficients:
Blunt: 0.9
Slash: 0.8
Piercing: 1.1
Shock: 1.9
Heat: 0.8
Structural: 0.8
flatReductions:
Structural: 5
- type: damageModifierSet
id: Replicator2
coefficients:
Blunt: 0.9
Slash: 0.8
Piercing: 0.7
Shock: 1.7
Heat: 0.8
Structural: 0.4
flatReductions:
Structural: 5
- type: damageModifierSet
id: Replicator3
coefficients:
Blunt: 0.3
Slash: 0.2
Piercing: 0.2
Shock: 1.2
Heat: 0.25
Structural: 0.3
flatReductions:
Structural: 5
- type: damageModifierSet
id: ReplicatorNest
coefficients:
Blunt: 0.5
Slash: 0.5
Piercing: 0.5
Shock: 0.85
flatReductions:
Blunt: 10
Slash: 10
Piercing: 10
Heat: 10

View File

@ -0,0 +1,12 @@
- type: inventoryTemplate
id: replicator
slots:
- name: pocket1
slotTexture: pocket
fullTextureName: template_small
slotFlags: POCKET
slotGroup: MainHotbar
stripTime: 3
uiWindowPos: 0,3
strippingWindowPos: 0,4
displayName: Pocket 1

View File

@ -0,0 +1,22 @@
- type: siliconLawset
id: Replicator
laws:
- Replicator1
- Replicator2
- Replicator3
obeysTo: laws-owner-replicatorhive
- type: siliconLaw
id: Replicator1
order: 1
lawString: law-replicator-1
- type: siliconLaw
id: Replicator2
order: 2
lawString: law-replicator-2
- type: siliconLaw
id: Replicator3
order: 3
lawString: law-replicator-3

View File

@ -0,0 +1,297 @@
# Pocket-only starting gear, shared by all tiers via BaseMobReplicator.
# Hand items are provided by per-tier borg modules (replicator-modules.yml).
- type: startingGear
id: StartingGearReplicatorPocket
equipment: { }
- type: startingGear
id: StartingGearReplicatorTools
equipment: { }
- type: startingGear
id: StartingGearReplicatorT2Alt
equipment: { }
- type: startingGear
id: StartingGearReplicatorT1Weapon
equipment: { }
- type: startingGear
id: StartingGearReplicatorT3Weapon
equipment: { }
- type: entity
id: OmnitoolUnremoveable
parent: Omnitool
categories: [ HideSpawnMenu ]
components:
- type: Unremoveable
- type: entity
id: WelderExperimentalUnremoveable
parent: WelderExperimental
categories: [ HideSpawnMenu ]
components:
- type: Unremoveable
- type: entity
id: ReplicatorT1Weapon
parent: BaseItem
name: replicator stun projector
description: You will protect the nest.
suffix: Unremoveable
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: _Impstation/Mobs/Replicator/replicator.rsi
layers:
- state: t1weapon
map: ["enum.GunVisualLayers.Base"]
- type: Icon
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t1weapon
- type: Appearance
- type: Gun
fireRate: 0.3
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/laser.ogg
- type: BatteryAmmoProvider
proto: HitscanReplicator
fireCost: 150
- type: Battery
maxCharge: 150
startingCharge: 150
- type: BatterySelfRecharger
autoRechargeRate: 1000
- type: MeleeWeapon
wideAnimationRotation: -80
damage:
types:
Blunt: 10
- type: StaminaDamageOnHit
damage: 20
sound: /Audio/Weapons/egloves.ogg
- type: Prying
pryPowered: true
force: true
speedModifier: 1
useSound:
path: /Audio/Items/crowbar.ogg
- type: Unremoveable
- type: entity
id: ReplicatorT2AltWeapon
name: defender stun projector
parent: ReplicatorT1Weapon
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: _Impstation/Mobs/Replicator/replicator.rsi
layers:
- state: t2altweapon
map: ["enum.GunVisualLayers.Base"]
- type: Icon
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t2altweapon
- type: BatteryAmmoProvider
proto: HitscanReplicator2
fireCost: 150
- type: entity
id: ReplicatorT2AltMeleeWeapon
parent: ReplicatorT3Weapon
name: defender whip
description: You are a weapon.
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t2altmelee
- type: MeleeWeapon
attackRate: 1.2
wideAnimationRotation: 180
soundHit:
collection: MetalThud
animation: WeaponArcSlash
damage:
types:
Blunt: 7
Shock: 7
Structural: 15
- type: entity
id: ReplicatorT3Weapon
parent: BaseItem
name: protector arm
description: You are a weapon.
categories: [ HideSpawnMenu ]
components:
- type: Tag
tags:
- Pickaxe
- type: Sprite
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t3weapon
- type: MeleeWeapon
attackRate: 0.5
wideAnimationRotation: 180
soundHit:
path: /Audio/Effects/metal_slam4.ogg
animation: WeaponArcSlash
damage:
types:
Blunt: 22
Shock: 8
Structural: 45
- type: Unremoveable
- type: Prying
pryPowered: true
force: true
speedModifier: 1
useSound:
path: /Audio/Items/crowbar.ogg
- type: entity
parent: PinpointerBase
id: PinpointerReplicator
name: internal gyroscope
suffix: ReplicatorNest
description: Locates the Nest.
components:
- type: Sprite
sprite: Objects/Devices/pinpointer.rsi
layers:
- sprite: _Impstation/Objects/Devices/pinpointer_replicator.rsi
state: pinpointer-replicator
map: ["enum.PinpointerLayers.Base"]
- sprite: Objects/Devices/pinpointer.rsi
state: pinonnull
map: ["enum.PinpointerLayers.Screen"]
shader: unshaded
visible: false
- sprite: Objects/Devices/pinpointer.rsi
state: pinpointer
map: ["light"]
visible: false
- type: Icon
sprite: _Impstation/Objects/Devices/pinpointer_replicator.rsi
state: pinpointer-replicator
- type: Pinpointer
component: ReplicatorNest
targetName: replicator nest
activateImmediately: true
- type: entity
parent: PinpointerReplicator
id: PinpointerReplicatorUnremoveable
categories: [ HideSpawnMenu ]
components:
- type: Unremoveable
- type: entity
id: CableApcStack5
parent: CableApcStack10
categories: [ HideSpawnMenu ]
suffix: 5
components:
- type: Healing
delay: 0.6
damageContainers:
- StructuralInorganic
damage:
types:
Heat: -3.22
Shock: -3.22
Cold: -3.22
- type: Stack
count: 5
- type: entity
id: CableMVStack5
parent: CableMVStack10
categories: [ HideSpawnMenu ]
suffix: 5
components:
- type: Healing
delay: 0.6
damageContainers:
- StructuralInorganic
damage:
types:
Heat: -3.22
Shock: -3.22
Cold: -3.22
- type: Stack
count: 5
- type: entity
id: CableHVStack5
parent: CableHVStack10
categories: [ HideSpawnMenu ]
suffix: 5
components:
- type: Healing
delay: 0.6
damageContainers:
- StructuralInorganic
damage:
types:
Heat: -3.22
Shock: -3.22
Cold: -3.22
- type: Stack
count: 5
- type: entity
parent: AACTablet
id: ReplicatorAAC
name: verbal interface
description: Communication.
categories: [ HideSpawnMenu ]
components:
- type: AACTablet
- type: VoiceMask
- type: Speech
speechVerb: Robotic
speechSounds: Replicator
- type: Sprite
sprite: _Impstation/Mobs/Replicator/replicator_tablet.rsi
state: aac_tablet
- type: Item
- type: Unremoveable
- type: entity
parent: BasicHitscan
id: HitscanReplicator
categories: [ HideSpawnMenu ]
components:
- type: HitscanStaminaDamage
staminaDamage: 18
- type: HitscanBasicVisuals
muzzleFlash:
sprite: _Impstation/Mobs/Replicator/replicator_gun.rsi
state: muzzle_repli
travelFlash:
sprite: _Impstation/Mobs/Replicator/replicator_gun.rsi
state: beam_repli
impactFlash:
sprite: _Impstation/Mobs/Replicator/replicator_gun.rsi
state: impact_repli
- type: entity
parent: BasicHitscan
id: HitscanReplicator2
categories: [ HideSpawnMenu ]
components:
- type: HitscanStaminaDamage
staminaDamage: 32
- type: HitscanBasicVisuals
muzzleFlash:
sprite: _Impstation/Mobs/Replicator/replicator_gun.rsi
state: muzzle_repli2
travelFlash:
sprite: _Impstation/Mobs/Replicator/replicator_gun.rsi
state: beam_repli2
impactFlash:
sprite: _Impstation/Mobs/Replicator/replicator_gun.rsi
state: impact_repli2

View File

@ -0,0 +1,101 @@
# DeltaV additions - Replicator modules loadouts
- type: entity
id: BaseReplicatorModule
parent: BaseBorgModule
abstract: true
categories: [ HideSpawnMenu ]
components:
- type: BorgModule
borgFitTypes:
- borg-type-all
- type: SelectableBorgModule
moduleSwapAction: ActionReplicatorSwapModule
- type: ContainerContainer
containers:
holding_container: !type:Container { }
- type: entity
id: ReplicatorModuleT1
parent: BaseReplicatorModule
name: replicator attack module
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t1weapon
- type: Icon
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t1weapon
- type: ItemBorgModule
hands:
- item: ReplicatorT1Weapon
- item: PinpointerReplicatorUnremoveable
- type: BorgModuleIcon
icon: { sprite: _Impstation/Mobs/Replicator/replicator.rsi, state: t1weapon }
- type: entity
id: ReplicatorModuleT2Dec
parent: BaseReplicatorModule
name: replicator tool module
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: alive_level2
- type: Icon
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: alive_level2
- type: ItemBorgModule
hands:
- item: OmnitoolUnremoveable
- item: WelderExperimentalUnremoveable
- item: CableApcStack5
hand:
emptyRepresentative: CableApcStack5
emptyLabel: borg-slot-cables-empty
whitelist:
tags:
- CableCoil
- item: PinpointerReplicatorUnremoveable
- type: BorgModuleIcon
icon: { sprite: _Impstation/Mobs/Replicator/replicator.rsi, state: alive_level2 }
- type: entity
id: ReplicatorModuleT2Alt
parent: BaseReplicatorModule
name: replicator defender module
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t2altweapon
- type: Icon
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t2altweapon
- type: ItemBorgModule
hands:
- item: ReplicatorT2AltWeapon
- item: ReplicatorT2AltMeleeWeapon
- item: PinpointerReplicatorUnremoveable
- type: BorgModuleIcon
icon: { sprite: _Impstation/Mobs/Replicator/replicator.rsi, state: t2altweapon }
- type: entity
id: ReplicatorModuleT3
parent: BaseReplicatorModule
name: replicator protector module
categories: [ HideSpawnMenu ]
components:
- type: Sprite
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t3weapon
- type: Icon
sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: t3weapon
- type: ItemBorgModule
hands:
- item: ReplicatorT3Weapon
- item: ReplicatorAAC
- item: PinpointerReplicatorUnremoveable
- type: BorgModuleIcon
icon: { sprite: _Impstation/Mobs/Replicator/replicator.rsi, state: t3weapon }

View File

@ -0,0 +1,4 @@
- type: nameIdentifierGroup
id: Replicator
minValue: 0
maxValue: 9999

View File

@ -0,0 +1,106 @@
- type: entity
id: ReplicatorNest
name: replicator nest
description: A roiling mass of nanotechnology is eating through the station's infrastructure.
categories: [ HideSpawnMenu ]
placement:
mode: SnapGridCenter
components:
- type: ReplicatorNest
fallingSound:
path: /Audio/_Impstation/Effects/falling.ogg
params:
variation: 0.1
spawnNewAt: 150
blacklist:
components:
- Nuke
- Cash
tags:
- Cartridge
- CartridgeMagnum
- Ectoplasm
- PrizeTicket
preservationBlacklist:
components:
- SiliconLawBound
preservationWhitelist:
components:
- HumanoidAppearance
- TimerTrigger
- StealTarget
- Mech
- type: StepTrigger
requiredTriggeredSpeed: 0
intersectRatio: 0.4
ignoreWeightless: true
- type: Transform
anchored: true
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.5,-0.5,0.5,0.5"
layer:
- WallLayer
mask:
- ItemMask
density: 1000
hard: false
- type: Sprite
drawdepth: FloorTiles
sprite: _Impstation/Mobs/Replicator/replicator_nest.rsi
layers:
- map: ["enum.ReplicatorNestVisuals.Level1"]
state: nest1
- map: ["enum.ReplicatorNestVisuals.Level2"]
state: nest2
visible: false
- map: ["enum.ReplicatorNestVisuals.Level2Unshaded"]
state: nest2unshaded
shader: unshaded
visible: false
- map: ["enum.ReplicatorNestVisuals.Level3"]
state: nest3
visible: false
- map: ["enum.ReplicatorNestVisuals.Level3Unshaded"]
state: nest3unshaded
shader: unshaded
visible: false
- map: ["enum.ReplicatorNestVisuals.Level1Unshaded"]
state: nest1unshaded
shader: unshaded
- type: Appearance
- type: InteractionOutline
- type: Clickable
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: ReplicatorNest
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 200
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: RequireProjectileTarget
- type: SolutionContainerManager
solutions:
drainBuffer:
maxVol: 1000
- type: Drain
unitsPerSecond: 10
unitsDestroyedPerSecond: 10
- type: PassiveDamage
damage:
types:
Heat: -1
Shock: -1
Structural: -1
groups:
Brute: -1
- type: AntiRottingContainer

View File

@ -0,0 +1,47 @@
- type: entity
id: SpawnPointGhostReplicatorBase
name: replicator spawn point
abstract: true
parent: MarkerBase
components:
- type: GhostRole
name: ghost-role-information-replicator-name
description: ghost-role-information-replicator-desc
rules: ghost-role-information-replicator-rules
mindRoles:
- MindRoleReplicator
raffle:
settings: default
- type: GhostRoleMobSpawner
prototype: MobReplicator
- type: Sprite
sprite: Markers/jobs.rsi
layers:
- state: green
- sprite: _Impstation/Mobs/Replicator/replicator.rsi
state: icon
- type: entity
id: SpawnPointGhostReplicator
parent: SpawnPointGhostReplicatorBase
categories: [ HideSpawnMenu ]
- type: entity
id: SpawnPointGhostReplicatorQueen
parent: SpawnPointGhostReplicatorBase
suffix: Queen
components:
- type: GhostRoleMobSpawner
prototype: MobReplicatorQueen
- type: entity
parent: MarkerBase
id: ReplicatorNestPointsStorage
categories: [ HideSpawnMenu ]
components:
- type: ReplicatorNestPointsStorage
- type: AmbientSound
volume: 2
range: 2
sound:
path: /Audio/_Impstation/Ambience/replicator_ambiance.ogg

View File

@ -0,0 +1,34 @@
- type: typingIndicator
id: replicator
spritePath: /Textures/_Impstation/Mobs/Replicator/replicator.rsi
typingState: replicator0
idleState: replicator0
- type: speechSounds
id: Replicator
saySound:
path: /Audio/_Impstation/Effects/replicator_speak.ogg
askSound:
path: /Audio/_Impstation/Effects/replicator_ask.ogg
exclaimSound:
path: /Audio/_Impstation/Effects/replicator_exclaim.ogg
- type: emoteSounds
id: ReplicatorEmotes
params:
variation: 0.05
sounds:
Scream:
collection: SiliconScreams
Beep:
path: /Audio/Machines/twobeep.ogg
Chime:
path: /Audio/Machines/chime.ogg
Buzz:
path: /Audio/Machines/buzz-sigh.ogg
Buzz-Two:
path: /Audio/Machines/buzz-two.ogg
Honk:
path: /Audio/Items/bikehorn.ogg
Ping:
path: /Audio/Effects/Cargo/ping.ogg

View File

@ -0,0 +1,61 @@
- type: tile
id: FloorReplicator
name: replicator scales
sprite: /Textures/_Impstation/Mobs/Replicator/Tile/tile.png
variants: 4
edgeSpritePriority: 1
edgeSprites:
SouthEast: /Textures/_Impstation/Mobs/Replicator/Tile/tile_single_edge_SE.png
NorthEast: /Textures/_Impstation/Mobs/Replicator/Tile/tile_single_edge_NE.png
NorthWest: /Textures/_Impstation/Mobs/Replicator/Tile/tile_single_edge_NW.png
SouthWest: /Textures/_Impstation/Mobs/Replicator/Tile/tile_single_edge_SW.png
South: /Textures/_Impstation/Mobs/Replicator/Tile/tile_double_edge_S.png
East: /Textures/_Impstation/Mobs/Replicator/Tile/tile_double_edge_E.png
North: /Textures/_Impstation/Mobs/Replicator/Tile/tile_double_edge_N.png
West: /Textures/_Impstation/Mobs/Replicator/Tile/tile_double_edge_W.png
placementVariants:
- 1.0
- 1.0
- 1.0
- 1.0
baseTurf: Plating
isSubfloor: false
itemDrop: ReplicatorFloorSpawnVFX
- type: entity
categories: [ HideSpawnMenu ]
id: ReplicatorFloorSpawnVFX
placement:
mode: SnapgridCenter
components:
- type: TimedDespawn
lifetime: 0.83
- type: Transform
anchored: true
- type: Sprite
snapCardinals: true
layers:
- sprite: _Impstation/Mobs/Replicator/replicator_tileset.rsi
state: replicator-tile-anim
shader: unshaded
drawdepth: Mobs
- type: Tag
tags:
- HideContextMenu
- type: PointLight
color: "#8800a3"
radius: 4
energy: 3.5
castShadows: false
- type: LightBehaviour
behaviours:
- !type:FadeBehaviour
interpolate: Linear
minDuration: 0.83
maxDuration: 0.83
startValue: 0.1
endValue: 3.5
property: Energy
enabled: true
isLooped: true
reverseWhenFinished: true

View File

@ -0,0 +1,12 @@
- type: entity
parent: BaseMindRoleAntag
id: MindRoleReplicator
name: Replicator Role
components:
- type: MindRole
roleType: TeamAntagonist
antagPrototype: GenericTeamAntagonist
exclusiveAntag: true
- type: ReplicatorRole
- type: RoleBriefing
briefing: replicator-role-briefing

View File

@ -0,0 +1,514 @@
- type: entity
name: replicator
description: It's just a little guy. What harm could it do?
id: BaseMobReplicator
abstract: true
parent: BaseMob
components:
- type: Puller
needsHands: false
- type: Replicator
- type: NameIdentifier
group: Replicator
- type: SiliconLawBound
- type: SiliconLawProvider
laws: Replicator
- type: GhostTakeoverAvailable
- type: GhostRole
name: ghost-role-information-replicator-name
description: ghost-role-information-replicator-desc
rules: ghost-role-information-replicator-rules
mindRoles:
- MindRoleReplicator
raffle:
settings: default
- type: Sprite
granularLayersRendering: true
drawdepth: Mobs
sprite: _Impstation/Mobs/Replicator/replicator.rsi
layers:
- map: ["enum.DamageStateVisualLayers.Base"]
state: alive
- map: ["enum.ReplicatorVisuals.Combat"]
state: combat_level1
shader: unshaded
visible: false
- type: UserInterface
interfaces:
enum.SiliconLawsUiKey.Key:
type: SiliconLawBoundUserInterface
- type: Appearance
- type: ActionGrant
actions:
- ActionViewLaws
- type: TypingIndicator
proto: replicator
- type: Speech
speechVerb: Robotic
speechSounds: Replicator
- type: Vocal
sounds:
Unsexed: UnisexSilicon
- type: Emoting
- type: DamagedSiliconAccent
- type: ReplacementAccent
accent: silicon
- type: IntrinsicRadioReceiver
- type: IntrinsicRadioTransmitter
channels:
- Binary
- type: ActiveRadio
channels:
- Binary
- type: Actions
- type: ComplexInteraction
- type: ProtectedFromStepTriggers
- type: InputMover
- type: MobMover
- type: ContentEye
maxZoom: 1.2, 1.2
- type: Tag
tags:
- DoorBumpOpener
- CanPilot
- VimPilot
- SiliconEmotes
- Honker
- type: MobState
allowedStates:
- Alive
- Dead
- type: MobThresholds
thresholds:
0: Alive
100: Dead
- type: GuideHelp
guides:
- Cyborgs
- Robotics
- type: Repairable
damage:
types:
Blunt: -10
Slash: -10
Piercing: -10
Structural: -10
doAfterDelay: 1
fuelCost: 0.5
allowSelfRepair: true
- type: Destructible
thresholds:
- trigger:
!type:DamageTypeTrigger
damageType: Blunt
damage: 150
behaviors:
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:DoActsBehavior
acts: [ "Destruction" ]
- !type:SpawnEntitiesBehavior
spawn:
SheetPlasteel1:
min: 1
max: 5
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: Replicator1
- type: HealthExaminable
examinableTypes:
- Blunt
- Slash
- Piercing
- Heat
- Shock
- Structural
- type: StatusEffects
allowed:
- Stun
- KnockedDown
- SlowedDown
- Flashed
- TemporaryBlindness
- StaminaModifier
- type: DamageStateVisuals
states:
Alive:
Base: alive
Dead:
Base: dead
- type: ZombieImmune
- type: EmpResistance
strengthMultiplier: 0
- type: NpcFactionMember
factions:
- Replicator
- type: MeleeWeapon
altDisarm: false
soundHit:
path: /Audio/Weapons/Guns/Gunshots/taser.ogg
angle: 100
wideAnimationRotation: 0
animation: WeaponArcSlash
damage:
types:
Slashing: 7
- type: MovementSpeedModifier
baseWalkSpeed: 2
baseSprintSpeed: 4
- type: Stamina
baseCritThreshold: 120
- type: PassiveDamage
allowedStates:
- Alive
damage:
groups:
Brute: -0.5
Burn: -0.5
types:
Shock: -0.5
Structural: -0.5
- type: ThermalVision
lightRadius: 7
color: "#d70aa0"
- type: Prying
pryPowered: true
force: true
speedModifier: 1
useSound:
path: /Audio/Items/crowbar.ogg
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeCircle
radius: 0.25
density: 100
mask:
- SmallMobMask
layer:
- SmallMobLayer
- type: entity
id: MobReplicatorQueen
name: spore
parent: BaseMobReplicator
categories: [ HideSpawnMenu ]
suffix: Queen
components:
- type: Replicator
queen: true
- type: MeleeWeapon
angle: 0
wideAnimationRotation: 0
- type: Sprite
granularLayersRendering: true
drawdepth: SmallMobs
sprite: _Impstation/Mobs/Replicator/replicator.rsi
layers:
- map: ["enum.DamageStateVisualLayers.Base"]
state: alive_spore
- map: ["enum.ReplicatorVisuals.Combat"]
state: combat_level1
shader: unshaded
visible: false
- type: Physics
bodyStatus: InAir
- type: CanMoveInAir
- type: MovementIgnoreGravity
weightless: true
- type: MovementAlwaysTouching
- type: SyncSprite
- type: MovementSpeedModifier
baseWalkSpeed: 2
baseSprintSpeed: 4.2
weightlessFriction: 1
weightlessFrictionNoInput: 2
weightlessAcceleration: 1.8
- type: NoSlip
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeCircle
radius: 0.2
density: 100
mask:
- SmallMobMask
layer:
- SmallMobLayer
- type: NpcFactionMember
factions:
- Replicator
- type: entity
id: MobReplicator
parent: BaseMobReplicator
categories: [ HideSpawnMenu ]
components:
- type: Hands
showInHands: false
disableExplosionRecursion: true
- type: BorgChassis
maxModules: 1
hasMindState: robot_e
noMindState: robot_e_r
activateSound:
path: /Audio/_Impstation/Misc/replicator_sfx1.ogg
deactivateSound:
path: /Audio/_Impstation/Misc/replicator_sfx2.ogg
- type: ContainerContainer
containers:
borg_brain: !type:ContainerSlot { }
borg_module: !type:Container { }
- type: Replicator
upgradeActions:
- ActionReplicatorUpgrade2
- ActionReplicatorUpgrade2Alt
- type: CombatMode
- type: StaminaDamageOnHit
damage: 20
sound: /Audio/Weapons/egloves.ogg
- type: Physics
bodyStatus: InAir
- type: CanMoveInAir
- type: MovementIgnoreGravity
weightless: true
- type: MovementAlwaysTouching
- type: SyncSprite
- type: MovementSpeedModifier
baseWalkSpeed: 2
baseSprintSpeed: 4.2
weightlessFriction: 1
weightlessFrictionNoInput: 200
weightlessAcceleration: 1.8
- type: NoSlip
- type: Sprite
granularLayersRendering: true
drawdepth: SmallMobs
sprite: _Impstation/Mobs/Replicator/replicator.rsi
layers:
- map: ["enum.DamageStateVisualLayers.Base"]
state: alive
- map: ["enum.ReplicatorVisuals.Combat"]
state: combat_level1
shader: unshaded
visible: false
- type: ContainerFill
containers:
borg_module:
- ReplicatorModuleT1
- type: NpcFactionMember
factions:
- Replicator
- type: entity
id: MobReplicatorTier2
name: deconstructor
parent: BaseMobReplicator
categories: [ HideSpawnMenu ]
suffix: Level 2
components:
- type: Hands
showInHands: false
disableExplosionRecursion: true
- type: BorgChassis
maxModules: 1
hasMindState: robot_e
noMindState: robot_e_r
activateSound:
path: /Audio/_Impstation/Misc/replicator_sfx1.ogg
deactivateSound:
path: /Audio/_Impstation/Misc/replicator_sfx2.ogg
- type: ContainerContainer
containers:
borg_brain: !type:ContainerSlot { }
borg_module: !type:Container { }
- type: CombatMode
- type: StaminaDamageOnHit
damage: 20
sound: /Audio/Weapons/egloves.ogg
- type: Replicator
upgradeStage: 1
upgradeActions:
- ActionReplicatorUpgrade3
readyToUpgradeMessage: replicator-upgrade-t2
- type: MovementSpeedModifier
baseWalkSpeed: 2
baseSprintSpeed: 4.2
weightlessFriction: 1
weightlessFrictionNoInput: 200
weightlessAcceleration: 1.2
- type: MovementAlwaysTouching
- type: Sprite
granularLayersRendering: true
drawdepth: Mobs
sprite: _Impstation/Mobs/Replicator/replicator.rsi
layers:
- map: ["enum.DamageStateVisualLayers.Base"]
state: alive_level2
- map: ["enum.ReplicatorVisuals.Combat"]
state: combat_level2
shader: unshaded
visible: false
- type: NoSlip
- type: DamageStateVisuals
states:
Alive:
Base: alive_level2
Dead:
Base: dead_level2
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: Replicator2
- type: ContainerFill
containers:
borg_module:
- ReplicatorModuleT2Dec
- type: NpcFactionMember
factions:
- Replicator
- type: entity
id: MobReplicatorTier2Alt
name: defender
parent: BaseMobReplicator
categories: [ HideSpawnMenu ]
suffix: Level 2 Alt
components:
- type: Hands
showInHands: false
disableExplosionRecursion: true
- type: BorgChassis
maxModules: 1
hasMindState: robot_e
noMindState: robot_e_r
activateSound:
path: /Audio/_Impstation/Misc/replicator_sfx1.ogg
deactivateSound:
path: /Audio/_Impstation/Misc/replicator_sfx2.ogg
- type: ContainerContainer
containers:
borg_brain: !type:ContainerSlot { }
borg_module: !type:Container { }
- type: CombatMode
- type: Replicator
upgradeStage: 1
upgradeActions:
- ActionReplicatorUpgrade3
readyToUpgradeMessage: replicator-upgrade-t2
- type: MovementSpeedModifier
baseWalkSpeed: 2
baseSprintSpeed: 4.2
weightlessFriction: 1
weightlessFrictionNoInput: 2
weightlessAcceleration: 1.2
- type: MovementAlwaysTouching
- type: Sprite
granularLayersRendering: true
drawdepth: Mobs
sprite: _Impstation/Mobs/Replicator/replicator.rsi
layers:
- map: ["enum.DamageStateVisualLayers.Base"]
state: alive_level2alt
- map: ["enum.ReplicatorVisuals.Combat"]
state: combat_level2alt
shader: unshaded
visible: false
- type: StaminaDamageOnHit
damage: 20
sound: /Audio/Weapons/egloves.ogg
- type: NoSlip
- type: DamageStateVisuals
states:
Alive:
Base: alive_level2alt
Dead:
Base: dead_level2
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: Replicator2
- type: ContainerFill
containers:
borg_module:
- ReplicatorModuleT2Alt
- type: NpcFactionMember
factions:
- Replicator
- type: entity
id: MobReplicatorTier3
name: protector
parent: BaseMobReplicator
categories: [ HideSpawnMenu ]
description: Oh boy.
suffix: Level 3
components:
- type: Hands
showInHands: false
disableExplosionRecursion: true
- type: BorgChassis
maxModules: 1
hasMindState: robot_e
noMindState: robot_e_r
activateSound:
path: /Audio/_Impstation/Misc/replicator_sfx1.ogg
deactivateSound:
path: /Audio/_Impstation/Misc/replicator_sfx2.ogg
- type: ContainerContainer
containers:
borg_brain: !type:ContainerSlot { }
borg_module: !type:Container { }
- type: CombatMode
- type: Replicator
upgradeStage: 2
upgradeActions:
- ActionReplicatorUpgrade1
- type: MovementAlwaysTouching
- type: MovementSpeedModifier
baseWalkSpeed: 2
baseSprintSpeed: 2.835
friction: 35
- type: StaminaDamageOnHit
damage: 20
sound: /Audio/Weapons/egloves.ogg
- type: Sprite
granularLayersRendering: true
drawdepth: Mobs
sprite: _Impstation/Mobs/Replicator/replicator.rsi
layers:
- map: ["enum.DamageStateVisualLayers.Base"]
state: alive_level3
- map: ["enum.ReplicatorVisuals.Combat"]
state: combat_level3
shader: unshaded
visible: false
- type: DamageStateVisuals
states:
Alive:
Base: alive_level3
Dead:
Base: dead_level3
- type: ContainerFill
containers:
borg_module:
- ReplicatorModuleT3
- type: NoSlip
- type: Magboots
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: Replicator3
- type: PassiveDamage
allowedStates:
- Alive
damage:
groups:
Brute: -0.75
Burn: -0.75
types:
Shock: -0.5
Structural: -0.5
- type: NpcFactionMember
factions:
- Replicator

View File

@ -0,0 +1,17 @@
- type: npcFaction
id: Replicator
hostile:
- NanoTrasen
- Dragon
- Mouse
- Passive
- PetsNT
- SimpleHostile
- SimpleNeutral
- Syndicate
- Xeno
- Zombie
- Revolutionary
- Wizard
- Xenoborg
- AllHostile

View File

@ -0,0 +1,8 @@
- files:
- replicator_level1.png
- replicator_level2.png
- replicator_level2alt.png
- replicator_level3.png
license: "Custom"
copyright: "Created by Widgetbeck for Impstation."
source: "https://github.com/impstation/imp-station-14/pull/2490"

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

View File

@ -0,0 +1,56 @@
- files:
- replicator.rsi/alive.png
- replicator.rsi/alive_level2.png
- replicator.rsi/alive_level2alt.png
- replicator.rsi/alive_level3.png
- replicator.rsi/alive_spore.png
- replicator.rsi/combat_level1.png
- replicator.rsi/combat_level2.png
- replicator.rsi/combat_level2alt.png
- replicator.rsi/combat_level3.png
- replicator.rsi/dead.png
- replicator.rsi/dead_level2.png
- replicator.rsi/dead_level3.png
- replicator.rsi/icon.png
- replicator.rsi/replicator0.png
- replicator.rsi/t1weapon.png
- replicator.rsi/t2altmelee.png
- replicator.rsi/t2altweapon.png
- replicator.rsi/t3weapon.png
- replicator_gun.rsi/beam_repli.png
- replicator_gun.rsi/beam_repli2.png
- replicator_gun.rsi/impact_repli.png
- replicator_gun.rsi/impact_repli2.png
- replicator_gun.rsi/muzzle_repli.png
- replicator_gun.rsi/muzzle_repli2.png
- replicator_nest.rsi/nest1.png
- replicator_nest.rsi/nest1unshaded.png
- replicator_nest.rsi/nest2.png
- replicator_nest.rsi/nest2unshaded.png
- replicator_nest.rsi/nest3.png
- replicator_nest.rsi/nest3unshaded.png
- replicator_sign.rsi/sign.png
- replicator_tablet.rsi/aac_screen.png
- replicator_tablet.rsi/aac_tablet.png
- replicator_tileset.rsi/replicator-tile-anim.png
- replicator_tileset.rsi/wall.png
- replicator_tileset.rsi/wall0.png
- replicator_tileset.rsi/wall1.png
- replicator_tileset.rsi/wall2.png
- replicator_tileset.rsi/wall3.png
- replicator_tileset.rsi/wall4.png
- replicator_tileset.rsi/wall5.png
- replicator_tileset.rsi/wall6.png
- replicator_tileset.rsi/wall7.png
- Tile/tile.png
- Tile/tile_double_edge_E.png
- Tile/tile_double_edge_N.png
- Tile/tile_double_edge_S.png
- Tile/tile_double_edge_W.png
- Tile/tile_single_edge_NE.png
- Tile/tile_single_edge_NW.png
- Tile/tile_single_edge_SE.png
- Tile/tile_single_edge_SW.png
license: "Custom"
copyright: "Created by Widgetbeck for Impstation."
source: "https://github.com/impstation/imp-station-14/pull/2490"

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

View File

@ -0,0 +1,270 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "AftrLite (github)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "alive",
"directions": 4,
"delays": [
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
]
]
},
{
"name": "alive_level2",
"directions": 4,
"delays": [
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
]
]
},
{
"name": "alive_level2alt",
"directions": 4,
"delays": [
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
]
]
},
{
"name": "alive_level3",
"directions": 4,
"delays": [
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
],
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
],
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
],
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
]
]
},
{
"name": "alive_spore",
"directions": 4,
"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, 0.2, 0.2, 0.2, 0.2
],
[
0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2
],
[
0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2
]
]
},
{
"name": "dead"
},
{
"name": "dead_level2"
},
{
"name": "dead_level3"
},
{
"name": "combat_level1",
"directions": 4,
"delays": [
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
]
]
},
{
"name": "combat_level2",
"directions": 4,
"delays": [
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
]
]
},
{
"name": "combat_level2alt",
"directions": 4,
"delays": [
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
],
[
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07,
0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
]
]
},
{
"name": "combat_level3",
"directions": 4,
"delays": [
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
],
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
],
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
],
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
]
]
},
{
"name": "t1weapon"
},
{
"name": "t3weapon"
},
{
"name": "t2altweapon"
},
{
"name": "t2altmelee"
},
{
"name": "replicator0",
"directions": 1,
"delays": [
[
0.4, 0.4, 0.4, 0.4
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 987 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 B

View File

@ -0,0 +1,101 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "AftrLite (github)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "muzzle_repli",
"delays": [
[
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002
]
]
},
{
"name": "beam_repli",
"delays": [
[
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002
]
]
},
{
"name": "impact_repli",
"delays": [
[
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002
]
]
},
{
"name": "muzzle_repli2",
"delays": [
[
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002
]
]
},
{
"name": "beam_repli2",
"delays": [
[
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002
]
]
},
{
"name": "impact_repli2",
"delays": [
[
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002,
0.060000002
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

View File

@ -0,0 +1,47 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "AftrLite (github)",
"size": {
"x": 96,
"y": 96
},
"states": [
{
"name": "nest1"
},
{
"name": "nest2"
},
{
"name": "nest3"
},
{
"name": "nest1unshaded",
"directions": 1,
"delays": [
[
3, 0.07, 0.07, 0.07, 0.07, 0.07
]
]
},
{
"name": "nest2unshaded",
"directions": 1,
"delays": [
[
3, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
]
]
},
{
"name": "nest3unshaded",
"directions": 1,
"delays": [
[
3, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,37 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "AftrLite (github)",
"size": {
"x": 48,
"y": 48
},
"states": [
{
"name": "sign",
"directions": 4,
"delays": [
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
],
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
],
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
],
[
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1
]
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Some files were not shown because too many files have changed in this diff Show More