[feat] Loadout, DeathGasps, EnergyDoubleCraftSystem
@@ -130,6 +130,10 @@ namespace Content.Client.Entry
|
|||||||
_prototypeManager.RegisterIgnore("alertLevels");
|
_prototypeManager.RegisterIgnore("alertLevels");
|
||||||
_prototypeManager.RegisterIgnore("nukeopsRole");
|
_prototypeManager.RegisterIgnore("nukeopsRole");
|
||||||
|
|
||||||
|
//WD-EDIT
|
||||||
|
_prototypeManager.RegisterIgnore("loadout");
|
||||||
|
//WD-EDIT
|
||||||
|
|
||||||
_componentFactory.GenerateNetIds();
|
_componentFactory.GenerateNetIds();
|
||||||
_adminManager.Initialize();
|
_adminManager.Initialize();
|
||||||
_screenshotHook.Initialize();
|
_screenshotHook.Initialize();
|
||||||
|
|||||||
@@ -179,7 +179,8 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
ICommonSession? player = null,
|
ICommonSession? player = null,
|
||||||
string? nameOverride = null,
|
string? nameOverride = null,
|
||||||
bool checkRadioPrefix = true,
|
bool checkRadioPrefix = true,
|
||||||
bool ignoreActionBlocker = false
|
bool ignoreActionBlocker = false,
|
||||||
|
bool force = false
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (HasComp<GhostComponent>(source))
|
if (HasComp<GhostComponent>(source))
|
||||||
@@ -201,7 +202,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CanSendInGame(message, shell, player))
|
if (!force && !CanSendInGame(message, shell, player))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ignoreActionBlocker = CheckIgnoreSpeechBlocker(source, ignoreActionBlocker);
|
ignoreActionBlocker = CheckIgnoreSpeechBlocker(source, ignoreActionBlocker);
|
||||||
@@ -233,9 +234,9 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
message = SanitizeInGameICMessage(source, message, out var emoteStr, shouldCapitalize, shouldPunctuate, sanitizeSlang);
|
message = SanitizeInGameICMessage(source, message, out var emoteStr, shouldCapitalize, shouldPunctuate, sanitizeSlang);
|
||||||
|
|
||||||
// Was there an emote in the message? If so, send it.
|
// Was there an emote in the message? If so, send it.
|
||||||
if (player != null && emoteStr != message && emoteStr != null)
|
if (emoteStr != message && emoteStr != null)
|
||||||
{
|
{
|
||||||
SendEntityEmote(source, emoteStr, range, nameOverride, ignoreActionBlocker);
|
SendEntityEmote(source, emoteStr, range, nameOverride, ignoreActionBlocker, force: force);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This can happen if the entire string is sanitized out.
|
// This can happen if the entire string is sanitized out.
|
||||||
@@ -262,7 +263,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
SendEntityWhisper(source, message, range, null, nameOverride, hideLog, ignoreActionBlocker);
|
SendEntityWhisper(source, message, range, null, nameOverride, hideLog, ignoreActionBlocker);
|
||||||
break;
|
break;
|
||||||
case InGameICChatType.Emote:
|
case InGameICChatType.Emote:
|
||||||
SendEntityEmote(source, message, range, nameOverride, hideLog: hideLog, ignoreActionBlocker: ignoreActionBlocker);
|
SendEntityEmote(source, message, range, nameOverride, hideLog: hideLog, ignoreActionBlocker: ignoreActionBlocker, force: force);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -566,7 +567,8 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
bool hideLog = false,
|
bool hideLog = false,
|
||||||
bool checkEmote = true,
|
bool checkEmote = true,
|
||||||
bool ignoreActionBlocker = false,
|
bool ignoreActionBlocker = false,
|
||||||
NetUserId? author = null
|
NetUserId? author = null,
|
||||||
|
bool force = false
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!_actionBlocker.CanEmote(source) && !ignoreActionBlocker)
|
if (!_actionBlocker.CanEmote(source) && !ignoreActionBlocker)
|
||||||
|
|||||||
29
Content.Server/White/Loadout/LoadoutPrototype.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using Content.Shared.Roles;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||||
|
|
||||||
|
namespace Content.Server.White.Loadout;
|
||||||
|
|
||||||
|
[Prototype("loadout")]
|
||||||
|
public sealed class LoadoutItemPrototype : IPrototype
|
||||||
|
{
|
||||||
|
[IdDataFieldAttribute] public string ID { get; } = default!;
|
||||||
|
|
||||||
|
[DataField("entity", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||||
|
public string EntityId { get; } = default!;
|
||||||
|
|
||||||
|
// WD-Sponsors-Start
|
||||||
|
[DataField("sponsorOnly")]
|
||||||
|
public bool SponsorOnly = false;
|
||||||
|
// WD-Sponsors-End
|
||||||
|
|
||||||
|
[DataField("whitelistJobs", customTypeSerializer: typeof(PrototypeIdListSerializer<JobPrototype>))]
|
||||||
|
public List<string>? WhitelistJobs { get; }
|
||||||
|
|
||||||
|
[DataField("blacklistJobs", customTypeSerializer: typeof(PrototypeIdListSerializer<JobPrototype>))]
|
||||||
|
public List<string>? BlacklistJobs { get; }
|
||||||
|
|
||||||
|
[DataField("speciesRestriction")]
|
||||||
|
public List<string>? SpeciesRestrictions { get; }
|
||||||
|
}
|
||||||
97
Content.Server/White/Loadout/LoadoutSystem.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.White.Sponsors;
|
||||||
|
using Content.Server.GameTicking;
|
||||||
|
using Content.Server.Hands.Systems;
|
||||||
|
using Content.Server.Storage.EntitySystems;
|
||||||
|
using Content.Shared.Clothing.Components;
|
||||||
|
using Content.Shared.Inventory;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.White.Loadout;
|
||||||
|
|
||||||
|
// NOTE: Full implementation will be in future, now just sponsor items
|
||||||
|
public sealed class LoadoutSystem : EntitySystem
|
||||||
|
{
|
||||||
|
private const string BackpackSlotId = "back";
|
||||||
|
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||||
|
[Dependency] private readonly HandsSystem _handsSystem = default!;
|
||||||
|
[Dependency] private readonly StorageSystem _storageSystem = default!;
|
||||||
|
[Dependency] private readonly SponsorsManager _sponsorsManager = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<PlayerSpawnCompleteEvent>(OnPlayerSpawned);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPlayerSpawned(PlayerSpawnCompleteEvent ev)
|
||||||
|
{
|
||||||
|
if (_sponsorsManager.TryGetInfo(ev.Player.UserId, out var sponsor))
|
||||||
|
{
|
||||||
|
foreach (var loadoutId in sponsor.AllowedMarkings)
|
||||||
|
{
|
||||||
|
// NOTE: Now is easy to not extract method because event give all info we need
|
||||||
|
if (_prototypeManager.TryIndex<LoadoutItemPrototype>(loadoutId, out var loadout))
|
||||||
|
{
|
||||||
|
var isSponsorOnly = loadout.SponsorOnly &&
|
||||||
|
!sponsor.AllowedMarkings.Contains(loadoutId);
|
||||||
|
var isWhitelisted = ev.JobId != null &&
|
||||||
|
loadout.WhitelistJobs != null &&
|
||||||
|
!loadout.WhitelistJobs.Contains(ev.JobId);
|
||||||
|
var isBlacklisted = ev.JobId != null &&
|
||||||
|
loadout.BlacklistJobs != null &&
|
||||||
|
loadout.BlacklistJobs.Contains(ev.JobId);
|
||||||
|
var isSpeciesRestricted = loadout.SpeciesRestrictions != null &&
|
||||||
|
loadout.SpeciesRestrictions.Contains(ev.Profile.Species);
|
||||||
|
|
||||||
|
if (isSponsorOnly || isWhitelisted || isBlacklisted || isSpeciesRestricted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var entity = Spawn(loadout.EntityId, Transform(ev.Mob).Coordinates);
|
||||||
|
|
||||||
|
// Take in hand if not clothes
|
||||||
|
if (!TryComp<ClothingComponent>(entity, out var clothing))
|
||||||
|
{
|
||||||
|
_handsSystem.TryPickup(ev.Mob, entity);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically search empty slot for clothes to equip
|
||||||
|
string? firstSlotName = null;
|
||||||
|
bool isEquiped = false;
|
||||||
|
foreach (var slot in _inventorySystem.GetSlots(ev.Mob))
|
||||||
|
{
|
||||||
|
if (!clothing.Slots.HasFlag(slot.SlotFlags))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (firstSlotName == null)
|
||||||
|
firstSlotName = slot.Name;
|
||||||
|
|
||||||
|
if (_inventorySystem.TryGetSlotEntity(ev.Mob, slot.Name, out var _))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (_inventorySystem.TryEquip(ev.Mob, entity, slot.Name, true))
|
||||||
|
{
|
||||||
|
isEquiped = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEquiped || firstSlotName == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Force equip to first valid clothes slot
|
||||||
|
// Get occupied entity -> Insert to backpack -> Equip loadout entity
|
||||||
|
if (_inventorySystem.TryGetSlotEntity(ev.Mob, firstSlotName, out var slotEntity) &&
|
||||||
|
_inventorySystem.TryGetSlotEntity(ev.Mob, BackpackSlotId, out var backEntity) &&
|
||||||
|
_storageSystem.CanInsert(backEntity.Value, slotEntity.Value, out _))
|
||||||
|
{
|
||||||
|
_storageSystem.Insert(backEntity.Value, slotEntity.Value);
|
||||||
|
}
|
||||||
|
_inventorySystem.TryEquip(ev.Mob, entity, firstSlotName, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
57
Content.Server/White/Other/EnergySword/DoubleSwordCraft.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using Content.Shared.Hands.EntitySystems;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
|
||||||
|
namespace Content.Server.White.Other.EnergySword;
|
||||||
|
|
||||||
|
public sealed class EnergyDoubleSwordCraftSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<DoubleSwordCraftComponent, InteractUsingEvent>(Combine);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string NeededEnt = "EnergySword";
|
||||||
|
private const string EnergyDoubleSword = "EnergyDoubleSword";
|
||||||
|
|
||||||
|
private void Combine(EntityUid uid, DoubleSwordCraftComponent component, InteractUsingEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var user = args.User;
|
||||||
|
var usedEnt = _entityManager.GetComponent<MetaDataComponent>(args.Used).EntityPrototype!.ID;
|
||||||
|
var usedTo = _entityManager.GetComponent<MetaDataComponent>(uid).EntityPrototype!.ID;
|
||||||
|
|
||||||
|
if (usedTo is EnergyDoubleSword)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (usedEnt != NeededEnt || usedTo != NeededEnt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DeleteUsed(args.Used, uid);
|
||||||
|
SpawnEnergyDoubleSword(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void DeleteUsed(EntityUid itemA, EntityUid itemB)
|
||||||
|
{
|
||||||
|
_entityManager.DeleteEntity(itemA);
|
||||||
|
_entityManager.DeleteEntity(itemB);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SpawnEnergyDoubleSword(EntityUid player)
|
||||||
|
{
|
||||||
|
var transform = CompOrNull<TransformComponent>(player)?.Coordinates;
|
||||||
|
|
||||||
|
if (transform == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var weaponEntity = _entityManager.SpawnEntity(EnergyDoubleSword, transform.Value);
|
||||||
|
_handsSystem.PickupOrDrop(player, weaponEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Content.Server.White.Other.EnergySword;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class DoubleSwordCraftComponent : Component
|
||||||
|
{
|
||||||
|
}
|
||||||
16
Content.Server/White/Other/Lazy/EarsSpawnComponent.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Content.Shared.Actions.ActionTypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.White.Other.Lazy;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class EarsSpawnComponent : Component
|
||||||
|
{
|
||||||
|
[DataField("summonAction")] public InstantAction SummonAction = new()
|
||||||
|
{
|
||||||
|
Icon = new SpriteSpecifier.Texture(new ResPath("Clothing/Head/Hats/witch.rsi/icon.png")),
|
||||||
|
DisplayName = "summon cat ears",
|
||||||
|
Description = "meow!",
|
||||||
|
Event = new SummonActionEarsEvent()
|
||||||
|
};
|
||||||
|
}
|
||||||
88
Content.Server/White/Other/Lazy/EarsSpawnSystem.cs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
using Content.Shared.ActionBlocker;
|
||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Hands.EntitySystems;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.White.Other.Lazy;
|
||||||
|
|
||||||
|
public sealed class EarsSpawnSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<EarsSpawnComponent, GetVerbsEvent<AlternativeVerb>>(AddSummonVerb);
|
||||||
|
SubscribeLocalEvent<EarsSpawnComponent, GetItemActionsEvent>(GetSummonAction);
|
||||||
|
SubscribeLocalEvent<EarsSpawnComponent, SummonActionEarsEvent>(OnSummon);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string Ears = "ClothingHeadHatCatEars";
|
||||||
|
private const string UserNeededKey = "merkkaa";
|
||||||
|
|
||||||
|
private void AddSummonVerb(EntityUid uid, EarsSpawnComponent component, GetVerbsEvent<AlternativeVerb> args)
|
||||||
|
{
|
||||||
|
if (!args.CanInteract || !args.CanAccess)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AlternativeVerb verb = new()
|
||||||
|
{
|
||||||
|
Act = () =>
|
||||||
|
{
|
||||||
|
AttemptSummon(component, args.User);
|
||||||
|
},
|
||||||
|
Text = Loc.GetString("summon cat ears"),
|
||||||
|
Priority = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
args.Verbs.Add(verb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSummon(EntityUid uid, EarsSpawnComponent component, SummonActionEarsEvent args)
|
||||||
|
{
|
||||||
|
AttemptSummon(component, args.Performer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AttemptSummon(EarsSpawnComponent component, EntityUid user)
|
||||||
|
{
|
||||||
|
if (!_blocker.CanInteract(user, component.Owner))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp<ActorComponent>(user, out var actorComponent))
|
||||||
|
{
|
||||||
|
var userKey = actorComponent.PlayerSession.Name;
|
||||||
|
if (userKey != UserNeededKey)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity("Вы не являетесь потомком кошко-богини.", user, PopupType.Medium);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SpawnEars(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SpawnEars(EntityUid player)
|
||||||
|
{
|
||||||
|
var transform = CompOrNull<TransformComponent>(player)?.Coordinates;
|
||||||
|
|
||||||
|
if (transform == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var ears = _entityManager.SpawnEntity(Ears, transform.Value);
|
||||||
|
_handsSystem.PickupOrDrop(player, ears);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetSummonAction(EntityUid uid, EarsSpawnComponent component, GetItemActionsEvent args)
|
||||||
|
{
|
||||||
|
args.Actions.Add(component.SummonAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class SummonActionEarsEvent : InstantActionEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
98
Content.Server/White/Other/OnDeath.cs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
using Content.Server.Chat.Systems;
|
||||||
|
using Content.Server.Ghost.Components;
|
||||||
|
using Content.Shared.Humanoid;
|
||||||
|
using Content.Shared.Mobs;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Server.White.Other;
|
||||||
|
|
||||||
|
public sealed class OnDeath : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly ChatSystem _chat = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<HumanoidAppearanceComponent, MobStateChangedEvent>(HandleDeathEvent);
|
||||||
|
SubscribeLocalEvent<GhostComponent, ComponentInit>(OnGhosted);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<EntityUid, IPlayingAudioStream> _playingStreams = new();
|
||||||
|
private static readonly SoundSpecifier DeathSounds = new SoundCollectionSpecifier("deathSounds");
|
||||||
|
private static readonly SoundSpecifier HeartSounds = new SoundCollectionSpecifier("heartSounds");
|
||||||
|
private static readonly string[] DeathGaspMessages =
|
||||||
|
{
|
||||||
|
"death-gasp-high",
|
||||||
|
"death-gasp-medium",
|
||||||
|
"death-gasp-normal"
|
||||||
|
};
|
||||||
|
|
||||||
|
private void HandleDeathEvent(EntityUid uid, HumanoidAppearanceComponent component, MobStateChangedEvent args)
|
||||||
|
{
|
||||||
|
//^.^
|
||||||
|
switch (args.NewMobState)
|
||||||
|
{
|
||||||
|
case MobState.Invalid:
|
||||||
|
StopPlayingStream(uid);
|
||||||
|
break;
|
||||||
|
case MobState.Alive:
|
||||||
|
StopPlayingStream(uid);
|
||||||
|
break;
|
||||||
|
case MobState.Critical:
|
||||||
|
PlayPlayingStream(uid);
|
||||||
|
break;
|
||||||
|
case MobState.Dead:
|
||||||
|
StopPlayingStream(uid);
|
||||||
|
var deathGaspMessage = SelectRandomDeathGaspMessage();
|
||||||
|
var localizedMessage = LocalizeDeathGaspMessage(deathGaspMessage);
|
||||||
|
SendDeathGaspMessage(uid, localizedMessage);
|
||||||
|
PlayDeathSound(uid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void PlayPlayingStream(EntityUid uid)
|
||||||
|
{
|
||||||
|
if (_playingStreams.TryGetValue(uid, out var currentStream))
|
||||||
|
{
|
||||||
|
currentStream.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
var newStream = _audio.PlayEntity(HeartSounds, uid, uid, AudioParams.Default.WithLoop(true));
|
||||||
|
if (newStream != null)
|
||||||
|
{
|
||||||
|
_playingStreams[uid] = newStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopPlayingStream(EntityUid uid)
|
||||||
|
{
|
||||||
|
if (_playingStreams.TryGetValue(uid, out var currentStream))
|
||||||
|
{
|
||||||
|
currentStream.Stop();
|
||||||
|
_playingStreams.Remove(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SelectRandomDeathGaspMessage()
|
||||||
|
=> DeathGaspMessages[_random.Next(DeathGaspMessages.Length)];
|
||||||
|
|
||||||
|
private string LocalizeDeathGaspMessage(string message)
|
||||||
|
=> Loc.GetString(message);
|
||||||
|
|
||||||
|
private void SendDeathGaspMessage(EntityUid uid, string message)
|
||||||
|
=> _chat.TrySendInGameICMessage(uid, message, InGameICChatType.Emote, false, force: true);
|
||||||
|
|
||||||
|
private void PlayDeathSound(EntityUid uid)
|
||||||
|
=> _audio.PlayEntity(DeathSounds, uid, uid, AudioParams.Default);
|
||||||
|
|
||||||
|
private void OnGhosted(EntityUid uid, GhostComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
StopPlayingStream(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -31,3 +31,5 @@ marking-FoxEarsMaury-ears_fox_tip = Градиент
|
|||||||
marking-CatTailDouble = Двойной хвост
|
marking-CatTailDouble = Двойной хвост
|
||||||
marking-CatTailDouble-double_tail_cat_back = Первый хвост
|
marking-CatTailDouble-double_tail_cat_back = Первый хвост
|
||||||
marking-CatTailDouble-double_tail_cat_front = Второй хвост
|
marking-CatTailDouble-double_tail_cat_front = Второй хвост
|
||||||
|
|
||||||
|
marking-DemonTailWarete = Демонический хвост
|
||||||
|
|||||||
@@ -213,70 +213,29 @@
|
|||||||
shader: unshaded
|
shader: unshaded
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: Double Bladed Energy Sword
|
name: double energy sword
|
||||||
parent: EnergySword
|
parent: EnergySword
|
||||||
id: EnergySwordDouble
|
id: EnergyDoubleSword
|
||||||
description: Syndicate Command Interns thought that having one blade on the energy sword was not enough. This can be stored in pockets.
|
description: A very dangerous doubled energy sword. Can be stored in pockets when turned off. Makes a lot of noise when used or turned on.
|
||||||
components:
|
components:
|
||||||
- type: EnergySword
|
- type: Sprite
|
||||||
- type: ItemToggle
|
sprite: Objects/Weapons/Melee/double_esword.rsi
|
||||||
soundActivate:
|
layers:
|
||||||
path: /Audio/Weapons/ebladeon.ogg
|
- state: e_sword
|
||||||
params:
|
- state: e_sword_blade
|
||||||
volume: 3
|
visible: false
|
||||||
soundDeactivate:
|
shader: unshaded
|
||||||
path: /Audio/Weapons/ebladeoff.ogg
|
map: [ "blade" ]
|
||||||
params:
|
- type: Wieldable
|
||||||
volume: 3
|
- type: IncreaseDamageOnWield
|
||||||
- type: ItemToggleMeleeWeapon
|
damage:
|
||||||
activatedSoundOnSwing:
|
|
||||||
path: /Audio/Weapons/eblademiss.ogg
|
|
||||||
params:
|
|
||||||
volume: 3
|
|
||||||
variation: 0.250
|
|
||||||
activatedDamage:
|
|
||||||
types:
|
types:
|
||||||
Slash: 12
|
Slash: 15
|
||||||
Heat: 12
|
Heat: 13
|
||||||
Structural: 15
|
- type: MeleeWeapon
|
||||||
- type: ItemToggleActiveSound
|
attackRate: 1
|
||||||
activeSound:
|
- type: Reflect
|
||||||
path: /Audio/Weapons/ebladehum.ogg
|
enabled: false
|
||||||
params:
|
energeticChance: 0.7
|
||||||
volume: 3
|
kineticChance: 0.7
|
||||||
- type: ItemToggleDisarmMalus
|
spread: 45
|
||||||
activatedDisarmMalus: 0.7
|
|
||||||
- type: Wieldable
|
|
||||||
- type: MeleeWeapon
|
|
||||||
wideAnimationRotation: -135
|
|
||||||
attackRate: 1.5
|
|
||||||
angle: 100
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Blunt: 4.5
|
|
||||||
- type: Sprite
|
|
||||||
sprite: Objects/Weapons/Melee/e_sword_double.rsi
|
|
||||||
layers:
|
|
||||||
- state: e_sword_double
|
|
||||||
- state: e_sword_double_blade
|
|
||||||
color: "#FFFFFF"
|
|
||||||
visible: false
|
|
||||||
shader: unshaded
|
|
||||||
map: [ "blade" ]
|
|
||||||
- type: Item
|
|
||||||
size: Small
|
|
||||||
sprite: Objects/Weapons/Melee/e_sword_double-inhands.rsi
|
|
||||||
- type: Reflect
|
|
||||||
reflectProb: .75
|
|
||||||
spread: 75
|
|
||||||
- type: UseDelay
|
|
||||||
delay: 1
|
|
||||||
- type: ToggleableLightVisuals
|
|
||||||
spriteLayer: blade
|
|
||||||
inhandVisuals:
|
|
||||||
left:
|
|
||||||
- state: inhand-left-blade
|
|
||||||
shader: unshaded
|
|
||||||
right:
|
|
||||||
- state: inhand-right-blade
|
|
||||||
shader: unshaded
|
|
||||||
|
|||||||
13
Resources/Prototypes/SoundCollections/white.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
- type: soundCollection
|
||||||
|
id: deathSounds
|
||||||
|
files:
|
||||||
|
- /White/Audio/Death/death.ogg
|
||||||
|
- /White/Audio/Death/death.wav
|
||||||
|
|
||||||
|
- type: soundCollection
|
||||||
|
id: heartSounds
|
||||||
|
files:
|
||||||
|
- /White/Audio/Heart/heart.ogg
|
||||||
|
- /White/Audio/Heart/heart2.wav
|
||||||
|
- /White/Audio/Heart/heart3.ogg
|
||||||
|
- /White/Audio/Heart/heart4.ogg
|
||||||
112
Resources/Prototypes/White/Fluff/fluff.yml
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
# DOOMMAX
|
||||||
|
- type: entity
|
||||||
|
parent: ClothingOuterEVASuitBase
|
||||||
|
id: ClothingOuterSuitGlamorous
|
||||||
|
name: glamorous suit
|
||||||
|
description: An emergency suit in cases of... emergencies. But glamorous.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Fluff/DOOMMAX/glamorous.rsi
|
||||||
|
- type: Clothing
|
||||||
|
sprite: White/Fluff/DOOMMAX/glamorous.rsi
|
||||||
|
- type: ClothingSpeedModifier
|
||||||
|
walkModifier: 0.7
|
||||||
|
sprintModifier: 0.7
|
||||||
|
- type: TemperatureProtection
|
||||||
|
coefficient: 0.7
|
||||||
|
- type: ToggleableClothing
|
||||||
|
clothingPrototype: ClothingHeadHelmetEVA
|
||||||
|
- type: ContainerContainer
|
||||||
|
containers:
|
||||||
|
toggleable-clothing: !type:ContainerSlot {}
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: ClothingOuterHardsuitEVA
|
||||||
|
id: ClothingOuterHardsuitEVAGLAMOUR
|
||||||
|
name: скафандр EVA GLAMOUR
|
||||||
|
description: Улучшеный Скафандр Гламура! Модный, стильный, совершенный! Способен защитить вас от космического вакуума. В этом скафандре все главы будут ваши. На скафандре подписан владелец - Алина Бэккен.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Fluff/DOOMMAX/evaglamour.rsi
|
||||||
|
- type: Clothing
|
||||||
|
sprite: White/Fluff/DOOMMAX/evaglamour.rsi
|
||||||
|
- type: ToggleableClothing
|
||||||
|
clothingPrototype: ClothingHeadHelmetEVAGLAMOUR
|
||||||
|
- type: ContainerContainer
|
||||||
|
containers:
|
||||||
|
toggleable-clothing: !type:ContainerSlot { }
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: ClothingHeadHelmetEVA
|
||||||
|
id: ClothingHeadHelmetEVAGLAMOUR
|
||||||
|
name: шлем EVA GLAMOUR
|
||||||
|
description: Гламурный вариант шлема EVA.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Fluff/DOOMMAX/helmetglamour.rsi
|
||||||
|
- type: Clothing
|
||||||
|
sprite: White/Fluff/DOOMMAX/helmetglamour.rsi
|
||||||
|
|
||||||
|
# Maury
|
||||||
|
- type: entity
|
||||||
|
parent: ClothingUniformJumpsuitChemistry
|
||||||
|
id: ClothingUniformJumpsuitMauryZ #Should be ClothingUniformJumpsuitMaury but i`m retard and lazy idiot
|
||||||
|
name: Rupi's chemist uniform
|
||||||
|
description: Обычно NanoTrasen не позволяет сотрудникам изменять выданную им униформу, но по отношению к Руперту они проявили снисходительность.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Fluff/Maury/chemshit.rsi
|
||||||
|
- type: Clothing
|
||||||
|
sprite: White/Fluff/Maury/chemshit.rsi
|
||||||
|
|
||||||
|
# YouWellLeer
|
||||||
|
- type: entity
|
||||||
|
parent: Crowbar
|
||||||
|
id: Sledgebar
|
||||||
|
name: Mjolnir
|
||||||
|
description: Отлично ломает кости ассистентам и клоуну.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Fluff/YouWellLeer/sledgebar.rsi
|
||||||
|
state: icon
|
||||||
|
netsync: false
|
||||||
|
- type: Item
|
||||||
|
sprite: White/Fluff/YouWellLeer/sledgebar.rsi
|
||||||
|
size: 30
|
||||||
|
- type: Wieldable
|
||||||
|
- type: IncreaseDamageOnWield
|
||||||
|
damage:
|
||||||
|
types:
|
||||||
|
Blunt: 10
|
||||||
|
|
||||||
|
# merkkaa
|
||||||
|
- type: entity
|
||||||
|
parent: Bible
|
||||||
|
name: няко библия
|
||||||
|
description: Книга является заметками кошко богини. Её потомки используют эту книгу как Библию.
|
||||||
|
id: BibleNya
|
||||||
|
components:
|
||||||
|
- type: EarsSpawn
|
||||||
|
- type: Sprite
|
||||||
|
netsync: false
|
||||||
|
sprite: White/Fluff/merkkaa/bible.rsi
|
||||||
|
state: icon
|
||||||
|
- type: Item
|
||||||
|
size: 10
|
||||||
|
sprite: White/Fluff/merkkaa/bible.rsi
|
||||||
|
- type: PointLight
|
||||||
|
radius: 2
|
||||||
|
energy: 2
|
||||||
|
color: pink
|
||||||
|
|
||||||
|
# Warete
|
||||||
|
- type: entity
|
||||||
|
parent: ClothingUniformBase
|
||||||
|
id: WareteJumpskirt
|
||||||
|
name: репонит
|
||||||
|
description: Жаростойкая куртка. С предупреждением о возможной взрывоопасности.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Fluff/Warete/warete_jumpsuit.rsi
|
||||||
|
- type: Clothing
|
||||||
|
sprite: White/Fluff/Warete/warete_jumpsuit.rsi
|
||||||
41
Resources/Prototypes/White/Fluff/sponsor.yml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# DOOMMAX
|
||||||
|
- type: loadout
|
||||||
|
id: SuitGlamorousLoadout
|
||||||
|
entity: ClothingOuterSuitGlamorous
|
||||||
|
sponsorOnly: true
|
||||||
|
blacklistJobs: [Captain, HeadOfPersonnel, ChiefEngineer, ChiefMedicalOfficer, ResearchDirector, HeadOfSecurity, Quartermaster]
|
||||||
|
|
||||||
|
- type: loadout
|
||||||
|
id: ClothingOuterHardsuitEVAGLAMOURsLoadout
|
||||||
|
entity: ClothingOuterHardsuitEVAGLAMOUR
|
||||||
|
sponsorOnly: true
|
||||||
|
whitelistJobs: [Captain, HeadOfPersonnel, ChiefEngineer, ChiefMedicalOfficer, ResearchDirector, HeadOfSecurity, Quartermaster]
|
||||||
|
|
||||||
|
# Maury
|
||||||
|
- type: loadout
|
||||||
|
id: ClothingUniformJumpsuitMaury #Should be ClothingUniformMauryLoadout but like i said i`m retard
|
||||||
|
entity: ClothingUniformJumpsuitMauryZ
|
||||||
|
sponsorOnly: true
|
||||||
|
|
||||||
|
# YouWellLeer
|
||||||
|
- type: loadout
|
||||||
|
id: SledgebarLoadout
|
||||||
|
entity: Sledgebar
|
||||||
|
sponsorOnly: true
|
||||||
|
|
||||||
|
# мурка
|
||||||
|
- type: loadout
|
||||||
|
id: BibleNyaLoadout
|
||||||
|
entity: BibleNya
|
||||||
|
sponsorOnly: true
|
||||||
|
|
||||||
|
- type: loadout # WHITEGPT HUETA ДЛЯ КЛОУНОВ И ВЫШЕ
|
||||||
|
id: WhiteGPTLoadout
|
||||||
|
entity: PersonalNeuralAI
|
||||||
|
sponsorOnly: true
|
||||||
|
|
||||||
|
# Warete
|
||||||
|
- type: loadout
|
||||||
|
id: WareteJumpskirtLoadout
|
||||||
|
entity: WareteJumpskirt
|
||||||
|
sponsorOnly: true
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
- type: marking
|
||||||
|
id: CatTailStripes
|
||||||
|
bodyPart: Tail
|
||||||
|
markingCategory: Tail
|
||||||
|
speciesRestriction: [Human]
|
||||||
|
sponsorOnly: true
|
||||||
|
sprites:
|
||||||
|
- sprite: White/Mobs/Customization/cat_parts.rsi
|
||||||
|
state: tail_cat_wag_stripes_prime
|
||||||
|
- sprite: White/Mobs/Customization/cat_parts.rsi
|
||||||
|
state: tail_cat_wag_stripes_second
|
||||||
|
|
||||||
|
- type: marking
|
||||||
|
id: CatTailMaury
|
||||||
|
bodyPart: Tail
|
||||||
|
markingCategory: Tail
|
||||||
|
speciesRestriction: [Human]
|
||||||
|
sponsorOnly: true
|
||||||
|
sprites:
|
||||||
|
- sprite: White/Mobs/Customization/cat_parts.rsi
|
||||||
|
state: tail_cat_wag_z
|
||||||
|
- sprite: White/Mobs/Customization/cat_parts.rsi
|
||||||
|
state: tail_cat_wag_tip
|
||||||
|
|
||||||
|
- type: marking
|
||||||
|
id: CatTailDouble
|
||||||
|
bodyPart: Tail
|
||||||
|
markingCategory: Tail
|
||||||
|
sponsorOnly: true
|
||||||
|
sprites:
|
||||||
|
- sprite: White/Mobs/Customization/double_cat.rsi
|
||||||
|
state: double_tail_cat_back
|
||||||
|
- sprite: White/Mobs/Customization/double_cat.rsi
|
||||||
|
state: double_tail_cat_front
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
- type: marking
|
||||||
|
id: FoxEars
|
||||||
|
bodyPart: HeadTop
|
||||||
|
markingCategory: HeadTop
|
||||||
|
speciesRestriction: [Human]
|
||||||
|
sponsorOnly: true
|
||||||
|
sprites:
|
||||||
|
- sprite: White/Mobs/Customization/fox_parts.rsi
|
||||||
|
state: ears_fox_outer
|
||||||
|
- sprite: White/Mobs/Customization/fox_parts.rsi
|
||||||
|
state: ears_fox_inner
|
||||||
|
|
||||||
|
- type: marking
|
||||||
|
id: FoxEarsMaury
|
||||||
|
bodyPart: HeadTop
|
||||||
|
markingCategory: HeadTop
|
||||||
|
speciesRestriction: [Human]
|
||||||
|
sponsorOnly: true
|
||||||
|
sprites:
|
||||||
|
- sprite: White/Mobs/Customization/fox_parts.rsi
|
||||||
|
state: ears_fox_outer
|
||||||
|
- sprite: White/Mobs/Customization/fox_parts.rsi
|
||||||
|
state: ears_fox_inner
|
||||||
|
- sprite: White/Mobs/Customization/fox_parts.rsi
|
||||||
|
state: ears_fox_tip
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
- type: marking
|
||||||
|
id: DemonHairWarete
|
||||||
|
bodyPart: Hair
|
||||||
|
markingCategory: HeadTop
|
||||||
|
speciesRestriction: [ Human ]
|
||||||
|
sponsorOnly: true
|
||||||
|
sprites:
|
||||||
|
- sprite: White/Mobs/Customization/warete_hair.rsi
|
||||||
|
state: hair
|
||||||
|
|
||||||
|
- type: marking
|
||||||
|
id: DemonTailWarete
|
||||||
|
bodyPart: Tail
|
||||||
|
markingCategory: Tail
|
||||||
|
speciesRestriction: [Human]
|
||||||
|
sponsorOnly: true
|
||||||
|
sprites:
|
||||||
|
- sprite: White/Mobs/Customization/demon_tail.rsi
|
||||||
|
state: tail
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#YouWellLeer
|
||||||
|
- type: marking
|
||||||
|
id: WolfEarsLeer
|
||||||
|
bodyPart: HeadTop
|
||||||
|
markingCategory: HeadTop
|
||||||
|
speciesRestriction: [ Human ]
|
||||||
|
sponsorOnly: true
|
||||||
|
sprites:
|
||||||
|
- sprite: White/Mobs/Customization/wolf_parts.rsi
|
||||||
|
state: wolf_ears_outer
|
||||||
|
- sprite: White/Mobs/Customization/wolf_parts.rsi
|
||||||
|
state: wolf_ears_inner
|
||||||
|
|
||||||
|
- type: marking
|
||||||
|
id: WolfTailLeer
|
||||||
|
bodyPart: Tail
|
||||||
|
markingCategory: Tail
|
||||||
|
speciesRestriction: [Human]
|
||||||
|
sponsorOnly: true
|
||||||
|
sprites:
|
||||||
|
- sprite: White/Mobs/Customization/wolf_parts.rsi
|
||||||
|
state: wolf_tail
|
||||||
|
After Width: | Height: | Size: 231 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 447 B |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 464 B |
@@ -0,0 +1,184 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "e_sword"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "e_sword_blade",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-left-blade",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-right-blade",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15,
|
||||||
|
0.15,
|
||||||
|
0.05,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.05,
|
||||||
|
0.15
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||