Рефактор аспектов, немного потыкал значений (#670)

* aspects update

* aspects mini refactor
This commit is contained in:
ThereDrD
2024-08-28 08:20:16 +03:00
committed by GitHub
parent e335e1d128
commit ef0ac9f2e5
5 changed files with 235 additions and 201 deletions

View File

@@ -1,4 +1,3 @@
using Content.Server.GameTicking.Rules.Components;
using Content.Server._White.AspectsSystem.Aspects.Components; using Content.Server._White.AspectsSystem.Aspects.Components;
using Content.Server._White.AspectsSystem.Base; using Content.Server._White.AspectsSystem.Base;
using Content.Server.GameTicking.Components; using Content.Server.GameTicking.Components;

View File

@@ -1,39 +1,29 @@
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server._White.AspectsSystem.Base namespace Content.Server._White.AspectsSystem.Base;
[RegisterComponent]
public sealed partial class AspectComponent : Component
{ {
[RegisterComponent] [DataField] public string? Name;
public sealed partial class AspectComponent : Component
{
[DataField("name")]
public string? Name;
[DataField("description")] [DataField] public string? Description;
public string? Description;
[DataField("requires")] [DataField] public string? Requires;
public string? Requires;
[DataField("weight")] [DataField] public float Weight = 1.0f;
public float Weight = 1.0f;
[DataField("forbidden")] [DataField] public bool IsForbidden;
public bool IsForbidden;
[DataField("hidden")] [DataField] public bool IsHidden;
public bool IsHidden;
[DataField("startAudio")] [DataField] public SoundSpecifier? StartAudio;
public SoundSpecifier? StartAudio;
[DataField("endAudio")] [DataField] public SoundSpecifier? EndAudio;
public SoundSpecifier? EndAudio;
[DataField("startDelay")] [DataField] public TimeSpan StartDelay = TimeSpan.Zero;
public TimeSpan StartDelay = TimeSpan.Zero;
[DataField("startTime", customTypeSerializer: typeof(TimeOffsetSerializer))] [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan StartTime; public TimeSpan StartTime;
}
} }

View File

@@ -1,145 +1,182 @@
using System.Linq;
using Content.Server.Administration; using Content.Server.Administration;
using Content.Server.GameTicking; using Content.Server.GameTicking;
using Content.Server._White.AspectsSystem.Managers; using Content.Server._White.AspectsSystem.Managers;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Shared.Console; using Robust.Shared.Console;
namespace Content.Server._White.AspectsSystem.Commands namespace Content.Server._White.AspectsSystem.Commands;
[AdminCommand(AdminFlags.Fun)]
public sealed class ForceAspectCommand : IConsoleCommand
{ {
[AdminCommand(AdminFlags.Fun)] [Dependency] private readonly IEntityManager _entityManager = default!;
public sealed class ForceAspectCommand : IConsoleCommand
public string Command => "forceaspect";
public string Description => "Принудительно форсит аспект по его ID.";
public string Help => "forceaspect <aspectId>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
public string Command => "forceaspect"; var ticker = _entityManager.System<GameTicker>();
public string Description => "Принудительно форсит аспект по его ID.";
public string Help => "forceaspect <aspectId>";
public void Execute(IConsoleShell shell, string argStr, string[] args) if (ticker.RunLevel != GameRunLevel.PreRoundLobby)
{ {
var ticker = EntitySystem.Get<GameTicker>(); shell.WriteLine("This can only be executed while the game is in the pre-round lobby.");
if (ticker.RunLevel != GameRunLevel.PreRoundLobby) return;
{
shell.WriteLine("This can only be executed while the game is in the pre-round lobby.");
return;
}
if (args.Length != 1)
{
shell.WriteError("Использование: forceaspect <aspectId>");
return;
}
var aspectId = args[0];
var aspectManager = EntitySystem.Get<AspectManager>();
var result = aspectManager.ForceAspect(aspectId);
shell.WriteLine(result);
} }
if (args.Length != 1)
{
shell.WriteError("Использование: forceaspect <aspectId>");
return;
}
var aspectManager = _entityManager.System<AspectManager>();
var aspectId = args[0];
var result = aspectManager.ForceAspect(aspectId);
shell.WriteLine(result);
} }
[AdminCommand(AdminFlags.Fun)] public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
public sealed class DeForceAspectCommand : IConsoleCommand
{ {
public string Command => "deforceaspect"; if (args.Length != 1)
public string Description => "Дефорсит принудительно установленный аспект."; return CompletionResult.Empty;
public string Help => "deforceaspect";
public void Execute(IConsoleShell shell, string argStr, string[] args) var aspectManager = _entityManager.System<AspectManager>();
{
var ticker = EntitySystem.Get<GameTicker>();
if (ticker.RunLevel != GameRunLevel.PreRoundLobby)
{
shell.WriteLine("This can only be executed while the game is in the pre-round lobby.");
return;
}
var aspectManager = EntitySystem.Get<AspectManager>(); var options = aspectManager
var result = aspectManager.DeForceAspect(); .GetAspectsPrototypesId()
shell.WriteLine(result); .Select(p => new CompletionOption(p.Key.ID, p.Value.Name))
} .OrderBy(p => p.Value);
return CompletionResult.FromHintOptions(options, Loc.GetString("forcemap-command-arg-map"));
} }
}
[AdminCommand(AdminFlags.Fun)] [AdminCommand(AdminFlags.Fun)]
public sealed class GetForcedAspectCommand : IConsoleCommand public sealed class DeForceAspectCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entityManager = default!;
public string Command => "deforceaspect";
public string Description => "Дефорсит принудительно установленный аспект.";
public string Help => "deforceaspect";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
public string Command => "getforcedaspect"; var ticker = _entityManager.System<GameTicker>();
public string Description => "Получает информацию о принудительно установленном аспекте.";
public string Help => "getforcedaspect";
public void Execute(IConsoleShell shell, string argStr, string[] args) if (ticker.RunLevel != GameRunLevel.PreRoundLobby)
{ {
var ticker = EntitySystem.Get<GameTicker>(); shell.WriteLine("This can only be executed while the game is in the pre-round lobby.");
if (ticker.RunLevel != GameRunLevel.PreRoundLobby) return;
{
shell.WriteLine("This can only be executed while the game is in the pre-round lobby.");
return;
}
var aspectManager = EntitySystem.Get<AspectManager>();
var result = aspectManager.GetForcedAspect();
shell.WriteLine(result);
} }
var aspectManager = _entityManager.System<AspectManager>();
var result = aspectManager.DeForceAspect();
shell.WriteLine(result);
} }
}
[AdminCommand(AdminFlags.Fun)] [AdminCommand(AdminFlags.Fun)]
public sealed class ListAspectsCommand : IConsoleCommand public sealed class GetForcedAspectCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entityManager = default!;
public string Command => "getforcedaspect";
public string Description => "Получает информацию о принудительно установленном аспекте.";
public string Help => "getforcedaspect";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
public string Command => "listaspects"; var ticker = _entityManager.System<GameTicker>();
public string Description => "Список всех доступных аспектов.";
public string Help => "listaspects";
public void Execute(IConsoleShell shell, string argStr, string[] args) if (ticker.RunLevel != GameRunLevel.PreRoundLobby)
{ {
var aspectManager = EntitySystem.Get<AspectManager>(); shell.WriteLine("This can only be executed while the game is in the pre-round lobby.");
var aspectIds = aspectManager.GetAllAspectIds(); return;
if (aspectIds.Count == 0)
{
shell.WriteLine("Нет доступных аспектов.");
}
else
{
shell.WriteLine("Список доступных аспектов:");
foreach (var aspectId in aspectIds)
{
shell.WriteLine(aspectId);
}
}
} }
var aspectManager = _entityManager.System<AspectManager>();
var result = aspectManager.GetForcedAspect();
shell.WriteLine(result);
} }
}
[AdminCommand(AdminFlags.Fun)] [AdminCommand(AdminFlags.Fun)]
public sealed class RunAspectCommand : IConsoleCommand public sealed class ListAspectsCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entityManager = default!;
public string Command => "listaspects";
public string Description => "Список всех доступных аспектов.";
public string Help => "listaspects";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
public string Command => "runaspect"; var aspectManager = _entityManager.System<AspectManager>();
public string Description => "Запускает аспект по его ID.";
public string Help => "runaspect <aspectId>";
public void Execute(IConsoleShell shell, string argStr, string[] args) var aspectIds = aspectManager.GetAllAspectIds();
if (aspectIds.Count == 0)
{ {
if (args.Length != 1) shell.WriteLine("Нет доступных аспектов.");
{
shell.WriteError("Использование: runaspect <aspectId>");
return;
}
var aspectId = args[0];
var aspectManager = EntitySystem.Get<AspectManager>();
var result = aspectManager.RunAspect(aspectId);
shell.WriteLine(result);
} }
} else
[AdminCommand(AdminFlags.Fun)]
public sealed class RunRandomAspectCommand : IConsoleCommand
{
public string Command => "runrandomaspect";
public string Description => "Запускает случайный аспект.";
public string Help => "runrandomaspect";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var aspectManager = EntitySystem.Get<AspectManager>(); shell.WriteLine("Список доступных аспектов:");
var result = aspectManager.RunRandomAspect(); foreach (var aspectId in aspectIds)
shell.WriteLine(result); {
shell.WriteLine(aspectId);
}
} }
} }
} }
[AdminCommand(AdminFlags.Fun)]
public sealed class RunAspectCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entityManager = default!;
public string Command => "runaspect";
public string Description => "Запускает аспект по его ID.";
public string Help => "runaspect <aspectId>";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteError("Использование: runaspect <aspectId>");
return;
}
var aspectId = args[0];
var aspectManager = _entityManager.System<AspectManager>();
var result = aspectManager.RunAspect(aspectId);
shell.WriteLine(result);
}
}
[AdminCommand(AdminFlags.Fun)]
public sealed class RunRandomAspectCommand : IConsoleCommand
{
[Dependency] private readonly IEntityManager _entityManager = default!;
public string Command => "runrandomaspect";
public string Description => "Запускает случайный аспект.";
public string Help => "runrandomaspect";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var aspectManager = _entityManager.System<AspectManager>();
var result = aspectManager.RunRandomAspect();
shell.WriteLine(result);
}
}

View File

@@ -1,3 +1,4 @@
using System.Linq;
using Content.Server.GameTicking; using Content.Server.GameTicking;
using Content.Server._White.AspectsSystem.Base; using Content.Server._White.AspectsSystem.Base;
using Content.Shared.GameTicking; using Content.Shared.GameTicking;
@@ -193,6 +194,13 @@ namespace Content.Server._White.AspectsSystem.Managers
return aspectIds; return aspectIds;
} }
public Dictionary<EntityPrototype, AspectComponent> GetAspectsPrototypesId()
{
var availableAspects = AllAspects();
return availableAspects;
}
/// <summary> /// <summary>
/// Runs the specified aspect and adds it as a game rule. /// Runs the specified aspect and adds it as a game rule.
/// </summary> /// </summary>

View File

@@ -4,8 +4,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Акценты вне контроля" name: Акценты вне контроля
description: "Всегда интересно, какой акцент вы услышите следующим." description: Всегда интересно, какой акцент вы услышите следующим
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -17,8 +17,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Fast and Furious" name: Fast and Furious
description: "Люди спешат и не важно куда." description: Люди спешат и не важно куда
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -30,8 +30,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Random appearance" name: Random appearance
description: "Экипаж перестал узнавать друг-друга в лицо." description: Экипаж перестал узнавать друг-друга в лицо
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -43,9 +43,9 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Bombass" name: Bombass
description: "Кто-то заложил мины на станции!" description: Кто-то заложил мины на станции!
weight: 1 weight: 2
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
- type: BombassAspect - type: BombassAspect
@@ -56,8 +56,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Drunk" name: Drunk
description: "На станции стоит явный запах вчерашнего веселья... и кажется оно только начинается." description: На станции стоит явный запах вчерашнего веселья... и кажется оно только начинается
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -69,8 +69,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Cargo Rich" name: Cargo Rich
description: "Карго работало усердно в прошлую смену, за что они и были награждены премией в размере 100000 кредитов." description: Карго работало усердно в прошлую смену, за что они и были награждены премией в размере 100000 кредитов
weight: 2 weight: 2
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -82,11 +82,11 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Traitored" name: Traitored
description: "Кто-то сдал всех предателей!" description: Кто-то сдал всех предателей!
requires: "Traitors" requires: Traitors
weight: 1 weight: 1
hidden: true isHidden: true
- type: TraitoredAspect - type: TraitoredAspect
- type: entity - type: entity
@@ -95,8 +95,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Weak Walls" name: Weak Walls
description: "На стенах явно экономили." description: На стенах явно экономили
weight: 2 weight: 2
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -108,8 +108,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "No engine" name: No engine
description: "Какой-то смышлённый агент синдиката решил украсть все ваши генераторы энергии целиком." description: Какой-то смышлённый агент синдиката решил украсть все ваши генераторы энергии целиком
weight: 2 weight: 2
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -121,11 +121,12 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Airunlock" name: Airunlock
description: "Кого волнует безопасность? Экипаж свободно может ходить по всем отсекам, ведь все шлюзы теперь для них доступны." description: Кого волнует безопасность? Экипаж свободно может ходить по всем отсекам, ведь все шлюзы теперь для них доступны
weight: 2 weight: 2
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
isForbidden: true
- type: AiRunLockAspect - type: AiRunLockAspect
- type: entity - type: entity
@@ -134,9 +135,9 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Bloody" name: Bloody
description: "В эту смену любая незначительная травма может оказаться летальной." description: В эту смену любая незначительная травма может оказаться летальной
weight: 1 weight: 2
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
- type: BloodyAspect - type: BloodyAspect
@@ -147,8 +148,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Weak" name: Weak
description: "Удары стали слабее. Пули мягче. К чему это приведёт?" description: Удары стали слабее. Пули мягче. К чему это приведёт?
weight: 1 weight: 1
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -160,8 +161,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Battled" name: Battled
description: "Люди очень насторожены и готовы дать отпор в любую секунду." description: Люди очень насторожены и готовы дать отпор в любую секунду
weight: 1 weight: 1
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -173,8 +174,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "I Have Two Butts But I must Seat" name: I Have Two Butts But I must Seat
description: "Стулья украли!" description: Стулья украли!
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -186,9 +187,9 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Presents" name: Presents
description: "А вы верите в Деда Мороза?" description: А вы верите в Деда Мороза?
weight: 2 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
- type: PresentAspect - type: PresentAspect
@@ -199,12 +200,11 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Dance" name: Dance
description: "Танцуют все!" description: Танцуют все!
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
forbidden: true
- type: DancingAspect - type: DancingAspect
- type: entity - type: entity
@@ -213,8 +213,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Reflect" name: Reflect
description: "Ваше отражение повсюду." description: Ваше отражение повсюду
weight: 2 weight: 2
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -226,8 +226,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Slippery" name: Slippery
description: "Постарайтесь не поскальзываться!" description: Постарайтесь не поскальзываться!
weight: 2 weight: 2
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -239,11 +239,11 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Extra TC" name: Extra TC
description: "Синдикат выделил 10 дополнительных телекристаллов для предателей." description: Синдикат выделил 10 дополнительных телекристаллов для предателей
requires: "Traitors" requires: Traitors
weight: 2 weight: 3
hidden: true isHidden: true
- type: TraitorRichAspect - type: TraitorRichAspect
- type: entity - type: entity
@@ -252,12 +252,12 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Whisper" name: Whisper
description: "Из-за боли в горле речь дается вам с трудом." description: Из-за боли в горле речь дается вам с трудом
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
forbidden: true isForbidden: true
- type: WhisperAspect - type: WhisperAspect
- type: entity - type: entity
@@ -266,8 +266,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Darkness" name: Darkness
description: "Почему все так темно?" description: Почему все так темно?
weight: 2 weight: 2
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -279,8 +279,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Stolen Floor" name: Stolen Floor
description: "Рабочие забыли положить плитку при строительстве станции." description: Рабочие забыли положить плитку при строительстве станции
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -292,8 +292,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Are We In Dungeon" name: Are We In Dungeon
description: "В связи с невероятной хрупкостью окон было решено заменить их на стены." description: В связи с невероятной хрупкостью окон было решено заменить их на стены
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -305,8 +305,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Cat Ears And Tail" name: Cat Ears And Tail
description: "Из-за ошибки в системе клонирования на ЦК все члены экипажа стали походить на фелинидов." description: Из-за ошибки в системе клонирования на ЦК все члены экипажа стали походить на фелинидов
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -318,11 +318,11 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Nothing" name: Nothing
description: "Ничего." description: Ничего
weight: 3 weight: 3
forbidden: true isForbidden: true
hidden: true isHidden: true
- type: NothingAspect - type: NothingAspect
- type: entity - type: entity
@@ -331,8 +331,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Random item" name: Random item
description: "ЦК выдало каждому члену экипажа определённый предмет." description: ЦК выдало каждому члену экипажа определённый предмет
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -344,8 +344,8 @@
noSpawn: true noSpawn: true
components: components:
- type: Aspect - type: Aspect
name: "Immersive" name: Immersive
description: "В связи с недавними трагичными событиями экипаж станции погрузился в себя" description: В связи с недавними трагичными событиями экипаж станции погрузился в себя
weight: 3 weight: 3
startAudio: startAudio:
path: /Audio/White/Aspects/accent.ogg path: /Audio/White/Aspects/accent.ogg
@@ -358,8 +358,8 @@
# noSpawn: true # noSpawn: true
# components: # components:
# - type: Aspect # - type: Aspect
# name: "Skeletons" # name: Skeletons
# description: "АЧК АЧК!" # description: АЧК АЧК!
# weight: 1 # weight: 1
# startAudio: # startAudio:
# path: /Audio/White/Aspects/accent.ogg # path: /Audio/White/Aspects/accent.ogg