Skip to content

Commit

Permalink
[Feature] Xenomorphs
Browse files Browse the repository at this point in the history
Co-Authored-By: Kai5 <[email protected]>
Co-Authored-By: sanek31 <[email protected]>
  • Loading branch information
3 people committed Oct 3, 2024
1 parent 4c2f775 commit 9de5f00
Show file tree
Hide file tree
Showing 428 changed files with 7,328 additions and 19 deletions.
5 changes: 5 additions & 0 deletions Content.Client/Chat/Managers/ChatManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ public void SendMessage(string text, ChatSelectChannel channel)
_consoleHost.ExecuteCommand($"tsay \"{CommandParsing.Escape(str)}\"");
break;

// WWDP
case ChatSelectChannel.XenoHivemind:
_consoleHost.ExecuteCommand($"aliensay \"{CommandParsing.Escape(str)}\"");
break;

default:
throw new ArgumentOutOfRangeException(nameof(channel), channel, null);
}
Expand Down
40 changes: 40 additions & 0 deletions Content.Client/Overlays/ShowInfectedIconsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Linq;
using Content.Shared.Aliens.Components;
using Content.Shared.Mobs;
using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Robust.Shared.Prototypes;

namespace Content.Client.Overlays; // WWDP SYSTEM

/// <summary>
/// This handles...
/// </summary>
public sealed class ShowInfectedIconsSystem : EquipmentHudSystem<ShowInfectedIconsComponent>
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
/// <inheritdoc/>
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<AlienInfectedComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
}

private void OnGetStatusIconsEvent(EntityUid uid, AlienInfectedComponent component, ref GetStatusIconsEvent ev)
{
if (!IsActive)
return;
if (component.GrowthStage <= 5)
{
if (_prototype.TryIndex(component.InfectedIcons.ElementAt(component.GrowthStage), out var iconPrototype))
ev.StatusIcons.Add(iconPrototype);
}
else
{
if (_prototype.TryIndex(component.InfectedIcons.ElementAt(5), out var iconPrototype))
ev.StatusIcons.Add(iconPrototype);
}

}
}
8 changes: 6 additions & 2 deletions Content.Client/UserInterface/Systems/Chat/ChatUIController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ public sealed class ChatUIController : UIController
{SharedChatSystem.AdminPrefix, ChatSelectChannel.Admin},
{SharedChatSystem.RadioCommonPrefix, ChatSelectChannel.Radio},
{SharedChatSystem.DeadPrefix, ChatSelectChannel.Dead},
{SharedChatSystem.TelepathicPrefix, ChatSelectChannel.Telepathic} //Nyano - Summary: adds the telepathic prefix =.
{SharedChatSystem.TelepathicPrefix, ChatSelectChannel.Telepathic}, //Nyano - Summary: adds the telepathic prefix =.
{SharedChatSystem.XenoHivemindPrefix, ChatSelectChannel.XenoHivemind} // WWDP
};

public static readonly Dictionary<ChatSelectChannel, char> ChannelPrefixes = new()
Expand All @@ -95,7 +96,8 @@ public sealed class ChatUIController : UIController
{ChatSelectChannel.Admin, SharedChatSystem.AdminPrefix},
{ChatSelectChannel.Radio, SharedChatSystem.RadioCommonPrefix},
{ChatSelectChannel.Dead, SharedChatSystem.DeadPrefix},
{ChatSelectChannel.Telepathic, SharedChatSystem.TelepathicPrefix } //Nyano - Summary: associates telepathic with =.
{ChatSelectChannel.Telepathic, SharedChatSystem.TelepathicPrefix }, //Nyano - Summary: associates telepathic with =.
{ChatSelectChannel.XenoHivemind, SharedChatSystem.XenoHivemindPrefix } // WWDP
};

/// <summary>
Expand Down Expand Up @@ -530,6 +532,7 @@ private void UpdateChannelPermissions()
FilterableChannels |= ChatChannel.Radio;
FilterableChannels |= ChatChannel.Emotes;
FilterableChannels |= ChatChannel.Notifications;
FilterableChannels |= ChatChannel.XenoHivemind; // WWDP

// Can only send local / radio / emote when attached to a non-ghost entity.
// TODO: this logic is iffy (checking if controlling something that's NOT a ghost), is there a better way to check this?
Expand All @@ -539,6 +542,7 @@ private void UpdateChannelPermissions()
CanSendChannels |= ChatSelectChannel.Whisper;
CanSendChannels |= ChatSelectChannel.Radio;
CanSendChannels |= ChatSelectChannel.Emotes;
CanSendChannels |= ChatSelectChannel.XenoHivemind; // WWDP
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public sealed partial class ChannelFilterPopup : Popup
ChatChannel.Admin,
ChatChannel.AdminAlert,
ChatChannel.AdminChat,
ChatChannel.Server
ChatChannel.Server,
ChatChannel.XenoHivemind // WWDP
};

private readonly Dictionary<ChatChannel, ChannelFilterCheckbox> _filterStates = new();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public Color ChannelSelectColor(ChatSelectChannel channel)
ChatSelectChannel.Dead => Color.MediumPurple,
ChatSelectChannel.Admin => Color.HotPink,
ChatSelectChannel.Telepathic => Color.PaleVioletRed, //Nyano - Summary: determines the color for the chat.
ChatSelectChannel.XenoHivemind => Color.FromHex("#5b0c82"), // WWDP
_ => Color.DarkGray
};
}
Expand Down
17 changes: 17 additions & 0 deletions Content.Client/_White/Xenomorphs/JumpVisualsComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Robust.Client.Graphics;

namespace Content.Client.Aliens;

/// <summary>
/// This is used for...
/// </summary>
[RegisterComponent]
public sealed partial class JumpVisualsComponent : Component
{

}

public enum JumpLayers : byte
{
Jumping
}
13 changes: 13 additions & 0 deletions Content.Client/_White/Xenomorphs/Systems/PlasmaVesselSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Content.Client.Aliens.Systems;

/// <summary>
/// This handles...
/// </summary>
public sealed class PlasmaVesselSystem : EntitySystem
{
/// <inheritdoc/>
public override void Initialize()
{

}
}
73 changes: 73 additions & 0 deletions Content.Server/Chat/Systems/ChatSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.ActionBlocker;
using Content.Shared.Aliens.Components; // WWDP
using Content.Shared.CCVar;
using Content.Shared.Chat;
using Content.Shared.Database;
Expand Down Expand Up @@ -323,6 +324,35 @@ public void TrySendInGameOOCMessage(
}
}

// WWDP START
public void TrySendXenoHivemindMessage(
EntityUid source,
string message,
InGameOOCChatType type,
bool hideChat,
IConsoleShell? shell = null,
ICommonSession? player = null
)
{
if (!CanSendInGame(message, shell, player))
return;
if (player != null && !_chatManager.HandleRateLimit(player))
return;
// It doesn't make any sense for a non-player to send in-game OOC messages, whereas non-players may be sending
// in-game IC messages.
if (player?.AttachedEntity is not { Valid: true } entity || source != entity)
return;
message = SanitizeInGameOOCMessage(message);
var sendType = type;
switch (sendType)
{
case InGameOOCChatType.HiveXeno:
SendXenoHivemindChat(source, player, message, hideChat);
break;
}
}
// WWDP END

#region Announcements

/// <summary>
Expand Down Expand Up @@ -654,6 +684,39 @@ private void SendDeadChat(EntityUid source, ICommonSession player, string messag

_chatManager.ChatMessageToMany(ChatChannel.Dead, message, wrappedMessage, source, hideChat, true, clients.ToList(), author: player.UserId);
}

// WWDP START
private void SendXenoHivemindChat(EntityUid source, ICommonSession player, string message, bool hideChat)
{
var clients = GetXenoChatClients();
var playerName = Name(source);
var speech = GetSpeechVerb(source, message);
string wrappedMessage;
if (!HasComp<AlienQueenComponent>(source))
{
wrappedMessage = Loc.GetString(speech.Bold ? "chat-manager-entity-say-bold-wrap-message" : "chat-manager-entity-say-wrap-message",
("entityName", playerName),
("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))),
("fontType", speech.FontId),
("fontSize", speech.FontSize),
("message", FormattedMessage.EscapeText(message)));
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Xeno Hivemind chat from {player:Player}: {message}");
}
else
{
wrappedMessage = Loc.GetString(speech.Bold ? "chat-manager-entity-say-bold-wrap-message" : "chat-manager-entity-say-wrap-message",
("entityName", playerName),
("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))),
("fontType", speech.FontId),
("fontSize", 25),
("message", FormattedMessage.EscapeText(message)));
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Xeno Hivemind chat from queen {player:Player}: {message}");
}
if (HasComp<AlienComponent>(source))
_chatManager.ChatMessageToMany(ChatChannel.XenoHivemind, message, wrappedMessage, source, hideChat, true, clients.ToList(), author: player.UserId);
}
// WWDP END

#endregion

#region Utility
Expand Down Expand Up @@ -823,6 +886,16 @@ private IEnumerable<INetChannel> GetDeadChatClients()
.Select(p => p.Channel);
}

// WWDP START
private IEnumerable<INetChannel> GetXenoChatClients()
{
return Filter.Empty()
.AddWhereAttachedEntity(HasComp<AlienComponent>)
.Recipients
.Select(p => p.Channel);
}
// WWDP END

private string SanitizeMessagePeriod(string message)
{
if (string.IsNullOrEmpty(message))
Expand Down
26 changes: 26 additions & 0 deletions Content.Server/Medical/VomitActionSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Content.Server.Body.Systems;
using Content.Server.Medical.Components;
using Content.Shared.Medical;

namespace Content.Server.Medical; // WWDP SYSTEM

/// <summary>
/// This handles...
/// </summary>
public sealed class VomitActionSystem : SharedVomitActionSystem
{
/// <inheritdoc/>
[Dependency] private readonly VomitSystem _vomit = default!;
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<VomitActionComponent, VomitActionEvent>(OnVomitAction);
}

protected void OnVomitAction(EntityUid uid, VomitActionComponent component, VomitActionEvent args)
{
_vomit.Vomit(uid, component.ThirstAdded, component.HungerAdded);
ContainerSystem.EmptyContainer(component.Stomach, true);
}
}
28 changes: 28 additions & 0 deletions Content.Server/Polymorph/Components/TimedPolymorphComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Threading;
using Content.Shared.Polymorph;
using Content.Shared.Whitelist;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;

namespace Content.Server.Polymorph.Components; // WWDP SYSTEM

/// <summary>
/// This is used for polymorphing entity after time
/// </summary>
[RegisterComponent]
public sealed partial class TimedPolymorphComponent : Component
{
[DataField(required: true)]
public ProtoId<PolymorphPrototype> PolymorphPrototype;

[DataField]
public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Magic/forcewall.ogg");

[DataField]
public float PolymorphTime = 5f;

[DataField]
public bool Enabled = true;

public CancellationTokenSource? TokenSource;
}
37 changes: 37 additions & 0 deletions Content.Server/Polymorph/Systems/TimedPolymorphSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Threading;
using Content.Server.Polymorph.Components;

namespace Content.Server.Polymorph.Systems; // WWDP SYSTEM

/// <summary>
/// This handles polymorphing entity after time
/// </summary>
public sealed class TimedPolymorphSystem : EntitySystem
{
[Dependency] private readonly PolymorphSystem _polymorph = default!;
/// <inheritdoc/>
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<TimedPolymorphComponent, ComponentInit>(OnPolymorphInit);
SubscribeLocalEvent<TimedPolymorphComponent, ComponentShutdown>(OnTimedPolymorphShutdown);
}

private void OnPolymorphInit(EntityUid uid, TimedPolymorphComponent component, ComponentInit args)
{
component.TokenSource?.Cancel();
component.TokenSource = new CancellationTokenSource();
uid.SpawnRepeatingTimer(TimeSpan.FromSeconds(component.PolymorphTime), () => OnTimerFired(uid, component), component.TokenSource.Token);
}

private void OnTimerFired(EntityUid uid, TimedPolymorphComponent component)
{
if (component.Enabled)
_polymorph.PolymorphEntity(uid, component.PolymorphPrototype);
}

private void OnTimedPolymorphShutdown(EntityUid uid, TimedPolymorphComponent component, ComponentShutdown args)
{
component.TokenSource?.Cancel();
}
}
37 changes: 37 additions & 0 deletions Content.Server/Spawners/Components/AreaSpawnerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Threading;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;

namespace Content.Server.Spawners.Components; // WWDP SYSTEM

/// <summary>
/// Spawns Entities in area around spawner
/// </summary>
[RegisterComponent]
public sealed partial class AreaSpawnerComponent : Component
{
// Maximum offset of entities spawned.
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public float Radius;

// Prototype of entity spawned
[ViewVariables(VVAccess.ReadWrite)]
[DataField("spawnPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string SpawnPrototype;

/// <summary>
/// Length of the interval between spawn attempts.
/// </summary>
[DataField]
public int IntervalSeconds = 20;

// This will spawn entities to every tile in spawn radius
[DataField]
public bool SpawnToAllValidTiles = true;

[ViewVariables]
public int SpawnRadius;

public CancellationTokenSource? TokenSource;
}
Loading

0 comments on commit 9de5f00

Please sign in to comment.