- add: Changeling antagonist (#2)
* Changeling WIP * UI * Pointers fix * Moved out abilities * Regenerate ability * Fixed Regenerate ability Prevent ghosting while regenerating * Cleanup * Base lesser form * Finished Lesser Form && Transform * Transform Sting * Blind Sting * Mute Sting Added OnExamine on absorbed human * Hallucination Sting Changeling Absorb and transfer absorbed entities to absorber * Cryogenic Sting * Adrenaline Sacs * Transform now uses Polymorph * Armblade, Shield, Armor * Tentacle Arm ability Tentacle Gun system * WIP with bugs * WiP bugs * fix implant transfer * Fixed bugs with shop transfer and actions transfer * Just in case * Vi sitter i ventrilo och spelar DotA * Fixes and proper LesserForm tracking * !!!!! * Fixed empty buttons * WIP Gamerule Ready - shop * nerf stun time cause its sucks * cleaning * just in case * Absorb DNA Objective. * Partial objectives with bugs * fix * fix pointer * Changeling objectives * Changeling objectives №2 * Admin verb, game rule * Fixed empty list check Icons for objectives * Changeling chat, changeling names etc. * fix some merge errors * - fix: Fixed all bugs with changeling --------- Co-authored-by: Y-Parvus <yevhen.parvus@gmail.com> Co-authored-by: Y-Parvus <61109031+Y-Parvus@users.noreply.github.com> Co-authored-by: HitPanda <104197232+EnefFlow@users.noreply.github.com> Co-authored-by: EnefFlow <regeto90@mail.ru>
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
using System.Linq;
|
||||
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!;
|
||||
|
||||
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));
|
||||
|
||||
_metaData.SetEntityName(uid, title, 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.AbsorbedEntities.Count - 1; // 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.AbsorbedEntities.Count - 1; // 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.AbsorbedEntities.Count - 1;
|
||||
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);
|
||||
if (allHumans.Count == 0)
|
||||
{
|
||||
args.Cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_target.SetTarget(uid, _random.Pick(allHumans), target);
|
||||
}
|
||||
|
||||
private void OnEscapeWithIdentityGetProgress(EntityUid uid, EscapeWithIdentityConditionComponent component, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
if (!_target.GetTarget(uid, out var target))
|
||||
return;
|
||||
|
||||
args.Progress = GetEscapeWithIdentityProgress(args.Mind, target.Value);
|
||||
}
|
||||
|
||||
private float GetEscapeWithIdentityProgress(MindComponent mind, EntityUid target)
|
||||
{
|
||||
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))
|
||||
return 0f;
|
||||
|
||||
if (!TryComp<ChangelingComponent>(mind.CurrentEntity, out var changeling))
|
||||
return 0f;
|
||||
|
||||
if (!changeling.AbsorbedEntities.ContainsKey(targetDna.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 == targetDna.DNA)
|
||||
progress += 0.5f;
|
||||
|
||||
if (_emergencyShuttle.ShuttlesLeft)
|
||||
return progress;
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user