Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions EXILED/Exiled.API/Enums/CameraType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ public enum CameraType
EzGateAElevators,
EzGateBInterior,
EzGateBSide,
EzGateAStairwell,
EzGateAUpper,
#endregion
}
}
33 changes: 11 additions & 22 deletions EXILED/Exiled.API/Extensions/MirrorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace Exiled.API.Extensions

using AdminToys;
using AudioPooling;
using Cassie;
using CustomPlayerEffects;
using Exiled.API.Enums;
using Exiled.API.Features.Items;
Expand Down Expand Up @@ -512,13 +513,12 @@ public static void ResyncKeycardPickup(CustomKeycardPickup customKeycard)
/// <param name="isSubtitles">Same on <see cref="Cassie.Message(string, bool, bool, bool)"/>'s isSubtitles.</param>
public static void PlayCassieAnnouncement(this Player player, string words, bool makeHold = false, bool makeNoise = true, bool isSubtitles = false)
{
foreach (RespawnEffectsController controller in RespawnEffectsController.AllControllers)
{
if (controller != null)
{
SendFakeTargetRpc(player, controller.netIdentity, typeof(RespawnEffectsController), nameof(RespawnEffectsController.RpcCassieAnnouncement), words, makeHold, makeNoise, isSubtitles);
}
}
CassieAnnouncement announcement = new(new CassieTtsPayload(words, isSubtitles, makeHold), 0, makeNoise ? 1 : 0);

// processes makeNoise
announcement.OnStartedPlaying();

announcement.Payload.SendToHubsConditionally(hub => hub == player.ReferenceHub);
}

/// <summary>
Expand All @@ -533,23 +533,12 @@ public static void PlayCassieAnnouncement(this Player player, string words, bool
/// <param name="isSubtitles">Same on <see cref="Cassie.MessageTranslated(string, string, bool, bool, bool)"/>'s isSubtitles.</param>
public static void MessageTranslated(this Player player, string words, string translation, string customSubtitles, bool makeHold = false, bool makeNoise = true, bool isSubtitles = true)
{
StringBuilder announcement = StringBuilderPool.Pool.Get();
CassieAnnouncement announcement = new(new CassieTtsPayload(words, customSubtitles, makeHold), 0, makeNoise ? 1 : 0);

string[] cassies = words.Split('\n');
string[] translations = translation.Split('\n');
// processes makeNoise
announcement.OnStartedPlaying();

for (int i = 0; i < cassies.Length; i++)
announcement.Append($"{translations[i].Replace(' ', ' ')}<size=0> {cassies[i]} </size><split>");

string message = StringBuilderPool.Pool.ToStringReturn(announcement);

foreach (RespawnEffectsController controller in RespawnEffectsController.AllControllers)
{
if (controller != null)
{
SendFakeTargetRpc(player, controller.netIdentity, typeof(RespawnEffectsController), nameof(RespawnEffectsController.RpcCassieAnnouncement), message, makeHold, makeNoise, isSubtitles, customSubtitles);
}
}
announcement.Payload.SendToHubsConditionally(hub => hub == player.ReferenceHub);
}

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions EXILED/Exiled.API/Features/Camera.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ public class Camera : IWrapper<Scp079Camera>, IWorldSpace
["GATE A ELEVATORS"] = CameraType.EzGateAElevators,
["GATE B INTERIOR"] = CameraType.EzGateBInterior,
["GATE B SIDE"] = CameraType.EzGateBSide,
["GATE A STAIRWELL"] = CameraType.EzGateAStairwell,
["GATE A UPPER"] = CameraType.EzGateAUpper,

// CustomCamera
["EZ ARM CAMERA TOY"] = CameraType.EzArmCameraToy,
Expand Down
101 changes: 74 additions & 27 deletions EXILED/Exiled.API/Features/Cassie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@

namespace Exiled.API.Features
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Exiled.API.Features.Pools;

using global::Cassie;
using global::Cassie.Interpreters;
using MEC;

using PlayerRoles;

using PlayerStatsSystem;

using Respawning;
using Respawning.NamingRules;

using CustomFirearmHandler = DamageHandlers.FirearmDamageHandler;
using CustomHandlerBase = DamageHandlers.DamageHandlerBase;
Expand All @@ -29,20 +29,15 @@ namespace Exiled.API.Features
/// </summary>
public static class Cassie
{
/// <summary>
/// Gets the <see cref="NineTailedFoxAnnouncer"/> singleton.
/// </summary>
public static NineTailedFoxAnnouncer Announcer => NineTailedFoxAnnouncer.singleton;

/// <summary>
/// Gets a value indicating whether C.A.S.S.I.E is currently announcing. Does not include decontamination or Alpha Warhead Messages.
/// </summary>
public static bool IsSpeaking => Announcer.queue.Count != 0;
public static bool IsSpeaking => CassieAnnouncementDispatcher.AllAnnouncements.Count != 0;

/// <summary>
/// Gets a <see cref="IReadOnlyCollection{T}"/> of <see cref="NineTailedFoxAnnouncer.VoiceLine"/> objects that C.A.S.S.I.E recognizes.
/// Gets a <see cref="IReadOnlyCollection{T}"/> of <see cref="CassieAnnouncementDispatcher.AllAnnouncements"/> objects that C.A.S.S.I.E recognizes.
/// </summary>
public static IReadOnlyCollection<NineTailedFoxAnnouncer.VoiceLine> VoiceLines => Announcer.voiceLines;
public static IReadOnlyCollection<CassieAnnouncement> VoiceLines => CassieAnnouncementDispatcher.AllAnnouncements;

/// <summary>
/// Reproduce a non-glitched C.A.S.S.I.E message.
Expand All @@ -52,7 +47,7 @@ public static class Cassie
/// <param name="isNoisy">Indicates whether C.A.S.S.I.E has to make noises during the message.</param>
/// <param name="isSubtitles">Indicates whether C.A.S.S.I.E has to make subtitles.</param>
public static void Message(string message, bool isHeld = false, bool isNoisy = true, bool isSubtitles = false) =>
RespawnEffectsController.PlayCassieAnnouncement(message, isHeld, isNoisy, isSubtitles);
new CassieAnnouncement(new CassieTtsPayload(message, isSubtitles, isHeld), 0f, isNoisy ? 1 : 0).AddToQueue();

/// <summary>
/// Reproduce a non-glitched C.A.S.S.I.E message with a possibility to custom the subtitles.
Expand All @@ -70,7 +65,7 @@ public static void MessageTranslated(string message, string translation, bool is
for (int i = 0; i < cassies.Length; i++)
announcement.Append($"{translations[i].Replace(' ', ' ')}<size=0> {cassies[i]} </size><split>");

RespawnEffectsController.PlayCassieAnnouncement(announcement.ToString(), isHeld, isNoisy, isSubtitles);
new CassieAnnouncement(new CassieTtsPayload(message, isSubtitles, isHeld), 0f, isNoisy ? 1 : 0).AddToQueue();
StringBuilderPool.Pool.Return(announcement);
}

Expand All @@ -81,7 +76,7 @@ public static void MessageTranslated(string message, string translation, bool is
/// <param name="glitchChance">The chance of placing a glitch between each word.</param>
/// <param name="jamChance">The chance of jamming each word.</param>
public static void GlitchyMessage(string message, float glitchChance, float jamChance) =>
Announcer.ServerOnlyAddGlitchyPhrase(message, glitchChance, jamChance);
new CassieAnnouncement(new CassieTtsPayload(CassieGlitchifier.Glitchify(message, glitchChance, jamChance), true, true), 0f, 0f).AddToQueue();

/// <summary>
/// Reproduce a non-glitched C.A.S.S.I.E message after a certain amount of seconds.
Expand All @@ -92,7 +87,7 @@ public static void GlitchyMessage(string message, float glitchChance, float jamC
/// <param name="isNoisy">Indicates whether C.A.S.S.I.E has to make noises during the message.</param>
/// <param name="isSubtitles">Indicates whether C.A.S.S.I.E has to make subtitles.</param>
public static void DelayedMessage(string message, float delay, bool isHeld = false, bool isNoisy = true, bool isSubtitles = false) =>
Timing.CallDelayed(delay, () => RespawnEffectsController.PlayCassieAnnouncement(message, isHeld, isNoisy, isSubtitles));
Timing.CallDelayed(delay, () => new CassieAnnouncement(new CassieTtsPayload(message, isSubtitles, isHeld), 0f, isNoisy ? 1 : 0).AddToQueue());

/// <summary>
/// Reproduce a glitchy C.A.S.S.I.E announcement after a certain period of seconds.
Expand All @@ -102,42 +97,94 @@ public static void DelayedMessage(string message, float delay, bool isHeld = fal
/// <param name="glitchChance">The chance of placing a glitch between each word.</param>
/// <param name="jamChance">The chance of jamming each word.</param>
public static void DelayedGlitchyMessage(string message, float delay, float glitchChance, float jamChance) =>
Timing.CallDelayed(delay, () => Announcer.ServerOnlyAddGlitchyPhrase(message, glitchChance, jamChance));
Timing.CallDelayed(delay, () => new CassieAnnouncement(new CassieTtsPayload(CassieGlitchifier.Glitchify(message, glitchChance, jamChance), true, true), 0f, 0f).AddToQueue());

/// <summary>
/// Calculates the duration of a C.A.S.S.I.E message.
/// </summary>
/// <param name="message">The message, which duration will be calculated.</param>
/// <param name="rawNumber">Determines if a number won't be converted to its full pronunciation.</param>
/// <param name="speed">The speed of the message.</param>
/// <param name="obsolete1">An obsolete parameter.</param>
/// <param name="obsolete2">Another obsolete parameter.</param>
/// <returns>Duration (in seconds) of specified message.</returns>
public static float CalculateDuration(string message, bool rawNumber = false, float speed = 1f)
=> Announcer.CalculateDuration(message, rawNumber, speed);
public static float CalculateDuration(string message, bool obsolete1, float obsolete2)
{
if (!CassieTtsAnnouncer.TryGetDatabase(out CassieLineDatabase cassieLineDatabase))
{
return 0;
}

float value = 0;
string[] lines = message.Split(' ', StringSplitOptions.RemoveEmptyEntries);

CassiePlaybackModifiers modifiers = new();
StringBuilder builder = StringBuilderPool.Pool.Get();

for (int i = 0; i < lines.Length; i++)
{
foreach (CassieInterpreter interpreter in CassieTtsAnnouncer.Interpreters)
{
bool halt;
foreach (CassieInterpreter.Result result in interpreter.GetResults(cassieLineDatabase, ref modifiers, lines[i], builder, out halt))
{
value += (float)result.Modifiers.GetTimeUntilNextWord(result.Line);
}

if (halt)
break;
}
}

return value;
}

/// <summary>
/// Converts a <see cref="Team"/> into a Cassie-Readable <c>CONTAINMENTUNIT</c>.
/// </summary>
/// <param name="team"><see cref="Team"/>.</param>
/// <param name="unitName">Unit Name.</param>
/// <returns><see cref="string"/> Containment Unit text.</returns>
public static string ConvertTeam(Team team, string unitName)
=> NineTailedFoxAnnouncer.ConvertTeam(team, unitName);
public static string ConvertTeam(Team team, string unitName) => team switch
{
Team.FoundationForces when NamingRulesManager.TryGetNamingRule(team, out UnitNamingRule unitNamingRule) => "CONTAINMENTUNIT " + unitNamingRule.TranslateToCassie(unitName),
Team.FoundationForces => "CONTAINMENTUNIT UNKNOWN",
Team.ChaosInsurgency => "BY CHAOSINSURGENCY",
Team.Scientists => "BY SCIENCE PERSONNEL",
Team.ClassD => "BY CLASSD PERSONNEL",
Team.Flamingos => "BY FLAMINGOS",
_ => "UNKNOWN",
};

/// <summary>
/// Converts a number into a Cassie-Readable String.
/// </summary>
/// <param name="num">Number to convert.</param>
/// <returns>A CASSIE-readable <see cref="string"/> representing the number.</returns>
public static string ConvertNumber(int num)
=> NineTailedFoxAnnouncer.ConvertNumber(num);
{
if (!CassieTtsAnnouncer.TryGetDatabase(out CassieLineDatabase cassieLineDatabase))
{
return string.Empty;
}

NumberInterpreter numberInterpreter = (NumberInterpreter)CassieTtsAnnouncer.Interpreters.FirstOrDefault((CassieInterpreter x) => x is NumberInterpreter);
if (numberInterpreter == null)
{
return string.Empty;
}

CassiePlaybackModifiers cassiePlaybackModifiers = default;
StringBuilder stringBuilder = new();
numberInterpreter.GetResults(cassieLineDatabase, ref cassiePlaybackModifiers, num.ToString(), stringBuilder, out bool flag);
return stringBuilder.ToString();
}

/// <summary>
/// Announce a SCP Termination.
/// </summary>
/// <param name="scp">SCP to announce termination of.</param>
/// <param name="info">HitInformation.</param>
public static void ScpTermination(Player scp, DamageHandlerBase info)
=> NineTailedFoxAnnouncer.AnnounceScpTermination(scp.ReferenceHub, info);
=> CassieScpTerminationAnnouncement.AnnounceScpTermination(scp.ReferenceHub, info);

/// <summary>
/// Announces the termination of a custom SCP name.
Expand Down Expand Up @@ -167,14 +214,14 @@ public static void CustomScpTermination(string scpName, CustomHandlerBase info)
/// <summary>
/// Clears the C.A.S.S.I.E queue.
/// </summary>
public static void Clear() => RespawnEffectsController.ClearQueue();
public static void Clear() => CassieAnnouncementDispatcher.ClearAll();

/// <summary>
/// Gets a value indicating whether the given word is a valid C.A.S.S.I.E word.
/// </summary>
/// <param name="word">The word to check.</param>
/// <returns><see langword="true"/> if the word is valid; otherwise, <see langword="false"/>.</returns>
public static bool IsValid(string word) => Announcer.voiceLines.Any(line => line.apiName.ToUpper() == word.ToUpper());
public static bool IsValid(string word) => CassieTtsAnnouncer.TryGetDatabase(out CassieLineDatabase cassieLineDatabase) ? cassieLineDatabase.AllLines.Any(line => line.ApiName.ToUpper() == word.ToUpper()) : false;

/// <summary>
/// Gets a value indicating whether the given sentence is all valid C.A.S.S.I.E word.
Expand Down
24 changes: 12 additions & 12 deletions EXILED/Exiled.API/Features/Items/Jailbird.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,55 +52,55 @@ internal Jailbird()
/// </summary>
public float MeleeDamage
{
get => Base._hitreg._damageMelee;
set => Base._hitreg._damageMelee = value;
get => Base.MeleeDamage;
set => Base.MeleeDamage = value;
}

/// <summary>
/// Gets or sets the amount of damage dealt with a Jailbird charge hit.
/// </summary>
public float ChargeDamage
{
get => Base._hitreg._damageCharge;
set => Base._hitreg._damageCharge = value;
get => Base._chargeDamage;
set => Base._chargeDamage = value;
}

/// <summary>
/// Gets or sets the amount of time in seconds that the <see cref="CustomPlayerEffects.Flashed"/> effect will be applied on being hit.
/// </summary>
public float FlashDuration
{
get => Base._hitreg._flashedDuration;
set => Base._hitreg._flashedDuration = value;
get => Base._flashedDuration;
set => Base._flashedDuration = value;
}

/// <summary>
/// Gets or sets the amount of time in seconds that the <see cref="CustomPlayerEffects.Concussed"/> effect will be applied on being hit.
/// </summary>
public float ConcussionDuration
{
get => Base._hitreg._concussionDuration;
set => Base._hitreg._concussionDuration = value;
get => Base._concussionDuration;
set => Base._concussionDuration = value;
}

/// <summary>
/// Gets or sets the radius of the Jailbird's hit register.
/// </summary>
public float Radius
{
get => Base._hitreg._hitregRadius;
set => Base._hitreg._hitregRadius = value;
get => Radius;
set => Radius = value;
}

/// <summary>
/// Gets or sets the total amount of damage dealt with the Jailbird.
/// </summary>
public float TotalDamageDealt
{
get => Base._hitreg.TotalMeleeDamageDealt;
get => Base.TotalMeleeDamageDealt;
set
{
Base._hitreg.TotalMeleeDamageDealt = value;
Base.TotalMeleeDamageDealt = value;
Base._deterioration.RecheckUsage();
}
}
Expand Down
7 changes: 7 additions & 0 deletions EXILED/Exiled.API/Features/Lift.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class Lift : IWrapper<ElevatorChamber>, IWorldSpace
internal Lift(ElevatorChamber elevator)
{
Base = elevator;
ElevatorAutoReturn = elevator.GetComponent<ElevatorAutoReturn>();
ElevatorChamberToLift.Add(elevator, this);

internalDoorsList.AddRange(Elevator.AllElevatorDoors[Group]);
Expand All @@ -73,6 +74,12 @@ internal Lift(ElevatorChamber elevator)
/// </summary>
public ElevatorChamber Base { get; }

/// <summary>
/// Gets the base <see cref="ElevatorAutoReturn"/>.
/// </summary>
/// <remarks>Would be null for any elevator that do not used <see cref="Interactables.Interobjects.ElevatorAutoReturn"/>.</remarks>
public ElevatorAutoReturn ElevatorAutoReturn { get; }

/// <summary>
/// Gets a value of the internal doors list.
/// </summary>
Expand Down
10 changes: 5 additions & 5 deletions EXILED/Exiled.API/Features/Pickups/JailbirdPickup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,11 @@ protected override void InitializeProperties(ItemBase itemBase)
base.InitializeProperties(itemBase);
if (itemBase is JailbirdItem jailbirdItem)
{
MeleeDamage = jailbirdItem._hitreg._damageMelee;
ChargeDamage = jailbirdItem._hitreg._damageCharge;
FlashDuration = jailbirdItem._hitreg._flashedDuration;
ConcussionDuration = jailbirdItem._hitreg._concussionDuration;
Radius = jailbirdItem._hitreg._hitregRadius;
MeleeDamage = jailbirdItem.MeleeDamage;
ChargeDamage = jailbirdItem._chargeDamage;
FlashDuration = jailbirdItem._flashedDuration;
ConcussionDuration = jailbirdItem._concussionDuration;
Radius = Radius;
}
}
}
Expand Down
Loading
Loading