Files
OldThink/Content.Server/Changeling/Objectives/ChangelingConditionsSystem.cs
Jabak ada2b18c6d ChangelogHonk (#161)
* ChangelogHonk

* шлюха

* optimizaaaaaations (#769)

* Переводы (#770)

* Мелочёчки

* А когда ты будешь делать что-то полезное, кроме переводов?

* Я удалил НаноТрейзен

* Automatic changelog update

---------

Co-authored-by: Valtos <valtos@spaces.ru>
Co-authored-by: BIGZi0348 <118811750+BIGZi0348@users.noreply.github.com>
Co-authored-by: RavmorganButOnCocaine <valtos@nextmail.ru>
2024-11-05 22:40:00 +03:00

252 lines
8.4 KiB
C#

using System.Linq;
using Content.Server._Miracle.Components;
using Content.Server._Miracle.GulagSystem;
using Content.Server.Changeling.Objectives.Components;
using Content.Server.Forensics;
using Content.Server.Mind;
using Content.Server.Objectives.Components;
using Content.Server.Objectives.Systems;
using Content.Server.Shuttles.Systems;
using Content.Shared.Changeling;
using Content.Shared.Mind;
using Content.Shared.Objectives.Components;
using Robust.Shared.Random;
namespace Content.Server.Changeling.Objectives;
public sealed class ChangelingConditionsSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly TargetObjectiveSystem _target = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
[Dependency] private readonly GulagSystem _gulag = default!;
public override void Initialize()
{
base.Initialize();
// Absorb DNA condition
SubscribeLocalEvent<AbsorbDnaConditionComponent, ObjectiveAssignedEvent>(OnAbsorbDnaAssigned);
SubscribeLocalEvent<AbsorbDnaConditionComponent, ObjectiveAfterAssignEvent>(OnAbsorbDnaAfterAssigned);
SubscribeLocalEvent<AbsorbDnaConditionComponent, ObjectiveGetProgressEvent>(OnAbsorbDnaGetProgress);
//Absorb more genomes, than others changelings
SubscribeLocalEvent<AbsorbMoreConditionComponent, ObjectiveGetProgressEvent>(OnAbsorbMoreGetProgress);
//Absorb other changeling
SubscribeLocalEvent<PickRandomChangelingComponent, ObjectiveAssignedEvent>(OnAbsorbChangelingAssigned);
SubscribeLocalEvent<AbsorbChangelingConditionComponent, ObjectiveGetProgressEvent>(OnAbsorbChangelingGetProgress);
//Escape with identity
SubscribeLocalEvent<PickRandomIdentityComponent, ObjectiveAssignedEvent>(OnEscapeWithIdentityAssigned);
SubscribeLocalEvent<EscapeWithIdentityConditionComponent, ObjectiveGetProgressEvent>(OnEscapeWithIdentityGetProgress);
}
#region AbsorbDNA
private void OnAbsorbDnaAssigned(EntityUid uid, AbsorbDnaConditionComponent component, ref ObjectiveAssignedEvent args)
{
component.NeedToAbsorb = _random.Next(2, 6);
}
private void OnAbsorbDnaAfterAssigned(EntityUid uid, AbsorbDnaConditionComponent component, ref ObjectiveAfterAssignEvent args)
{
var title = Loc.GetString("objective-condition-absorb-dna", ("count", component.NeedToAbsorb));
var description = Loc.GetString("objective-condition-absorb-dna-desc");
_metaData.SetEntityName(uid, title, args.Meta);
_metaData.SetEntityDescription(uid, description, args.Meta);
}
private void OnAbsorbDnaGetProgress(EntityUid uid, AbsorbDnaConditionComponent component, ref ObjectiveGetProgressEvent args)
{
args.Progress = GetAbsorbProgress(args.Mind, component.NeedToAbsorb);
}
private float GetAbsorbProgress(MindComponent mind, int requiredDna)
{
if (!TryComp<ChangelingComponent>(mind.CurrentEntity, out var changelingComponent))
return 0f;
var absorbed = changelingComponent.AbsorbedCount; // Because first - it's the owner
if (requiredDna == absorbed)
return 1f;
var progress = MathF.Min(absorbed / (float) requiredDna, 1f);
return progress;
}
#endregion
#region AbsorbMoreDNA
private void OnAbsorbMoreGetProgress(EntityUid uid, AbsorbMoreConditionComponent comp, ref ObjectiveGetProgressEvent args)
{
args.Progress = GetAbsorbMoreProgress(args.Mind);
}
private float GetAbsorbMoreProgress(MindComponent mind)
{
if (!TryComp<ChangelingComponent>(mind.CurrentEntity, out var changelingComponent))
return 0f;
var selfAbsorbed = changelingComponent.AbsorbedCount; // Because first - it's the owner
var query = EntityQueryEnumerator<ChangelingComponent>();
List<int> otherAbsorbed = new();
while (query.MoveNext(out var uid, out var comp))
{
if (uid == mind.CurrentEntity)
continue; //don't include self
var absorbed = comp.AbsorbedCount;
otherAbsorbed.Add(absorbed);
}
if (otherAbsorbed.Count == 0)
return 1f;
var isTheMost = otherAbsorbed.Max() < selfAbsorbed;
return isTheMost ? 1f : 0f;
}
#endregion
#region AbsorbChangeling
private void OnAbsorbChangelingAssigned(EntityUid uid, PickRandomChangelingComponent comp, ref ObjectiveAssignedEvent args)
{
if (!TryComp<TargetObjectiveComponent>(uid, out var target))
{
args.Cancelled = true;
return;
}
if (target.Target != null)
return;
foreach (var changelingRule in EntityQuery<ChangelingRuleComponent>())
{
var changelingMinds = changelingRule.ChangelingMinds
.Except(new List<EntityUid> { args.MindId })
.ToList();
if (changelingMinds.Count == 0)
{
args.Cancelled = true;
return;
}
_target.SetTarget(uid, _random.Pick(changelingMinds), target);
}
}
private void OnAbsorbChangelingGetProgress(EntityUid uid, AbsorbChangelingConditionComponent comp, ref ObjectiveGetProgressEvent args)
{
if (!_target.GetTarget(uid, out var target))
return;
args.Progress = GetAbsorbChangelingProgress(args.Mind, target.Value);
}
private float GetAbsorbChangelingProgress(MindComponent mind, EntityUid target)
{
if (!_mind.TryGetMind(mind.CurrentEntity!.Value, out var selfMindId, out _))
return 0f;
if (!TryComp<MindComponent>(target, out var targetMind))
return 0f;
if (!HasComp<ChangelingComponent>(targetMind.CurrentEntity))
return 0f;
if (!TryComp<AbsorbedComponent>(targetMind.CurrentEntity, out var absorbedComponent))
return 0f;
return absorbedComponent.AbsorberMind == selfMindId ? 1f : 0f;
}
#endregion
#region EscapeWithIdentity
private void OnEscapeWithIdentityAssigned(EntityUid uid, PickRandomIdentityComponent component, ref ObjectiveAssignedEvent args)
{
if (!TryComp<TargetObjectiveComponent>(uid, out var target))
{
args.Cancelled = true;
return;
}
if (target.Target != null)
return;
var allHumans = _mind.GetAliveHumansExcept(args.MindId);
allHumans = allHumans.Where(x => !_gulag.IsMindGulagged(x)).ToList();
if (allHumans.Count == 0)
{
args.Cancelled = true;
return;
}
var targetMindId = _random.Pick(allHumans);
if (TryComp(targetMindId, out MindComponent? mind) && TryComp(mind.CurrentEntity, out DnaComponent? dna))
component.DNA = dna.DNA;
_target.SetTarget(uid, targetMindId, target);
}
private void OnEscapeWithIdentityGetProgress(EntityUid uid, EscapeWithIdentityConditionComponent component, ref ObjectiveGetProgressEvent args)
{
if (!_target.GetTarget(uid, out var target))
return;
var fallbackDNA = string.Empty;
if (TryComp(uid, out PickRandomIdentityComponent? pickIdentity))
fallbackDNA = pickIdentity.DNA;
args.Progress = GetEscapeWithIdentityProgress(args.Mind, target.Value, fallbackDNA);
}
private float GetEscapeWithIdentityProgress(MindComponent mind, EntityUid target, string DNA)
{
var progress = 0f;
if (!TryComp<DnaComponent>(mind.CurrentEntity, out var selfDna))
return 0f;
if (!TryComp<MindComponent>(target, out var targetMind))
return 0f;
if (TryComp<DnaComponent>(targetMind.CurrentEntity, out var targetDna))
DNA = targetDna.DNA;
if (!TryComp<ChangelingComponent>(mind.CurrentEntity, out var changeling))
return 0f;
if (!changeling.AbsorbedEntities.ContainsKey(DNA))
return 0f;
//Target absorbed by this changeling, so 50% of work is done
progress += 0.5f;
if (_emergencyShuttle.IsTargetEscaping(mind.CurrentEntity.Value) && selfDna.DNA == DNA)
progress += 0.5f;
return progress;
}
#endregion
}