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
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Content.Server._Starlight.Objectives;

/// <summary>
/// Requires that a target at least dies once.
/// Depends on <see cref="TargetObjectiveComponent"/> to function.
/// </summary>

[RegisterComponent]
public sealed partial class TeachALessonConditionComponent : Component
{
/// <summary>
/// Checks to see if the target has died
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public bool HasDied = false;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using Content.Server.Ghost;
using Content.Server.Objectives.Components;
using Content.Shared.Bed.Cryostorage;
using Content.Shared.Mind;
using Content.Shared.Mind.Components; // goob - fix teach a lesson
using Content.Shared.Mobs;
using Content.Shared.Objectives.Components;

namespace Content.Server._Starlight.Objectives;

/// <summary>
/// Handles Teach a Lesson logic on if a specific entity has died at least once during the round
/// </summary>
public sealed class TeachALessonConditionSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<TeachALessonTargetComponent, MobStateChangedEvent>(OnMobStateChanged);
SubscribeLocalEvent<TeachALessonTargetComponent, MindAddedMessage>(OnMindAdded);
SubscribeLocalEvent<TeachALessonTargetComponent, MindRemovedMessage>(OnMindRemoved); // goob - fix teach a lesson
SubscribeLocalEvent<GhostAttemptHandleEvent>(OnGhostAttempt); // goob - fix teach a lesson
SubscribeLocalEvent<TeachALessonConditionComponent, ObjectiveAfterAssignEvent>(OnAfterAssign);
SubscribeLocalEvent<TeachALessonConditionComponent, ObjectiveGetProgressEvent>(OnGetProgress);
}

private void OnGetProgress(Entity<TeachALessonConditionComponent> ent, ref ObjectiveGetProgressEvent args)
{
args.Progress = ent.Comp.HasDied ? 1.0f : 0.0f;
}

private void OnAfterAssign(Entity<TeachALessonConditionComponent> ent, ref ObjectiveAfterAssignEvent args)
{
if (!TryComp(ent.Owner, out TargetObjectiveComponent? targetObjective))
return;
var targetMindUid = targetObjective.Target;
if (targetMindUid is null)
return;
if (!TryComp(targetMindUid, out MindComponent? targetMind))
return;
var targetMobUid = targetMind.CurrentEntity;
if (targetMobUid is null)
return;
var targetComponent = EnsureComp<TeachALessonTargetComponent>(targetMobUid.Value);
targetComponent.Teachers.Add(ent.Owner);
}

private void OnMindAdded(EntityUid uid, TeachALessonTargetComponent component, MindAddedMessage args) // goob - fix teach a lesson
{
var targetComponent = EnsureComp<TeachALessonTargetComponent>(args.Container.Owner);
foreach (var teacher in component.Teachers)
{
targetComponent.Teachers.Add(teacher);
}
}

private void OnMindRemoved(EntityUid uid, TeachALessonTargetComponent component, MindRemovedMessage args) // goob - fix teach a lesson
{
// cryo storage fix godo
if (TryComp<CryostorageContainedComponent>(uid, out var contained) && contained.GracePeriodEndTime == null)
{
TriggerObjective(component);
}

RemCompDeferred<TeachALessonTargetComponent>(uid);
}

private void OnGhostAttempt(GhostAttemptHandleEvent args) // goob - fix teach a lesson
{
if (args.Mind.OwnedEntity is not { } owned || !TryComp<TeachALessonTargetComponent>(owned, out var target))
return;

if (args.CanReturnGlobal && args.Mind.VisitingEntity == null)
{
TriggerObjective(target);
return;
}

if (args.CanReturnGlobal)
return;

TriggerObjective(target);
}

private void OnMobStateChanged(Entity<TeachALessonTargetComponent> ent, ref MobStateChangedEvent args)
{
if (args.NewMobState != MobState.Dead)
return;

TriggerObjective(ent.Comp);
}

private void TriggerObjective(TeachALessonTargetComponent component) // goob - fix teach a lesson
{
foreach (var teacher in component.Teachers)
{
if (!TryComp(teacher, out TeachALessonConditionComponent? condition))
continue;

condition.HasDied = true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Content.Server._Starlight.Objectives;

/// <summary>
/// Marker component for the target of Teach a lesson Objective
/// Holds HashSet of entities with this objective
/// </summary>

[RegisterComponent ]
public sealed partial class TeachALessonTargetComponent : Component
{
[DataField]
public HashSet<EntityUid> Teachers = new HashSet<EntityUid>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
objective-condition-teach-lesson-title = Проучите { $targetName }, { CAPITALIZE($job) }
6 changes: 6 additions & 0 deletions Resources/Locale/ru-RU/prototypes/_corvaxgoob/traitor.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ent-BaseTeachALessonObjective = { ent-BaseTargetObjective }
.desc = { ent-BaseTargetObjective.desc }
ent-TeachRandomPersonObjective = { ent-BaseTraitorObjective }
.desc = Убедитесь, что этот человек умрёт хотя бы раз за смену. Он знает что натворил.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing comma in player-facing description.

Inconsistent with line 6 — "что" should be preceded by a comma.

✏️ Proposed fix
-    .desc = Убедитесь, что этот человек умрёт хотя бы раз за смену. Он знает что натворил.
+    .desc = Убедитесь, что этот человек умрёт хотя бы раз за смену. Он знает, что натворил.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Resources/Locale/ru-RU/prototypes/_corvaxgoob/traitor.ftl` at line 4, The
player-facing description string in the traitor.ftl entry (.desc) is missing a
comma before "что"; update the .desc value to insert a comma before "что" so it
reads "Убедитесь, что этот человек умрёт хотя бы раз за смену, он знает, что
натворил." (ensure the comma placement mirrors the style used on line 6 and
adjust any punctuation spacing accordingly).

ent-TeachRandomHeadObjective = { ent-BaseTraitorObjective }
.desc = Убедитесь, что этот руководитель умрёт хотя бы раз за смену. Он знает, что натворил.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- type: weightedRandom
id: TraitorObjectiveGroupTeach
weights:
TeachRandomPersonObjective: 1 #Goobstation Teach them a lesson
TeachRandomHeadObjective: 0.25 #Goobstation Teach them a lesson
KillRandomPersonObjective: 1
KillStationAiObjective: 0.25
KillRandomHeadObjective: 0.25
51 changes: 51 additions & 0 deletions Resources/Prototypes/_CorvaxGoob/Objectives/Traitor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# requires that the player kill someone only once
# disables social objectives and is disabled by social objectives

- type: entity
abstract: true
parent: BaseTargetObjective
id: BaseTeachALessonObjective
components:
- type: Objective
unique: false
icon:
sprite: Objects/Weapons/Melee/baseball_bat.rsi
state: icon
- type: ObjectiveBlacklistRequirement
blacklist:
components:
- SocialObjective
- type: TeachALessonCondition

#Teach a Lesson
- type: entity
parent: [BaseTraitorObjective, BaseTeachALessonObjective]
id: TeachRandomPersonObjective
description: Ensure they die at least once this shift. They know what they did.
components:
- type: Objective
difficulty: 0.5 #slightly under 1/3rd the diffculty of RR
unique: false
- type: TargetObjective
title: objective-condition-teach-lesson-title
- type: PickRandomPerson


- type: entity
parent: [BaseTraitorObjective, BaseTeachALessonObjective]
id: TeachRandomHeadObjective
description: Ensure this head dies at least once this shift. They know what they did.
components:
- type: Objective
# technically it's still possible for TeachRandomPersonObjective to roll a head but this is guaranteed, so higher difficulty
difficulty: 1
# killing 1 head is enough
unique: true
- type: TargetObjective
title: objective-condition-teach-lesson-title
- type: PickRandomPerson
filters:
- !type:BodyMindFilter
whitelist:
components:
- CommandStaff
Loading