Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mirror 26421: Nerf Ninja's Research Stealing #446

Merged
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
22 changes: 17 additions & 5 deletions Content.Server/Research/Systems/ResearchStealerSystem.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using Content.Shared.Research.Components;
using Content.Shared.Research.Systems;
using Robust.Shared.Random;

namespace Content.Server.Research.Systems;

public sealed class ResearchStealerSystem : SharedResearchStealerSystem
{
[Dependency] private readonly SharedResearchSystem _research = default!;
[Dependency] private readonly IRobustRandom _random = default!;

public override void Initialize()
{
Expand All @@ -24,16 +26,26 @@ private void OnDoAfter(EntityUid uid, ResearchStealerComponent comp, ResearchSte
if (!TryComp<TechnologyDatabaseComponent>(target, out var database))
return;

var ev = new ResearchStolenEvent(uid, target, database.UnlockedTechnologies);
var ev = new ResearchStolenEvent(uid, target, new());
var count = _random.Next(comp.MinToSteal, comp.MaxToSteal + 1);
for (var i = 0; i < count; i++)
{
if (database.UnlockedTechnologies.Count == 0)
break;

var toRemove = _random.Pick(database.UnlockedTechnologies);
if (_research.TryRemoveTechnology((target, database), toRemove))
ev.Techs.Add(toRemove);
}
RaiseLocalEvent(uid, ref ev);
// oops, no more advanced lasers!
_research.ClearTechs(target, database);

args.Handled = true;
}
}

/// <summary>
/// Event raised on the user when research is stolen from a R&D server.
/// Event raised on the user when research is stolen from a RND server.
/// Techs contains every technology id researched.
/// </summary>
[ByRefEvent]
public record struct ResearchStolenEvent(EntityUid Used, EntityUid Target, List<String> Techs);
public record struct ResearchStolenEvent(EntityUid Used, EntityUid Target, List<string> Techs);
12 changes: 12 additions & 0 deletions Content.Shared/Research/Components/ResearchStealerComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,16 @@ public sealed partial class ResearchStealerComponent : Component
/// </summary>
[DataField("delay"), ViewVariables(VVAccess.ReadWrite)]
public TimeSpan Delay = TimeSpan.FromSeconds(20);

/// <summary>
/// The minimum number of technologies that will be stolen
/// </summary>
[DataField]
public int MinToSteal = 4;

/// <summary>
/// The maximum number of technologies that will be stolen
/// </summary>
[DataField]
public int MaxToSteal = 8;
}
45 changes: 44 additions & 1 deletion Content.Shared/Research/Systems/SharedResearchSystem.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Linq;
using Content.Shared.Research.Components;
using Content.Shared.Research.Prototypes;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Utility;
Expand Down Expand Up @@ -219,16 +220,58 @@ public void TrySetMainDiscipline(TechnologyPrototype prototype, EntityUid uid, T
if (!Resolve(uid, ref component))
return;

var discipline = PrototypeManager.Index<TechDisciplinePrototype>(prototype.Discipline);
var discipline = PrototypeManager.Index(prototype.Discipline);
if (prototype.Tier < discipline.LockoutTier)
return;
component.MainDiscipline = prototype.Discipline;
Dirty(uid, component);
}

/// <summary>
/// Removes a technology and its recipes from a technology database.
/// </summary>
public bool TryRemoveTechnology(Entity<TechnologyDatabaseComponent> entity, ProtoId<TechnologyPrototype> tech)
{
return TryRemoveTechnology(entity, PrototypeManager.Index(tech));
}

/// <summary>
/// Removes a technology and its recipes from a technology database.
/// </summary>
[PublicAPI]
public bool TryRemoveTechnology(Entity<TechnologyDatabaseComponent> entity, TechnologyPrototype tech)
{
if (!entity.Comp.UnlockedTechnologies.Remove(tech.ID))
return false;

// check to make sure we didn't somehow get the recipe from another tech.
// unlikely, but whatever
var recipes = tech.RecipeUnlocks;
foreach (var recipe in recipes)
{
var hasTechElsewhere = false;
foreach (var unlockedTech in entity.Comp.UnlockedTechnologies)
{
var unlockedTechProto = PrototypeManager.Index<TechnologyPrototype>(unlockedTech);

if (!unlockedTechProto.RecipeUnlocks.Contains(recipe))
continue;
hasTechElsewhere = true;
break;
}

if (!hasTechElsewhere)
entity.Comp.UnlockedRecipes.Remove(recipe);
}
Dirty(entity, entity.Comp);
UpdateTechnologyCards(entity, entity);
return true;
}

/// <summary>
/// Clear all unlocked technologies from the database.
/// </summary>
[PublicAPI]
public void ClearTechs(EntityUid uid, TechnologyDatabaseComponent? comp = null)
{
if (!Resolve(uid, ref comp) || comp.UnlockedTechnologies.Count == 0)
Expand Down
4 changes: 2 additions & 2 deletions Resources/Prototypes/Objectives/ninja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
sprite: Structures/Machines/server.rsi
state: server
- type: NumberObjective
min: 5
max: 10
min: 9
max: 13
title: objective-condition-steal-research-title
- type: StealResearchCondition

Expand Down
Loading