Carp wave spawner and dragons as an actual event (#10254)
9
Content.Client/Dragon/DragonRiftComponent.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Content.Shared.Dragon;
|
||||||
|
|
||||||
|
namespace Content.Client.Dragon;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class DragonRiftComponent : SharedDragonRiftComponent
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
51
Content.Client/Dragon/DragonSystem.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using Content.Shared.Dragon;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Client.Dragon;
|
||||||
|
|
||||||
|
public sealed class DragonSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<DragonRiftComponent, ComponentHandleState>(OnRiftHandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRiftHandleState(EntityUid uid, DragonRiftComponent component, ref ComponentHandleState args)
|
||||||
|
{
|
||||||
|
if (args.Current is not DragonRiftComponentState state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (component.State == state.State) return;
|
||||||
|
|
||||||
|
component.State = state.State;
|
||||||
|
TryComp<SpriteComponent>(uid, out var sprite);
|
||||||
|
TryComp<PointLightComponent>(uid, out var light);
|
||||||
|
|
||||||
|
if (sprite == null && light == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (state.State)
|
||||||
|
{
|
||||||
|
case DragonRiftState.Charging:
|
||||||
|
sprite?.LayerSetColor(0, Color.FromHex("#569fff"));
|
||||||
|
|
||||||
|
if (light != null)
|
||||||
|
light.Color = Color.FromHex("#366db5");
|
||||||
|
break;
|
||||||
|
case DragonRiftState.AlmostFinished:
|
||||||
|
sprite?.LayerSetColor(0, Color.FromHex("#cf4cff"));
|
||||||
|
|
||||||
|
if (light != null)
|
||||||
|
light.Color = Color.FromHex("#9e2fc1");
|
||||||
|
break;
|
||||||
|
case DragonRiftState.Finished:
|
||||||
|
sprite?.LayerSetColor(0, Color.FromHex("#edbc36"));
|
||||||
|
|
||||||
|
if (light != null)
|
||||||
|
light.Color = Color.FromHex("#cbaf20");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
Content.Client/Sprite/RandomSpriteSystem.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using Content.Shared.Sprite;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Reflection;
|
||||||
|
|
||||||
|
namespace Content.Client.Sprite;
|
||||||
|
|
||||||
|
public sealed class RandomSpriteSystem : SharedRandomSpriteSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IReflectionManager _reflection = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<RandomSpriteComponent, ComponentHandleState>(OnHandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHandleState(EntityUid uid, RandomSpriteComponent component, ref ComponentHandleState args)
|
||||||
|
{
|
||||||
|
if (args.Current is not RandomSpriteColorComponentState state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (state.Selected.Equals(component.Selected))
|
||||||
|
return;
|
||||||
|
|
||||||
|
component.Selected.Clear();
|
||||||
|
component.Selected.EnsureCapacity(state.Selected.Count);
|
||||||
|
|
||||||
|
foreach (var layer in state.Selected)
|
||||||
|
{
|
||||||
|
component.Selected.Add(layer.Key, layer.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateAppearance(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAppearance(EntityUid uid, RandomSpriteComponent component, SpriteComponent? sprite = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref sprite, false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var layer in component.Selected)
|
||||||
|
{
|
||||||
|
object key;
|
||||||
|
if (_reflection.TryParseEnumReference(layer.Key, out var @enum))
|
||||||
|
{
|
||||||
|
key = @enum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key = layer.Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite.LayerSetState(key, layer.Value.State);
|
||||||
|
sprite.LayerSetColor(key, layer.Value.Color ?? Color.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,11 +32,42 @@ namespace Content.Server.Dragon
|
|||||||
[DataField("devourAction")]
|
[DataField("devourAction")]
|
||||||
public EntityTargetAction? DevourAction;
|
public EntityTargetAction? DevourAction;
|
||||||
|
|
||||||
[DataField("spawnActionId", customTypeSerializer: typeof(PrototypeIdSerializer<InstantActionPrototype>))]
|
/// <summary>
|
||||||
public string SpawnActionId = "DragonSpawn";
|
/// If we have active rifts.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables, DataField("rifts")]
|
||||||
|
public List<EntityUid> Rifts = new();
|
||||||
|
|
||||||
[DataField("spawnAction")]
|
public bool Weakened => WeakenedAccumulator > 0f;
|
||||||
public InstantAction? SpawnAction;
|
|
||||||
|
/// <summary>
|
||||||
|
/// When any rift is destroyed how long is the dragon weakened for
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("weakenedDuration")]
|
||||||
|
public float WeakenedDuration = 120f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Has a rift been destroyed and the dragon in a temporary weakened state?
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("weakenedAccumulator")]
|
||||||
|
public float WeakenedAccumulator = 0f;
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("riftAccumulator")]
|
||||||
|
public float RiftAccumulator = 0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum time the dragon can go without spawning a rift before they die.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("maxAccumulator")] public float RiftMaxAccumulator = 300f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spawns a rift which can summon more mobs.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables, DataField("spawnRiftAction")]
|
||||||
|
public InstantAction? SpawnRiftAction;
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("riftPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||||
|
public string RiftPrototype = "CarpRift";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of time it takes to devour something
|
/// The amount of time it takes to devour something
|
||||||
@@ -48,14 +79,7 @@ namespace Content.Server.Dragon
|
|||||||
public float StructureDevourTime = 10f;
|
public float StructureDevourTime = 10f;
|
||||||
|
|
||||||
[DataField("devourTime")]
|
[DataField("devourTime")]
|
||||||
public float DevourTime = 2f;
|
public float DevourTime = 3f;
|
||||||
|
|
||||||
[DataField("spawnCount")] public int SpawnsLeft = 2;
|
|
||||||
|
|
||||||
[DataField("maxSpawnCount")] public int MaxSpawns = 2;
|
|
||||||
|
|
||||||
[DataField("spawnProto", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
|
||||||
public string? SpawnPrototype = "MobCarpDragon";
|
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField("soundDeath")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("soundDeath")]
|
||||||
public SoundSpecifier? SoundDeath = new SoundPathSpecifier("/Audio/Animals/space_dragon_roar.ogg");
|
public SoundSpecifier? SoundDeath = new SoundPathSpecifier("/Audio/Animals/space_dragon_roar.ogg");
|
||||||
@@ -76,7 +100,7 @@ namespace Content.Server.Dragon
|
|||||||
public SoundSpecifier? SoundRoar =
|
public SoundSpecifier? SoundRoar =
|
||||||
new SoundPathSpecifier("/Audio/Animals/space_dragon_roar.ogg")
|
new SoundPathSpecifier("/Audio/Animals/space_dragon_roar.ogg")
|
||||||
{
|
{
|
||||||
Params = AudioParams.Default.WithVolume(-3f),
|
Params = AudioParams.Default.WithVolume(3f),
|
||||||
};
|
};
|
||||||
|
|
||||||
public CancellationTokenSource? CancelToken;
|
public CancellationTokenSource? CancelToken;
|
||||||
@@ -103,5 +127,5 @@ namespace Content.Server.Dragon
|
|||||||
|
|
||||||
public sealed class DragonDevourActionEvent : EntityTargetActionEvent {}
|
public sealed class DragonDevourActionEvent : EntityTargetActionEvent {}
|
||||||
|
|
||||||
public sealed class DragonSpawnActionEvent : InstantActionEvent {}
|
public sealed class DragonSpawnRiftActionEvent : InstantActionEvent {}
|
||||||
}
|
}
|
||||||
40
Content.Server/Dragon/Components/DragonRiftComponent.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using Content.Shared.Dragon;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
|
namespace Content.Server.Dragon;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class DragonRiftComponent : SharedDragonRiftComponent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Dragon that spawned this rift.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables, DataField("dragon")] public EntityUid Dragon;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How long the rift has been active.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("accumulator")]
|
||||||
|
public float Accumulator = 0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum amount we can accumulate before becoming impervious.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("maxAccumuluator")] public float MaxAccumulator = 300f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Accumulation of the spawn timer.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("spawnAccumulator")]
|
||||||
|
public float SpawnAccumulator = 60f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How long it takes for a new spawn to be added.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("spawnCooldown")]
|
||||||
|
public float SpawnCooldown = 60f;
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("spawn", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||||
|
public string SpawnPrototype = "MobCarpDragon";
|
||||||
|
}
|
||||||
67
Content.Server/Dragon/DragonSystem.Rule.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.GameTicking;
|
||||||
|
using Content.Server.StationEvents.Components;
|
||||||
|
using Content.Shared.Dragon;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Server.Dragon;
|
||||||
|
|
||||||
|
public sealed partial class DragonSystem
|
||||||
|
{
|
||||||
|
public override string Prototype => "Dragon";
|
||||||
|
|
||||||
|
private int RiftsMet(DragonComponent component)
|
||||||
|
{
|
||||||
|
var finished = 0;
|
||||||
|
|
||||||
|
foreach (var rift in component.Rifts)
|
||||||
|
{
|
||||||
|
if (!TryComp<DragonRiftComponent>(rift, out var drift) ||
|
||||||
|
drift.State != DragonRiftState.Finished)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
finished++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Started()
|
||||||
|
{
|
||||||
|
var spawnLocations = EntityManager.EntityQuery<IMapGridComponent, TransformComponent>().ToList();
|
||||||
|
|
||||||
|
if (spawnLocations.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var location = _random.Pick(spawnLocations);
|
||||||
|
Spawn("MobDragon", location.Item2.MapPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Ended()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRiftRoundEnd(RoundEndTextAppendEvent args)
|
||||||
|
{
|
||||||
|
if (!RuleAdded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.AddLine(Loc.GetString("dragon-round-end-summary"));
|
||||||
|
|
||||||
|
foreach (var dragon in EntityQuery<DragonComponent>(true))
|
||||||
|
{
|
||||||
|
var met = RiftsMet(dragon);
|
||||||
|
|
||||||
|
if (TryComp<ActorComponent>(dragon.Owner, out var actor))
|
||||||
|
{
|
||||||
|
args.AddLine(Loc.GetString("dragon-round-end-dragon-player", ("name", dragon.Owner), ("rifts", met), ("player", actor.PlayerSession)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
args.AddLine(Loc.GetString("dragon-round-end-dragon", ("name", dragon.Owner), ("rifts", met)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,15 +9,27 @@ using Content.Shared.MobState.Components;
|
|||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
|
using Content.Server.GameTicking;
|
||||||
|
using Content.Server.GameTicking.Rules;
|
||||||
|
using Content.Shared.Damage;
|
||||||
|
using Content.Shared.Dragon;
|
||||||
|
using Content.Shared.Examine;
|
||||||
|
using Content.Shared.Movement.Systems;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Dragon
|
namespace Content.Server.Dragon
|
||||||
{
|
{
|
||||||
public sealed class DragonSystem : EntitySystem
|
public sealed partial class DragonSystem : GameRuleSystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly ChatSystem _chat = default!;
|
||||||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||||
|
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||||
|
|
||||||
@@ -26,13 +38,200 @@ namespace Content.Server.Dragon
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<DragonComponent, ComponentStartup>(OnStartup);
|
SubscribeLocalEvent<DragonComponent, ComponentStartup>(OnStartup);
|
||||||
|
SubscribeLocalEvent<DragonComponent, ComponentShutdown>(OnShutdown);
|
||||||
SubscribeLocalEvent<DragonComponent, DragonDevourComplete>(OnDragonDevourComplete);
|
SubscribeLocalEvent<DragonComponent, DragonDevourComplete>(OnDragonDevourComplete);
|
||||||
SubscribeLocalEvent<DragonComponent, DragonDevourActionEvent>(OnDevourAction);
|
SubscribeLocalEvent<DragonComponent, DragonDevourActionEvent>(OnDevourAction);
|
||||||
SubscribeLocalEvent<DragonComponent, DragonSpawnActionEvent>(OnDragonSpawnAction);
|
SubscribeLocalEvent<DragonComponent, DragonSpawnRiftActionEvent>(OnDragonRift);
|
||||||
|
SubscribeLocalEvent<DragonComponent, RefreshMovementSpeedModifiersEvent>(OnDragonMove);
|
||||||
|
|
||||||
SubscribeLocalEvent<DragonComponent, DragonStructureDevourComplete>(OnDragonStructureDevourComplete);
|
SubscribeLocalEvent<DragonComponent, DragonStructureDevourComplete>(OnDragonStructureDevourComplete);
|
||||||
SubscribeLocalEvent<DragonComponent, DragonDevourCancelledEvent>(OnDragonDevourCancelled);
|
SubscribeLocalEvent<DragonComponent, DragonDevourCancelledEvent>(OnDragonDevourCancelled);
|
||||||
SubscribeLocalEvent<DragonComponent, MobStateChangedEvent>(OnMobStateChanged);
|
SubscribeLocalEvent<DragonComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<DragonRiftComponent, ComponentShutdown>(OnRiftShutdown);
|
||||||
|
SubscribeLocalEvent<DragonRiftComponent, ComponentGetState>(OnRiftGetState);
|
||||||
|
SubscribeLocalEvent<DragonRiftComponent, AnchorStateChangedEvent>(OnAnchorChange);
|
||||||
|
SubscribeLocalEvent<DragonRiftComponent, ExaminedEvent>(OnRiftExamined);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<RoundEndTextAppendEvent>(OnRiftRoundEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
|
||||||
|
foreach (var comp in EntityQuery<DragonComponent>())
|
||||||
|
{
|
||||||
|
if (comp.WeakenedAccumulator > 0f)
|
||||||
|
{
|
||||||
|
comp.WeakenedAccumulator -= frameTime;
|
||||||
|
|
||||||
|
// No longer weakened.
|
||||||
|
if (comp.WeakenedAccumulator < 0f)
|
||||||
|
{
|
||||||
|
comp.WeakenedAccumulator = 0f;
|
||||||
|
_movement.RefreshMovementSpeedModifiers(comp.Owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// At max rifts
|
||||||
|
if (comp.Rifts.Count >= 3)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's an active rift don't accumulate.
|
||||||
|
if (comp.Rifts.Count > 0)
|
||||||
|
{
|
||||||
|
var lastRift = comp.Rifts[^1];
|
||||||
|
|
||||||
|
if (TryComp<DragonRiftComponent>(lastRift, out var rift) && rift.State != DragonRiftState.Finished)
|
||||||
|
{
|
||||||
|
comp.RiftAccumulator = 0f;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
comp.RiftAccumulator += frameTime;
|
||||||
|
|
||||||
|
// Delete it, naughty dragon!
|
||||||
|
if (comp.RiftAccumulator >= comp.RiftMaxAccumulator)
|
||||||
|
{
|
||||||
|
Roar(comp);
|
||||||
|
QueueDel(comp.Owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var comp in EntityQuery<DragonRiftComponent>())
|
||||||
|
{
|
||||||
|
if (comp.State != DragonRiftState.Finished && comp.Accumulator >= comp.MaxAccumulator)
|
||||||
|
{
|
||||||
|
// TODO: When we get autocall you can buff if the rift finishes / 3 rifts are up
|
||||||
|
// for now they just keep 3 rifts up.
|
||||||
|
|
||||||
|
comp.Accumulator = comp.MaxAccumulator;
|
||||||
|
RemComp<DamageableComponent>(comp.Owner);
|
||||||
|
comp.State = DragonRiftState.Finished;
|
||||||
|
Dirty(comp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
comp.Accumulator += frameTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
comp.SpawnAccumulator += frameTime;
|
||||||
|
|
||||||
|
if (comp.State < DragonRiftState.AlmostFinished && comp.SpawnAccumulator > comp.MaxAccumulator / 2f)
|
||||||
|
{
|
||||||
|
comp.State = DragonRiftState.AlmostFinished;
|
||||||
|
Dirty(comp);
|
||||||
|
var location = Transform(comp.Owner).LocalPosition;
|
||||||
|
|
||||||
|
_chat.DispatchGlobalAnnouncement(Loc.GetString("carp-rift-warning", ("location", location)), playSound: false, colorOverride: Color.Red);
|
||||||
|
_audioSystem.PlayGlobal("/Audio/Misc/notice1.ogg", Filter.Broadcast());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp.SpawnAccumulator > comp.SpawnCooldown)
|
||||||
|
{
|
||||||
|
comp.SpawnAccumulator -= comp.SpawnCooldown;
|
||||||
|
Spawn(comp.SpawnPrototype, Transform(comp.Owner).MapPosition);
|
||||||
|
// TODO: When NPC refactor make it guard the rift.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Rift
|
||||||
|
|
||||||
|
private void OnRiftExamined(EntityUid uid, DragonRiftComponent component, ExaminedEvent args)
|
||||||
|
{
|
||||||
|
args.PushMarkup(Loc.GetString("carp-rift-examine", ("percentage", MathF.Round(component.Accumulator / component.MaxAccumulator * 100))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAnchorChange(EntityUid uid, DragonRiftComponent component, ref AnchorStateChangedEvent args)
|
||||||
|
{
|
||||||
|
if (!args.Anchored && component.State == DragonRiftState.Charging)
|
||||||
|
{
|
||||||
|
QueueDel(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRiftShutdown(EntityUid uid, DragonRiftComponent component, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
if (TryComp<DragonComponent>(component.Dragon, out var dragon) && !dragon.Weakened)
|
||||||
|
{
|
||||||
|
foreach (var rift in dragon.Rifts)
|
||||||
|
{
|
||||||
|
QueueDel(rift);
|
||||||
|
}
|
||||||
|
|
||||||
|
dragon.Rifts.Clear();
|
||||||
|
|
||||||
|
// We can't predict the rift being destroyed anyway so no point adding weakened to shared.
|
||||||
|
dragon.WeakenedAccumulator = dragon.WeakenedDuration;
|
||||||
|
_movement.RefreshMovementSpeedModifiers(component.Dragon);
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("carp-rift-destroyed"), component.Dragon, Filter.Entities(component.Dragon));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRiftGetState(EntityUid uid, DragonRiftComponent component, ref ComponentGetState args)
|
||||||
|
{
|
||||||
|
args.State = new DragonRiftComponentState()
|
||||||
|
{
|
||||||
|
State = component.State
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDragonMove(EntityUid uid, DragonComponent component, RefreshMovementSpeedModifiersEvent args)
|
||||||
|
{
|
||||||
|
if (component.Weakened)
|
||||||
|
{
|
||||||
|
args.ModifySpeed(0.5f, 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDragonRift(EntityUid uid, DragonComponent component, DragonSpawnRiftActionEvent args)
|
||||||
|
{
|
||||||
|
if (component.Weakened)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("carp-rift-weakened"), uid, Filter.Entities(uid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component.Rifts.Count >= 3)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("carp-rift-max"), uid, Filter.Entities(uid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component.Rifts.Count > 0 && TryComp<DragonRiftComponent>(component.Rifts[^1], out var rift) && rift.State != DragonRiftState.Finished)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("carp-rift-duplicate"), uid, Filter.Entities(uid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var xform = Transform(uid);
|
||||||
|
|
||||||
|
// Have to be on a grid fam
|
||||||
|
if (xform.GridUid == null)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("carp-rift-anchor"), uid, Filter.Entities(uid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var carpUid = Spawn(component.RiftPrototype, xform.MapPosition);
|
||||||
|
component.Rifts.Add(carpUid);
|
||||||
|
Comp<DragonRiftComponent>(carpUid).Dragon = uid;
|
||||||
|
_audioSystem.Play("/Audio/Weapons/Guns/Gunshots/rocket_launcher.ogg", Filter.Pvs(carpUid, entityManager: EntityManager), carpUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void OnShutdown(EntityUid uid, DragonComponent component, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
foreach (var rift in component.Rifts)
|
||||||
|
{
|
||||||
|
QueueDel(rift);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMobStateChanged(EntityUid uid, DragonComponent component, MobStateChangedEvent args)
|
private void OnMobStateChanged(EntityUid uid, DragonComponent component, MobStateChangedEvent args)
|
||||||
@@ -59,13 +258,7 @@ namespace Content.Server.Dragon
|
|||||||
var ichorInjection = new Solution(component.DevourChem, component.DevourHealRate);
|
var ichorInjection = new Solution(component.DevourChem, component.DevourHealRate);
|
||||||
|
|
||||||
//Humanoid devours allow dragon to get eggs, corpses included
|
//Humanoid devours allow dragon to get eggs, corpses included
|
||||||
if (EntityManager.HasComponent<HumanoidAppearanceComponent>(args.Target))
|
if (!EntityManager.HasComponent<HumanoidAppearanceComponent>(args.Target))
|
||||||
{
|
|
||||||
// Add a spawn for a consumed humanoid
|
|
||||||
component.SpawnsLeft = Math.Min(component.SpawnsLeft + 1, component.MaxSpawns);
|
|
||||||
}
|
|
||||||
//Non-humanoid mobs can only heal dragon for half the normal amount, with no additional spawn tickets
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
ichorInjection.ScaleSolution(0.5f);
|
ichorInjection.ScaleSolution(0.5f);
|
||||||
}
|
}
|
||||||
@@ -87,10 +280,14 @@ namespace Content.Server.Dragon
|
|||||||
_audioSystem.PlayPvs(component.SoundDevour, uid, component.SoundDevour.Params);
|
_audioSystem.PlayPvs(component.SoundDevour, uid, component.SoundDevour.Params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Roar(DragonComponent component)
|
||||||
|
{
|
||||||
|
if (component.SoundRoar != null)
|
||||||
|
_audioSystem.Play(component.SoundRoar, Filter.Pvs(component.Owner, 4f, EntityManager), component.Owner, component.SoundRoar.Params);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnStartup(EntityUid uid, DragonComponent component, ComponentStartup args)
|
private void OnStartup(EntityUid uid, DragonComponent component, ComponentStartup args)
|
||||||
{
|
{
|
||||||
component.SpawnsLeft = Math.Min(component.SpawnsLeft, component.MaxSpawns);
|
|
||||||
|
|
||||||
//Dragon doesn't actually chew, since he sends targets right into his stomach.
|
//Dragon doesn't actually chew, since he sends targets right into his stomach.
|
||||||
//I did it mom, I added ERP content into upstream. Legally!
|
//I did it mom, I added ERP content into upstream. Legally!
|
||||||
component.DragonStomach = _containerSystem.EnsureContainer<Container>(uid, "dragon_stomach");
|
component.DragonStomach = _containerSystem.EnsureContainer<Container>(uid, "dragon_stomach");
|
||||||
@@ -98,11 +295,10 @@ namespace Content.Server.Dragon
|
|||||||
if (component.DevourAction != null)
|
if (component.DevourAction != null)
|
||||||
_actionsSystem.AddAction(uid, component.DevourAction, null);
|
_actionsSystem.AddAction(uid, component.DevourAction, null);
|
||||||
|
|
||||||
if (component.SpawnAction != null)
|
if (component.SpawnRiftAction != null)
|
||||||
_actionsSystem.AddAction(uid, component.SpawnAction, null);
|
_actionsSystem.AddAction(uid, component.SpawnRiftAction, null);
|
||||||
|
|
||||||
if (component.SoundRoar != null)
|
Roar(component);
|
||||||
_audioSystem.Play(component.SoundRoar, Filter.Pvs(uid, 4f, EntityManager), uid, component.SoundRoar.Params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -117,7 +313,6 @@ namespace Content.Server.Dragon
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
var target = args.Target;
|
var target = args.Target;
|
||||||
|
|
||||||
@@ -164,22 +359,6 @@ namespace Content.Server.Dragon
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDragonSpawnAction(EntityUid dragonuid, DragonComponent component, DragonSpawnActionEvent args)
|
|
||||||
{
|
|
||||||
if (component.SpawnPrototype == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If dragon has spawns then add one.
|
|
||||||
if (component.SpawnsLeft > 0)
|
|
||||||
{
|
|
||||||
Spawn(component.SpawnPrototype, Transform(dragonuid).Coordinates);
|
|
||||||
component.SpawnsLeft--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_popupSystem.PopupEntity(Loc.GetString("dragon-spawn-action-popup-message-fail-no-eggs"), dragonuid, Filter.Entities(dragonuid));
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class DragonDevourComplete : EntityEventArgs
|
private sealed class DragonDevourComplete : EntityEventArgs
|
||||||
{
|
{
|
||||||
public EntityUid User { get; }
|
public EntityUid User { get; }
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ namespace Content.Server.RatKing
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
[Dependency] private readonly ActionsSystem _action = default!;
|
[Dependency] private readonly ActionsSystem _action = default!;
|
||||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
|
||||||
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
||||||
[Dependency] private readonly TransformSystem _xform = default!;
|
[Dependency] private readonly TransformSystem _xform = default!;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
namespace Content.Server.Sprite.Components
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class RandomSpriteColorComponent : Component
|
|
||||||
{
|
|
||||||
// This should handle random states + colors for layers.
|
|
||||||
// Saame with RandomSpriteState
|
|
||||||
[DataField("selected")] public string? SelectedColor;
|
|
||||||
[DataField("state")] public string BaseState = "error";
|
|
||||||
|
|
||||||
[DataField("colors")] public readonly Dictionary<string, Color> Colors = new();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace Content.Server.Sprite.Components
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class RandomSpriteStateComponent : Component
|
|
||||||
{
|
|
||||||
[DataField("spriteStates")] public List<string>? SpriteStates;
|
|
||||||
|
|
||||||
[DataField("spriteLayer")] public int SpriteLayer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +1,53 @@
|
|||||||
using Content.Server.Sprite.Components;
|
using System.Linq;
|
||||||
using Content.Shared.Random.Helpers;
|
using Content.Shared.Decals;
|
||||||
using Robust.Server.GameObjects;
|
using Content.Shared.Sprite;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Sprite;
|
namespace Content.Server.Sprite;
|
||||||
|
|
||||||
public sealed class RandomSpriteSystem: EntitySystem
|
public sealed class RandomSpriteSystem: SharedRandomSpriteSystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<RandomSpriteColorComponent, ComponentStartup>(OnSpriteColorStartup);
|
SubscribeLocalEvent<RandomSpriteComponent, ComponentGetState>(OnGetState);
|
||||||
SubscribeLocalEvent<RandomSpriteColorComponent, MapInitEvent>(OnSpriteColorMapInit);
|
SubscribeLocalEvent<RandomSpriteComponent, MapInitEvent>(OnMapInit);
|
||||||
|
|
||||||
SubscribeLocalEvent<RandomSpriteStateComponent, MapInitEvent>(OnSpriteStateMapInit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSpriteColorStartup(EntityUid uid, RandomSpriteColorComponent component, ComponentStartup args)
|
private void OnMapInit(EntityUid uid, RandomSpriteComponent component, MapInitEvent args)
|
||||||
{
|
{
|
||||||
UpdateColor(component);
|
if (component.Selected.Count > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (component.Available.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var group = _random.Pick(component.Available);
|
||||||
|
component.Selected.EnsureCapacity(group.Count);
|
||||||
|
|
||||||
|
foreach (var layer in group)
|
||||||
|
{
|
||||||
|
Color? color = null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(layer.Value.Color))
|
||||||
|
color = _random.Pick(_prototype.Index<ColorPalettePrototype>(layer.Value.Color).Colors.Values);
|
||||||
|
|
||||||
|
component.Selected.Add(layer.Key, (layer.Value.State, color));
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirty(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSpriteColorMapInit(EntityUid uid, RandomSpriteColorComponent component, MapInitEvent args)
|
private void OnGetState(EntityUid uid, RandomSpriteComponent component, ref ComponentGetState args)
|
||||||
{
|
{
|
||||||
component.SelectedColor = _random.Pick(component.Colors.Keys);
|
args.State = new RandomSpriteColorComponentState()
|
||||||
UpdateColor(component);
|
{
|
||||||
}
|
Selected = component.Selected,
|
||||||
|
};
|
||||||
private void OnSpriteStateMapInit(EntityUid uid, RandomSpriteStateComponent component, MapInitEvent args)
|
|
||||||
{
|
|
||||||
if (component.SpriteStates == null) return;
|
|
||||||
if (!TryComp<SpriteComponent>(uid, out var spriteComponent)) return;
|
|
||||||
spriteComponent.LayerSetState(component.SpriteLayer, _random.Pick(component.SpriteStates));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateColor(RandomSpriteColorComponent component)
|
|
||||||
{
|
|
||||||
if (!TryComp<SpriteComponent>(component.Owner, out var spriteComponent) || component.SelectedColor == null) return;
|
|
||||||
|
|
||||||
spriteComponent.LayerSetState(0, component.BaseState);
|
|
||||||
spriteComponent.LayerSetColor(0, component.Colors[component.SelectedColor]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
Content.Shared/Dragon/DragonRiftComponentState.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Dragon;
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class DragonRiftComponentState : ComponentState
|
||||||
|
{
|
||||||
|
public DragonRiftState State;
|
||||||
|
}
|
||||||
19
Content.Shared/Dragon/SharedDragonRiftComponent.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Dragon;
|
||||||
|
|
||||||
|
[NetworkedComponent]
|
||||||
|
public abstract class SharedDragonRiftComponent : Component
|
||||||
|
{
|
||||||
|
[ViewVariables, DataField("state")]
|
||||||
|
public DragonRiftState State = DragonRiftState.Charging;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum DragonRiftState : byte
|
||||||
|
{
|
||||||
|
Charging,
|
||||||
|
AlmostFinished,
|
||||||
|
Finished,
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Movement.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is this entity always considered to be touching a wall?
|
||||||
|
/// i.e. when weightless they're floaty but still have free movement.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed class MovementAlwaysTouchingComponent : Component
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,9 @@ using Robust.Shared.Serialization;
|
|||||||
|
|
||||||
namespace Content.Shared.Movement.Components
|
namespace Content.Shared.Movement.Components
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Ignores gravity entirely.
|
||||||
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
public sealed class MovementIgnoreGravityComponent : Component
|
public sealed class MovementIgnoreGravityComponent : Component
|
||||||
{
|
{
|
||||||
@@ -17,7 +20,6 @@ namespace Content.Shared.Movement.Components
|
|||||||
[DataField("gravityState")] public bool Weightless = false;
|
[DataField("gravityState")] public bool Weightless = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[NetSerializable, Serializable]
|
[NetSerializable, Serializable]
|
||||||
public sealed class MovementIgnoreGravityComponentState : ComponentState
|
public sealed class MovementIgnoreGravityComponentState : ComponentState
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,55 +56,55 @@ namespace Content.Shared.Movement.Components
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimum speed a mob has to be moving before applying movement friction.
|
/// Minimum speed a mob has to be moving before applying movement friction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("minimumFrictionSpeed")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("minimumFrictionSpeed")]
|
||||||
public float MinimumFrictionSpeed = DefaultMinimumFrictionSpeed;
|
public float MinimumFrictionSpeed = DefaultMinimumFrictionSpeed;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The negative velocity applied for friction when weightless and providing inputs.
|
/// The negative velocity applied for friction when weightless and providing inputs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("weightlessFriction")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("weightlessFriction")]
|
||||||
public float WeightlessFriction = DefaultWeightlessFriction;
|
public float WeightlessFriction = DefaultWeightlessFriction;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The negative velocity applied for friction when weightless and not providing inputs.
|
/// The negative velocity applied for friction when weightless and not providing inputs.
|
||||||
/// This is essentially how much their speed decreases per second.
|
/// This is essentially how much their speed decreases per second.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("weightlessFrictionNoInput")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("weightlessFrictionNoInput")]
|
||||||
public float WeightlessFrictionNoInput = DefaultWeightlessFrictionNoInput;
|
public float WeightlessFrictionNoInput = DefaultWeightlessFrictionNoInput;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The movement speed modifier applied to a mob's total input velocity when weightless.
|
/// The movement speed modifier applied to a mob's total input velocity when weightless.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("weightlessModifier")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("weightlessModifier")]
|
||||||
public float WeightlessModifier = DefaultWeightlessModifier;
|
public float WeightlessModifier = DefaultWeightlessModifier;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The acceleration applied to mobs when moving and weightless.
|
/// The acceleration applied to mobs when moving and weightless.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("weightlessAcceleration")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("weightlessAcceleration")]
|
||||||
public float WeightlessAcceleration = DefaultWeightlessAcceleration;
|
public float WeightlessAcceleration = DefaultWeightlessAcceleration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The acceleration applied to mobs when moving.
|
/// The acceleration applied to mobs when moving.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("acceleration")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("acceleration")]
|
||||||
public float Acceleration = DefaultAcceleration;
|
public float Acceleration = DefaultAcceleration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The negative velocity applied for friction.
|
/// The negative velocity applied for friction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("friction")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("friction")]
|
||||||
public float Friction = DefaultFriction;
|
public float Friction = DefaultFriction;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The negative velocity applied for friction.
|
/// The negative velocity applied for friction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("frictionNoInput")] public float? FrictionNoInput = null;
|
[ViewVariables(VVAccess.ReadWrite), DataField("frictionNoInput")] public float? FrictionNoInput = null;
|
||||||
|
|
||||||
[DataField("baseWalkSpeed")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("baseWalkSpeed")]
|
||||||
public float BaseWalkSpeed { get; set; } = DefaultBaseWalkSpeed;
|
public float BaseWalkSpeed { get; set; } = DefaultBaseWalkSpeed;
|
||||||
|
|
||||||
[DataField("baseSprintSpeed")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("baseSprintSpeed")]
|
||||||
public float BaseSprintSpeed { get; set; } = DefaultBaseSprintSpeed;
|
public float BaseSprintSpeed { get; set; } = DefaultBaseSprintSpeed;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
|
using Content.Shared.Movement.Events;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
namespace Content.Shared.Movement.Systems;
|
namespace Content.Shared.Movement.Systems;
|
||||||
@@ -9,6 +10,12 @@ public sealed class MovementIgnoreGravitySystem : EntitySystem
|
|||||||
{
|
{
|
||||||
SubscribeLocalEvent<MovementIgnoreGravityComponent, ComponentGetState>(GetState);
|
SubscribeLocalEvent<MovementIgnoreGravityComponent, ComponentGetState>(GetState);
|
||||||
SubscribeLocalEvent<MovementIgnoreGravityComponent, ComponentHandleState>(HandleState);
|
SubscribeLocalEvent<MovementIgnoreGravityComponent, ComponentHandleState>(HandleState);
|
||||||
|
SubscribeLocalEvent<MovementAlwaysTouchingComponent, CanWeightlessMoveEvent>(OnWeightless);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWeightless(EntityUid uid, MovementAlwaysTouchingComponent component, ref CanWeightlessMoveEvent args)
|
||||||
|
{
|
||||||
|
args.CanMove = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleState(EntityUid uid, MovementIgnoreGravityComponent component, ref ComponentHandleState args)
|
private void HandleState(EntityUid uid, MovementIgnoreGravityComponent component, ref ComponentHandleState args)
|
||||||
|
|||||||
20
Content.Shared/Sprite/RandomSpriteComponent.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Sprite;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed class RandomSpriteComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Available colors based on group, parsed layer enum, state, and color.
|
||||||
|
/// Stored as a list so we can have groups of random sprites (e.g. tech_base + tech_flare for holoparasite)
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("available")]
|
||||||
|
public List<Dictionary<string, (string State, string? Color)>> Available = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Selected colors
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite), DataField("selected")]
|
||||||
|
public Dictionary<string, (string State, Color? Color)> Selected = new();
|
||||||
|
}
|
||||||
11
Content.Shared/Sprite/SharedRandomSpriteSystem.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Sprite;
|
||||||
|
|
||||||
|
public abstract class SharedRandomSpriteSystem : EntitySystem {}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class RandomSpriteColorComponentState : ComponentState
|
||||||
|
{
|
||||||
|
public Dictionary<string, (string State, Color? Color)> Selected = default!;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
atreides.ogg, c-20r.ogg, flaregun.ogg, mateba.ogg, minigun.ogg, mk58.ogg were taken from https://gitlab.com/cmdevs/colonial-warfare/-/tree/32cb5892413243cc74bb2d11df8e3085f8ef1164/sound/weapons
|
atreides.ogg, c-20r.ogg, flaregun.ogg, mateba.ogg, minigun.ogg, mk58.ogg were taken from https://gitlab.com/cmdevs/colonial-warfare/-/tree/32cb5892413243cc74bb2d11df8e3085f8ef1164/sound/weapons
|
||||||
They are licensed under CC-BY-SA 3.0
|
They are licensed under CC-BY-SA 3.0
|
||||||
|
|
||||||
taser2.ogg and kinetic_accel.ogg were taken from https://github.com/tgstation/tgstation/tree/88d7dbfc105fbf40284d7b7c4587f8d23c0ac3ac
|
rocket_launcher.ogg and taser2.ogg and kinetic_accel.ogg were taken from https://github.com/tgstation/tgstation/tree/88d7dbfc105fbf40284d7b7c4587f8d23c0ac3ac
|
||||||
It is licensed under CC-BY-SA 3.0
|
It is licensed under CC-BY-SA 3.0
|
||||||
BIN
Resources/Audio/Weapons/Guns/Gunshots/rocket_launcher.ogg
Normal file
@@ -2,7 +2,7 @@ devour-action-popup-message-structure = Your jaws dig into thick material..
|
|||||||
devour-action-popup-message-fail-target-not-valid = That doesn't look particularly edible.
|
devour-action-popup-message-fail-target-not-valid = That doesn't look particularly edible.
|
||||||
devour-action-popup-message-fail-target-alive = You can't consume creatures that are alive!
|
devour-action-popup-message-fail-target-alive = You can't consume creatures that are alive!
|
||||||
|
|
||||||
dragon-spawn-action-popup-message-fail-no-eggs = You don't have the stamina to create a carp!
|
dragon-spawn-action-popup-message-fail-no-eggs = You don't have the stamina to do that!
|
||||||
|
|
||||||
|
|
||||||
action-name-devour = [color=red]Devour[/color]
|
action-name-devour = [color=red]Devour[/color]
|
||||||
@@ -10,3 +10,17 @@ action-description-devour = Attempt to break a structure with your jaws or swall
|
|||||||
|
|
||||||
action-name-carp-summon = Summon carp
|
action-name-carp-summon = Summon carp
|
||||||
action-description-carp-summon = Summon a carp to aid you at seizing the station!
|
action-description-carp-summon = Summon a carp to aid you at seizing the station!
|
||||||
|
|
||||||
|
# Rifts
|
||||||
|
carp-rift-warning = A rift is causing an unnaturally large energy flux at {$location}. Stop it at all costs!
|
||||||
|
carp-rift-duplicate = Cannot have 2 charging rifts at the same time!
|
||||||
|
carp-rift-examine = It is [color=yellow]{$percentage}%[/color] charged!
|
||||||
|
carp-rift-max = You have reached your maximum amount of rifts
|
||||||
|
carp-rift-anchor = Rifts require a stable surface to spawn.
|
||||||
|
carp-rift-weakened = You are unable to summon more rifts in your weakened state.
|
||||||
|
carp-rift-destroyed = A rift has been destroyed! You are now weakened temporarily.
|
||||||
|
|
||||||
|
# Round end
|
||||||
|
dragon-round-end-summary = The dragons were:
|
||||||
|
dragon-round-end-dragon = {$name} with {$count} rifts
|
||||||
|
dragon-round-end-dragon-player = {$name} ({$player}) with {$count} rifts
|
||||||
|
|||||||
@@ -307,6 +307,7 @@
|
|||||||
baseSprintSpeed : 6
|
baseSprintSpeed : 6
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
drawdepth: Mobs
|
drawdepth: Mobs
|
||||||
|
netsync: false
|
||||||
layers:
|
layers:
|
||||||
- map: ["enum.DamageStateVisualLayers.Base"]
|
- map: ["enum.DamageStateVisualLayers.Base"]
|
||||||
state: butterfly
|
state: butterfly
|
||||||
@@ -327,16 +328,10 @@
|
|||||||
0: Alive
|
0: Alive
|
||||||
5: Critical
|
5: Critical
|
||||||
10: Dead
|
10: Dead
|
||||||
- type: RandomSpriteColor
|
- type: RandomSprite
|
||||||
state: butterfly
|
available:
|
||||||
colors:
|
- enum.DamageStateVisualLayers.Base:
|
||||||
blue: "#1861d5"
|
butterfly: Rainbow
|
||||||
red: "#951710"
|
|
||||||
pink: "#d5188d"
|
|
||||||
brown: "#a05212"
|
|
||||||
green: "#0e7f1b"
|
|
||||||
cyan: "#18a2d5"
|
|
||||||
yellow: "#d58c18"
|
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
- type: DamageStateVisuals
|
- type: DamageStateVisuals
|
||||||
states:
|
states:
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
- MobMask
|
- MobMask
|
||||||
layer:
|
layer:
|
||||||
- MobLayer
|
- MobLayer
|
||||||
- type: MovementIgnoreGravity
|
- type: MovementAlwaysTouching
|
||||||
- type: MobState
|
- type: MobState
|
||||||
thresholds:
|
thresholds:
|
||||||
0: Alive
|
0: Alive
|
||||||
|
|||||||
@@ -1,77 +1,95 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
name: space carp
|
name: space carp
|
||||||
id: MobCarp
|
id: BaseMobCarp
|
||||||
parent: SimpleSpaceMobBase
|
parent: SimpleSpaceMobBase
|
||||||
description: It's a space carp.
|
description: It's a space carp.
|
||||||
|
abstract: true
|
||||||
components:
|
components:
|
||||||
- type: InputMover
|
- type: InputMover
|
||||||
- type: MobMover
|
- type: MobMover
|
||||||
- type: UtilityNPC
|
- type: UtilityNPC
|
||||||
behaviorSets:
|
behaviorSets:
|
||||||
- Idle
|
- Idle
|
||||||
- UnarmedAttackHostiles
|
- UnarmedAttackHostiles
|
||||||
- type: AiFactionTag
|
- type: AiFactionTag
|
||||||
factions:
|
factions:
|
||||||
- SimpleHostile
|
- SimpleHostile
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
drawdepth: Mobs
|
drawdepth: Mobs
|
||||||
layers:
|
netsync: false
|
||||||
- map: ["enum.DamageStateVisualLayers.Base"]
|
layers:
|
||||||
state: alive
|
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
sprite: Mobs/Aliens/Carps/space.rsi
|
state: base
|
||||||
- type: CombatMode
|
sprite: Mobs/Aliens/Carps/space.rsi
|
||||||
disarmAction:
|
- map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||||
enabled: false
|
state: mouth
|
||||||
autoPopulate: false
|
sprite: Mobs/Aliens/Carps/space.rsi
|
||||||
name: action-name-disarm
|
shader: unshaded
|
||||||
- type: Physics
|
- type: RandomSprite
|
||||||
- type: Fixtures
|
available:
|
||||||
fixtures:
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- shape:
|
base: Rainbow
|
||||||
!type:PhysShapeCircle
|
enum.DamageStateVisualLayers.BaseUnshaded:
|
||||||
radius: 0.40
|
mouth: ""
|
||||||
mass: 40
|
- type: CombatMode
|
||||||
mask:
|
disarmAction:
|
||||||
- MobMask
|
enabled: false
|
||||||
layer:
|
autoPopulate: false
|
||||||
- MobLayer
|
name: action-name-disarm
|
||||||
- type: MobState
|
- type: Physics
|
||||||
thresholds:
|
- type: Fixtures
|
||||||
0: Alive
|
fixtures:
|
||||||
50: Critical
|
- shape:
|
||||||
100: Dead
|
!type:PhysShapeCircle
|
||||||
- type: MovementIgnoreGravity
|
radius: 0.40
|
||||||
- type: Appearance
|
mass: 40
|
||||||
- type: DamageStateVisuals
|
mask:
|
||||||
states:
|
- MobMask
|
||||||
Alive:
|
layer:
|
||||||
Base: alive
|
- MobLayer
|
||||||
Critical:
|
- type: MobState
|
||||||
Base: crit
|
thresholds:
|
||||||
Dead:
|
0: Alive
|
||||||
Base: dead
|
50: Critical
|
||||||
- type: Butcherable
|
100: Dead
|
||||||
spawned:
|
- type: MovementAlwaysTouching
|
||||||
- id: FoodMeatFish
|
- type: Appearance
|
||||||
amount: 2
|
- type: DamageStateVisuals
|
||||||
- type: MeleeWeapon
|
states:
|
||||||
range: 1.5
|
Alive:
|
||||||
arcwidth: 0
|
Base: base
|
||||||
arc: bite
|
BaseUnshaded: mouth
|
||||||
hitSound:
|
Dead:
|
||||||
path: /Audio/Effects/bite.ogg
|
Base: base_dead
|
||||||
damage:
|
BaseUnshaded: dead_mouth
|
||||||
types:
|
- type: Butcherable
|
||||||
Piercing: 5
|
spawned:
|
||||||
Slash: 10
|
- id: FoodMeatFish
|
||||||
- type: ReplacementAccent
|
amount: 2
|
||||||
accent: genericAggressive
|
- type: MeleeWeapon
|
||||||
- type: TypingIndicator
|
range: 1.5
|
||||||
proto: alien
|
arcwidth: 0
|
||||||
- type: NoSlip
|
arc: bite
|
||||||
- type: Tag
|
hitSound:
|
||||||
tags:
|
path: /Audio/Effects/bite.ogg
|
||||||
- Carp
|
damage:
|
||||||
|
types:
|
||||||
|
Piercing: 5
|
||||||
|
Slash: 10
|
||||||
|
- type: TypingIndicator
|
||||||
|
proto: alien
|
||||||
|
- type: NoSlip
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Carp
|
||||||
|
- DoorBumpOpener
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseMobCarp
|
||||||
|
id: MobCarp
|
||||||
|
components:
|
||||||
|
- type: ReplacementAccent
|
||||||
|
accent: genericAggressive
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: magicarp
|
name: magicarp
|
||||||
@@ -79,14 +97,14 @@
|
|||||||
id: MobCarpMagic
|
id: MobCarpMagic
|
||||||
description: Looks like some kind of fish. Might be magical.
|
description: Looks like some kind of fish. Might be magical.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
drawdepth: Mobs
|
drawdepth: Mobs
|
||||||
layers:
|
layers:
|
||||||
- map: ["enum.DamageStateVisualLayers.Base"]
|
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
state: alive
|
state: base
|
||||||
sprite: Mobs/Aliens/Carps/magic.rsi
|
sprite: Mobs/Aliens/Carps/magic.rsi
|
||||||
- type: TypingIndicator
|
- type: TypingIndicator
|
||||||
proto: guardian
|
proto: guardian
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: holocarp
|
name: holocarp
|
||||||
@@ -94,37 +112,37 @@
|
|||||||
id: MobCarpHolo
|
id: MobCarpHolo
|
||||||
description: Carp made out of holographic energies. Sadly for you, it is very much real.
|
description: Carp made out of holographic energies. Sadly for you, it is very much real.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
drawdepth: Mobs
|
drawdepth: Mobs
|
||||||
layers:
|
layers:
|
||||||
- map: ["enum.DamageStateVisualLayers.Base"]
|
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
state: alive
|
state: base
|
||||||
sprite: Mobs/Aliens/Carps/holo.rsi
|
sprite: Mobs/Aliens/Carps/holo.rsi
|
||||||
- type: Physics
|
- type: Physics
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
fixtures:
|
fixtures:
|
||||||
- shape:
|
- shape:
|
||||||
!type:PhysShapeCircle
|
!type:PhysShapeCircle
|
||||||
radius: 0.40
|
radius: 0.40
|
||||||
mass: 5
|
mass: 5
|
||||||
mask:
|
mask:
|
||||||
- MobMask
|
- MobMask
|
||||||
layer:
|
layer:
|
||||||
- Opaque
|
- Opaque
|
||||||
- type: TypingIndicator
|
- type: TypingIndicator
|
||||||
proto: robot
|
proto: robot
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: MobCarpSalvage
|
id: MobCarpSalvage
|
||||||
parent: MobCarp
|
parent: MobCarp
|
||||||
suffix: "Salvage Ruleset"
|
suffix: "Salvage Ruleset"
|
||||||
components:
|
components:
|
||||||
- type: GhostTakeoverAvailable
|
- type: GhostTakeoverAvailable
|
||||||
prob: 0.33
|
prob: 0.33
|
||||||
name: space carp on salvage wreck
|
name: space carp on salvage wreck
|
||||||
description: |
|
description: |
|
||||||
Defend the loot inside the salvage wreck!
|
Defend the loot inside the salvage wreck!
|
||||||
- type: SalvageMobRestrictions
|
- type: SalvageMobRestrictions
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: space carp
|
name: space carp
|
||||||
@@ -132,8 +150,7 @@
|
|||||||
suffix: DragonBrood
|
suffix: DragonBrood
|
||||||
parent: MobCarp
|
parent: MobCarp
|
||||||
components:
|
components:
|
||||||
- type: GhostTakeoverAvailable
|
- type: GhostTakeoverAvailable
|
||||||
makeSentient: true
|
makeSentient: true
|
||||||
name: Sentient Carp
|
name: Sentient Carp
|
||||||
description: Help the dragon flood the station with carps!
|
description: Help the dragon flood the station with carps!
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
thresholds:
|
thresholds:
|
||||||
0: Alive
|
0: Alive
|
||||||
15: Dead
|
15: Dead
|
||||||
- type: MovementIgnoreGravity
|
- type: MovementAlwaysTouching
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
- type: DamageStateVisuals
|
- type: DamageStateVisuals
|
||||||
states:
|
states:
|
||||||
|
|||||||
@@ -5,106 +5,112 @@
|
|||||||
suffix:
|
suffix:
|
||||||
description: A flying leviathan, loosely related to space carps.
|
description: A flying leviathan, loosely related to space carps.
|
||||||
components:
|
components:
|
||||||
- type: GhostTakeoverAvailable
|
- type: GhostTakeoverAvailable
|
||||||
makeSentient: true
|
makeSentient: true
|
||||||
name: Space dragon!
|
name: Space dragon
|
||||||
description: Crash, roast, flood the station with carps!
|
description: Call in 3 carp rifts and take over this quadrant! You have only 5 minutes in between each rift before you will disappear.
|
||||||
- type: Speech
|
- type: Speech
|
||||||
- type: CombatMode
|
- type: CombatMode
|
||||||
disarmAction:
|
disarmAction:
|
||||||
enabled: false
|
enabled: false
|
||||||
autoPopulate: false
|
autoPopulate: false
|
||||||
name: action-name-disarm
|
name: action-name-disarm
|
||||||
- type: MobMover
|
- type: MobMover
|
||||||
- type: InputMover
|
- type: InputMover
|
||||||
- type: MovementSpeedModifier
|
- type: MovementSpeedModifier
|
||||||
baseWalkSpeed : 5
|
baseWalkSpeed: 3
|
||||||
baseSprintSpeed : 5
|
baseSprintSpeed: 5
|
||||||
- type: Sprite
|
weightlessModifier: 1.5
|
||||||
sprite: Mobs/Aliens/Carps/dragon.rsi
|
- type: RandomSprite
|
||||||
noRot: true
|
available:
|
||||||
# TODO: Randomise colors when RandomSpriteColor isn't poopoo
|
- enum.DamageStateVisualLayers.Base:
|
||||||
layers:
|
alive: Rainbow
|
||||||
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
- type: Sprite
|
||||||
state: alive
|
sprite: Mobs/Aliens/Carps/dragon.rsi
|
||||||
- map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
netsync: false
|
||||||
state: alive-unshaded
|
noRot: true
|
||||||
shader: unshaded
|
layers:
|
||||||
- type: Appearance
|
- map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
- type: DamageStateVisuals
|
state: alive
|
||||||
states:
|
- map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||||
Alive:
|
state: alive-unshaded
|
||||||
Base: alive
|
shader: unshaded
|
||||||
BaseUnshaded: alive-unshaded
|
- type: Appearance
|
||||||
Critical:
|
- type: DamageStateVisuals
|
||||||
Base: crit
|
states:
|
||||||
Dead:
|
Alive:
|
||||||
Base: dead
|
Base: alive
|
||||||
BaseUnshaded: dead-unshaded
|
BaseUnshaded: alive-unshaded
|
||||||
- type: Physics
|
Critical:
|
||||||
bodyType: KinematicController
|
Base: crit
|
||||||
- type: Fixtures
|
Dead:
|
||||||
fixtures:
|
Base: dead
|
||||||
- shape:
|
BaseUnshaded: dead-unshaded
|
||||||
!type:PhysShapeCircle
|
- type: Physics
|
||||||
radius: 0.40
|
bodyType: KinematicController
|
||||||
mass: 50
|
- type: Fixtures
|
||||||
mask:
|
fixtures:
|
||||||
- FlyingMobMask
|
- shape:
|
||||||
layer:
|
!type:PhysShapeCircle
|
||||||
- FlyingMobLayer
|
radius: 0.40
|
||||||
- type: MobState
|
mass: 50
|
||||||
thresholds:
|
mask:
|
||||||
0: Alive
|
- FlyingMobMask
|
||||||
450: Critical
|
layer:
|
||||||
500: Dead
|
- FlyingMobLayer
|
||||||
- type: Metabolizer
|
- type: MobState
|
||||||
solutionOnBody: false
|
thresholds:
|
||||||
updateFrequency: 0.25
|
0: Alive
|
||||||
metabolizerTypes: [Dragon]
|
450: Critical
|
||||||
groups:
|
500: Dead
|
||||||
- id: Medicine
|
- type: Metabolizer
|
||||||
- id: Poison
|
solutionOnBody: false
|
||||||
- type: MovementIgnoreGravity
|
updateFrequency: 0.25
|
||||||
- type: NoSlip
|
metabolizerTypes: [ Dragon ]
|
||||||
- type: Butcherable
|
groups:
|
||||||
spawned:
|
- id: Medicine
|
||||||
- id: FoodMeatDragon
|
- id: Poison
|
||||||
amount: 2
|
- type: MovementAlwaysTouching
|
||||||
- type: InteractionPopup
|
- type: NoSlip
|
||||||
successChance: 0.25 # It's no goose, but you better smell like carp.
|
- type: Butcherable
|
||||||
interactSuccessString: petting-success-dragon
|
spawned:
|
||||||
interactFailureString: petting-failure-dragon
|
- id: FoodMeatDragon
|
||||||
interactFailureSound:
|
amount: 2
|
||||||
path: /Audio/Animals/space_dragon_roar.ogg
|
- type: InteractionPopup
|
||||||
soundPerceivedByOthers: false # A 75% chance for a loud roar would get old fast.
|
successChance: 0.25 # It's no goose, but you better smell like carp.
|
||||||
- type: MeleeWeapon
|
interactSuccessString: petting-success-dragon
|
||||||
hitSound:
|
interactFailureString: petting-failure-dragon
|
||||||
path: /Audio/Effects/bite.ogg
|
interactFailureSound:
|
||||||
damage:
|
path: /Audio/Animals/space_dragon_roar.ogg
|
||||||
types:
|
soundPerceivedByOthers: false # A 75% chance for a loud roar would get old fast.
|
||||||
Piercing: 15
|
- type: MeleeWeapon
|
||||||
Slash: 15
|
hitSound:
|
||||||
- type: Dragon
|
path: /Audio/Effects/bite.ogg
|
||||||
spawnsLeft: 2
|
damage:
|
||||||
spawnsProto: MobCarpDragon
|
types:
|
||||||
devourAction:
|
Piercing: 15
|
||||||
event: !type:DragonDevourActionEvent
|
Slash: 15
|
||||||
icon: Interface/Actions/devour.png
|
- type: Dragon
|
||||||
name: action-name-devour
|
spawnsLeft: 2
|
||||||
description: action-description-devour
|
spawnsProto: MobCarpDragon
|
||||||
devourChemical: Ichor
|
devourAction:
|
||||||
devourHealRate: 15.0
|
event: !type:DragonDevourActionEvent
|
||||||
whitelist:
|
icon: Interface/Actions/devour.png
|
||||||
components:
|
name: action-name-devour
|
||||||
- MobState
|
description: action-description-devour
|
||||||
- Door
|
devourChemical: Ichor
|
||||||
tags:
|
devourHealRate: 15.0
|
||||||
- Wall
|
whitelist:
|
||||||
spawnAction:
|
components:
|
||||||
event: !type:DragonSpawnActionEvent
|
- MobState
|
||||||
icon: Interface/Actions/carp_summon.png
|
- Door
|
||||||
name: action-name-carp-summon
|
tags:
|
||||||
description: action-description-carp-summon
|
- Wall
|
||||||
useDelay: 5
|
spawnRiftAction:
|
||||||
|
event: !type:DragonSpawnRiftActionEvent
|
||||||
|
icon:
|
||||||
|
sprite: Interface/Actions/carp_rift.rsi
|
||||||
|
state: icon
|
||||||
|
name: action-name-carp-rift
|
||||||
|
description: action-description-carp-rift
|
||||||
|
useDelay: 1
|
||||||
|
|||||||
@@ -5,78 +5,94 @@
|
|||||||
id: MobGuardianBase
|
id: MobGuardianBase
|
||||||
description: guardian
|
description: guardian
|
||||||
components:
|
components:
|
||||||
- type: GhostTakeoverAvailable
|
- type: GhostTakeoverAvailable
|
||||||
makeSentient: true
|
makeSentient: true
|
||||||
name: Guardian
|
name: Guardian
|
||||||
description: Listen to your owner. Don't tank damage. Punch people hard.
|
description: Listen to your owner. Don't tank damage. Punch people hard.
|
||||||
- type: Input
|
- type: Input
|
||||||
context: "human"
|
context: "human"
|
||||||
- type: MobMover
|
- type: MobMover
|
||||||
- type: InputMover
|
- type: InputMover
|
||||||
- type: MovementSpeedModifier
|
- type: MovementSpeedModifier
|
||||||
baseWalkSpeed : 7
|
baseWalkSpeed: 4
|
||||||
baseSprintSpeed : 7
|
baseSprintSpeed: 5.5
|
||||||
- type: DamageOnHighSpeedImpact
|
- type: DamageOnHighSpeedImpact
|
||||||
damage:
|
damage:
|
||||||
types:
|
types:
|
||||||
Blunt: 5
|
Blunt: 5
|
||||||
soundHit:
|
soundHit:
|
||||||
path: /Audio/Effects/hit_kick.ogg
|
path: /Audio/Effects/hit_kick.ogg
|
||||||
# TODO: Randomise sprites and randomise the layer color
|
- type: RandomSprite
|
||||||
- type: Sprite
|
available:
|
||||||
drawdepth: Mobs
|
- enum.DamageStateVisualLayers.Base:
|
||||||
sprite: Mobs/Aliens/Guardians/guardians.rsi
|
magic_base: ""
|
||||||
layers:
|
enum.DamageStateVisualLayers.BaseUnshaded:
|
||||||
- state: tech_base
|
magic_flare: Sixteen
|
||||||
- state: tech_flare
|
- enum.DamageStateVisualLayers.Base:
|
||||||
color: "#40a7d7"
|
miner_base: ""
|
||||||
shader: unshaded
|
enum.DamageStateVisualLayers.BaseUnshaded:
|
||||||
noRot: true
|
miner_flare: Sixteen
|
||||||
- type: Clickable
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- type: InteractionOutline
|
tech_base: ""
|
||||||
- type: Physics
|
enum.DamageStateVisualLayers.BaseUnshaded:
|
||||||
bodyType: KinematicController
|
tech_flare: Sixteen
|
||||||
- type: Fixtures
|
- type: Sprite
|
||||||
fixtures:
|
drawdepth: Mobs
|
||||||
- shape:
|
sprite: Mobs/Aliens/Guardians/guardians.rsi
|
||||||
!type:PhysShapeCircle
|
netsync: false
|
||||||
radius: 0.35
|
layers:
|
||||||
mass: 10
|
- state: tech_base
|
||||||
mask:
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
- FlyingMobMask
|
- state: tech_flare
|
||||||
layer:
|
map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||||
- FlyingMobLayer
|
color: "#40a7d7"
|
||||||
- type: Damageable
|
shader: unshaded
|
||||||
damageContainer: Biological
|
noRot: true
|
||||||
- type: MobState
|
- type: Clickable
|
||||||
thresholds:
|
- type: InteractionOutline
|
||||||
0: Alive
|
- type: Physics
|
||||||
- type: HeatResistance
|
bodyType: KinematicController
|
||||||
- type: CombatMode
|
- type: Fixtures
|
||||||
- type: Internals
|
fixtures:
|
||||||
- type: Examiner
|
- shape:
|
||||||
- type: Speech
|
!type:PhysShapeCircle
|
||||||
- type: TypingIndicator
|
radius: 0.35
|
||||||
proto: guardian
|
mass: 10
|
||||||
- type: Pullable
|
mask:
|
||||||
- type: MeleeWeapon
|
- FlyingMobMask
|
||||||
range: 2
|
layer:
|
||||||
arcwidth: 30
|
- FlyingMobLayer
|
||||||
arc: fist
|
- type: Damageable
|
||||||
cooldownTime: 0.7
|
damageContainer: Biological
|
||||||
arcCooldownTime: 0.7
|
- type: MobState
|
||||||
damage:
|
thresholds:
|
||||||
types:
|
0: Alive
|
||||||
Blunt: 22
|
- type: HeatResistance
|
||||||
- type: Actions
|
- type: CombatMode
|
||||||
- type: Guardian
|
- type: Internals
|
||||||
- type: InteractionPopup
|
- type: Examiner
|
||||||
interactSuccessString: petting-success-holo
|
- type: Speech
|
||||||
interactFailureString: petting-failure-holo
|
- type: TypingIndicator
|
||||||
successChance: 0.7
|
proto: guardian
|
||||||
- type: Tag
|
- type: Pullable
|
||||||
tags:
|
- type: MeleeWeapon
|
||||||
- CannotSuicide
|
range: 2
|
||||||
|
arcwidth: 30
|
||||||
|
arc: fist
|
||||||
|
cooldownTime: 0.7
|
||||||
|
arcCooldownTime: 0.7
|
||||||
|
damage:
|
||||||
|
types:
|
||||||
|
Blunt: 22
|
||||||
|
- type: Actions
|
||||||
|
- type: Guardian
|
||||||
|
- type: InteractionPopup
|
||||||
|
interactSuccessString: petting-success-holo
|
||||||
|
interactFailureString: petting-failure-holo
|
||||||
|
successChance: 0.7
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- CannotSuicide
|
||||||
|
|
||||||
# From the uplink injector
|
# From the uplink injector
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -85,20 +101,22 @@
|
|||||||
parent: MobGuardianBase
|
parent: MobGuardianBase
|
||||||
description: A mesmerising whirl of hard-light patterns weaves a marvelous, yet oddly familiar visage. It stands proud, tuning into its owner's life to sustain itself.
|
description: A mesmerising whirl of hard-light patterns weaves a marvelous, yet oddly familiar visage. It stands proud, tuning into its owner's life to sustain itself.
|
||||||
components:
|
components:
|
||||||
- type: GhostTakeoverAvailable
|
- type: GhostTakeoverAvailable
|
||||||
makeSentient: true
|
makeSentient: true
|
||||||
name: Holoparasite
|
name: Holoparasite
|
||||||
description: Listen to your owner. Don't tank damage. Punch people hard.
|
description: Listen to your owner. Don't tank damage. Punch people hard.
|
||||||
- type: NameIdentifier
|
- type: NameIdentifier
|
||||||
group: Holoparasite
|
group: Holoparasite
|
||||||
- type: TypingIndicator
|
- type: TypingIndicator
|
||||||
proto: holo
|
proto: holo
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
layers:
|
layers:
|
||||||
- state: tech_base
|
- state: tech_base
|
||||||
- state: tech_flare
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
color: "#40a7d7"
|
- state: tech_flare
|
||||||
shader: unshaded
|
map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||||
|
color: "#40a7d7"
|
||||||
|
shader: unshaded
|
||||||
|
|
||||||
# From Wizard deck of cards
|
# From Wizard deck of cards
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -107,13 +125,19 @@
|
|||||||
id: MobIfritGuardian
|
id: MobIfritGuardian
|
||||||
description: A corrupted jinn, ripped from fitra to serve the wizard's petty needs. It stands wicked, tuning into it's owner's life to sustain itself.
|
description: A corrupted jinn, ripped from fitra to serve the wizard's petty needs. It stands wicked, tuning into it's owner's life to sustain itself.
|
||||||
components:
|
components:
|
||||||
- type: GhostTakeoverAvailable
|
- type: GhostTakeoverAvailable
|
||||||
makeSentient: true
|
makeSentient: true
|
||||||
name: Ifrit
|
name: Ifrit
|
||||||
description: Listen to your owner. Don't tank damage. Punch people hard.
|
description: Listen to your owner. Don't tank damage. Punch people hard.
|
||||||
- type: Sprite
|
- type: RandomSprite
|
||||||
layers:
|
available:
|
||||||
- state: magic_base
|
- enum.DamageStateVisualLayers.BaseUnshaded:
|
||||||
- state: magic_flare
|
magic_flare: Sixteen
|
||||||
color: "#d14730"
|
- type: Sprite
|
||||||
shader: unshaded
|
layers:
|
||||||
|
- state: magic_base
|
||||||
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
|
- state: magic_flare
|
||||||
|
map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||||
|
color: "#40a7d7"
|
||||||
|
shader: unshaded
|
||||||
|
|||||||
@@ -176,14 +176,20 @@
|
|||||||
- Nugget
|
- Nugget
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Consumable/Food/Baked/nuggets.rsi
|
sprite: Objects/Consumable/Food/Baked/nuggets.rsi
|
||||||
state: tendie
|
layers:
|
||||||
netsync: true
|
- state: tendie
|
||||||
- type: RandomSpriteState
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
spriteStates:
|
netsync: false
|
||||||
- tendie
|
- type: RandomSprite
|
||||||
- lizard
|
available:
|
||||||
- star
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- corgi
|
tendie: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
lizard: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
star: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
corgi: ""
|
||||||
- type: SolutionContainerManager
|
- type: SolutionContainerManager
|
||||||
solutions:
|
solutions:
|
||||||
food:
|
food:
|
||||||
|
|||||||
@@ -126,8 +126,13 @@
|
|||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Consumable/Food/egg.rsi
|
sprite: Objects/Consumable/Food/egg.rsi
|
||||||
state: icon
|
layers:
|
||||||
- type: RandomSpriteState
|
- state: icon
|
||||||
spriteStates:
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
- icon
|
netsync: false
|
||||||
- white
|
- type: RandomSprite
|
||||||
|
available:
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
icon: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
white: ""
|
||||||
|
|||||||
@@ -237,11 +237,16 @@
|
|||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Consumable/Food/frozen.rsi
|
sprite: Objects/Consumable/Food/frozen.rsi
|
||||||
state: stick
|
netsync: false
|
||||||
- type: RandomSpriteState
|
layers:
|
||||||
spriteStates:
|
- state: stick
|
||||||
- stick
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
- stick2
|
- type: RandomSprite
|
||||||
|
available:
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
stick: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
stick2: ""
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
|
|||||||
@@ -87,12 +87,14 @@
|
|||||||
tags:
|
tags:
|
||||||
- Raw
|
- Raw
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
netsync: true
|
netsync: false
|
||||||
state: bacon
|
state: bacon
|
||||||
- type: RandomSpriteState
|
- type: RandomSprite
|
||||||
spriteStates:
|
available:
|
||||||
- bacon
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- bacon2
|
bacon: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
bacon2: ""
|
||||||
- type: SolutionContainerManager
|
- type: SolutionContainerManager
|
||||||
solutions:
|
solutions:
|
||||||
food:
|
food:
|
||||||
@@ -501,11 +503,13 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: plate-meat
|
- state: plate-meat
|
||||||
- state: bacon-cooked
|
- state: bacon-cooked
|
||||||
- type: RandomSpriteState
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
spriteLayer: 1
|
- type: RandomSprite
|
||||||
spriteStates:
|
available:
|
||||||
- bacon-cooked
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- bacon2-cooked
|
bacon-cooked: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
bacon2-cooked: ""
|
||||||
- type: SolutionContainerManager
|
- type: SolutionContainerManager
|
||||||
solutions:
|
solutions:
|
||||||
food:
|
food:
|
||||||
@@ -608,12 +612,16 @@
|
|||||||
- type: Food
|
- type: Food
|
||||||
trash: FoodPlateSmall
|
trash: FoodPlateSmall
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
netsync: true
|
netsync: false
|
||||||
state: chicken-fried
|
layers:
|
||||||
- type: RandomSpriteState
|
- state: chicken-fried
|
||||||
spriteStates:
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
- chicken-fried
|
- type: RandomSprite
|
||||||
- chicken2-fried
|
available:
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
chicken-fried: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
chicken2-fried: ""
|
||||||
- type: SolutionContainerManager
|
- type: SolutionContainerManager
|
||||||
solutions:
|
solutions:
|
||||||
food:
|
food:
|
||||||
|
|||||||
@@ -5,13 +5,19 @@
|
|||||||
description: It's a shard of some unknown material.
|
description: It's a shard of some unknown material.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Materials/Shards/shard.rsi
|
layers:
|
||||||
state: shard1
|
- sprite: Objects/Materials/Shards/shard.rsi
|
||||||
- type: RandomSpriteState
|
state: shard1
|
||||||
spriteStates:
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
- shard1
|
netsync: false
|
||||||
- shard2
|
- type: RandomSprite
|
||||||
- shard3
|
available:
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
shard1: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
shard2: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
shard3: ""
|
||||||
- type: ItemCooldown
|
- type: ItemCooldown
|
||||||
- type: MeleeWeapon
|
- type: MeleeWeapon
|
||||||
damage:
|
damage:
|
||||||
|
|||||||
@@ -6,8 +6,10 @@
|
|||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Misc/books.rsi
|
sprite: Objects/Misc/books.rsi
|
||||||
|
netsync: false
|
||||||
layers:
|
layers:
|
||||||
- state: book0
|
- state: book0
|
||||||
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
- type: Paper
|
- type: Paper
|
||||||
- type: ActivatableUI
|
- type: ActivatableUI
|
||||||
key: enum.PaperUiKey.Key
|
key: enum.PaperUiKey.Key
|
||||||
@@ -21,15 +23,23 @@
|
|||||||
id: BookRandom
|
id: BookRandom
|
||||||
suffix: random
|
suffix: random
|
||||||
components:
|
components:
|
||||||
- type: RandomSpriteState
|
- type: RandomSprite
|
||||||
spriteLayer: 0
|
available:
|
||||||
spriteStates:
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- book0
|
book0: ""
|
||||||
- book1
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- book2
|
book1: ""
|
||||||
- book3
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- book4
|
book2: ""
|
||||||
- book5
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- book6
|
book3: ""
|
||||||
- book7
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- book8
|
book4: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
book5: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
book6: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
book7: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
book8: ""
|
||||||
|
|||||||
@@ -4,21 +4,34 @@
|
|||||||
id: Lighter
|
id: Lighter
|
||||||
description: "A simple plastic cigarette lighter."
|
description: "A simple plastic cigarette lighter."
|
||||||
components:
|
components:
|
||||||
- type: RandomSpriteState #this has to be before sprite component for the flame to toggle right because weldercomponent behaves weird (and i dont trust myself to fix it right)
|
# Sloth: What is this comment ?????????
|
||||||
spriteStates:
|
- type: RandomSprite #this has to be before sprite component for the flame to toggle right because weldercomponent behaves weird (and i dont trust myself to fix it right)
|
||||||
- basic_icon_base-1
|
available:
|
||||||
- basic_icon_base-2
|
- enum.WelderLayers.Base:
|
||||||
- basic_icon_base-3
|
basic_icon_base-1: ""
|
||||||
- basic_icon_base-4
|
- enum.WelderLayers.Base:
|
||||||
- basic_icon_base-5
|
basic_icon_base-2: ""
|
||||||
- basic_icon_base-6
|
- enum.WelderLayers.Base:
|
||||||
- basic_icon_base-7
|
basic_icon_base-3: ""
|
||||||
- basic_icon_base-8
|
- enum.WelderLayers.Base:
|
||||||
- basic_icon_base-9
|
basic_icon_base-4: ""
|
||||||
- basic_icon_base-10
|
- enum.WelderLayers.Base:
|
||||||
- basic_icon_base-11
|
basic_icon_base-5: ""
|
||||||
|
- enum.WelderLayers.Base:
|
||||||
|
basic_icon_base-6: ""
|
||||||
|
- enum.WelderLayers.Base:
|
||||||
|
basic_icon_base-7: ""
|
||||||
|
- enum.WelderLayers.Base:
|
||||||
|
basic_icon_base-8: ""
|
||||||
|
- enum.WelderLayers.Base:
|
||||||
|
basic_icon_base-9: ""
|
||||||
|
- enum.WelderLayers.Base:
|
||||||
|
basic_icon_base-10: ""
|
||||||
|
- enum.WelderLayers.Base:
|
||||||
|
basic_icon_base-11: ""
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Tools/lighters.rsi
|
sprite: Objects/Tools/lighters.rsi
|
||||||
|
netsync: false
|
||||||
layers:
|
layers:
|
||||||
- state: icon_map
|
- state: icon_map
|
||||||
map: ["enum.WelderLayers.Base"]
|
map: ["enum.WelderLayers.Base"]
|
||||||
@@ -69,16 +82,10 @@
|
|||||||
id: CheapLighter
|
id: CheapLighter
|
||||||
description: "A dangerously inexpensive plastic lighter, don't burn your thumb!"
|
description: "A dangerously inexpensive plastic lighter, don't burn your thumb!"
|
||||||
components:
|
components:
|
||||||
- type: RandomSpriteColor
|
- type: RandomSprite
|
||||||
state: cheap_icon_base
|
available:
|
||||||
colors:
|
- enum.WelderLayers.Base:
|
||||||
blue: "#1861d5"
|
cheap_icon_base: Rainbow
|
||||||
red: "#951710"
|
|
||||||
pink: "#d5188d"
|
|
||||||
brown: "#a05212"
|
|
||||||
green: "#0e7f1b"
|
|
||||||
cyan: "#18a2d5"
|
|
||||||
yellow: "#d58c18" #all colours proudly stolen from wirecutters
|
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Tools/lighters.rsi
|
sprite: Objects/Tools/lighters.rsi
|
||||||
layers:
|
layers:
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
- Wirecutter
|
- Wirecutter
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Tools/wirecutters.rsi
|
sprite: Objects/Tools/wirecutters.rsi
|
||||||
|
netsync: false
|
||||||
layers:
|
layers:
|
||||||
- state: cutters-map
|
- state: cutters
|
||||||
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
- state: cutters-cutty-thingy
|
- state: cutters-cutty-thingy
|
||||||
- type: ItemCooldown
|
- type: ItemCooldown
|
||||||
- type: MeleeWeapon
|
- type: MeleeWeapon
|
||||||
@@ -26,16 +28,10 @@
|
|||||||
- Cutting
|
- Cutting
|
||||||
useSound:
|
useSound:
|
||||||
path: /Audio/Items/wirecutter.ogg
|
path: /Audio/Items/wirecutter.ogg
|
||||||
- type: RandomSpriteColor
|
- type: RandomSprite
|
||||||
state: cutters
|
available:
|
||||||
colors:
|
- enum.DamageStateVisualLayers.Base:
|
||||||
blue: "#1861d5"
|
cutters: Rainbow
|
||||||
red: "#951710"
|
|
||||||
pink: "#d5188d"
|
|
||||||
brown: "#a05212"
|
|
||||||
green: "#0e7f1b"
|
|
||||||
cyan: "#18a2d5"
|
|
||||||
yellow: "#d58c18"
|
|
||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tools/wirecutters.rsi
|
sprite: Objects/Tools/wirecutters.rsi
|
||||||
|
|
||||||
@@ -53,8 +49,10 @@
|
|||||||
- Screwdriver
|
- Screwdriver
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Tools/screwdriver.rsi
|
sprite: Objects/Tools/screwdriver.rsi
|
||||||
|
netsync: false
|
||||||
layers:
|
layers:
|
||||||
- state: screwdriver-map
|
- state: screwdriver
|
||||||
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
- state: screwdriver-screwybits
|
- state: screwdriver-screwybits
|
||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tools/screwdriver.rsi
|
sprite: Objects/Tools/screwdriver.rsi
|
||||||
@@ -68,16 +66,10 @@
|
|||||||
- Screwing
|
- Screwing
|
||||||
useSound:
|
useSound:
|
||||||
collection: Screwdriver
|
collection: Screwdriver
|
||||||
- type: RandomSpriteColor
|
- type: RandomSprite
|
||||||
state: screwdriver
|
available:
|
||||||
colors:
|
- enum.DamageStateVisualLayers.Base:
|
||||||
blue: "#1861d5"
|
screwdriver: Rainbow
|
||||||
red: "#ff0000"
|
|
||||||
pink: "#d5188d"
|
|
||||||
brown: "#a05212"
|
|
||||||
green: "#0e7f1b"
|
|
||||||
cyan: "#18a2d5"
|
|
||||||
yellow: "#ffa500"
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: wrench
|
name: wrench
|
||||||
|
|||||||
@@ -9,15 +9,21 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: base
|
- state: base
|
||||||
- state: book-0
|
- state: book-0
|
||||||
- type: RandomSpriteState
|
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||||
spriteLayer: 1
|
- type: RandomSprite
|
||||||
spriteStates:
|
available:
|
||||||
- book-0
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- book-1
|
book-0: ""
|
||||||
- book-2
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- book-3
|
book-1: ""
|
||||||
- book-4
|
- enum.DamageStateVisualLayers.Base:
|
||||||
- book-5
|
book-2: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
book-3: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
book-4: ""
|
||||||
|
- enum.DamageStateVisualLayers.Base:
|
||||||
|
book-5: ""
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageModifierSet: Wood
|
damageModifierSet: Wood
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
|
|||||||
39
Resources/Prototypes/Entities/Structures/Specific/dragon.yml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
- type: entity
|
||||||
|
id: CarpRift
|
||||||
|
name: carp rift
|
||||||
|
description: A rift akin to the ones space carp use to travel long distances.
|
||||||
|
placement:
|
||||||
|
mode: SnapgridCenter
|
||||||
|
components:
|
||||||
|
- type: DragonRift
|
||||||
|
- type: Transform
|
||||||
|
anchored: true
|
||||||
|
- type: Physics
|
||||||
|
bodyType: Static
|
||||||
|
- type: Fixtures
|
||||||
|
- type: Sprite
|
||||||
|
netsync: false
|
||||||
|
layers:
|
||||||
|
- sprite: Structures/Specific/carp_rift.rsi
|
||||||
|
state: icon
|
||||||
|
color: "#569fff"
|
||||||
|
shader: unshaded
|
||||||
|
- type: InteractionOutline
|
||||||
|
- type: Clickable
|
||||||
|
- type: PointLight
|
||||||
|
enabled: true
|
||||||
|
color: "#366db5"
|
||||||
|
radius: 10.0
|
||||||
|
energy: 5.0
|
||||||
|
netsync: false
|
||||||
|
- type: Damageable
|
||||||
|
damageContainer: Inorganic
|
||||||
|
damageModifierSet: Metallic
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 300
|
||||||
|
behaviors:
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: [ "Destruction" ]
|
||||||
@@ -32,6 +32,17 @@
|
|||||||
earliestStart: 15
|
earliestStart: 15
|
||||||
maxOccurrences: 3
|
maxOccurrences: 3
|
||||||
|
|
||||||
|
- type: gameRule
|
||||||
|
id: Dragon
|
||||||
|
config:
|
||||||
|
!type:StationEventRuleConfiguration
|
||||||
|
id: Dragon
|
||||||
|
weight: 10
|
||||||
|
endAfter: 2
|
||||||
|
earliestStart: 15
|
||||||
|
maxOccurrences: 7
|
||||||
|
minimumPlayers: 15
|
||||||
|
|
||||||
- type: gameRule
|
- type: gameRule
|
||||||
id: FalseAlarm
|
id: FalseAlarm
|
||||||
config:
|
config:
|
||||||
|
|||||||
@@ -1,4 +1,16 @@
|
|||||||
- type: palette
|
- type: palette
|
||||||
|
id: Rainbow
|
||||||
|
name: Rainbow
|
||||||
|
colors:
|
||||||
|
blue: "#1861d5"
|
||||||
|
red: "#951710"
|
||||||
|
pink: "#d5188d"
|
||||||
|
brown: "#a05212"
|
||||||
|
green: "#0e7f1b"
|
||||||
|
cyan: "#18a2d5"
|
||||||
|
yellow: "#d58c18"
|
||||||
|
|
||||||
|
- type: palette
|
||||||
id: Sixteen
|
id: Sixteen
|
||||||
name: Sixteen
|
name: Sixteen
|
||||||
colors:
|
colors:
|
||||||
|
|||||||
BIN
Resources/Textures/Interface/Actions/carp_rift.rsi/icon.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
21
Resources/Textures/Interface/Actions/carp_rift.rsi/meta.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "https://github.com/tgstation/tgstation/blob/19da0cee1869bad0186d54d6bcd8a55ed30b9db6/icons/obj/carp_rift.dmi",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -33,29 +33,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "crit",
|
"name": "base",
|
||||||
"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
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "alive",
|
|
||||||
"directions": 4,
|
"directions": 4,
|
||||||
"delays": [
|
"delays": [
|
||||||
[
|
[
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 473 B |
@@ -14,10 +14,7 @@
|
|||||||
"name": "dead"
|
"name": "dead"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "crit"
|
"name": "base",
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "alive",
|
|
||||||
"directions": 4,
|
"directions": 4,
|
||||||
"delays": [
|
"delays": [
|
||||||
[
|
[
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.6 KiB |
BIN
Resources/Textures/Mobs/Aliens/Carps/space.rsi/base.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Resources/Textures/Mobs/Aliens/Carps/space.rsi/base_dead.png
Normal file
|
After Width: | Height: | Size: 517 B |
|
Before Width: | Height: | Size: 293 B |
|
Before Width: | Height: | Size: 294 B |
BIN
Resources/Textures/Mobs/Aliens/Carps/space.rsi/dead_mouth.png
Normal file
|
After Width: | Height: | Size: 135 B |
@@ -11,13 +11,39 @@
|
|||||||
"name": "icon"
|
"name": "icon"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "dead"
|
"name": "mouth",
|
||||||
|
"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
|
||||||
|
]
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "crit"
|
"name": "dead_mouth"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "alive",
|
"name": "base_dead"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "base",
|
||||||
"directions": 4,
|
"directions": 4,
|
||||||
"delays": [
|
"delays": [
|
||||||
[
|
[
|
||||||
|
|||||||
BIN
Resources/Textures/Mobs/Aliens/Carps/space.rsi/mouth.png
Normal file
|
After Width: | Height: | Size: 590 B |
@@ -1 +0,0 @@
|
|||||||
Eventually we'll have some kind of unifying "RandomSpriteStateComponent" but til now i'm just leaving these here in protest.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Eventually we'll have some kind of unifying "RandomSpriteStateComponent" but til now i'm just leaving these here in protest.
|
|
||||||
BIN
Resources/Textures/Structures/Specific/carp_rift.rsi/icon.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "https://github.com/tgstation/tgstation/blob/19da0cee1869bad0186d54d6bcd8a55ed30b9db6/icons/obj/carp_rift.dmi",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||