Upstream core (#284)
* [Feature] Holo Update (#948) * Это база, основа, фундамент. * update icons * based2 * zamena headcoder * протоНовые функции Обновлены окна персонажа для отображения статистики и навыков игрока. Добавлена система боевой музыки, которая активируется во время боя. Реализована функция широковещательной передачи сообщений в чате для нескольких получателей. Внедрены изменения на основе навыков и статистики для медицинских систем, включая дефибриллятор и лечение. Улучшена система ближнего боя с новыми действиями и сообщениями. Введена система предсказуемого рандома для продвинутой генерации случайных значений. Навыки и статистика теперь зависят от назначений на работу. * abilities * zvuk * tweaks & fixes * sprite fix * govno * govno2 * fix govna * GOVNOOOOOOOOOOOO * finally * цена (cherry picked from commit cf4a7d0a7ccb780905e0df7db80d60d2338c02d0) * Automatic changelog update (cherry picked from commit 32a1f13849b4593fa03eafff99179814278f5f11) --------- Co-authored-by: RavmorganButOnCocaine <valtos@nextmail.ru>
This commit is contained in:
114
Content.Client/_White/Guardian/GuardianSelectorBUI.cs
Normal file
114
Content.Client/_White/Guardian/GuardianSelectorBUI.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using Content.Client._White.UserInterface.Radial;
|
||||
using Content.Shared._White.Guardian;
|
||||
|
||||
namespace Content.Client._White.Guardian;
|
||||
|
||||
public sealed class GuardianSelectorBUI : BoundUserInterface
|
||||
{
|
||||
private readonly Dictionary<GuardianSelector, string> _names = new()
|
||||
{
|
||||
{ GuardianSelector.Assasin, Loc.GetString("guardian-assasin-name")},
|
||||
{ GuardianSelector.Charger, Loc.GetString("guardian-charger-name")},
|
||||
{ GuardianSelector.Lighting, Loc.GetString("guardian-lighting-name")},
|
||||
{ GuardianSelector.Standart, Loc.GetString("guardian-standart-name")},
|
||||
};
|
||||
|
||||
private readonly Dictionary<GuardianSelector, string> _icons = new()
|
||||
{
|
||||
{ GuardianSelector.Assasin, "/Textures/White/Interface/guardianselector.rsi/assasin.png" },
|
||||
{ GuardianSelector.Charger, "/Textures/White/Interface/guardianselector.rsi/charger.png" },
|
||||
{ GuardianSelector.Lighting, "/Textures/White/Interface/guardianselector.rsi/lighting.png" },
|
||||
{ GuardianSelector.Standart, "/Textures/White/Interface/guardianselector.rsi/standart.png" },
|
||||
};
|
||||
|
||||
private readonly Dictionary<string, GuardianSelector> _guardianSelectors = new()
|
||||
{
|
||||
{ "Assasin", GuardianSelector.Assasin },
|
||||
{ "Charger", GuardianSelector.Charger },
|
||||
{ "Lighting", GuardianSelector.Lighting },
|
||||
{ "Standart", GuardianSelector.Standart },
|
||||
};
|
||||
|
||||
private RadialContainer? _radialContainer;
|
||||
private bool _updated;
|
||||
|
||||
public GuardianSelectorBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
if (_radialContainer != null)
|
||||
UIReset();
|
||||
|
||||
_radialContainer = new RadialContainer();
|
||||
|
||||
_radialContainer.Closed += Close;
|
||||
|
||||
if (State != null)
|
||||
UpdateState(State);
|
||||
}
|
||||
|
||||
private void UIReset()
|
||||
{
|
||||
_radialContainer?.Close();
|
||||
_radialContainer = null;
|
||||
_updated = false;
|
||||
}
|
||||
|
||||
private void PopulateRadial(IReadOnlyCollection<string> ids, NetEntity target)
|
||||
{
|
||||
foreach (var id in ids)
|
||||
{
|
||||
if (_radialContainer == null)
|
||||
continue;
|
||||
|
||||
if(!_guardianSelectors.TryGetValue(id, out var guardianSelector))
|
||||
return;
|
||||
|
||||
if(!_names.TryGetValue(guardianSelector, out var name) || !_icons.TryGetValue(guardianSelector, out var icon))
|
||||
return;
|
||||
|
||||
var button = _radialContainer.AddButton(name, icon);
|
||||
button.Controller.OnPressed += _ =>
|
||||
{
|
||||
Select(guardianSelector, target);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void Select(GuardianSelector type, NetEntity target)
|
||||
{
|
||||
SendMessage(new GuardianSelectorSelectedBuiMessage(type, target));
|
||||
UIReset();
|
||||
Close();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
_radialContainer?.Close();
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (_updated)
|
||||
return;
|
||||
|
||||
if (state is GuardianSelectorBUIState newState)
|
||||
{
|
||||
PopulateRadial(newState.Ids, newState.Target);
|
||||
}
|
||||
|
||||
if (_radialContainer == null)
|
||||
return;
|
||||
|
||||
_radialContainer?.OpenAttachedLocalPlayer();
|
||||
_updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
using Content.Shared._White.Guardian;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Guardian
|
||||
{
|
||||
/// <summary>
|
||||
@@ -15,20 +20,63 @@ namespace Content.Server.Guardian
|
||||
/// <summary>
|
||||
/// Percentage of damage reflected from the guardian to the host
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("damageShare")]
|
||||
public float DamageShare { get; set; } = 0.65f;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum distance the guardian can travel before it's forced to recall, use YAML to set
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("distance")]
|
||||
public float DistanceAllowed { get; set; } = 5f;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum default distance the guardian can travel before it's forced to recall, use YAML to set
|
||||
/// </summary>
|
||||
[DataField("distanceDefault")]
|
||||
public float DistanceAllowedDefault { get; set; } = 10f;
|
||||
|
||||
[DataField]
|
||||
public float DistancePowerAssasin { get; set; } = 25f;
|
||||
|
||||
/// <summary>
|
||||
/// If the guardian is currently manifested
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool GuardianLoose;
|
||||
|
||||
[DataField]
|
||||
public GuardianSelector GuardianType = GuardianSelector.Standart;
|
||||
|
||||
[DataField("powerToggleAction", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string PowerToggleAction = "ActionGuardianPowerToggle";
|
||||
|
||||
[DataField]
|
||||
public EntityUid? PowerToggleActionEntity;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
||||
public bool IsInPowerMode;
|
||||
|
||||
[DataField("chargerPowerAction", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string ChargerPowerAction = "ActionChargerPower";
|
||||
|
||||
[DataField]
|
||||
public EntityUid? ChargerPowerActionEntity;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
||||
public bool IsCharged;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("assasinDamageModifier")]
|
||||
public float AssasinDamageModifier = 3F;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
||||
public int LightingCount = 1;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField]
|
||||
public SoundSpecifier? ChargerSound = new SoundPathSpecifier("/Audio/White/Guardian/charger.ogg");
|
||||
|
||||
[DataField]
|
||||
public EntProtoId Action = "ActionToggleGuardian";
|
||||
|
||||
[DataField] public EntityUid? ActionEntity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Guardian
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a GuardianComponent attached to the user's GuardianHost.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class GuardianCreatorComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Counts as spent upon exhausting the injection
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We don't mark as deleted as examine depends on this.
|
||||
/// </remarks>
|
||||
public bool Used = false;
|
||||
|
||||
/// <summary>
|
||||
/// The prototype of the guardian entity which will be created
|
||||
/// </summary>
|
||||
[DataField("guardianProto", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>), required: true)]
|
||||
public string GuardianProto { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// How long it takes to inject someone.
|
||||
/// </summary>
|
||||
[DataField("delay")]
|
||||
public float InjectionDelay = 5f;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using Content.Server._White.IncorporealSystem;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Lightning;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared._White.Guardian;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Examine;
|
||||
@@ -12,7 +14,7 @@ using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Server.GameObjects;
|
||||
using Content.Shared.Weapons.Melee;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
@@ -35,6 +37,9 @@ namespace Content.Server.Guardian
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
|
||||
[Dependency] private readonly LightningSystem _lightningSystem = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -58,8 +63,93 @@ namespace Content.Server.Guardian
|
||||
SubscribeLocalEvent<GuardianHostComponent, GuardianToggleActionEvent>(OnPerformAction);
|
||||
|
||||
SubscribeLocalEvent<GuardianComponent, AttackAttemptEvent>(OnGuardianAttackAttempt);
|
||||
|
||||
// PARSEC EDIT START
|
||||
SubscribeLocalEvent<GuardianCreatorComponent, GuardianSelectorSelectedBuiMessage>(OnGuardianSelected);
|
||||
SubscribeLocalEvent<GuardianComponent, ToggleGuardianPowerActionEvent>(OnPerformGuardianPowerAction);
|
||||
SubscribeLocalEvent<GuardianComponent, ChargerPowerActionEvent>(OnPerformChargerPowerAction);
|
||||
SubscribeLocalEvent<GuardianComponent, GuardianToggleActionEvent>(OnPerformGuardianAction);
|
||||
}
|
||||
|
||||
// PARSEC EDIT START
|
||||
|
||||
private void OnGuardianSelected(EntityUid uid,
|
||||
GuardianCreatorComponent component,
|
||||
GuardianSelectorSelectedBuiMessage args)
|
||||
{
|
||||
var target = GetEntity(args.Target);
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.Actor, component.InjectionDelay, new GuardianCreatorDoAfterEvent{SelectedType = args.GuardianType}, uid, target: target, used: uid){BreakOnMove = true});
|
||||
}
|
||||
|
||||
private void OnPerformGuardianPowerAction(EntityUid uid,
|
||||
GuardianComponent component,
|
||||
ToggleGuardianPowerActionEvent args)
|
||||
{
|
||||
if(args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
ToggleGuardianPower(uid, component, !component.IsInPowerMode);
|
||||
}
|
||||
|
||||
private void ToggleGuardianPower(EntityUid uid, GuardianComponent component, bool toggleValue)
|
||||
{
|
||||
if (component.IsInPowerMode == toggleValue)
|
||||
return;
|
||||
|
||||
if(component.PowerToggleActionEntity == null)
|
||||
return;
|
||||
|
||||
if (component is { IsInPowerMode: false, GuardianLoose: true })
|
||||
{
|
||||
_popupSystem.PopupEntity("Вы должны находится в теле, чтобы активировать способность!", uid, uid, PopupType.MediumCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
component.IsInPowerMode = toggleValue;
|
||||
|
||||
_actionSystem.SetToggled(component.PowerToggleActionEntity, component.IsInPowerMode);
|
||||
SetupPower(uid, component, component.GuardianType);
|
||||
}
|
||||
|
||||
private void SetupPower(EntityUid uid, GuardianComponent component, GuardianSelector type)
|
||||
{
|
||||
if (type == GuardianSelector.Assasin)
|
||||
SetupAssasin(uid, component);
|
||||
}
|
||||
|
||||
private void SetupAssasin(EntityUid uid, GuardianComponent component)
|
||||
{
|
||||
if (HasComp<IncorporealComponent>(uid))
|
||||
{
|
||||
RemComp<IncorporealComponent>(uid);
|
||||
_actionSystem.SetToggled(component.PowerToggleActionEntity, !component.IsInPowerMode);
|
||||
component.IsInPowerMode = false;
|
||||
component.DistanceAllowed = component.DistanceAllowedDefault;
|
||||
return;
|
||||
}
|
||||
|
||||
var incorporealComp = EnsureComp<IncorporealComponent>(uid);
|
||||
incorporealComp.Effect = false;
|
||||
component.DistanceAllowed = component.DistancePowerAssasin;
|
||||
}
|
||||
|
||||
private void OnPerformChargerPowerAction(EntityUid uid, GuardianComponent component, ChargerPowerActionEvent args)
|
||||
{
|
||||
if(args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
if(component.IsCharged)
|
||||
return;
|
||||
|
||||
component.IsCharged = true;
|
||||
_audio.PlayPvs(component.ChargerSound, uid);
|
||||
}
|
||||
|
||||
//Parsec edit end
|
||||
|
||||
private void OnGuardianShutdown(EntityUid uid, GuardianComponent component, ComponentShutdown args)
|
||||
{
|
||||
var host = component.Host;
|
||||
@@ -70,6 +160,10 @@ namespace Content.Server.Guardian
|
||||
|
||||
_container.Remove(uid, hostComponent.GuardianContainer);
|
||||
hostComponent.HostedGuardian = null;
|
||||
if(component.PowerToggleActionEntity != null)
|
||||
_actionSystem.RemoveAction(uid, component.PowerToggleActionEntity); // Parsec
|
||||
if(component.ChargerPowerActionEntity != null)
|
||||
_actionSystem.RemoveAction(uid, component.ChargerPowerActionEntity); // parsec
|
||||
Dirty(host.Value, hostComponent);
|
||||
QueueDel(hostComponent.ActionEntity);
|
||||
hostComponent.ActionEntity = null;
|
||||
@@ -86,6 +180,24 @@ namespace Content.Server.Guardian
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPerformGuardianAction(EntityUid uid, GuardianComponent component, GuardianToggleActionEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if(component.Host == null)
|
||||
return;
|
||||
|
||||
var host = (EntityUid) component.Host;
|
||||
|
||||
if(!TryComp<GuardianHostComponent>(host, out var guardianHostComponent))
|
||||
return;
|
||||
|
||||
ToggleGuardian(host, guardianHostComponent);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnGuardianPlayerDetached(EntityUid uid, GuardianComponent component, PlayerDetachedEvent args)
|
||||
{
|
||||
var host = component.Host;
|
||||
@@ -109,6 +221,19 @@ namespace Content.Server.Guardian
|
||||
}
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("guardian-available"), host.Value, host.Value);
|
||||
|
||||
_actionSystem.AddAction(uid, ref component.ActionEntity, component.Action);
|
||||
|
||||
if (component.GuardianType is GuardianSelector.Standart or GuardianSelector.Lighting)
|
||||
return;
|
||||
|
||||
if (component.GuardianType == GuardianSelector.Charger)
|
||||
{
|
||||
_actionSystem.AddAction(uid, ref component.ChargerPowerActionEntity, component.ChargerPowerAction);
|
||||
return;
|
||||
}
|
||||
|
||||
_actionSystem.AddAction(uid, ref component.PowerToggleActionEntity, component.PowerToggleAction);
|
||||
}
|
||||
|
||||
private void OnHostInit(EntityUid uid, GuardianHostComponent component, ComponentInit args)
|
||||
@@ -133,12 +258,55 @@ namespace Content.Server.Guardian
|
||||
|
||||
private void OnGuardianAttackAttempt(EntityUid uid, GuardianComponent component, AttackAttemptEvent args)
|
||||
{
|
||||
if (args.Cancelled || args.Target != component.Host)
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
// why is this server side code? This should be in shared
|
||||
_popupSystem.PopupCursor(Loc.GetString("guardian-attack-host"), uid, PopupType.LargeCaution);
|
||||
args.Cancel();
|
||||
if (args.Target == null)
|
||||
return;
|
||||
|
||||
if (args.Target == component.Host)
|
||||
{
|
||||
_popupSystem.PopupCursor(Loc.GetString("guardian-attack-host"), uid, PopupType.LargeCaution);
|
||||
args.Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
var target = (EntityUid) args.Target;
|
||||
|
||||
if (component.GuardianType == GuardianSelector.Lighting)
|
||||
{
|
||||
for (var i = 0; i < component.LightingCount; i++)
|
||||
{
|
||||
_lightningSystem.ShootLightning(uid, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (component.GuardianType == GuardianSelector.Assasin)
|
||||
{
|
||||
if (!component.IsInPowerMode)
|
||||
return;
|
||||
|
||||
if (!TryComp<MeleeWeaponComponent>(args.Weapon, out var meleeWeaponComponent))
|
||||
return;
|
||||
|
||||
_damageableSystem.TryChangeDamage(args.Target,
|
||||
meleeWeaponComponent.Damage * component.AssasinDamageModifier,
|
||||
true);
|
||||
SetupAssasin(uid, component);
|
||||
}
|
||||
|
||||
if (component.GuardianType == GuardianSelector.Charger)
|
||||
{
|
||||
if(!component.IsCharged)
|
||||
return;
|
||||
|
||||
foreach (var hand in _handsSystem.EnumerateHands(target))
|
||||
{
|
||||
_handsSystem.TryDrop(target, hand);
|
||||
}
|
||||
|
||||
component.IsCharged = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleGuardian(EntityUid user, GuardianHostComponent hostComponent)
|
||||
@@ -172,6 +340,7 @@ namespace Content.Server.Guardian
|
||||
args.Handled = true;
|
||||
UseCreator(args.User, args.Target.Value, uid, component);
|
||||
}
|
||||
|
||||
private void UseCreator(EntityUid user, EntityUid target, EntityUid injector, GuardianCreatorComponent component)
|
||||
{
|
||||
if (component.Used)
|
||||
@@ -194,10 +363,11 @@ namespace Content.Server.Guardian
|
||||
return;
|
||||
}
|
||||
|
||||
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, user, component.InjectionDelay, new GuardianCreatorDoAfterEvent(), injector, target: target, used: injector){BreakOnMove = true});
|
||||
_ui.SetUiState(injector, GuardianSelectorUiKey.Key, new GuardianSelectorBUIState(component.GuardiansAvaliable, GetNetEntity(target)));
|
||||
_ui.OpenUi(injector, GuardianSelectorUiKey.Key, user);
|
||||
}
|
||||
|
||||
private void OnDoAfter(EntityUid uid, GuardianCreatorComponent component, DoAfterEvent args)
|
||||
private void OnDoAfter(EntityUid uid, GuardianCreatorComponent component, GuardianCreatorDoAfterEvent args)
|
||||
{
|
||||
if (args.Handled || args.Args.Target == null)
|
||||
return;
|
||||
@@ -207,14 +377,16 @@ namespace Content.Server.Guardian
|
||||
|
||||
var hostXform = Transform(args.Args.Target.Value);
|
||||
var host = EnsureComp<GuardianHostComponent>(args.Args.Target.Value);
|
||||
var guardianProto = component.GuardianSelectorToProto[args.SelectedType]; // Parsec
|
||||
// Use map position so it's not inadvertantly parented to the host + if it's in a container it spawns outside I guess.
|
||||
var guardian = Spawn(component.GuardianProto, _transform.GetMapCoordinates(args.Args.Target.Value, xform: hostXform));
|
||||
var guardian = Spawn(guardianProto, _transform.GetMapCoordinates(args.Args.Target.Value, xform: hostXform)); // Parsec edit
|
||||
|
||||
_container.Insert(guardian, host.GuardianContainer);
|
||||
host.HostedGuardian = guardian;
|
||||
|
||||
if (TryComp<GuardianComponent>(guardian, out var guardianComp))
|
||||
{
|
||||
guardianComp.GuardianType = args.SelectedType;
|
||||
guardianComp.Host = args.Args.Target.Value;
|
||||
_audio.PlayPvs("/Audio/Effects/guardian_inject.ogg", args.Args.Target.Value);
|
||||
_popupSystem.PopupEntity(Loc.GetString("guardian-created"), args.Args.Target.Value, args.Args.Target.Value);
|
||||
@@ -273,8 +445,8 @@ namespace Content.Server.Guardian
|
||||
/// </summary>
|
||||
private void OnCreatorExamine(EntityUid uid, GuardianCreatorComponent component, ExaminedEvent args)
|
||||
{
|
||||
if (component.Used)
|
||||
args.PushMarkup(Loc.GetString("guardian-activator-empty-examine"));
|
||||
if (component.Used)
|
||||
args.PushMarkup(Loc.GetString("guardian-activator-empty-examine"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -344,7 +516,7 @@ namespace Content.Server.Guardian
|
||||
guardianComponent.GuardianLoose = true;
|
||||
}
|
||||
|
||||
private void RetractGuardian(EntityUid host,GuardianHostComponent hostComponent, EntityUid guardian, GuardianComponent guardianComponent)
|
||||
private void RetractGuardian(EntityUid host, GuardianHostComponent hostComponent, EntityUid guardian, GuardianComponent guardianComponent)
|
||||
{
|
||||
if (!guardianComponent.GuardianLoose)
|
||||
{
|
||||
@@ -355,6 +527,20 @@ namespace Content.Server.Guardian
|
||||
_container.Insert(guardian, hostComponent.GuardianContainer);
|
||||
DebugTools.Assert(hostComponent.GuardianContainer.Contains(guardian));
|
||||
_popupSystem.PopupEntity(Loc.GetString("guardian-entity-recall"), host);
|
||||
if (guardianComponent.IsInPowerMode)
|
||||
{
|
||||
if (guardianComponent.GuardianType == GuardianSelector.Assasin)
|
||||
{
|
||||
SetupPower(guardian, guardianComponent, guardianComponent.GuardianType);
|
||||
return;
|
||||
}
|
||||
|
||||
guardianComponent.IsInPowerMode = false;
|
||||
if (guardianComponent.PowerToggleActionEntity != null)
|
||||
{
|
||||
_actionSystem.SetToggled(guardianComponent.PowerToggleActionEntity, guardianComponent.IsInPowerMode);
|
||||
}
|
||||
}
|
||||
guardianComponent.GuardianLoose = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public sealed class PoshelnahuiCommand : IConsoleCommand
|
||||
public string Command => "poshelnahui";
|
||||
public string Description => "Close client game lol";
|
||||
public string Help => "poshelnahui <ckey>";
|
||||
private readonly List<string> _vip = ["Valtos", "SamsungS", "Dosharus", "BIG_Zi_348"];
|
||||
private readonly List<string> _vip = ["Valtos", "SamsungS", "Dosharus", "CaypenNow"];
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1 || string.IsNullOrEmpty(args[0]))
|
||||
|
||||
@@ -157,6 +157,8 @@ public partial class CultSystem
|
||||
_statusEffectsSystem.TryAddStatusEffect<IncorporealComponent>(ev.Performer, ev.StatusEffectId,
|
||||
TimeSpan.FromSeconds(ev.Duration), false);
|
||||
|
||||
Spawn("EffectEmpPulse", Transform(ev.Performer).Coordinates);
|
||||
|
||||
ev.Handled = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,11 @@ namespace Content.Server._White.IncorporealSystem;
|
||||
public sealed partial class IncorporealComponent : Component
|
||||
{
|
||||
[DataField] public float MovementSpeedBuff = 1.5f;
|
||||
[DataField] public bool Effect = true;
|
||||
|
||||
[DataField] public int CollisionMask = (int) CollisionGroup.GhostImpassable;
|
||||
[DataField] public int CollisionLayer = 0;
|
||||
|
||||
|
||||
public int StoredMask;
|
||||
public int StoredLayer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ public sealed class IncorporealSystem : EntitySystem
|
||||
_visibilitySystem.RefreshVisibility(uid);
|
||||
}
|
||||
|
||||
Spawn("EffectEmpPulse", Transform(uid).Coordinates);
|
||||
EnsureComp<StealthComponent>(uid);
|
||||
_stealth.SetVisibility(uid, -1);
|
||||
if (TryComp(uid, out PullableComponent? pullable))
|
||||
@@ -79,7 +78,12 @@ public sealed class IncorporealSystem : EntitySystem
|
||||
}
|
||||
|
||||
component.MovementSpeedBuff = 1;
|
||||
Spawn("EffectEmpPulse", _transform.GetMapCoordinates(uid));
|
||||
|
||||
if (component.Effect)
|
||||
{
|
||||
Spawn("EffectEmpPulse", _transform.GetMapCoordinates(uid));
|
||||
}
|
||||
|
||||
_stealth.SetVisibility(uid, 1);
|
||||
RemComp<StealthComponent>(uid);
|
||||
_movement.RefreshMovementSpeedModifiers(uid);
|
||||
|
||||
@@ -404,6 +404,8 @@ public sealed class WizardSpellsSystem : EntitySystem
|
||||
_statusEffectsSystem.TryAddStatusEffect<IncorporealComponent>(msg.Performer, "Incorporeal",
|
||||
TimeSpan.FromSeconds(10), false);
|
||||
|
||||
Spawn("EffectEmpPulse", Transform(msg.Performer).Coordinates);
|
||||
|
||||
Cast(msg);
|
||||
}
|
||||
|
||||
|
||||
49
Content.Shared/Guardian/GuardianCreatorComponent.cs
Normal file
49
Content.Shared/Guardian/GuardianCreatorComponent.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Content.Shared._White.Guardian;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Guardian
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a GuardianComponent attached to the user's GuardianHost.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class GuardianCreatorComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Counts as spent upon exhausting the injection
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We don't mark as deleted as examine depends on this.
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
public bool Used = false;
|
||||
|
||||
/// <summary>
|
||||
/// The prototype of the guardian entity which will be created
|
||||
/// </summary>
|
||||
[DataField("guardianProto",
|
||||
customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>),
|
||||
required: true)]
|
||||
public string GuardianProto;
|
||||
|
||||
/// <summary>
|
||||
/// How long it takes to inject someone.
|
||||
/// </summary>
|
||||
[DataField("delay")]
|
||||
public float InjectionDelay = 5f;
|
||||
|
||||
[DataField("guardiansAvaliable")]
|
||||
public IReadOnlyCollection<string> GuardiansAvaliable = ArraySegment<string>.Empty;
|
||||
|
||||
[DataField]
|
||||
public Dictionary<GuardianSelector, string> GuardianSelectorToProto = new()
|
||||
{
|
||||
{ GuardianSelector.Assasin, "MobHoloparasiteGuardianAssasin" },
|
||||
{ GuardianSelector.Standart, "MobHoloparasiteGuardianStandart" },
|
||||
{ GuardianSelector.Charger, "MobHoloparasiteGuardianCharger" },
|
||||
{ GuardianSelector.Lighting, "MobHoloparasiteGuardianLighting" }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared._White.Guardian;
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Guardian;
|
||||
@@ -6,4 +7,5 @@ namespace Content.Shared.Guardian;
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class GuardianCreatorDoAfterEvent : SimpleDoAfterEvent
|
||||
{
|
||||
public GuardianSelector SelectedType; // Parsec Edit
|
||||
}
|
||||
|
||||
53
Content.Shared/_White/Guardian/GuardianEvents.cs
Normal file
53
Content.Shared/_White/Guardian/GuardianEvents.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Content.Shared.Actions;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._White.Guardian;
|
||||
|
||||
public enum GuardianSelector : byte
|
||||
{
|
||||
Assasin,
|
||||
Standart,
|
||||
Charger,
|
||||
Lighting
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum GuardianSelectorUiKey : byte
|
||||
{
|
||||
Key
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class GuardianSelectorBUIState : BoundUserInterfaceState
|
||||
{
|
||||
public IReadOnlyCollection<string> Ids { get; set; }
|
||||
|
||||
public NetEntity Target { get; set; }
|
||||
|
||||
public GuardianSelectorBUIState(IReadOnlyCollection<string> ids, NetEntity target)
|
||||
{
|
||||
Ids = ids;
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class GuardianSelectorSelectedBuiMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public GuardianSelector GuardianType;
|
||||
public NetEntity Target;
|
||||
|
||||
public GuardianSelectorSelectedBuiMessage(GuardianSelector guardianType, NetEntity target)
|
||||
{
|
||||
GuardianType = guardianType;
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class ToggleGuardianPowerActionEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
|
||||
public sealed partial class ChargerPowerActionEvent : InstantActionEvent
|
||||
{
|
||||
}
|
||||
BIN
Resources/Audio/White/Guardian/charger.ogg
Normal file
BIN
Resources/Audio/White/Guardian/charger.ogg
Normal file
Binary file not shown.
@@ -1,16 +1,4 @@
|
||||
Entries:
|
||||
- author: Aviu
|
||||
changes:
|
||||
- message: "\u0411\u0417 \u0442\u0435\u043F\u0435\u0440\u044C \u0443\u0441\u044B\
|
||||
\u043F\u043B\u044F\u0435\u0442 \u0433\u0435\u043D\u043E\u043A\u0440\u0430\u0434\
|
||||
\u043E\u0432."
|
||||
type: Add
|
||||
- message: "\u041D\u0438\u0442\u0440\u0438\u0443\u043C \u0441\u043D\u043E\u0432\u0430\
|
||||
\ \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442."
|
||||
type: Fix
|
||||
id: 178
|
||||
time: '2024-03-03T08:09:04.0000000+00:00'
|
||||
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/167
|
||||
- author: ThereDrD
|
||||
changes:
|
||||
- message: "\u0424\u0438\u043A\u0441 \u043F\u0443\u0441\u0442\u044B\u0445 \u0441\
|
||||
@@ -9078,3 +9066,45 @@
|
||||
id: 677
|
||||
time: '2025-04-13T16:14:06.0000000+00:00'
|
||||
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/947
|
||||
- author: CaypenNow
|
||||
changes:
|
||||
- message: "\u0413\u043E\u043B\u043E\u043F\u0430\u0440\u0430\u0437\u0438\u0442\u044B\
|
||||
\ \u043F\u043E\u043B\u0443\u0447\u0438\u043B\u0438 \u043F\u043E\u043B\u043D\u043E\
|
||||
\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435. \u0422\u0435\
|
||||
\u043F\u0435\u0440\u044C, \u043F\u0440\u0438 \u0438\u043C\u043F\u043B\u0430\u043D\
|
||||
\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0438 \u0433\u043E\u043B\u043E\
|
||||
\u043F\u0430\u0440\u0430\u0437\u0438\u0442\u0430, \u0435\u0441\u0442\u044C \u0432\
|
||||
\u043E\u0437\u043C\u043E\u0436\u043D\u043E\u0441\u0442\u044C \u0432\u044B\u0431\
|
||||
\u0440\u0430\u0442\u044C \u043E\u0434\u0438\u043D \u0438\u0437 4 \u043A\u043B\
|
||||
\u0430\u0441\u0441\u043E\u0432. \u041A\u0430\u0436\u0434\u044B\u0439 \u043A\u043B\
|
||||
\u0430\u0441\u0441 \u0438\u043C\u0435\u0435\u0442 \u0440\u0430\u0437\u043B\u0438\
|
||||
\u0447\u0438\u044F, \u0430 \u043D\u0435\u043A\u043E\u0442\u043E\u0440\u044B\u0435\
|
||||
\ \u0438 \u0441\u043E\u0431\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u0435\
|
||||
\ \u0441\u043F\u043E\u0441\u043E\u0431\u043D\u043E\u0441\u0442\u0438."
|
||||
type: Add
|
||||
- message: "\u0413\u043E\u043B\u043E\u043F\u0430\u0440\u0430\u0437\u0438\u0442 \u043F\
|
||||
\u043E\u043B\u0443\u0447\u0438\u043B \u043D\u043E\u0432\u044B\u0439 \u0441\u043F\
|
||||
\u0440\u0430\u0439\u0442"
|
||||
type: Add
|
||||
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0433\u043E\u043B\u043E\u043F\u0430\
|
||||
\u0440\u0430\u0437\u0438\u0442 \u043C\u043E\u0436\u0435\u0442 \u0432\u044B\u0445\
|
||||
\u043E\u0434\u0438\u0442\u044C \u0438\u0437 \u0442\u0435\u043B\u0430 \u0441\u0430\
|
||||
\u043C"
|
||||
type: Tweak
|
||||
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0433\u043E\u043B\u043E\u043F\u0430\
|
||||
\u0440\u0430\u0437\u0438\u0442 \u043C\u043E\u0436\u0435\u0442 \u0442\u0430\u0441\
|
||||
\u043A\u0430\u0442\u044C \u0432\u0435\u0449\u0438\u0442\u044C"
|
||||
type: Tweak
|
||||
- message: "\u0422\u0435\u043F\u0435\u0440\u044C \u0446\u0432\u0435\u0442 \u0433\
|
||||
\u043E\u043B\u043E\u043F\u0430\u0440\u0430\u0437\u0438\u0442\u0430 - \u0443\u043D\
|
||||
\u0438\u043A\u0430\u043B\u044C\u043D\u044B\u0439 \u0434\u043B\u044F \u043A\u043B\
|
||||
\u0430\u0441\u0441\u0430, \u0430 \u043D\u0435 \u043F\u0440\u043E\u0441\u0442\
|
||||
\u043E \u0440\u0430\u043D\u0434\u043E\u043C\u043D\u044B\u0439."
|
||||
type: Tweak
|
||||
- message: "\u0426\u0435\u043D\u0430 \u0433\u043E\u043B\u043E\u043F\u0430\u0440\u0430\
|
||||
\u0437\u0438\u0442\u0430 \u043F\u043E\u0432\u044B\u0448\u0435\u043D\u0430. 12\
|
||||
\ \u0422\u041A --> 13 \u0422\u041A"
|
||||
type: Tweak
|
||||
id: 678
|
||||
time: '2025-04-18T03:18:09.0000000+00:00'
|
||||
url: https://api.github.com/repos/frosty-dev/ss14-core/pulls/948
|
||||
|
||||
4
Resources/Locale/ru-RU/_white/guardian/guardian.ftl
Normal file
4
Resources/Locale/ru-RU/_white/guardian/guardian.ftl
Normal file
@@ -0,0 +1,4 @@
|
||||
guardian-assasin-name = Ассасин
|
||||
guardian-lighting-name = Молниеносный
|
||||
guardian-charger-name = Быстрый
|
||||
guardian-standart-name = Классический
|
||||
@@ -922,7 +922,7 @@
|
||||
icon: { sprite: /Textures/Objects/Misc/guardian_info.rsi, state: icon }
|
||||
productEntity: BoxHoloparasite
|
||||
cost:
|
||||
Telecrystal: 12
|
||||
Telecrystal: 13
|
||||
categories:
|
||||
- UplinkAllies
|
||||
conditions:
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
context: "human"
|
||||
- type: MobMover
|
||||
- type: InputMover
|
||||
- type: Puller
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 4
|
||||
baseSprintSpeed: 5.5
|
||||
@@ -29,20 +30,6 @@
|
||||
Blunt: 5
|
||||
soundHit:
|
||||
collection: MetalThud
|
||||
- type: RandomSprite
|
||||
available:
|
||||
- enum.DamageStateVisualLayers.Base:
|
||||
magic_base: ""
|
||||
enum.DamageStateVisualLayers.BaseUnshaded:
|
||||
magic_flare: Sixteen
|
||||
- enum.DamageStateVisualLayers.Base:
|
||||
miner_base: ""
|
||||
enum.DamageStateVisualLayers.BaseUnshaded:
|
||||
miner_flare: Sixteen
|
||||
- enum.DamageStateVisualLayers.Base:
|
||||
tech_base: ""
|
||||
enum.DamageStateVisualLayers.BaseUnshaded:
|
||||
tech_flare: Sixteen
|
||||
- type: Sprite
|
||||
drawdepth: Mobs
|
||||
sprite: White/Mobs/Aliens/Guardians/guardians.rsi
|
||||
@@ -112,8 +99,8 @@
|
||||
|
||||
# From the uplink injector
|
||||
- type: entity
|
||||
name: Holoparasite
|
||||
id: MobHoloparasiteGuardian
|
||||
name: HoloparasiteStandart
|
||||
id: MobHoloparasiteGuardianStandart
|
||||
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.
|
||||
components:
|
||||
@@ -126,22 +113,208 @@
|
||||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Sprite
|
||||
drawdepth: Mobs
|
||||
sprite: White/Mobs/Aliens/Guardians/guardians.rsi
|
||||
layers:
|
||||
- state: tech_base
|
||||
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
- state: tech_flare
|
||||
map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||
color: "#707070"
|
||||
shader: unshaded
|
||||
noRot: true
|
||||
- type: Guardian
|
||||
damageShare: 0.5
|
||||
distance: 6
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 4.5
|
||||
baseSprintSpeed: 6
|
||||
- type: DamageOnHighSpeedImpact
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
soundHit:
|
||||
collection: MetalThud
|
||||
- type: MeleeWeapon
|
||||
hidden: false
|
||||
altDisarm: false
|
||||
animation: WeaponArcFist
|
||||
attackRate: 2.2
|
||||
autoAttack: true
|
||||
soundHit:
|
||||
collection: Punch
|
||||
damage:
|
||||
types:
|
||||
Blunt: 24
|
||||
Structural: 24
|
||||
- type: NameIdentifier
|
||||
group: Holoparasite
|
||||
- type: TypingIndicator
|
||||
proto: holo
|
||||
- type: Sprite
|
||||
layers:
|
||||
- state: tech_base
|
||||
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
- state: tech_flare
|
||||
map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||
color: "#40a7d7"
|
||||
shader: unshaded
|
||||
- type: HTN
|
||||
rootTask:
|
||||
task: SimpleHumanoidHostileCompound
|
||||
|
||||
- type: entity
|
||||
name: HoloparasiteAssasin
|
||||
id: MobHoloparasiteGuardianAssasin
|
||||
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.
|
||||
components:
|
||||
- type: GhostRole
|
||||
allowMovement: true
|
||||
allowSpeech: true
|
||||
makeSentient: true
|
||||
name: ghost-role-information-holoparasite-name
|
||||
description: ghost-role-information-holoparasite-description
|
||||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Sprite
|
||||
drawdepth: Mobs
|
||||
sprite: White/Mobs/Aliens/Guardians/guardians.rsi
|
||||
layers:
|
||||
- state: tech_base
|
||||
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
- state: tech_flare
|
||||
map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||
color: "#9d0016"
|
||||
shader: unshaded
|
||||
noRot: true
|
||||
- type: Guardian
|
||||
damageShare: 1
|
||||
distance: 10
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 4
|
||||
baseSprintSpeed: 5.5
|
||||
- type: DamageOnHighSpeedImpact
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
soundHit:
|
||||
collection: MetalThud
|
||||
- type: MeleeWeapon
|
||||
hidden: false
|
||||
altDisarm: false
|
||||
animation: WeaponArcFist
|
||||
attackRate: 2
|
||||
autoAttack: true
|
||||
soundHit:
|
||||
collection: Punch
|
||||
damage:
|
||||
types:
|
||||
Blunt: 14
|
||||
Structural: 14
|
||||
- type: NameIdentifier
|
||||
group: Holoparasite
|
||||
- type: TypingIndicator
|
||||
proto: holo
|
||||
- type: HTN
|
||||
rootTask:
|
||||
task: SimpleHumanoidHostileCompound
|
||||
|
||||
- type: entity
|
||||
name: HoloparasiteCharger
|
||||
id: MobHoloparasiteGuardianCharger
|
||||
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.
|
||||
components:
|
||||
- type: GhostRole
|
||||
allowMovement: true
|
||||
allowSpeech: true
|
||||
makeSentient: true
|
||||
name: ghost-role-information-holoparasite-name
|
||||
description: ghost-role-information-holoparasite-description
|
||||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Sprite
|
||||
drawdepth: Mobs
|
||||
sprite: White/Mobs/Aliens/Guardians/guardians.rsi
|
||||
layers:
|
||||
- state: tech_base
|
||||
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
- state: tech_flare
|
||||
map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||
color: "#54f3ff"
|
||||
shader: unshaded
|
||||
noRot: true
|
||||
- type: MovementSpeedModifier
|
||||
baseWalkSpeed: 6
|
||||
baseSprintSpeed: 7.5
|
||||
- type: DamageOnHighSpeedImpact
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
soundHit:
|
||||
collection: MetalThud
|
||||
- type: MeleeWeapon
|
||||
hidden: false
|
||||
altDisarm: false
|
||||
animation: WeaponArcFist
|
||||
attackRate: 2.5
|
||||
autoAttack: true
|
||||
soundHit:
|
||||
collection: Punch
|
||||
damage:
|
||||
types:
|
||||
Blunt: 15
|
||||
Structural: 15
|
||||
- type: NameIdentifier
|
||||
group: Holoparasite
|
||||
- type: TypingIndicator
|
||||
proto: holo
|
||||
- type: HTN
|
||||
rootTask:
|
||||
task: SimpleHumanoidHostileCompound
|
||||
|
||||
- type: entity
|
||||
name: HoloparasiteLighting
|
||||
id: MobHoloparasiteGuardianLighting
|
||||
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.
|
||||
components:
|
||||
- type: GhostRole
|
||||
allowMovement: true
|
||||
allowSpeech: true
|
||||
makeSentient: true
|
||||
name: ghost-role-information-holoparasite-name
|
||||
description: ghost-role-information-holoparasite-description
|
||||
raffle:
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Sprite
|
||||
drawdepth: Mobs
|
||||
sprite: White/Mobs/Aliens/Guardians/guardians.rsi
|
||||
layers:
|
||||
- state: tech_base
|
||||
map: [ "enum.DamageStateVisualLayers.Base" ]
|
||||
- state: tech_flare
|
||||
map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ]
|
||||
color: "#2000c8"
|
||||
shader: unshaded
|
||||
noRot: true
|
||||
- type: MeleeWeapon
|
||||
hidden: false
|
||||
altDisarm: false
|
||||
animation: WeaponArcFist
|
||||
attackRate: 1.8
|
||||
autoAttack: true
|
||||
soundHit:
|
||||
collection: Punch
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
Structural: 5
|
||||
- type: NameIdentifier
|
||||
group: Holoparasite
|
||||
- type: TypingIndicator
|
||||
proto: holo
|
||||
- type: HTN
|
||||
rootTask:
|
||||
task: SimpleHumanoidHostileCompound
|
||||
|
||||
# From Wizard deck of cards
|
||||
- type: entity
|
||||
name: Ifrit
|
||||
|
||||
@@ -9,6 +9,15 @@
|
||||
state: combat_hypo
|
||||
- type: GuardianCreator
|
||||
guardianProto: MobHoloparasiteGuardian
|
||||
guardiansAvaliable:
|
||||
- Assasin
|
||||
- Charger
|
||||
- Standart
|
||||
- Lighting
|
||||
- type: UserInterface # PARSEC EDIT
|
||||
interfaces:
|
||||
enum.GuardianSelectorUiKey.Key:
|
||||
type: GuardianSelectorBUI
|
||||
|
||||
- type: entity
|
||||
name: holoclown injector
|
||||
|
||||
36
Resources/Prototypes/_White/Actions/guardian.yml
Normal file
36
Resources/Prototypes/_White/Actions/guardian.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
- type: entity
|
||||
id: ActionGuardianPowerToggle
|
||||
name: "[color=green]Сила голопаразита[/color]"
|
||||
description: Уникальная способность голопаразита.
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: InstantAction
|
||||
checkCanInteract: false
|
||||
checkConsciousness: false
|
||||
icon: White/Interface/Guardian/powerOff.png
|
||||
iconOn: White/Interface/Guardian/power.png
|
||||
event: !type:ToggleGuardianPowerActionEvent
|
||||
|
||||
- type: entity
|
||||
id: ActionGuardianPowerOff
|
||||
parent: ActionCombatModeToggle
|
||||
name: "[color=red]Сила голопаразита[/color]"
|
||||
description: Уникальная способность голопаразита.
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: InstantAction
|
||||
enabled: false
|
||||
autoPopulate: false
|
||||
|
||||
- type: entity
|
||||
id: ActionChargerPower
|
||||
name: "[color=green]Сила голопаразита[/color]"
|
||||
description: Уникальная способность голопаразита, позволяет зарядить ваш кулак и одним ударом поразить цель.
|
||||
noSpawn: true
|
||||
components:
|
||||
- type: InstantAction
|
||||
useDelay: 4
|
||||
checkCanInteract: false
|
||||
checkConsciousness: false
|
||||
icon: White/Interface/Guardian/powerOff.png
|
||||
event: !type:ChargerPowerActionEvent
|
||||
BIN
Resources/Textures/White/Interface/Guardian/power.png
Normal file
BIN
Resources/Textures/White/Interface/Guardian/power.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Resources/Textures/White/Interface/Guardian/powerOff.png
Normal file
BIN
Resources/Textures/White/Interface/Guardian/powerOff.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 297 B |
Binary file not shown.
|
After Width: | Height: | Size: 276 B |
Binary file not shown.
|
After Width: | Height: | Size: 252 B |
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "https://github.com/tgstation/tgstation/blob/master/icons/hud/guardian.dmi",
|
||||
"version": 1,
|
||||
"size": { "y": 32, "x": 32 },
|
||||
"states": [
|
||||
{
|
||||
"name": "charger"
|
||||
},
|
||||
{
|
||||
"name": "lighting"
|
||||
},
|
||||
{
|
||||
"name": "assasin"
|
||||
},
|
||||
{
|
||||
"name": "standart"
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 268 B |
Reference in New Issue
Block a user