forked from space-syndicate/space-station-14
Some checks failed
Build & Test Debug / build (ubuntu-latest) (push) Failing after 58s
Build & Test Debug / Build & Test Debug (push) Has been skipped
Publish / build (push) Failing after 2m36s
RGA schema validator / YAML RGA schema validator (push) Failing after 23s
RSI Validator / Validate RSIs (push) Successful in 28s
Map file schema validator / YAML map schema validator (push) Failing after 24s
Build & Test Map Renderer / Build & Test Debug (push) Has been cancelled
Build & Test Map Renderer / build (ubuntu-latest) (push) Has been cancelled
Test Packaging / Test Packaging (push) Has been cancelled
YAML Linter / YAML Linter (push) Has been cancelled
Blood Brothers are paired antagonists who must work together with shared objectives. Two players are bonded and must: - Escape together (mandatory) - Complete shared kill/steal/protect objectives - Both survive to win Includes: - 16 C# files (rule system, objective systems, components) - Game rule and sub-gamemode prototypes - 29 objective entity prototypes - Russian localization - Guidebook documentation Requirements: 50h playtime + 25h Security Min players: 20, Max antags: 8 (4 pairs) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
126 lines
4.4 KiB
C#
126 lines
4.4 KiB
C#
using Content.Server.Objectives.Components;
|
|
using Content.Server.Shuttles.Components;
|
|
using Content.Server.Shuttles.Systems;
|
|
using Content.Shared.Cuffs.Components;
|
|
using Content.Shared.Humanoid;
|
|
using Content.Shared.Mind;
|
|
using Content.Shared.Mobs.Components;
|
|
using Content.Shared.Mobs.Systems;
|
|
using Content.Shared.Objectives.Components;
|
|
using Content.Shared.Roles;
|
|
using Robust.Shared.Player;
|
|
|
|
namespace Content.Server.Objectives.Systems;
|
|
|
|
public sealed class BloodBrotherSharedHijackConditionSystem : EntitySystem
|
|
{
|
|
[Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
|
|
[Dependency] private readonly SharedMindSystem _mind = default!;
|
|
[Dependency] private readonly SharedRoleSystem _role = default!;
|
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
|
[Dependency] private readonly BloodBrotherSharedConditionSystem _sharedCondition = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<BloodBrotherSharedHijackConditionComponent, ObjectiveGetProgressEvent>(OnGetProgress);
|
|
}
|
|
|
|
private void OnGetProgress(EntityUid uid, BloodBrotherSharedHijackConditionComponent comp, ref ObjectiveGetProgressEvent args)
|
|
{
|
|
args.Progress = GetProgress(uid, args.MindId, args.Mind);
|
|
}
|
|
|
|
private float GetProgress(EntityUid objectiveUid, EntityUid mindId, MindComponent mind)
|
|
{
|
|
if (!CheckBaseHijackConditions(objectiveUid, mindId, mind))
|
|
return 0f;
|
|
|
|
if (!_emergencyShuttle.EmergencyShuttleArrived)
|
|
return 0f;
|
|
|
|
foreach (var stationData in EntityQuery<StationEmergencyShuttleComponent>())
|
|
{
|
|
if (stationData.EmergencyShuttle == null)
|
|
continue;
|
|
|
|
if (IsShuttleHijackedByBloodBrothers(stationData.EmergencyShuttle.Value, objectiveUid, mindId))
|
|
return 1f;
|
|
}
|
|
|
|
return 0f;
|
|
}
|
|
|
|
private bool CheckBaseHijackConditions(EntityUid objectiveUid, EntityUid mindId, MindComponent mind)
|
|
{
|
|
if (mind.OwnedEntity == null || TryComp<CuffableComponent>(mind.OwnedEntity, out var cuffed) && cuffed.CuffedHandCount > 0)
|
|
return false;
|
|
|
|
if (_sharedCondition.TryGetSharedCondition(objectiveUid, mindId, out var sharedCondition)
|
|
&& !_sharedCondition.CheckBaseConditions(mindId, sharedCondition, mind))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool IsShuttleHijackedByBloodBrothers(EntityUid shuttleGridId, EntityUid objectiveUid, EntityUid mindId)
|
|
{
|
|
var gridPlayers = Filter.BroadcastGrid(shuttleGridId).Recipients;
|
|
var humanoids = GetEntityQuery<HumanoidAppearanceComponent>();
|
|
var cuffable = GetEntityQuery<CuffableComponent>();
|
|
EntityQuery<MobStateComponent>();
|
|
|
|
var firstBrotherOnShuttle = false;
|
|
var secondBrotherOnShuttle = false;
|
|
EntityUid? brotherMindId = null;
|
|
|
|
if (_sharedCondition.TryGetSharedCondition(objectiveUid, mindId, out var sharedCondition)
|
|
&& sharedCondition.BrotherMind.HasValue)
|
|
{
|
|
brotherMindId = sharedCondition.BrotherMind.Value;
|
|
}
|
|
|
|
foreach (var player in gridPlayers)
|
|
{
|
|
if (player.AttachedEntity == null ||
|
|
!_mind.TryGetMind(player.AttachedEntity.Value, out var crewMindId, out _))
|
|
continue;
|
|
|
|
if (mindId == crewMindId)
|
|
{
|
|
firstBrotherOnShuttle = true;
|
|
continue;
|
|
}
|
|
|
|
if (brotherMindId.HasValue && brotherMindId.Value == crewMindId)
|
|
{
|
|
secondBrotherOnShuttle = true;
|
|
continue;
|
|
}
|
|
|
|
var isHumanoid = humanoids.HasComponent(player.AttachedEntity.Value);
|
|
if (!isHumanoid)
|
|
continue;
|
|
|
|
var isAntagonist = _role.MindIsAntagonist(crewMindId);
|
|
if (isAntagonist)
|
|
continue;
|
|
|
|
var isPersonIncapacitated = _mobState.IsIncapacitated(player.AttachedEntity.Value);
|
|
if (isPersonIncapacitated)
|
|
continue;
|
|
|
|
var isPersonCuffed =
|
|
cuffable.TryGetComponent(player.AttachedEntity.Value, out var cuffed)
|
|
&& cuffed.CuffedHandCount > 0;
|
|
if (isPersonCuffed)
|
|
continue;
|
|
|
|
return false;
|
|
}
|
|
|
|
return firstBrotherOnShuttle && secondBrotherOnShuttle;
|
|
}
|
|
}
|