Skip to content
Open
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
12 changes: 12 additions & 0 deletions Content.Server/Imperial/Medieval/Barrier/MagicBarrierComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,17 @@ public sealed partial class MagicBarrierComponent : Component
[DataField]
public Dictionary<NetUserId, int> ReviveCount = new();

[DataField]
public TimeSpan ElementalRiftNextSpawnTime = TimeSpan.Zero;

[DataField]
public float ElementalRiftStabilityLossPerMinute = 0.0015f;

[DataField]
public float ElementalRiftMinSpawnMinutes = 30f;

[DataField]
public float ElementalRiftMaxSpawnMinutes = 60f;

}
}
158 changes: 150 additions & 8 deletions Content.Server/Imperial/Medieval/Barrier/MagicBarrierPointSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ public sealed partial class MagicBarrierSystem : EntitySystem
[Dependency] private readonly DamageableSystem _damageable = default!;

public static bool IsBarrierActive = true;
private static readonly string[] ElementalRiftPrototypes =
[
"MedievalBarrierRiftEarth",
"MedievalBarrierRiftFire",
"MedievalBarrierRiftWater",
"MedievalBarrierRiftLight",
];

public override void Initialize()
{
Expand All @@ -48,6 +55,7 @@ public override void Initialize()
SubscribeLocalEvent<MagicBarrierComponent, ComponentStartup>(OnStart);
SubscribeLocalEvent<MagicBarrierComponent, GetVerbsEvent<AlternativeVerb>>(AddSuicideVerb);
SubscribeLocalEvent<MagicRuneKnowledgeComponent, BarrierSuicideDoAfterEvent>(OnBarrierSuicideDoAfterEvent);
SubscribeLocalEvent<MagicBarrierRiftComponent, EntityTerminatingEvent>(OnRiftTerminating);
}

private void OnRoundStarted(RoundStartedEvent args)
Expand Down Expand Up @@ -129,6 +137,9 @@ public void OnUse(EntityUid? target, EntityUid user, EntityUid used, MagicScroll
public void OnStart(EntityUid uid, MagicBarrierComponent component, ComponentStartup args)
{
var necrobookspawners = EntityManager.AllEntities<NecroBookSpawnComponent>().ToArray();
if (component.ElementalRiftNextSpawnTime == TimeSpan.Zero)
component.ElementalRiftNextSpawnTime = _timing.CurTime + GetNextRiftSpawnDelay(component);

if (!necrobookspawners.Any())
return;

Expand All @@ -138,6 +149,7 @@ public void OnStart(EntityUid uid, MagicBarrierComponent component, ComponentSta

for (var i = 0; i < 5; i++)
Spawn("MedievalDungeonKey", Transform(_random.Pick(necrobookspawners)).Coordinates);

}

private void OnCurseDamage(EntityUid uid, MagicBarrierCurseComponent component, ref BeforeDamageChangedEvent args)
Expand All @@ -158,7 +170,9 @@ private void OnCurseDamage(EntityUid uid, MagicBarrierCurseComponent component,
private void OnExamine(EntityUid uid, MagicBarrierComponent component, ExaminedEvent args)
{
args.PushMarkup("[color=red]Текущая стабильность барьера " + Math.Round(component.Stability, 2) + " из " + component.MaxStability + "[/color]", 1);
args.PushMarkup("[color=cyan]Текущий расход " + Math.Round(component.Lose, 2) + " стабильности в минуту[/color]", 0);
var riftCount = EntityManager.EntityQuery<MagicBarrierRiftComponent>().Count();
var riftLoss = component.ElementalRiftStabilityLossPerMinute * riftCount;
args.PushMarkup("[color=cyan]Текущий расход " + Math.Round(component.Lose + riftLoss, 2) + " стабильности в минуту[/color]", 0);
int sector1 = 0;
int sector2 = 0;
int sector3 = 0;
Expand Down Expand Up @@ -221,6 +235,73 @@ private void OnExamine(EntityUid uid, MagicBarrierComponent component, ExaminedE
args.PushMarkup(sector8 + " проклятых наростов в секторе 8 (Легион)", -8);
args.PushMarkup(sector9 + " проклятых наростов в секторе 9 (Племя)", -9);
args.PushMarkup(sector0 + " проклятых наростов скрыты в неизвестном месте под землей", -10);

int riftSector1 = 0;
int riftSector2 = 0;
int riftSector3 = 0;
int riftSector4 = 0;
int riftSector5 = 0;
int riftSector6 = 0;
int riftSector7 = 0;
int riftSector8 = 0;
int riftSector9 = 0;
int riftSector0 = 0;

foreach (var rift in EntityManager.EntityQuery<MagicBarrierRiftComponent>())
{
var riftTransform = Transform(rift.Owner);
if (TryComp<CultMapBlockerComponent>(riftTransform.ParentUid, out var riftBlocker))
{
switch (riftBlocker.Sector)
{
case "sector9":
riftSector9++;
break;
case "sector8":
riftSector8++;
break;
case "sector7":
riftSector7++;
break;
case "sector6":
riftSector6++;
break;
case "sector5":
riftSector5++;
break;
case "sector4":
riftSector4++;
break;
case "sector3":
riftSector3++;
break;
case "sector2":
riftSector2++;
break;
case "sector1":
riftSector1++;
break;
default:
riftSector0++;
break;
}
}
else
{
riftSector0++;
}
}

args.PushMarkup(riftSector1 + " разломов в секторе 1 (Некрополь)", -11);
args.PushMarkup(riftSector2 + " разломов в секторе 2 (Мятеж)", -12);
args.PushMarkup(riftSector3 + " разломов в секторе 3 (Церковь)", -13);
args.PushMarkup(riftSector4 + " разломов в секторе 4 (Пустыня)", -14);
args.PushMarkup(riftSector5 + " разломов в секторе 5 (Коллегия)", -15);
args.PushMarkup(riftSector6 + " разломов в секторе 6 (Шахта)", -16);
args.PushMarkup(riftSector7 + " разломов в секторе 7 (Гоблины)", -17);
args.PushMarkup(riftSector8 + " разломов в секторе 8 (Легион)", -18);
args.PushMarkup(riftSector9 + " разломов в секторе 9 (Племя)", -19);
args.PushMarkup(riftSector0 + " разломов скрыты в неизвестном месте под землей", -20);
}
public override void Update(float frameTime)
{
Expand All @@ -247,6 +328,9 @@ public override void Update(float frameTime)
if (comp.Stability > 0f)
{
comp.Stability -= comp.Lose;
var riftCount = EntityManager.EntityQuery<MagicBarrierRiftComponent>().Count();
if (riftCount > 0)
comp.Stability -= comp.ElementalRiftStabilityLossPerMinute * riftCount;
}
else
{
Expand All @@ -266,13 +350,25 @@ public override void Update(float frameTime)
{
comp.Lose = comp.Lose * comp.Rate;
var cursespawners = EntityManager.EntityQuery<MagicBarrierCurseSpawnComponent>().ToArray();
var choosenSpawner = _random.Pick(cursespawners);
var cursexform = Transform(choosenSpawner.Owner);
var cursecoords = cursexform.Coordinates;
Spawn("MedievalBarrierCurse", cursecoords);
_chat.DispatchGlobalAnnouncement("Расход стабильности барьера увеличен, тьма наступает.", playSound: false, colorOverride: Color.DeepPink, sender: "Барьер");
Spawn("ShockWaveEffect", cursecoords);
Spawn("ShockWaveEffect", coords);
if (cursespawners.Length > 0)
{
var choosenSpawner = _random.Pick(cursespawners);
var cursexform = Transform(choosenSpawner.Owner);
var cursecoords = cursexform.Coordinates;
Spawn("MedievalBarrierCurse", cursecoords);
_chat.DispatchGlobalAnnouncement("Расход стабильности барьера увеличен, тьма наступает.", playSound: false, colorOverride: Color.DeepPink, sender: "Барьер");
Spawn("ShockWaveEffect", cursecoords);
Spawn("ShockWaveEffect", coords);
}
}

if (comp.ElementalRiftNextSpawnTime == TimeSpan.Zero)
comp.ElementalRiftNextSpawnTime = _timing.CurTime + GetNextRiftSpawnDelay(comp);

if (_timing.CurTime > comp.ElementalRiftNextSpawnTime)
{
comp.ElementalRiftNextSpawnTime = _timing.CurTime + GetNextRiftSpawnDelay(comp);
SpawnRandomElementalRift();
}

comp.StarfallCurrentPoints++;
Expand Down Expand Up @@ -342,6 +438,52 @@ public override void Update(float frameTime)
}
}
}

private void SpawnRandomElementalRift()
{
var riftSpawners = EntityManager.EntityQuery<MagicBarrierRiftSpawnComponent>().ToList();
while (riftSpawners.Count > 0)
{
var chosenSpawner = _random.Pick(riftSpawners);
if (chosenSpawner.Occupied)
{
riftSpawners.Remove(chosenSpawner);
continue;
}

var riftTransform = Transform(chosenSpawner.Owner);
var riftCoords = riftTransform.Coordinates;
var riftPrototype = _random.Pick(ElementalRiftPrototypes);
var rift = Spawn(riftPrototype, riftCoords);
if (TryComp<MagicBarrierRiftComponent>(rift, out var riftComponent))
riftComponent.Spawner = chosenSpawner.Owner;
chosenSpawner.Occupied = true;
_chat.DispatchGlobalAnnouncement("Элементальный разлом открылся!", playSound: false, colorOverride: Color.DeepSkyBlue, sender: "Барьер");
Spawn("ShockWaveEffect", riftCoords);
return;
}

return;
}

private TimeSpan GetNextRiftSpawnDelay(MagicBarrierComponent component)
{
var delayMinutes = _random.NextFloat(component.ElementalRiftMinSpawnMinutes, component.ElementalRiftMaxSpawnMinutes);
return TimeSpan.FromMinutes(delayMinutes);
}

private void OnRiftTerminating(EntityUid uid, MagicBarrierRiftComponent component, ref EntityTerminatingEvent args)
{
foreach (var barrier in EntityManager.EntityQuery<MagicBarrierComponent>())
{
barrier.Stability += 4f;
barrier.Lose *= 0.72f;
}

if (component.Spawner.HasValue && TryComp<MagicBarrierRiftSpawnComponent>(component.Spawner.Value, out var spawner))
spawner.Occupied = false;
_chat.DispatchGlobalAnnouncement("Элементальный разлом уничтожен, стабильность барьера восстановлена.", playSound: false, colorOverride: Color.LimeGreen, sender: "Барьер");
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Numerics;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;

namespace Content.Server.MagicBarrier.Components
{
[RegisterComponent]
public sealed partial class MagicBarrierRiftComponent : Component
{
[DataField]
public string Element = "earth";

[DataField]
public bool GuardiansSpawned;

[DataField]
public List<EntityUid> Guardians = new();

[DataField(customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> GuardianEntities = new()
{
"MedievalMobSkeletMeat",
"MedievalMobSkeletMeat",
"MedievalMobSkeletMeat",
"MedievalMobSkeletMeat",
};

[DataField]
public List<Vector2> GuardianOffsets = new()
{
new(1f, 1f),
new(-1f, 1f),
new(1f, -1f),
new(-1f, -1f),
};

[DataField]
public EntityUid? Spawner;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Content.Server.MagicBarrier.Components
{
[RegisterComponent]
public sealed partial class MagicBarrierRiftSpawnComponent : Component
{
[DataField]
public bool Occupied;
}
}
74 changes: 74 additions & 0 deletions Content.Server/Imperial/Medieval/Barrier/MagicBarrierRiftSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System;
using System.Numerics;
using Content.Server.MagicBarrier.Components;
using Content.Shared.Interaction;
using Content.Shared.Mobs;
using Robust.Shared.Map;

namespace Content.Server.MagicBarrier;

public sealed class MagicBarrierRiftSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<MagicBarrierRiftComponent, AfterInteractUsingEvent>(OnRiftUse);
SubscribeLocalEvent<RiftGuardianComponent, MobStateChangedEvent>(OnGuardianStateChanged);
}

private void OnRiftUse(EntityUid uid, MagicBarrierRiftComponent component, AfterInteractUsingEvent args)
{
if (args.Handled || args.Target == null || !args.CanReach)
return;

if (!TryComp<RiftKeyComponent>(args.Used, out var keyComponent)
|| !string.Equals(keyComponent.Element, component.Element, StringComparison.OrdinalIgnoreCase))
return;

if (component.GuardiansSpawned)
return;

component.GuardiansSpawned = true;
component.Guardians.Clear();

QueueDel(args.Used);

for (var i = 0; i < component.GuardianEntities.Count; i++)
{
SpawnGuardian(uid, component, i);
}
args.Handled = true;
}

private void SpawnGuardian(EntityUid rift, MagicBarrierRiftComponent component, int index)
{
if (index < 0 || index >= component.GuardianEntities.Count)
return;

var offset = index < component.GuardianOffsets.Count
? component.GuardianOffsets[index]
: Vector2.Zero;
var coords = Transform(rift).Coordinates.Offset(offset);
var guardian = Spawn(component.GuardianEntities[index], coords);
var guardianComponent = EnsureComp<RiftGuardianComponent>(guardian);
guardianComponent.Rift = rift;
component.Guardians.Add(guardian);
}

private void OnGuardianStateChanged(EntityUid uid, RiftGuardianComponent component, MobStateChangedEvent args)
{
if (args.NewMobState != MobState.Dead)
return;

if (!TryComp<MagicBarrierRiftComponent>(component.Rift, out var riftComponent))
return;

riftComponent.Guardians.Remove(uid);
if (riftComponent.Guardians.Count == 0)
{
var coords = Transform(component.Rift).Coordinates;
Spawn("MedievalSkeletDespawnEffect", coords);
QueueDel(component.Rift);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Content.Server.MagicBarrier.Components
{
[RegisterComponent]
public sealed partial class RiftGuardianComponent : Component
{
[DataField]
public EntityUid Rift;
}
}
9 changes: 9 additions & 0 deletions Content.Server/Imperial/Medieval/Barrier/RiftKeyComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Content.Server.MagicBarrier.Components
{
[RegisterComponent]
public sealed partial class RiftKeyComponent : Component
{
[DataField]
public string Element = "earth";
}
}
Loading
Loading