diff --git a/Content.Server/_CorvaxGoob/OfferItem/Objectives/TeachALessonConditionComponent.cs b/Content.Server/_CorvaxGoob/OfferItem/Objectives/TeachALessonConditionComponent.cs new file mode 100644 index 0000000000..b9a397fed7 --- /dev/null +++ b/Content.Server/_CorvaxGoob/OfferItem/Objectives/TeachALessonConditionComponent.cs @@ -0,0 +1,17 @@ +namespace Content.Server._Starlight.Objectives; + +/// +/// Requires that a target at least dies once. +/// Depends on to function. +/// + +[RegisterComponent] +public sealed partial class TeachALessonConditionComponent : Component +{ + /// + /// Checks to see if the target has died + /// + [ViewVariables(VVAccess.ReadWrite)] + public bool HasDied = false; + +} diff --git a/Content.Server/_CorvaxGoob/OfferItem/Objectives/TeachALessonConditionSystem.cs b/Content.Server/_CorvaxGoob/OfferItem/Objectives/TeachALessonConditionSystem.cs new file mode 100644 index 0000000000..e198ae1735 --- /dev/null +++ b/Content.Server/_CorvaxGoob/OfferItem/Objectives/TeachALessonConditionSystem.cs @@ -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; + +/// +/// Handles Teach a Lesson logic on if a specific entity has died at least once during the round +/// +public sealed class TeachALessonConditionSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMobStateChanged); + SubscribeLocalEvent(OnMindAdded); + SubscribeLocalEvent(OnMindRemoved); // goob - fix teach a lesson + SubscribeLocalEvent(OnGhostAttempt); // goob - fix teach a lesson + SubscribeLocalEvent(OnAfterAssign); + SubscribeLocalEvent(OnGetProgress); + } + + private void OnGetProgress(Entity ent, ref ObjectiveGetProgressEvent args) + { + args.Progress = ent.Comp.HasDied ? 1.0f : 0.0f; + } + + private void OnAfterAssign(Entity 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(targetMobUid.Value); + targetComponent.Teachers.Add(ent.Owner); + } + + private void OnMindAdded(EntityUid uid, TeachALessonTargetComponent component, MindAddedMessage args) // goob - fix teach a lesson + { + var targetComponent = EnsureComp(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(uid, out var contained) && contained.GracePeriodEndTime == null) + { + TriggerObjective(component); + } + + RemCompDeferred(uid); + } + + private void OnGhostAttempt(GhostAttemptHandleEvent args) // goob - fix teach a lesson + { + if (args.Mind.OwnedEntity is not { } owned || !TryComp(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 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; + } + } +} diff --git a/Content.Server/_CorvaxGoob/OfferItem/Objectives/TeachALessonTargetComponent.cs b/Content.Server/_CorvaxGoob/OfferItem/Objectives/TeachALessonTargetComponent.cs new file mode 100644 index 0000000000..3a7d8fd5a4 --- /dev/null +++ b/Content.Server/_CorvaxGoob/OfferItem/Objectives/TeachALessonTargetComponent.cs @@ -0,0 +1,13 @@ +namespace Content.Server._Starlight.Objectives; + +/// +/// Marker component for the target of Teach a lesson Objective +/// Holds HashSet of entities with this objective +/// + +[RegisterComponent ] +public sealed partial class TeachALessonTargetComponent : Component +{ + [DataField] + public HashSet Teachers = new HashSet(); +} diff --git a/Resources/Locale/ru-RU/_CorvaxGoob/Objective/teach-a-lesson.ftl b/Resources/Locale/ru-RU/_CorvaxGoob/Objective/teach-a-lesson.ftl new file mode 100644 index 0000000000..883a7a5119 --- /dev/null +++ b/Resources/Locale/ru-RU/_CorvaxGoob/Objective/teach-a-lesson.ftl @@ -0,0 +1 @@ +objective-condition-teach-lesson-title = Проучите { $targetName }, { CAPITALIZE($job) } \ No newline at end of file diff --git a/Resources/Locale/ru-RU/prototypes/_corvaxgoob/traitor.ftl b/Resources/Locale/ru-RU/prototypes/_corvaxgoob/traitor.ftl new file mode 100644 index 0000000000..37d49fedc1 --- /dev/null +++ b/Resources/Locale/ru-RU/prototypes/_corvaxgoob/traitor.ftl @@ -0,0 +1,6 @@ +ent-BaseTeachALessonObjective = { ent-BaseTargetObjective } + .desc = { ent-BaseTargetObjective.desc } +ent-TeachRandomPersonObjective = { ent-BaseTraitorObjective } + .desc = Убедитесь, что этот человек умрёт хотя бы раз за смену. Он знает что натворил. +ent-TeachRandomHeadObjective = { ent-BaseTraitorObjective } + .desc = Убедитесь, что этот руководитель умрёт хотя бы раз за смену. Он знает, что натворил. diff --git a/Resources/Prototypes/_CorvaxGoob/Objectives/ObjectiveGroups.yml b/Resources/Prototypes/_CorvaxGoob/Objectives/ObjectiveGroups.yml new file mode 100644 index 0000000000..2059c3ea00 --- /dev/null +++ b/Resources/Prototypes/_CorvaxGoob/Objectives/ObjectiveGroups.yml @@ -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 diff --git a/Resources/Prototypes/_CorvaxGoob/Objectives/Traitor.yml b/Resources/Prototypes/_CorvaxGoob/Objectives/Traitor.yml new file mode 100644 index 0000000000..ad21a33482 --- /dev/null +++ b/Resources/Prototypes/_CorvaxGoob/Objectives/Traitor.yml @@ -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