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

The Rat King [Antag] #8706

Merged
merged 42 commits into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
1c46b73
Merge branch 'space-wizards-master'
EmoGarbage404 Apr 25, 2022
404cb6d
Merge branch 'space-wizards:master' into master
EmoGarbage404 Apr 27, 2022
bc28856
Merge branch 'space-wizards:master' into master
EmoGarbage404 Apr 28, 2022
b78709a
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 1, 2022
c8f849f
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 5, 2022
6ba6110
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 7, 2022
968f756
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 9, 2022
52cca51
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 11, 2022
71d3cb9
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 12, 2022
35dd2de
Merge https://github.com/space-wizards/space-station-14
EmoGarbage404 May 13, 2022
0a39235
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 13, 2022
f240894
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 13, 2022
95759d8
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 22, 2022
befe51c
Merge https://github.com/EmoGarbage404/space-station-14
EmoGarbage404 May 22, 2022
df20146
Merge branch 'master' of https://github.com/space-wizards/space-stati…
EmoGarbage404 May 27, 2022
1442766
Merge branch 'space-wizards-master'
EmoGarbage404 May 27, 2022
fa7b5dd
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 29, 2022
9e8e4f8
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 29, 2022
63178a8
Merge branch 'space-wizards:master' into master
EmoGarbage404 May 30, 2022
0188a18
Merge branch 'space-wizards:master' into master
EmoGarbage404 Jun 1, 2022
a345865
Merge remote-tracking branch 'origin/master'
EmoGarbage404 Jun 1, 2022
7afc2d0
Merge branch 'space-wizards:master' into master
EmoGarbage404 Jun 2, 2022
78ec269
Merge branch 'space-wizards:master' into master
EmoGarbage404 Jun 4, 2022
81c977b
Merge https://github.com/EmoGarbage404/space-station-14
EmoGarbage404 Jun 4, 2022
5b6f1b4
Merge branch 'space-wizards:master' into master
EmoGarbage404 Jun 5, 2022
ce5f0aa
vending machine go spit
EmoGarbage404 Jun 7, 2022
7e05173
who's da rat, bozo
EmoGarbage404 Jun 7, 2022
cc15040
fixes
EmoGarbage404 Jun 7, 2022
6d4eae8
crown + fixes
EmoGarbage404 Jun 7, 2022
1ffe394
aaaa
EmoGarbage404 Jun 8, 2022
ecabdcf
aa
EmoGarbage404 Jun 8, 2022
b426fba
lololol
EmoGarbage404 Jun 8, 2022
8051950
removing vending shit + most annoying fix alive
EmoGarbage404 Jun 8, 2022
755856e
Merge remote-tracking branch 'origin/regal-rat' into regal-rat
EmoGarbage404 Jun 8, 2022
94be490
paul review
EmoGarbage404 Jun 8, 2022
cee29ea
moony fixes
EmoGarbage404 Jun 14, 2022
cdf3fc8
sloth review
EmoGarbage404 Jun 14, 2022
865f1a1
Minor diseasesystem fix
metalgearsloth Jun 14, 2022
3209376
Merge remote-tracking branch 'upstream/master' into regal-rat
metalgearsloth Jun 14, 2022
bcf9d31
inverse moment
metalgearsloth Jun 14, 2022
1cf22f3
A
metalgearsloth Jun 14, 2022
5d84933
Also reduce args allocations
metalgearsloth Jun 14, 2022
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
20 changes: 16 additions & 4 deletions Content.Server/Disease/Components/DiseaseCarrierComponent.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,48 @@
using System.Linq;
using Content.Shared.Disease;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;

namespace Content.Server.Disease.Components
{
[RegisterComponent]
/// <summary>
/// Allows the enity to be infected with diseases.
/// Allows the entity to be infected with diseases.
/// Please use only on mobs.
/// </summary>
[RegisterComponent]
public sealed class DiseaseCarrierComponent : Component
{
/// <summary>
/// Shows the CURRENT diseases on the carrier
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public List<DiseasePrototype> Diseases = new();

/// <summary>
/// The carrier's resistance to disease
/// </summary>
[DataField("diseaseResist")]
[ViewVariables(VVAccess.ReadWrite)]
public float DiseaseResist = 0f;

/// <summary>
/// Diseases the carrier has had, used for immunity.
/// <summary>
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public List<DiseasePrototype> PastDiseases = new();

/// <summary>
/// All the diseases the carrier has or has had.
/// Checked against when trying to add a disease
/// <summary>
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public List<DiseasePrototype> AllDiseases => PastDiseases.Concat(Diseases).ToList();

/// <summary>
/// A list of diseases which the entity does not
/// exhibit direct symptoms from. They still transmit
/// these diseases, just without symptoms.
/// </summary>
[ViewVariables, DataField("carrierDiseases", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<DiseasePrototype>))]
public HashSet<string>? CarrierDiseases;
}
}
30 changes: 22 additions & 8 deletions Content.Server/Disease/DiseaseSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,23 @@ public override void Update(float frameTime)
for (var i = 0; i < carrierComp.Diseases.Count; i++) //this is a for-loop so that it doesn't break when new diseases are added
{
var disease = carrierComp.Diseases[i];
disease.Accumulator += frameTime;

if (disease.Accumulator < disease.TickTime) continue;

// if the disease is on the silent disease list, don't do effects
var doEffects = carrierComp.CarrierDiseases?.Contains(disease.ID) != true;
var args = new DiseaseEffectArgs(carrierComp.Owner, disease, EntityManager);
disease.Accumulator += frameTime;
if (disease.Accumulator >= disease.TickTime)
disease.Accumulator -= disease.TickTime;

foreach (var cure in disease.Cures)
{
if (cure.Cure(args))
CureDisease(carrierComp, disease);
}

if (doEffects)
{
disease.Accumulator -= disease.TickTime;
foreach (var cure in disease.Cures)
{
if (cure.Cure(args))
CureDisease(carrierComp, disease);
}
foreach (var effect in disease.Effects)
{
if (_random.Prob(effect.Probability))
Expand Down Expand Up @@ -383,6 +389,14 @@ public void TryInfect(DiseaseCarrierComponent carrier, DiseasePrototype? disease
TryAddDisease(carrier.Owner, disease, carrier);
}

public void TryInfect(DiseaseCarrierComponent carrier, string? disease, float chance = 0.7f, bool forced = false)
{
if (disease == null || !_prototypeManager.TryIndex<DiseasePrototype>(disease, out var d))
return;

TryInfect(carrier, d, chance, forced);
}

/// <summary>
/// Plays a sneeze/cough popup if applicable
/// and then tries to infect anyone in range
Expand Down
54 changes: 54 additions & 0 deletions Content.Server/RatKing/RatKingComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Content.Shared.Actions.ActionTypes;
using Content.Shared.Disease;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;

namespace Content.Server.RatKing
{
[RegisterComponent]
public sealed class RatKingComponent : Component
{
/// <summary>
/// The action for the Raise Army ability
/// </summary>
[DataField("actionRaiseArmy", required: true)]
public InstantAction ActionRaiseArmy = new();

/// <summary>
/// The amount of hunger one use of Raise Army consumes
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("hungerPerArmyUse", required: true)]
public float HungerPerArmyUse = 25f;

/// <summary>
/// The entity prototype of the mob that Raise Army summons
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("armyMobSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string ArmyMobSpawnId = "MobRatServant";

/// <summary>
/// The action for the Domain ability
/// </summary>
[ViewVariables, DataField("actionDomain", required: true)]
public InstantAction ActionDomain = new();

/// <summary>
/// The amount of hunger one use of Domain consumes
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("hungerPerDomainUse", required: true)]
public float HungerPerDomainUse = 50f;

/// <summary>
/// The disease prototype id that the Domain ability spreads
/// </summary>
[ViewVariables, DataField("domainDiseaseId", customTypeSerializer: typeof(PrototypeIdSerializer<DiseasePrototype>))]
public string DomainDiseaseId = "Plague";

/// <summary>
/// The range of the Domain ability.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("domainRange")]
public float DomainRange = 3f;

}
};
93 changes: 93 additions & 0 deletions Content.Server/RatKing/RatKingSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using Content.Server.Actions;
using Content.Server.Disease;
using Content.Server.Disease.Components;
using Content.Server.Nutrition.Components;
using Content.Server.Popups;
using Content.Shared.Actions;
using Robust.Shared.Player;

namespace Content.Server.RatKing
{
public sealed class RatKingSystem : EntitySystem
{
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly ActionsSystem _action = default!;
[Dependency] private readonly DiseaseSystem _disease = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<RatKingComponent, ComponentStartup>(OnStartup);

SubscribeLocalEvent<RatKingComponent, RatKingRaiseArmyActionEvent>(OnRaiseArmy);
SubscribeLocalEvent<RatKingComponent, RatKingDomainActionEvent>(OnDomain);
}

private void OnStartup(EntityUid uid, RatKingComponent component, ComponentStartup args)
{
_action.AddAction(uid, component.ActionRaiseArmy, null);
_action.AddAction(uid, component.ActionDomain, null);
}

/// <summary>
/// Summons an allied rat servant at the King, costing a small amount of hunger
/// </summary>
private void OnRaiseArmy(EntityUid uid, RatKingComponent component, RatKingRaiseArmyActionEvent args)
{
if (args.Handled)
return;

if (!TryComp<HungerComponent>(uid, out var hunger))
return;

//make sure the hunger doesn't go into the negatives
if (hunger.CurrentHunger < component.HungerPerArmyUse)
{
_popup.PopupEntity(Loc.GetString("rat-king-too-hungry"), uid, Filter.Entities(uid));
return;
}
args.Handled = true;
hunger.CurrentHunger -= component.HungerPerArmyUse;
Spawn(component.ArmyMobSpawnId, Transform(uid).Coordinates); //spawn the little mouse boi
}

/// <summary>
/// Gets all of the nearby disease-carrying entities in a radius
/// and gives them the specified disease. It has a hunger cost as well
/// </summary>
private void OnDomain(EntityUid uid, RatKingComponent component, RatKingDomainActionEvent args)
{
if (args.Handled)
return;

if (!TryComp<HungerComponent>(uid, out var hunger))
return;

//make sure the hunger doesn't go into the negatives
if (hunger.CurrentHunger < component.HungerPerDomainUse)
{
_popup.PopupEntity(Loc.GetString("rat-king-too-hungry"), uid, Filter.Entities(uid));
return;
}
args.Handled = true;
hunger.CurrentHunger -= component.HungerPerDomainUse;

_popup.PopupEntity(Loc.GetString("rat-king-domain-popup"), uid, Filter.Pvs(uid, default, EntityManager));

var tstalker = GetEntityQuery<DiseaseCarrierComponent>();
foreach (var entity in _lookup.GetEntitiesInRange(uid, component.DomainRange)) //go through all of them, filtering only those in range that are not the king itself
{
if (entity == uid)
continue;

if (tstalker.TryGetComponent(entity, out var diseasecomp))
_disease.TryInfect(diseasecomp, component.DomainDiseaseId); //infect them with w/e disease
}
}
}

public sealed class RatKingRaiseArmyActionEvent : InstantActionEvent { };
public sealed class RatKingDomainActionEvent : InstantActionEvent { };
};
50 changes: 50 additions & 0 deletions Content.Server/StationEvents/Events/MouseMigration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Linq;
using Content.Server.StationEvents.Components;
using Robust.Shared.Random;

namespace Content.Server.StationEvents.Events;

public sealed class MouseMigration : StationEvent
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;

public static List<string> SpawnedPrototypeChoices = new List<string>() //we double up for that ez fake probability
{"MobMouse", "MobMouse1", "MobMouse2", "MobRatServant"};

public override string Name => "MouseMigration";

public override string? StartAnnouncement =>
Loc.GetString("station-event-mouse-migration-announcement");

public override int EarliestStart => 30;

public override int MinimumPlayers => 35; //this just ensures that it doesn't spawn on lowpop maps.

public override float Weight => WeightLow;

public override int? MaxOccurrences => 1;

protected override float StartAfter => 30f;

protected override float EndAfter => 60;

public override void Startup()
{
base.Startup();

var spawnLocations = _entityManager.EntityQuery<VentCritterSpawnLocationComponent, TransformComponent>().ToList();
_random.Shuffle(spawnLocations);

var spawnAmount = _random.Next(7, 15); // A small colony of critters.

for (int i = 0; i < spawnAmount && i < spawnLocations.Count - 1; i++)
{
var spawnChoice = _random.Pick(SpawnedPrototypeChoices);
if (_random.Prob(0.01f) || i == 0) //small chance for multiple, but always at least 1
spawnChoice = "MobRatKing";

_entityManager.SpawnEntity(spawnChoice, spawnLocations[i].Item2.Coordinates);
}
}
}
8 changes: 8 additions & 0 deletions Resources/Locale/en-US/animals/rat-king/rat-king.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
rat-king-raise-army-name = Raise Army
rat-king-raise-army-description = Spend some hunger to summon an allied rat to help defend you.

rat-king-domain-name = Rat King's Domain
rat-king-domain-description = Spend some hunger to infect those around you with the plague.
rat-king-domain-popup = A cloud of plague is released into the air!

rat-king-too-hungry = You are too hungry to use this ability!
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
station-event-mouse-migration-announcement = We have detected an oncoming migration of rodents to the station. Please stay out of maintenance tunnels and try and avoid excessive contact.
25 changes: 25 additions & 0 deletions Resources/Prototypes/Diseases/infectious.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,31 @@
- !type:DiseaseReagentCure
reagent: DemonsBlood

- type: disease
id: Plague
name: plague
cureResist: 0.1
effects:
- !type:DiseaseVomit
probability: 0.005
- !type:DiseasePopUp
probability: 0.025
- !type:DiseaseSnough
probability: 0.025
snoughMessage: disease-cough
snoughSound:
collection: Coughs
- !type:DiseaseHealthChange
probability: 0.05
damage:
types:
Poison: 2
cures:
- !type:DiseaseBedrestCure
maxLength: 120
- !type:DiseaseJustWaitCure
maxLength: 240

- type: disease
id: OwOnavirus
name: OwOnavirus
Expand Down
13 changes: 13 additions & 0 deletions Resources/Prototypes/Entities/Clothing/Head/misc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,19 @@
- type: Clothing
sprite: Clothing/Head/Misc/cone.rsi

- type: entity
parent: ClothingHeadBase
id: ClothingHeadHatFancyCrown
name: fancy crown
description: It smells like dead rat.
components:
- type: Sprite
sprite: Clothing/Head/Misc/fancycrown.rsi
- type: Clothing
sprite: Clothing/Head/Misc/fancycrown.rsi
- type: MobPrice
price: 3000

- type: entity
parent: ClothingHeadBase
id: ClothingHeadHatCatEars
Expand Down
Loading