From 44c7d28e6498de4f0c672a6bacb62b3fdd7b9f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Schr=C3=B6dinger?= <132720404+Schrodinger71@users.noreply.github.com> Date: Sat, 4 Jan 2025 21:27:05 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=92=D0=B5=D0=B1=D1=85=D1=83=D0=BA=D0=B0=20=D0=B0-=D1=87?= =?UTF-8?q?=D0=B0=D1=82=D0=B0=20(#942)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Небольшие правки форма текста no cl, no fun --- .../Administration/Managers/AdminManager.cs | 11 ++++------- Content.Server/Chat/Managers/ChatManager.cs | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Content.Server/Administration/Managers/AdminManager.cs b/Content.Server/Administration/Managers/AdminManager.cs index c0cb1ca83ac..a57237eb20c 100644 --- a/Content.Server/Administration/Managers/AdminManager.cs +++ b/Content.Server/Administration/Managers/AdminManager.cs @@ -111,7 +111,7 @@ public async void DeAdmin(ICommonSession session) // ADT-tweak: add "async" return; var payload = new WebhookPayload { - Content = $"**Снял права**: **{session.Name}**" + Content = $"**Снял права**: `{session.Name}`" }; var identifier = webhookData.ToIdentifier(); await _discord.CreateMessage(identifier, payload); @@ -198,7 +198,7 @@ public async void ReAdmin(ICommonSession session) // ADT-tweak: add "async" return; var payload = new WebhookPayload { - Content = $"**Вернул права**: **{session.Name}**" + Content = $"**Вернул права**: `{session.Name}`" }; var identifier = webhookData.ToIdentifier(); await _discord.CreateMessage(identifier, payload); @@ -407,7 +407,7 @@ private async void DisconnectedAdminMaybe(ICommonSession session) return; var payload = new WebhookPayload { - Content = $"**Оповещение: Админ ВЫШЕЛ {senderName}**" + Content = $"**Оповещение: Админ ВЫШЕЛ** `{senderName}`" }; var identifier = webhookData.ToIdentifier(); await _discord.CreateMessage(identifier, payload); @@ -459,14 +459,11 @@ private async void LoginAdminMaybe(ICommonSession session) var senderAdmin = GetAdminData(session); if (senderAdmin == null) return; - var senderName = session.Name; - if (!string.IsNullOrEmpty(senderAdmin.Title)) - senderName += $"\\[{senderAdmin.Title}\\]"; if (await _discord.GetWebhook(webhookUrl) is not { } webhookData) return; var payload = new WebhookPayload { - Content = $"**Оповещение: Админ зашёл {senderName}**" + Content = $"**Оповещение: Админ ЗАШЁЛ** `{session.Name}`[{senderAdmin.Title}]" }; var identifier = webhookData.ToIdentifier(); await _discord.CreateMessage(identifier, payload); diff --git a/Content.Server/Chat/Managers/ChatManager.cs b/Content.Server/Chat/Managers/ChatManager.cs index e21ff29c9db..ddb9738d54b 100644 --- a/Content.Server/Chat/Managers/ChatManager.cs +++ b/Content.Server/Chat/Managers/ChatManager.cs @@ -331,7 +331,7 @@ private async void SendAdminChat(ICommonSession player, string message) return; var payload = new WebhookPayload { - Content = $"***AdminChat***: **{senderName}**: {message}" + Content = $"***AdminChat***: `{player.Name}`[{senderAdmin.Title}]: {message}" }; var identifier = webhookData.ToIdentifier(); await _discord.CreateMessage(identifier, payload); From bfbe905d24bb8cdc241e5682b0a58f45e749ebde Mon Sep 17 00:00:00 2001 From: FaDeOkno <143940725+FaDeOkno@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:28:13 +0400 Subject: [PATCH 2/2] =?UTF-8?q?=D0=94=D1=80=D0=B5=D0=B9=D0=BA=20=D0=B8=20?= =?UTF-8?q?=D0=B1=D0=B0=D0=B7=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=BC=D0=B5?= =?UTF-8?q?=D0=B3=D0=B0=D1=84=D0=B0=D1=83=D0=BD=D1=8B=20(#941)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Описание PR уэээ ## Почему / Баланс уэээ **Ссылка на публикацию в Discord** ## Техническая информация ## Медиа ## Требования - [ ] Я прочитал(а) и следую [Руководство по созданию пулл реквестов](https://docs.spacestation14.com/en/general-development/codebase-info/pull-request-guidelines.html). Я понимаю, что в противном случае мой ПР может быть закрыт по усмотрению мейнтейнера. - [ ] Я добавил скриншоты/видео к этому пулл реквесту, демонстрирующие его изменения в игре, **или** этот пулл реквест не требует демонстрации в игре ## Критические изменения **Чейнджлог** :cl: Котя & Крыса - fix: Исправлена генерация данжей. Они теперь снова появляются корректно. - tweak: Данжи стали чаще попадаться на лаваленде. - add: Добавлен дрейк. Ввиду своей незавершённости - пока что лишь в меню щитспавна. Можете попросить у админов организовать встречу, если невтерпёж. --------- Co-authored-by: Unlumination <144041835+Unlumy@users.noreply.github.com> --- .../ADT/Salvage/MegafaunaVisualsSystem.cs | 57 ++ .../Megafauna/MegafaunaSystem.Drake.cs | 112 ++++ .../Systems/Megafauna/MegafaunaSystem.cs | 5 + .../NPCUseActionOnTargetComponent.cs | 25 +- .../NPC/Systems/NPCUseActionOnTargetSystem.cs | 47 +- .../Procedural/DungeonSystem.Rooms.cs | 4 +- .../Salvage/Components/MegafaunaComponent.cs | 10 + .../ADT/Salvage/Events/ActionEvents.cs | 26 + .../Projectiles/ProjectileEmbedEvent.cs | 2 +- .../Projectiles/SharedProjectileSystem.cs | 2 +- .../Weapons/Misc/SharedGrapplingGunSystem.cs | 6 +- Resources/Prototypes/ADT/Actions/lava.yml | 65 ++ .../Entities/Mobs/NPCs/Megafauna/Drake.yml | 596 ++++++++++++++++++ .../ADT/Entities/Mobs/NPCs/lavaland.yml | 9 +- .../ADT/Procedural/biome_templates.yml | 4 +- .../Entities/Mobs/NPCs/asteroid.yml | 7 +- .../ADT/Effects/target_circle.rsi/icon.png | Bin 0 -> 733 bytes .../ADT/Effects/target_circle.rsi/meta.json | 23 + .../Mobs/Aliens/Lavaland/drake.rsi/dragon.png | Bin 0 -> 4268 bytes .../Aliens/Lavaland/drake.rsi/dragon_dead.png | Bin 0 -> 2358 bytes .../Mobs/Aliens/Lavaland/drake.rsi/meta.json | 31 + .../Mobs/Aliens/Lavaland/drake.rsi/shadow.png | Bin 0 -> 489 bytes .../Mobs/Aliens/Lavaland/drake.rsi/swoop.png | Bin 0 -> 9666 bytes 23 files changed, 1011 insertions(+), 20 deletions(-) create mode 100644 Content.Client/ADT/Salvage/MegafaunaVisualsSystem.cs create mode 100644 Content.Server/ADT/Salvage/Systems/Megafauna/MegafaunaSystem.Drake.cs create mode 100644 Content.Server/ADT/Salvage/Systems/Megafauna/MegafaunaSystem.cs create mode 100644 Content.Shared/ADT/Salvage/Components/MegafaunaComponent.cs create mode 100644 Content.Shared/ADT/Salvage/Events/ActionEvents.cs create mode 100644 Resources/Prototypes/ADT/Entities/Mobs/NPCs/Megafauna/Drake.yml create mode 100644 Resources/Textures/ADT/Effects/target_circle.rsi/icon.png create mode 100644 Resources/Textures/ADT/Effects/target_circle.rsi/meta.json create mode 100644 Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/dragon.png create mode 100644 Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/dragon_dead.png create mode 100644 Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/meta.json create mode 100644 Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/shadow.png create mode 100644 Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/swoop.png diff --git a/Content.Client/ADT/Salvage/MegafaunaVisualsSystem.cs b/Content.Client/ADT/Salvage/MegafaunaVisualsSystem.cs new file mode 100644 index 00000000000..f966151fb46 --- /dev/null +++ b/Content.Client/ADT/Salvage/MegafaunaVisualsSystem.cs @@ -0,0 +1,57 @@ +using Content.Client.DamageState; +using Content.Client.Humanoid; +using Content.Shared.ADT.Salvage; +using Content.Shared.ADT.Salvage.Components; +using Content.Shared.Mobs.Components; +using Robust.Client.GameObjects; +using Robust.Client.Player; +using Robust.Client.UserInterface; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Client.ADT.Salvage; + +public sealed class MegafaunaVisualsSystem : EntitySystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!; + [Dependency] private readonly IPlayerManager _playerMan = default!; + [Dependency] private readonly SpriteSystem _spriteSystem = default!; + [Dependency] private readonly HumanoidAppearanceSystem _appearanceSystem = default!; + [Dependency] private readonly IEntityManager _entManager = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAppearanceChange); + } + + private void OnAppearanceChange(EntityUid uid, MegafaunaComponent comp, ref AppearanceChangeEvent args) + { + if (!TryComp(uid, out var sprite)) + return; + if (!TryComp(uid, out var state)) + return; + if (!TryComp(uid, out var mob)) + return; + if (!state.States.TryGetValue(mob.CurrentState, out var layers)) + return; + + if (_appearance.TryGetData(uid, AshdrakeVisuals.Swoop, out var swoop)) + { + if (!sprite.LayerMapTryGet("drake_swoop", out var index)) + index = sprite.LayerMapReserveBlank("drake_swoop"); + sprite.LayerSetState(index, "swoop"); + sprite.LayerSetVisible(index, swoop); + + foreach (var (key, _) in layers) + { + if (!sprite.LayerMapTryGet(key, out var layer)) continue; + sprite.LayerSetVisible(layer, !swoop); + } + } + } +} diff --git a/Content.Server/ADT/Salvage/Systems/Megafauna/MegafaunaSystem.Drake.cs b/Content.Server/ADT/Salvage/Systems/Megafauna/MegafaunaSystem.Drake.cs new file mode 100644 index 00000000000..6dd4762012d --- /dev/null +++ b/Content.Server/ADT/Salvage/Systems/Megafauna/MegafaunaSystem.Drake.cs @@ -0,0 +1,112 @@ +using System.Numerics; +using Content.Server.Actions; +using Content.Server.ADT.Language; +using Content.Server.ADT.Salvage.Components; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; +using Content.Server.Interaction; +using Content.Server.Polymorph.Systems; +using Content.Server.Popups; +using Content.Server.Stunnable; +using Content.Server.Weapons.Ranged.Systems; +using Content.Shared.Access.Systems; +using Content.Shared.ADT.Language; +using Content.Shared.ADT.Salvage; +using Content.Shared.ADT.Salvage.Components; +using Content.Shared.Chasm; +using Content.Shared.Damage; +using Content.Shared.Damage.Prototypes; +using Content.Shared.Interaction.Events; +using Content.Shared.Inventory; +using Content.Shared.Lathe; +using Content.Shared.Mobs.Systems; +using Content.Shared.Popups; +using Content.Shared.Weapons.Ranged.Components; +using Robust.Server.Audio; +using Robust.Server.GameObjects; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Containers; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Server.ADT.Salvage.Systems; + +public sealed partial class MegafaunaSystem +{ + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly StunSystem _stun = default!; + [Dependency] private readonly AppearanceSystem _appearance = default!; + [Dependency] private readonly PolymorphSystem _polymorph = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly GunSystem _gun = default!; + [Dependency] private readonly TransformSystem _transform = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnSwoop); + SubscribeLocalEvent(OnMeteors); + SubscribeLocalEvent(OnFire); + SubscribeLocalEvent(OnBreath); + } + + private void OnSwoop(AshDrakeSwoopActionEvent args) + { + var uid = args.Performer; + + _appearance.SetData(uid, AshdrakeVisuals.Swoop, true); + + _stun.TryStun(uid, TimeSpan.FromSeconds(0.5f), false); + Timer.Spawn(TimeSpan.FromSeconds(0.5f), () => Swoop(uid)); + } + + private void OnMeteors(AshDrakeMeteoritesActionEvent args) + { + var uid = args.Performer; + + var randVector = _random.NextVector2(6); + + var pseudoGun = Spawn("WeaponDragonMeteorites", Transform(uid).Coordinates); + _gun.AttemptShoot(uid, pseudoGun, Comp(pseudoGun), new(Transform(uid).ParentUid, randVector.X, randVector.Y)); + QueueDel(pseudoGun); + _stun.TryStun(uid, TimeSpan.FromSeconds(0.5f), false); + } + + private void OnFire(AshDrakeFireActionEvent args) + { + var uid = args.Performer; + if (!args.Coords.HasValue) + return; + + var coords = args.Coords.Value; + + var pseudoGun = Spawn("WeaponDragonFire", Transform(uid).Coordinates); + _gun.AttemptShoot(uid, pseudoGun, Comp(pseudoGun), coords); + QueueDel(pseudoGun); + _stun.TryStun(uid, TimeSpan.FromSeconds(0.5f), false); + } + + private void OnBreath(AshDrakeBreathActionEvent args) + { + var uid = args.Performer; + if (!args.Coords.HasValue) + return; + + var coords = args.Coords.Value; + + var pseudoGun = Spawn("WeaponDragonBreath", Transform(uid).Coordinates); + _gun.AttemptShoot(uid, pseudoGun, Comp(pseudoGun), coords); + QueueDel(pseudoGun); + _stun.TryStun(uid, TimeSpan.FromSeconds(0.5f), false); + } + + private void Swoop(EntityUid uid) + { + _appearance.SetData(uid, AshdrakeVisuals.Swoop, false); + _polymorph.PolymorphEntity(uid, "SwoopDrake"); + } +} diff --git a/Content.Server/ADT/Salvage/Systems/Megafauna/MegafaunaSystem.cs b/Content.Server/ADT/Salvage/Systems/Megafauna/MegafaunaSystem.cs new file mode 100644 index 00000000000..d3f2993cd35 --- /dev/null +++ b/Content.Server/ADT/Salvage/Systems/Megafauna/MegafaunaSystem.cs @@ -0,0 +1,5 @@ +namespace Content.Server.ADT.Salvage.Systems; + +public sealed partial class MegafaunaSystem : EntitySystem +{ +} diff --git a/Content.Server/NPC/Components/NPCUseActionOnTargetComponent.cs b/Content.Server/NPC/Components/NPCUseActionOnTargetComponent.cs index f022a45eccb..f9498ffd079 100644 --- a/Content.Server/NPC/Components/NPCUseActionOnTargetComponent.cs +++ b/Content.Server/NPC/Components/NPCUseActionOnTargetComponent.cs @@ -1,9 +1,12 @@ using Content.Server.NPC.Systems; using Content.Shared.Actions; +using Content.Shared.Random; using Robust.Shared.Prototypes; namespace Content.Server.NPC.Components; +// ADT: Компонент был полностью переписан, заменяйте при апстриме на нашу версию. + /// /// This is used for an NPC that constantly tries to use an action on a given target. /// @@ -16,12 +19,24 @@ public sealed partial class NPCUseActionOnTargetComponent : Component [DataField] public string TargetKey = "Target"; - /// - /// Action that's going to attempt to be used. - /// + // /// + // /// Action that's going to attempt to be used. + // /// + // [DataField(required: true)] + // public EntProtoId ActionId; + + // [DataField] + // public EntityUid? ActionEnt; + [DataField(required: true)] - public EntProtoId ActionId; + public ProtoId Actions = "GoliathActions"; + + [ViewVariables] + public Dictionary ActionEntities = new(); [DataField] - public EntityUid? ActionEnt; + public float Delay = 7f; + + [ViewVariables] + public TimeSpan LastAction = TimeSpan.Zero; } diff --git a/Content.Server/NPC/Systems/NPCUseActionOnTargetSystem.cs b/Content.Server/NPC/Systems/NPCUseActionOnTargetSystem.cs index 33bc8f9074c..c793eedd8c1 100644 --- a/Content.Server/NPC/Systems/NPCUseActionOnTargetSystem.cs +++ b/Content.Server/NPC/Systems/NPCUseActionOnTargetSystem.cs @@ -1,14 +1,20 @@ +using System.Linq; using Content.Server.NPC.Components; using Content.Server.NPC.HTN; using Content.Shared.Actions; +using Content.Shared.Random.Helpers; +using Robust.Shared.Prototypes; using Robust.Shared.Timing; namespace Content.Server.NPC.Systems; +// ADT: Система была полностью переписан, заменяйте при апстриме на нашу версию. + public sealed class NPCUseActionOnTargetSystem : EntitySystem { [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly SharedActionsSystem _actions = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; /// public override void Initialize() @@ -20,32 +26,56 @@ public override void Initialize() private void OnMapInit(Entity ent, ref MapInitEvent args) { - ent.Comp.ActionEnt = _actions.AddAction(ent, ent.Comp.ActionId); + var weights = _proto.Index(ent.Comp.Actions); + foreach (var item in weights.Weights) + { + var actionEnt = _actions.AddAction(ent, item.Key); + if (actionEnt.HasValue) + ent.Comp.ActionEntities.Add(actionEnt.Value, item.Value); + } } - public bool TryUseTentacleAttack(Entity user, EntityUid target) + public bool TryUseAction(Entity user, EntityUid target) { if (!Resolve(user, ref user.Comp, false)) return false; - if (!TryComp(user.Comp.ActionEnt, out var action)) + var weights = _proto.Index(user.Comp.Actions); + var act = weights.Pick(); + var actionEntity = user.Comp.ActionEntities.Keys.Where(x => Prototype(x)?.ID == act).First(); + + if (!_actions.TryGetActionData(actionEntity, out var action)) return false; if (!_actions.ValidAction(action)) return false; - if (action.Event != null) + switch (action.BaseEvent) { - action.Event.Coords = Transform(target).Coordinates; + case InstantActionEvent instant: + break; + case EntityTargetActionEvent entityTarget: + entityTarget.Target = target; + break; + case EntityWorldTargetActionEvent entityWorldTarget: + entityWorldTarget.Entity = target; + entityWorldTarget.Coords = Transform(target).Coordinates; + break; + case WorldTargetActionEvent worldTarget: + worldTarget.Target = Transform(target).Coordinates; + break; } _actions.PerformAction(user, null, - user.Comp.ActionEnt.Value, + actionEntity, action, action.BaseEvent, _timing.CurTime, false); + + user.Comp.LastAction = _timing.CurTime; + return true; } @@ -57,10 +87,13 @@ public override void Update(float frameTime) var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp, out var htn)) { + if (_timing.CurTime < comp.LastAction + TimeSpan.FromSeconds(comp.Delay)) + continue; + if (!htn.Blackboard.TryGetValue(comp.TargetKey, out var target, EntityManager)) continue; - TryUseTentacleAttack((uid, comp), target); + TryUseAction((uid, comp), target); } } } diff --git a/Content.Server/Procedural/DungeonSystem.Rooms.cs b/Content.Server/Procedural/DungeonSystem.Rooms.cs index 43c7e225bda..83c243e71c7 100644 --- a/Content.Server/Procedural/DungeonSystem.Rooms.cs +++ b/Content.Server/Procedural/DungeonSystem.Rooms.cs @@ -186,7 +186,9 @@ public void SpawnRoom( _transform.SetLocalRotation(ent, childRot, childXform); // ADT - чиним тестер - if (grid == null || gridUid == childXform.GridUid) + _transform.AttachToGridOrMap(ent); + + if (grid == null || gridUid != childXform.GridUid) { Log.Debug("Спавнер данжа находится в космосе?"); return; diff --git a/Content.Shared/ADT/Salvage/Components/MegafaunaComponent.cs b/Content.Shared/ADT/Salvage/Components/MegafaunaComponent.cs new file mode 100644 index 00000000000..4554003910c --- /dev/null +++ b/Content.Shared/ADT/Salvage/Components/MegafaunaComponent.cs @@ -0,0 +1,10 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.ADT.Salvage.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class MegafaunaComponent : Component +{ + [DataField] + public bool Hardmode = false; +} diff --git a/Content.Shared/ADT/Salvage/Events/ActionEvents.cs b/Content.Shared/ADT/Salvage/Events/ActionEvents.cs new file mode 100644 index 00000000000..5e04b729000 --- /dev/null +++ b/Content.Shared/ADT/Salvage/Events/ActionEvents.cs @@ -0,0 +1,26 @@ +using Content.Shared.Actions; +using Robust.Shared.Serialization; + +namespace Content.Shared.ADT.Salvage; + +public sealed partial class AshDrakeSwoopActionEvent : InstantActionEvent +{ +} + +public sealed partial class AshDrakeMeteoritesActionEvent : InstantActionEvent +{ +} + +public sealed partial class AshDrakeFireActionEvent : EntityWorldTargetActionEvent +{ +} + +public sealed partial class AshDrakeBreathActionEvent : EntityWorldTargetActionEvent +{ +} + +[Serializable, NetSerializable] +public enum AshdrakeVisuals : byte +{ + Swoop, +} diff --git a/Content.Shared/Projectiles/ProjectileEmbedEvent.cs b/Content.Shared/Projectiles/ProjectileEmbedEvent.cs index e7dd6df8e29..675549c9d08 100644 --- a/Content.Shared/Projectiles/ProjectileEmbedEvent.cs +++ b/Content.Shared/Projectiles/ProjectileEmbedEvent.cs @@ -4,4 +4,4 @@ namespace Content.Shared.Projectiles; /// Raised directed on an entity when it embeds into something. /// [ByRefEvent] -public readonly record struct ProjectileEmbedEvent(EntityUid? Shooter, EntityUid Weapon, EntityUid Embedded); +public readonly record struct ProjectileEmbedEvent(EntityUid? Shooter, EntityUid? Weapon, EntityUid Embedded); diff --git a/Content.Shared/Projectiles/SharedProjectileSystem.cs b/Content.Shared/Projectiles/SharedProjectileSystem.cs index 85e75d6d291..4d7bf7a7f6c 100644 --- a/Content.Shared/Projectiles/SharedProjectileSystem.cs +++ b/Content.Shared/Projectiles/SharedProjectileSystem.cs @@ -106,7 +106,7 @@ private void OnEmbedProjectileHit(EntityUid uid, EmbeddableProjectileComponent c // Raise a specific event for projectiles. if (TryComp(uid, out ProjectileComponent? projectile)) { - var ev = new ProjectileEmbedEvent(projectile.Shooter!.Value, projectile.Weapon!.Value, args.Target); + var ev = new ProjectileEmbedEvent(projectile.Shooter, projectile.Weapon, args.Target); // ADT fix RaiseLocalEvent(uid, ref ev); } } diff --git a/Content.Shared/Weapons/Misc/SharedGrapplingGunSystem.cs b/Content.Shared/Weapons/Misc/SharedGrapplingGunSystem.cs index e790973538f..4f7a4d663e5 100644 --- a/Content.Shared/Weapons/Misc/SharedGrapplingGunSystem.cs +++ b/Content.Shared/Weapons/Misc/SharedGrapplingGunSystem.cs @@ -204,9 +204,13 @@ private void OnGrappleCollide(EntityUid uid, GrapplingProjectileComponent compon { if (!Timing.IsFirstTimePredicted) return; + // ADT fix start + if (!args.Shooter.HasValue || !args.Weapon.HasValue) + return; + // ADT fix end var jointComp = EnsureComp(uid); - var joint = _joints.CreateDistanceJoint(uid, args.Weapon, anchorA: new Vector2(0f, 0.5f), id: GrapplingJoint); + var joint = _joints.CreateDistanceJoint(uid, args.Weapon.Value, anchorA: new Vector2(0f, 0.5f), id: GrapplingJoint); joint.MaxLength = joint.Length + 0.2f; joint.Stiffness = 1f; joint.MinLength = 0.35f; diff --git a/Resources/Prototypes/ADT/Actions/lava.yml b/Resources/Prototypes/ADT/Actions/lava.yml index 79cee49e00c..89ee4a4480e 100644 --- a/Resources/Prototypes/ADT/Actions/lava.yml +++ b/Resources/Prototypes/ADT/Actions/lava.yml @@ -1,3 +1,4 @@ +# Игроки - type: entity id: ActionPumpCursedHeart name: action-pump-heart @@ -12,6 +13,7 @@ event: !type:PumpHeartActionEvent useDelay: 1 +# Фауна - type: entity id: ActionAncientGoliathTentacle name: "[color=red]Tentacle Slam[/color]" @@ -30,3 +32,66 @@ event: !type:GoliathSummonRandomTentacleAction useDelay: 1 range: 10 + +# Мегафауна +- type: entity + id: ActionDrakeFire + name: "[color=red]Dragon Fire[/color]" + description: fshhhhh + components: + - type: EntityWorldTargetAction + raiseOnUser: true + icon: + sprite: Mobs/Aliens/Asteroid/goliath.rsi + state: goliath_tentacle_spawn + iconOn: + sprite: Mobs/Aliens/Asteroid/goliath.rsi + state: goliath_tentacle_wiggle + event: !type:AshDrakeFireActionEvent + useDelay: 10 + range: 15 + +- type: entity + id: ActionDrakeBreath + name: "[color=red]Dragon Breath[/color]" + description: fshhhhh + components: + - type: EntityWorldTargetAction + raiseOnUser: true + icon: + sprite: Mobs/Aliens/Asteroid/goliath.rsi + state: goliath_tentacle_spawn + iconOn: + sprite: Mobs/Aliens/Asteroid/goliath.rsi + state: goliath_tentacle_wiggle + event: !type:AshDrakeBreathActionEvent + useDelay: 9 + range: 15 + +- type: entity + id: ActionDrakeMeteors + name: "[color=red]Meteorites![/color]" + description: fshhhhh + components: + - type: InstantAction + raiseOnUser: true + icon: + sprite: ADT/Objects/Specific/Lavaland/loot.rsi + state: cursed_heart + itemIconStyle: BigAction + event: !type:AshDrakeMeteoritesActionEvent + useDelay: 10 + +- type: entity + id: ActionDrakeSwoop + name: "[color=red]Fly[/color]" + description: fshhhhh + components: + - type: InstantAction + raiseOnUser: true + icon: + sprite: ADT/Objects/Specific/Lavaland/loot.rsi + state: cursed_heart + itemIconStyle: BigAction + event: !type:AshDrakeSwoopActionEvent + useDelay: 60 diff --git a/Resources/Prototypes/ADT/Entities/Mobs/NPCs/Megafauna/Drake.yml b/Resources/Prototypes/ADT/Entities/Mobs/NPCs/Megafauna/Drake.yml new file mode 100644 index 00000000000..0b5fdc3c6dd --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Mobs/NPCs/Megafauna/Drake.yml @@ -0,0 +1,596 @@ +#### Containers #### +- type: damageContainer + id: Drake + supportedGroups: + - Brute + - Toxin + - Airloss + - Genetic +#### Fire #### + +- type: entity + id: NazFire + name: огонь + placement: + mode: SnapgridCenter + snap: + - Wall + components: + - type: TileEntityEffect + effects: + - !type:FlammableReaction + multiplier: 0.5 + multiplierOnExisting: 0.75 + - !type:Ignite + - type: Sprite + sprite: Effects/fire.rsi + drawdepth: BelowFloor + layers: + - state: 1 + shader: unshaded + - type: Icon + sprite: Effects/fire.rsi + state: 1 + - type: TimedDespawn + lifetime: 1 + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.5,0.5,0.5" + layer: + - SlipLayer + mask: + - ItemMask + density: 1000 + hard: false + - type: Transform + anchored: true + - type: StepTrigger + requiredTriggeredSpeed: 0 + intersectRatio: 0.1 + blacklist: + tags: + - Catwalk + +#### Drake Projectiles #### + +- type: entity + id: BulletPistolHot + parent: BaseBulletIncendiary + name: bullet (.35 auto incendiary) + components: + - type: Projectile + damage: + types: + Heat: 15 + deleteOnCollide: false + - type: Timer + - type: TimedSpawner + prototypes: + - NazFire + chance: 1 + intervalSeconds: 0 + minimumEntitiesSpawned: 1 + maximumEntitiesSpawned: 1 + - type: TimedDespawn + lifetime: 2 + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/magic.rsi + layers: + - state: fireball + shader: unshaded + +- type: entity + id: BulletPistolMeteorites + parent: BaseBullet + name: bullet (.35 auto incendiary) + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/magic.rsi + layers: + - state: fireball + shader: unshaded + - type: Projectile + damage: + types: + Heat: 0 + deleteOnCollide: false + - type: TimedDespawn + lifetime: 1 + - type: Timer + - type: TimedSpawner + prototypes: + - FireballSignal + chance: 0.25 + intervalSeconds: 0 + minimumEntitiesSpawned: 1 + maximumEntitiesSpawned: 1 + +- type: entity + id: BulletFirethrow + parent: BaseBulletIncendiary + name: firethrow + components: + - type: Projectile + damage: + types: + Heat: 2 + Structural: 10 + deleteOnCollide: true + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/magic.rsi + layers: + - state: fireball + shader: unshaded + - type: TimedDespawn + lifetime: 0.68 + +- type: entity + id: FireballSignal + parent: BaseEffectGoliathTentacleSpawn + name: сигнал + components: + - type: SpawnOnDespawn + prototype: MeteorInstaExplosion + - type: Transform + anchored: True + - type: Physics + bodyType: Static + canCollide: false + - type: Sprite + drawdepth: Overdoors + sprite: ADT/Effects/target_circle.rsi + state: icon + - type: InteractionOutline + - type: TimedDespawn + lifetime: 2 + - type: PointLight + energy: 0.3 + radius: 1 + color: "#ff0000" + +- type: entity + name: drake fire barrage + id: LavalandDrakeFireBarrage + categories: [ HideSpawnMenu ] + parent: BulletPistolHot + components: + - type: ProjectileSpread + proto: BulletPistolHot + count: 3 #52 heat damage if you hit all your shots, but narrower spread + spread: 65 + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/magic.rsi + layers: + - state: fireball + shader: unshaded + +- type: entity + name: drake meteorites + id: LavalandDrakeMeteorBarrage + categories: [ HideSpawnMenu ] + parent: BulletPistolMeteorites + components: + - type: ProjectileSpread + proto: BulletPistolMeteorites + count: 36 #52 heat damage if you hit all your shots, but narrower spread + spread: 360 + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/magic.rsi + layers: + - state: fireball + shader: unshaded + +#### Drake itself №№№№ + +- type: entity + id: BaseMobDrake + parent: BaseMobAsteroid + name: пепельный дракон + abstract: true + description: + components: + - type: Destructible + thresholds: + - trigger: + !type:DamageTypeTrigger + damageType: Blunt + damage: 9000 + behaviors: + - !type:GibBehavior { } + - trigger: + !type:DamageTypeTrigger + damageType: Heat + damage: 100000 + behaviors: + - !type:SpawnEntitiesBehavior + spawnInContainer: true + spawn: + Ash: + min: 1 + max: 1 + - !type:BurnBodyBehavior { } + - !type:PlaySoundBehavior + sound: + collection: MeatLaserImpact + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 1 + density: 80 + mask: + - MobMask + layer: + - MobLayer + - type: Sprite + sprite: ADT/Mobs/Aliens/Lavaland/drake.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: dragon + - type: DamageStateVisuals + states: + Alive: + Base: dragon + Dead: + Base: dragon_dead + - type: MovementSpeedModifier + baseWalkSpeed : 1 + baseSprintSpeed : 2.5 + - type: MobThresholds + thresholds: + 0: Alive + 1350: Dead + - type: MeleeWeapon + soundHit: + path: "/Audio/Weapons/smash.ogg" + angle: 0 + attackRate: 1 + animation: WeaponArcPunch + damage: + types: + Blunt: 45 + Structural: 150 + range: 2 + - type: NpcFactionMember + factions: + - SimpleHostile + - type: Tag + tags: + - CannotSuicide + - DoorBumpOpener + - type: NoSlip + - type: Damageable + damageContainer: Drake + - type: ExplosionResistance + damageCoefficient: 0 + - type: NPCUseActionOnTarget + actions: DrakeActions + delay: 5 + - type: HTN + rootTask: + task: GoliathCompound + blackboard: + VisionRadius: !type:Single + 6 + AggroVisionRadius: !type:Single + 25 + - type: Fauna + - type: Megafauna + +- type: entity + id: MobDrake + parent: [ BaseMobDrake, BaseMobAsteroid ] + name: пепельный дракон + +#### Drake polymorphs + +- type: polymorph + id: SwoopDrake + configuration: + entity: MobDrakeSwoop #Not angry so ghosts can't just take over the wizard + transferName: true + inventory: None + revertOnDeath: true + revertOnCrit: true + duration: 4 + +- type: entity + id: MobDrakeSwoop + parent: BaseMobDrake + name: "Полёт" + description: + components: + - type: Sprite + sprite: ADT/Mobs/Aliens/Lavaland/drake.rsi + scale: 0.5, 0.5 + color: "#FFFFFF77" + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: shadow + - type: DamageStateVisuals + states: + Alive: + Base: shadow + Dead: + Base: dragon_dead + - type: MovementSpeedModifier + baseWalkSpeed : 4 + baseSprintSpeed : 8 + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 0.35 + density: 15 + layer: + - GhostImpassable + - type: MovementIgnoreGravity + - type: RepeatingTrigger + delay: 3.9 + - type: SpawnOnTrigger + proto: IgniteRuneDrake + - type: Timer + - type: TimedSpawner + prototypes: + - FireballSignalFlight + chance: 0.15 + intervalSeconds: 0 + minimumEntitiesSpawned: 1 + maximumEntitiesSpawned: 1 + - type: MeleeWeapon + soundHit: + path: "/Audio/Weapons/smash.ogg" + angle: 0 + attackRate: 0.01 + animation: WeaponArcPunch + damage: + types: + Blunt: 0 + range: 1 + +### Drake rune ### + +- type: entity + parent: CollideRune + id: IgniteRuneDrake + name: "руна" + components: + - type: Sprite + sprite: Structures/Magic/Cult/trap.rsi + scale: 3, 3 + layers: + - state: trap + color: '#FF000055' + - type: SpawnOnDespawn + prototype: DrakeRuneInstaExplosion + - type: TimedDespawn + lifetime: 0.5 + +#### Explosions #### + +- type: entity + name: Meteorite Instant Explosion + parent: BasePlasticExplosive + id: MeteorInstaExplosion + components: + - type: TriggerOnSpawn + - type: Sprite + sprite: ADT/Mobs/Phantom/phantom.rsi + drawdepth: Effects + layers: + - state: haunt + map: ["base"] + - type: Explosive + explosionType: FireBomb + totalIntensity: 2 + intensitySlope: 100 + maxIntensity: 2 + canCreateVacuum: false + deleteAfterExplosion: false + - type: ExplodeOnTrigger + - type: TimedDespawn + lifetime: 0.1 + +- type: entity + name: Drake Rune Instant Explosion + parent: BasePlasticExplosive + id: DrakeRuneInstaExplosion + components: + - type: TriggerOnSpawn + - type: Sprite + sprite: ADT/Mobs/Phantom/phantom.rsi + drawdepth: Effects + layers: + - state: haunt + map: ["base"] + - type: Explosive + explosionType: FireBomb + totalIntensity: 50 + intensitySlope: 5 + maxIntensity: 25 + canCreateVacuum: false + deleteAfterExplosion: false + - type: ExplodeOnTrigger + - type: TimedDespawn + lifetime: 0.1 + +### Signals ### + +- type: entity + id: FireballSignalPeriodic + parent: BaseEffectGoliathTentacleSpawn + name: сигнал + components: + - type: SpawnOnDespawn + prototype: MeteorInstaExplosion + - type: Transform + anchored: True + - type: Physics + bodyType: Static + canCollide: false + - type: Sprite + drawdepth: Overdoors + sprite: ADT/Effects/target_circle.rsi + state: icon + - type: InteractionOutline + - type: TimedDespawn + lifetime: 2.0 + - type: PointLight + energy: 0.3 + radius: 1 + color: "#ff0000" + - type: SpawnOnTrigger + proto: FirefallMeteors + - type: RepeatingTrigger + delay: 1.55 + + +- type: entity + id: FireballSignalFlight + parent: BaseEffectGoliathTentacleSpawn + name: сигнал + components: + - type: SpawnOnDespawn + prototype: MeteorInstaExplosion + - type: Transform + anchored: True + - type: Physics + bodyType: Static + canCollide: false + - type: Sprite + drawdepth: Overdoors + sprite: ADT/Effects/target_circle.rsi + state: icon + - type: InteractionOutline + - type: TimedDespawn + lifetime: 1.3 + - type: PointLight + energy: 0.3 + radius: 1 + color: "#ff0000" + + +#### Firefall #### + +- type: entity + id: FirefallMeteors + parent: BaseEffectGoliathTentacleSpawn + name: сигнал + components: + - type: Transform + anchored: True + - type: Physics + bodyType: Static + canCollide: false + - type: Sprite + drawdepth: Overdoors + sprite: Objects/Weapons/Guns/Projectiles/magic.rsi + layers: + - state: fireball + shader: unshaded + offset: 0, 1.7 + - type: InteractionOutline + - type: TimedDespawn + lifetime: 0.60 + +#### Random Actions #### + +- type: weightedRandomEntity + id: DrakeActions + weights: + ActionDrakeFire: 0.4 + ActionDrakeBreath: 0.2 + ActionDrakeSwoop: 0.2 + ActionDrakeMeteors: 0.2 + +#### Pseudo-guns #### +- type: entity + id: WeaponDragonFire + parent: BaseWeaponHeavyMachineGun + name: огненный плевок + description: + components: + - type: Gun + fireRate: 1 + projectileSpeed: 10 + soundGunshot: + path: /Audio/Magic/fireball.ogg + params: + volume: -10 + - type: BasicEntityAmmoProvider + proto: LavalandDrakeFireBarrage + capacity: 1 + count: 1 + - type: RechargeBasicEntityAmmo + rechargeCooldown: 4 + - type: Unremoveable + - type: Sprite + sprite: ADT/Mobs/Phantom/phantom.rsi + drawdepth: Effects + layers: + - state: haunt + +- type: entity + id: WeaponDragonMeteorites + parent: BaseWeaponHeavyMachineGun + name: метеоритный дождь + description: Горящие пламенем космические обьекты подчиняются вашей воли, разрушая все в округе + components: + - type: Gun + fireRate: 1 + projectileSpeed: 25 + soundGunshot: + path: /Audio/Magic/fireball.ogg + params: + volume: -10 + - type: BasicEntityAmmoProvider + proto: LavalandDrakeMeteorBarrage + capacity: 1 + count: 1 + - type: RechargeBasicEntityAmmo + rechargeCooldown: 25 + - type: Unremoveable + - type: Sprite + sprite: ADT/Mobs/Phantom/phantom.rsi + drawdepth: Effects + layers: + - state: haunt + +- type: entity + name: дыхание дракона + id: WeaponDragonBreath + parent: BaseWeaponHeavyMachineGun + description: Выпускает горячее пламя из вашей пасти, сжигая всё на своём пути. + components: + - type: Gun + fireRate: 10 + projectileSpeed: 8 + soundGunshot: + path: /Audio/Magic/fireball.ogg + params: + volume: -10 + - type: BallisticAmmoProvider + proto: BulletFirethrow + capacity: 69000 + - type: MagazineVisuals + magState: mag + steps: 4 + zeroVisible: true + - type: Appearance + - type: ContainerContainer + containers: + ballistic-ammo: !type:Container + ents: [] + - type: Unremoveable + - type: Sprite + sprite: ADT/Mobs/Phantom/phantom.rsi + drawdepth: Effects + layers: + - state: haunt diff --git a/Resources/Prototypes/ADT/Entities/Mobs/NPCs/lavaland.yml b/Resources/Prototypes/ADT/Entities/Mobs/NPCs/lavaland.yml index 7944778c61c..2a1b8cc3341 100644 --- a/Resources/Prototypes/ADT/Entities/Mobs/NPCs/lavaland.yml +++ b/Resources/Prototypes/ADT/Entities/Mobs/NPCs/lavaland.yml @@ -163,4 +163,11 @@ Slash: 20 Piercing: 5 - type: NPCUseActionOnTarget - actionId: ActionAncientGoliathTentacle + actions: AncientGoliathActions + delay: 3 + +- type: weightedRandomEntity + id: AncientGoliathActions + weights: + ActionAncientGoliathTentacle: 0.5 + ActionGoliathTentacle: 0.5 diff --git a/Resources/Prototypes/ADT/Procedural/biome_templates.yml b/Resources/Prototypes/ADT/Procedural/biome_templates.yml index b7ccc0e49bd..70fdffabf11 100644 --- a/Resources/Prototypes/ADT/Procedural/biome_templates.yml +++ b/Resources/Prototypes/ADT/Procedural/biome_templates.yml @@ -55,11 +55,11 @@ entities: - ADTSpawnMobPRandomLavaland - !type:BiomeEntityLayer - threshold: 0.997 + threshold: 0.995 noise: seed: 0 noiseType: OpenSimplex2 - frequency: 0.4 + frequency: 0.6 lacunarity: 0.6 allowedTiles: - FloorBasalt diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml b/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml index 3d3a4a02868..6a998caaccd 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml @@ -78,7 +78,7 @@ AggroVisionRadius: !type:Single 10 - type: NPCUseActionOnTarget - actionId: ActionGoliathTentacle + actions: GoliathActions - type: Tag tags: - CannotSuicide @@ -336,3 +336,8 @@ size: Normal - type: StaticPrice price: 500 + +- type: weightedRandomEntity + id: GoliathActions + weights: + ActionGoliathTentacle: 1 diff --git a/Resources/Textures/ADT/Effects/target_circle.rsi/icon.png b/Resources/Textures/ADT/Effects/target_circle.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..dc1ee4cdbc85dac09c742047d83ada3ea16a9743 GIT binary patch literal 733 zcmeAS@N?(olHy`uVBq!ia0vp^3xHUGgAGVdtuOuxq!^2X+?^QKos)S9a~60+7BevL9RXp+soH$f3=B*~o-U3d6>)E8#`-ZE^0bKi9hJ7_ZGV+{ zO8U6dI-!)MkLRas{%ZDPveu#_GdIR|ue!bc_SzBr9=ZKT_Pb?o~{VnHRkg8?4T5|QTYW9Ms|5h`1^z6*Ab+4Xt z(aj_3#P&}-|2Nez92LGKo6WHI-yV7Q>;7N9IdqG&PvG`s+VkPJTeG{f)9%+-=RWn1 z_&#y^)AhU$dZhMBbxf?Xu$eaD(ZlHzY&(m8+%;3=J$--nWuE_BZ#|`g_PJl}cPQNa z*S2a)|G6a<04W}5fanG2sjoEf)S;^oDc@-E-`jPjlQmCt$Q+wT3_(%#DWMb>{-?o&w%O2=b$uW$oIKArMHHNUTcl)y$EW?a8cTI~pdEdHW z&edP{Z5vM7xUm(O`u$h1ikvNTKxGORJR$cttIUpbBHl79-vg5*gQu&X%Q~loCIIx( BS|9)b literal 0 HcmV?d00001 diff --git a/Resources/Textures/ADT/Effects/target_circle.rsi/meta.json b/Resources/Textures/ADT/Effects/target_circle.rsi/meta.json new file mode 100644 index 00000000000..a7bfd0ec23d --- /dev/null +++ b/Resources/Textures/ADT/Effects/target_circle.rsi/meta.json @@ -0,0 +1,23 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from /tg/station at icons/mob/telegraphing/telegraph.dmi", + "states": [ + { + "name": "icon", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + } + ] +} diff --git a/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/dragon.png b/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/dragon.png new file mode 100644 index 0000000000000000000000000000000000000000..b2d616fda95eef48fb1063eec929cf42faae0735 GIT binary patch literal 4268 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/dragon_dead.png b/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/dragon_dead.png new file mode 100644 index 0000000000000000000000000000000000000000..8fcfed241ba662c1127e5e9c06afd51aa3cd3102 GIT binary patch literal 2358 zcmd6p`9IT-1IOQE*qoDNE3%`xQtrYB+Zfr}`tVuFnGcgfaz2CzxpHq-%*PkGMWJJ4 z5poj=Q9_RILX$f~Qr|xR#rKEj>-l*82d@;nKW(JMkB9>RAVnrw(SF$Tu+9d9&60_hSBpM@>ylH&Lb|{m$`bpnqLRqeG%d zQYTjb|0PNvi7Xih>F2)H)$|nA>!$%Q#)`W-QbP+wYK}C^P1H~VA^iW?S%dmk4)ym6 zUMZ*cp8)_~({;HcYJ18|!^=xq<9PWZZJ@7icWa7y3~8r8VBs$mtF?^}od$0+40B!Q z&Efa%ZdW?ps)7QWlbQLtl{;$^e5F+b|81i8y^`HpPPL8#h{P}TeAwP<-yp?%CeG)U zzF3ONIGc>Y9+>;8z?@sA+rNX@Q7fAUQk%EmiOj}l6z;}yKSWP)3U(*Vnu4v*2+)R! zDNZMK%B*ok^PuTV@WFc%wq7^tkurpqD0j-w&k~}=DQ?4T7`bQ3f}LQ2=oPzhs#f~4 zi@=o~F_*zMm?Ofso1o6A*=NcCOesPBLRlrL19a65 zr7u}NpNrmsQMVs|OO0|Fx^6F<6_LiU%)FMUtT{?#{V4EJ1gfBfWt%85E+Tmj;gXCB zxy=#8m8( z+-$Dw96f|W3b*==Rtm!B^SM<+y=vOArVol?w0p@>cONpD`Krb~4%IUW;S8qmX3&fu zZtogu40ZwT9OgB+R1z4^OS4MHX(gkOopQkf`5xhnUsz<$8>kWInj@as2oB!z-^g!WsPSJCTdvrH$Uj>g6hA~3@j-i#2#?6&JsPj9f7D6@#RXK{ zCvz0HzHxd^6gTK_Zuoo#!0|>f?Y$9~;|1%Yar3>451ika3_7+>9099|pvCv6_BVc% zb&IBm6EI}DwZrMD7;S!7U(d!9Mn{72PS=AB?)=ALTPA_QTg7Xc^#ig!;t7>qf8sQF<*$Lc4Q=5scg~5M3_m30l zFNh^3ZpM&7eCazSB&tp!hVfzw3!en@3*68@S2(6*`mzM zfvD~Pk}Q%LH2onqj~Ec^_(7&m23DPGce~L70smSKgBVfV{&t0!Mo^Uuj(;4wiv*RG zN(ps29T2P$q^=A4pij{uPP)OoK_AQ19g88pZ^dbR@yf#dq3Y}w6 zE`o0gsk9xaQ}L(`?xRWltK;JDY0at_LvA4|h9PM2TRS_48e6F4AY}=|tqb|ZnA|_*AnjJK0-DcE z%vng1Bd{2rT5+0=i0@CPjRP#+CG8Ir18q$joxOug;!)ayCXrb}TrD{dPtQqG%fs4_rgGm@Bb4I2F(L5K?7O*vtLR|8!2 z=G`KEUfW->_E1YP(mSgXhqAQ(Bv%WmBe0Ux8{_q`9!Uu1M~4#!+rj8ZF#mE+X7z@IpW*Ot-^)wdgVj3pU6ubxOmQ= z>dVIN)Gq*y$3h9qp}SU=Olo^Ch&0gF{)0w8ZA*{A0Gz0=@o#HvPJ@H6@ERlD+84{D z0?mpjCJ7P;p|*fo>lFdc1Lo7_4L253;alzd0X5=<_wT#Z-oree!N?O?m)`Z94)H{1 zW$A7al=8-ATyu?}p&-$~^8GM$vlnHhv!=fNcGzRjs9a-2VW;{W<0U literal 0 HcmV?d00001 diff --git a/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/meta.json b/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/meta.json new file mode 100644 index 00000000000..2e3cd70d351 --- /dev/null +++ b/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/meta.json @@ -0,0 +1,31 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from /tg/station at https://scrubby.melonmesa.com/dmi/icons/mob/simple/lavaland/96x96megafauna.dmi?codebase=tgstation", + "size": { + "x": 96, + "y": 96 + }, + "states": [ + { + "name": "dragon", + "directions": 4 + }, + { + "name": "dragon_dead" + }, + { + "name": "swoop", + "delays": [ + [ + 0.1, + 0.2, + 500 + ] + ] + }, + { + "name": "shadow" + } + ] +} diff --git a/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/shadow.png b/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..3a8262de0483711ce10e820113f12a45f8285ab0 GIT binary patch literal 489 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!Wi-X*q7}lMWc?smOq&xaLGB9lH z=l+w(3goi|_=LCuX&_jdzVkegVk!yp3;xgWbi08UkjGiz5n0T@z;^_M8K-LVNdpax z^K@|x$#8z#7hQD3fP>}j?|7@Kp44m>Db179f<=EN^YX0tZej1kp`tjU#X*S46UI0x zFL)!`dwZ7V^WzUWPQ~n5@My~N@)*a?i?=)+S#$X}-4|Gp{4DdSJlC!&5BDflM4u85R@N~FOUvmx+-`^iMT)1ZpUXO@ GgeCxHjk#0+ literal 0 HcmV?d00001 diff --git a/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/swoop.png b/Resources/Textures/ADT/Mobs/Aliens/Lavaland/drake.rsi/swoop.png new file mode 100644 index 0000000000000000000000000000000000000000..f3c4122a117ec0e2e2cbe6223613c06da88c06b4 GIT binary patch literal 9666 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