Skip to content

Commit

Permalink
Дрейк и база для мегафауны (#941)
Browse files Browse the repository at this point in the history
## Описание PR
<!-- Что вы изменили в этом пулл реквесте? -->
уэээ

## Почему / Баланс
<!-- Почему оно было изменено? Ссылайтесь на любые обсуждения или
вопросы здесь. Пожалуйста, обсудите, как это повлияет на игровой баланс.
-->
уэээ
**Ссылка на публикацию в Discord**
<!-- Укажите ссылки на соответствующие обсуждения, проблемы, баги,
заказы в разработку или предложения
- [Технические проблемы](ссылка)
- [Баги](ссылка)
- [Заказы-разработка](ссылка)
- [Предложения](ссылка)
- [Перенос контента](ссылка)-->

## Техническая информация
<!-- Если речь идет об изменении кода, кратко изложите на высоком уровне
принцип работы нового кода. Это облегчает рецензирование.- -->

## Медиа
<!--
Пулл реквесты, которые вносят внутриигровые изменения (добавление
одежды, предметов, новых возможностей и т.д.), должны содержать медиа,
демонстрирующие изменения.
Небольшие исправления/рефакторы не требуют медиа.

Если Вы не уверены в том, что Ваш пулл реквест требует медиа, спросите
мейнтейнера.
-->

## Требования
<!--
В связи с наплывом ПР'ов нам необходимо убедиться, что ПР'ы следуют
правильным рекомендациям.

Пожалуйста, уделите время прочтению, если делаете пулл реквест (ПР)
впервые.

Отметьте поля ниже, чтобы подтвердить, что Вы действительно видели их
(поставьте X в скобках, например [X]):
-->
- [ ] Я прочитал(а) и следую [Руководство по созданию пулл
реквестов](https://docs.spacestation14.com/en/general-development/codebase-info/pull-request-guidelines.html).
Я понимаю, что в противном случае мой ПР может быть закрыт по усмотрению
мейнтейнера.
- [ ] Я добавил скриншоты/видео к этому пулл реквесту, демонстрирующие
его изменения в игре, **или** этот пулл реквест не требует демонстрации
в игре

## Критические изменения
<!--
Перечислите все критические изменения, включая изменения пространства
имён, публичных классов/методов/полей, переименования прототипов, и
предоставьте инструкции по их исправлению.
-->

**Чейнджлог**
<!--
Здесь Вы можете заполнить журнал изменений, который будет автоматически
добавлен в игру при мердже Вашего пулл реквест.

Чтобы игроки узнали о новых возможностях и изменениях, которые могут
повлиять на их игру, добавьте запись в журнал изменений.

Не считайте суффикс типа записи (например, add) "частью" предложения:
плохо: - add: новый инструмент для инженеров
хорошо: - add: добавлен новый инструмент для инженеров

Помещение имени после символа 🆑 изменит имя, которое будет
отображаться в журнале изменений (в противном случае будет
использоваться ваше имя пользователя GitHub).
Например: 🆑 AruMoon
-->
<!--
Чтобы шаблон Чейнджлога отображался, уберите его из блока комментариев. 
Чейнджлог должен содержать cl символ, 
чтобы бот распознал изменения и добавил их в журнал изменений игры. 
Используйте ключевые слова add, remove, tweak и fix.
-->
🆑 Котя & Крыса
- fix: Исправлена генерация данжей. Они теперь снова появляются
корректно.
- tweak: Данжи стали чаще попадаться на лаваленде.
- add: Добавлен дрейк. Ввиду своей незавершённости - пока что лишь в
меню щитспавна. Можете попросить у админов организовать встречу, если
невтерпёж.

---------

Co-authored-by: Unlumination <[email protected]>
  • Loading branch information
FaDeOkno and Unlumy authored Jan 4, 2025
1 parent 44c7d28 commit bfbe905
Show file tree
Hide file tree
Showing 23 changed files with 1,011 additions and 20 deletions.
57 changes: 57 additions & 0 deletions Content.Client/ADT/Salvage/MegafaunaVisualsSystem.cs
Original file line number Diff line number Diff line change
@@ -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<MegafaunaComponent, AppearanceChangeEvent>(OnAppearanceChange);
}

private void OnAppearanceChange(EntityUid uid, MegafaunaComponent comp, ref AppearanceChangeEvent args)
{
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
if (!TryComp<DamageStateVisualsComponent>(uid, out var state))
return;
if (!TryComp<MobStateComponent>(uid, out var mob))
return;
if (!state.States.TryGetValue(mob.CurrentState, out var layers))
return;

if (_appearance.TryGetData<bool>(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);
}
}
}
}
112 changes: 112 additions & 0 deletions Content.Server/ADT/Salvage/Systems/Megafauna/MegafaunaSystem.Drake.cs
Original file line number Diff line number Diff line change
@@ -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<AshDrakeSwoopActionEvent>(OnSwoop);
SubscribeLocalEvent<AshDrakeMeteoritesActionEvent>(OnMeteors);
SubscribeLocalEvent<AshDrakeFireActionEvent>(OnFire);
SubscribeLocalEvent<AshDrakeBreathActionEvent>(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<GunComponent>(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<GunComponent>(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<GunComponent>(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");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Content.Server.ADT.Salvage.Systems;

public sealed partial class MegafaunaSystem : EntitySystem
{
}
25 changes: 20 additions & 5 deletions Content.Server/NPC/Components/NPCUseActionOnTargetComponent.cs
Original file line number Diff line number Diff line change
@@ -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: Компонент был полностью переписан, заменяйте при апстриме на нашу версию.

/// <summary>
/// This is used for an NPC that constantly tries to use an action on a given target.
/// </summary>
Expand All @@ -16,12 +19,24 @@ public sealed partial class NPCUseActionOnTargetComponent : Component
[DataField]
public string TargetKey = "Target";

/// <summary>
/// Action that's going to attempt to be used.
/// </summary>
// /// <summary>
// /// Action that's going to attempt to be used.
// /// </summary>
// [DataField(required: true)]
// public EntProtoId<EntityWorldTargetActionComponent> ActionId;

// [DataField]
// public EntityUid? ActionEnt;

[DataField(required: true)]
public EntProtoId<EntityWorldTargetActionComponent> ActionId;
public ProtoId<WeightedRandomEntityPrototype> Actions = "GoliathActions";

[ViewVariables]
public Dictionary<EntityUid, float> ActionEntities = new();

[DataField]
public EntityUid? ActionEnt;
public float Delay = 7f;

[ViewVariables]
public TimeSpan LastAction = TimeSpan.Zero;
}
47 changes: 40 additions & 7 deletions Content.Server/NPC/Systems/NPCUseActionOnTargetSystem.cs
Original file line number Diff line number Diff line change
@@ -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!;

/// <inheritdoc/>
public override void Initialize()
Expand All @@ -20,32 +26,56 @@ public override void Initialize()

private void OnMapInit(Entity<NPCUseActionOnTargetComponent> 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<NPCUseActionOnTargetComponent?> user, EntityUid target)
public bool TryUseAction(Entity<NPCUseActionOnTargetComponent?> user, EntityUid target)
{
if (!Resolve(user, ref user.Comp, false))
return false;

if (!TryComp<EntityWorldTargetActionComponent>(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;
}

Expand All @@ -57,10 +87,13 @@ public override void Update(float frameTime)
var query = EntityQueryEnumerator<NPCUseActionOnTargetComponent, HTNComponent>();
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<EntityUid>(comp.TargetKey, out var target, EntityManager))
continue;

TryUseTentacleAttack((uid, comp), target);
TryUseAction((uid, comp), target);
}
}
}
4 changes: 3 additions & 1 deletion Content.Server/Procedural/DungeonSystem.Rooms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions Content.Shared/ADT/Salvage/Components/MegafaunaComponent.cs
Original file line number Diff line number Diff line change
@@ -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;
}
26 changes: 26 additions & 0 deletions Content.Shared/ADT/Salvage/Events/ActionEvents.cs
Original file line number Diff line number Diff line change
@@ -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,
}
2 changes: 1 addition & 1 deletion Content.Shared/Projectiles/ProjectileEmbedEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ namespace Content.Shared.Projectiles;
/// Raised directed on an entity when it embeds into something.
/// </summary>
[ByRefEvent]
public readonly record struct ProjectileEmbedEvent(EntityUid? Shooter, EntityUid Weapon, EntityUid Embedded);
public readonly record struct ProjectileEmbedEvent(EntityUid? Shooter, EntityUid? Weapon, EntityUid Embedded);
2 changes: 1 addition & 1 deletion Content.Shared/Projectiles/SharedProjectileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
6 changes: 5 additions & 1 deletion Content.Shared/Weapons/Misc/SharedGrapplingGunSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<JointComponent>(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;
Expand Down
Loading

0 comments on commit bfbe905

Please sign in to comment.