From 9be066a8cb7bacbe19554ed55fc4d6f34703fec9 Mon Sep 17 00:00:00 2001 From: EmoGarbage404 <98561806+EmoGarbage404@users.noreply.github.com> Date: Wed, 15 Jun 2022 20:53:26 -0400 Subject: [PATCH] The Rat King [Antag] (#8706) * vending machine go spit * who's da rat, bozo * fixes * crown + fixes * aaaa * aa * lololol * removing vending shit + most annoying fix alive * paul review * moony fixes * sloth review * Minor diseasesystem fix * inverse moment * A * Also reduce args allocations Co-authored-by: metalgearsloth --- .../Components/DiseaseCarrierComponent.cs | 20 +- Content.Server/Disease/DiseaseSystem.cs | 32 ++- Content.Server/RatKing/RatKingComponent.cs | 54 +++++ Content.Server/RatKing/RatKingSystem.cs | 93 +++++++++ .../StationEvents/Events/MouseMigration.cs | 50 +++++ .../en-US/animals/rat-king/rat-king.ftl | 8 + .../station-events/events/mouse-migration.ftl | 1 + Resources/Prototypes/Diseases/infectious.yml | 25 +++ .../Entities/Clothing/Head/misc.yml | 13 ++ .../Entities/Mobs/NPCs/regalrat.yml | 189 ++++++++++++++++++ .../Misc/fancycrown.rsi/equipped-HELMET.png | Bin 0 -> 251 bytes .../Head/Misc/fancycrown.rsi/icon.png | Bin 0 -> 598 bytes .../Head/Misc/fancycrown.rsi/meta.json | 18 ++ .../Textures/Interface/Actions/meta.json | 8 +- .../Interface/Actions/ratKingArmy.png | Bin 0 -> 388 bytes .../Interface/Actions/ratKingDomain.png | Bin 0 -> 658 bytes .../Mobs/Animals/mouse.rsi/dead-3.png | Bin 0 -> 431 bytes .../Mobs/Animals/mouse.rsi/icon-3.png | Bin 0 -> 404 bytes .../Textures/Mobs/Animals/mouse.rsi/meta.json | 35 ++++ .../Mobs/Animals/mouse.rsi/mouse-3.png | Bin 0 -> 1493 bytes .../Mobs/Animals/mouse.rsi/splat-3.png | Bin 0 -> 535 bytes .../Mobs/Animals/regalrat.rsi/dead.png | Bin 0 -> 1207 bytes .../Mobs/Animals/regalrat.rsi/icon.png | Bin 0 -> 1285 bytes .../Mobs/Animals/regalrat.rsi/meta.json | 21 ++ .../Mobs/Animals/regalrat.rsi/regalrat.png | Bin 0 -> 3397 bytes 25 files changed, 553 insertions(+), 14 deletions(-) create mode 100644 Content.Server/RatKing/RatKingComponent.cs create mode 100644 Content.Server/RatKing/RatKingSystem.cs create mode 100644 Content.Server/StationEvents/Events/MouseMigration.cs create mode 100644 Resources/Locale/en-US/animals/rat-king/rat-king.ftl create mode 100644 Resources/Locale/en-US/station-events/events/mouse-migration.ftl create mode 100644 Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml create mode 100644 Resources/Textures/Clothing/Head/Misc/fancycrown.rsi/equipped-HELMET.png create mode 100644 Resources/Textures/Clothing/Head/Misc/fancycrown.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Head/Misc/fancycrown.rsi/meta.json create mode 100644 Resources/Textures/Interface/Actions/ratKingArmy.png create mode 100644 Resources/Textures/Interface/Actions/ratKingDomain.png create mode 100644 Resources/Textures/Mobs/Animals/mouse.rsi/dead-3.png create mode 100644 Resources/Textures/Mobs/Animals/mouse.rsi/icon-3.png create mode 100644 Resources/Textures/Mobs/Animals/mouse.rsi/mouse-3.png create mode 100644 Resources/Textures/Mobs/Animals/mouse.rsi/splat-3.png create mode 100644 Resources/Textures/Mobs/Animals/regalrat.rsi/dead.png create mode 100644 Resources/Textures/Mobs/Animals/regalrat.rsi/icon.png create mode 100644 Resources/Textures/Mobs/Animals/regalrat.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Animals/regalrat.rsi/regalrat.png diff --git a/Content.Server/Disease/Components/DiseaseCarrierComponent.cs b/Content.Server/Disease/Components/DiseaseCarrierComponent.cs index e9280235f3..56c71b46bc 100644 --- a/Content.Server/Disease/Components/DiseaseCarrierComponent.cs +++ b/Content.Server/Disease/Components/DiseaseCarrierComponent.cs @@ -1,13 +1,14 @@ using System.Linq; using Content.Shared.Disease; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; namespace Content.Server.Disease.Components { - [RegisterComponent] /// - /// Allows the enity to be infected with diseases. + /// Allows the entity to be infected with diseases. /// Please use only on mobs. /// + [RegisterComponent] public sealed class DiseaseCarrierComponent : Component { /// @@ -15,22 +16,33 @@ namespace Content.Server.Disease.Components /// [ViewVariables(VVAccess.ReadWrite)] public List Diseases = new(); + /// /// The carrier's resistance to disease /// [DataField("diseaseResist")] [ViewVariables(VVAccess.ReadWrite)] public float DiseaseResist = 0f; + /// /// Diseases the carrier has had, used for immunity. - /// + /// [ViewVariables(VVAccess.ReadWrite)] public List PastDiseases = new(); + /// /// All the diseases the carrier has or has had. /// Checked against when trying to add a disease - /// + /// [ViewVariables(VVAccess.ReadWrite)] public List AllDiseases => PastDiseases.Concat(Diseases).ToList(); + + /// + /// A list of diseases which the entity does not + /// exhibit direct symptoms from. They still transmit + /// these diseases, just without symptoms. + /// + [ViewVariables, DataField("carrierDiseases", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] + public HashSet? CarrierDiseases; } } diff --git a/Content.Server/Disease/DiseaseSystem.cs b/Content.Server/Disease/DiseaseSystem.cs index 97367115df..f55ee6b03d 100644 --- a/Content.Server/Disease/DiseaseSystem.cs +++ b/Content.Server/Disease/DiseaseSystem.cs @@ -96,17 +96,23 @@ namespace Content.Server.Disease 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]; - - var args = new DiseaseEffectArgs(carrierComp.Owner, disease, EntityManager); disease.Accumulator += frameTime; - if (disease.Accumulator >= disease.TickTime) + + 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 -= 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)) @@ -383,6 +389,14 @@ namespace Content.Server.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(disease, out var d)) + return; + + TryInfect(carrier, d, chance, forced); + } + /// /// Plays a sneeze/cough popup if applicable /// and then tries to infect anyone in range diff --git a/Content.Server/RatKing/RatKingComponent.cs b/Content.Server/RatKing/RatKingComponent.cs new file mode 100644 index 0000000000..4685d14cf2 --- /dev/null +++ b/Content.Server/RatKing/RatKingComponent.cs @@ -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 + { + /// + /// The action for the Raise Army ability + /// + [DataField("actionRaiseArmy", required: true)] + public InstantAction ActionRaiseArmy = new(); + + /// + /// The amount of hunger one use of Raise Army consumes + /// + [ViewVariables(VVAccess.ReadWrite), DataField("hungerPerArmyUse", required: true)] + public float HungerPerArmyUse = 25f; + + /// + /// The entity prototype of the mob that Raise Army summons + /// + [ViewVariables(VVAccess.ReadWrite), DataField("armyMobSpawnId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string ArmyMobSpawnId = "MobRatServant"; + + /// + /// The action for the Domain ability + /// + [ViewVariables, DataField("actionDomain", required: true)] + public InstantAction ActionDomain = new(); + + /// + /// The amount of hunger one use of Domain consumes + /// + [ViewVariables(VVAccess.ReadWrite), DataField("hungerPerDomainUse", required: true)] + public float HungerPerDomainUse = 50f; + + /// + /// The disease prototype id that the Domain ability spreads + /// + [ViewVariables, DataField("domainDiseaseId", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string DomainDiseaseId = "Plague"; + + /// + /// The range of the Domain ability. + /// + [ViewVariables(VVAccess.ReadWrite), DataField("domainRange")] + public float DomainRange = 3f; + + } +}; diff --git a/Content.Server/RatKing/RatKingSystem.cs b/Content.Server/RatKing/RatKingSystem.cs new file mode 100644 index 0000000000..c39dd090ad --- /dev/null +++ b/Content.Server/RatKing/RatKingSystem.cs @@ -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(OnStartup); + + SubscribeLocalEvent(OnRaiseArmy); + SubscribeLocalEvent(OnDomain); + } + + private void OnStartup(EntityUid uid, RatKingComponent component, ComponentStartup args) + { + _action.AddAction(uid, component.ActionRaiseArmy, null); + _action.AddAction(uid, component.ActionDomain, null); + } + + /// + /// Summons an allied rat servant at the King, costing a small amount of hunger + /// + private void OnRaiseArmy(EntityUid uid, RatKingComponent component, RatKingRaiseArmyActionEvent args) + { + if (args.Handled) + return; + + if (!TryComp(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 + } + + /// + /// Gets all of the nearby disease-carrying entities in a radius + /// and gives them the specified disease. It has a hunger cost as well + /// + private void OnDomain(EntityUid uid, RatKingComponent component, RatKingDomainActionEvent args) + { + if (args.Handled) + return; + + if (!TryComp(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(); + 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 { }; +}; diff --git a/Content.Server/StationEvents/Events/MouseMigration.cs b/Content.Server/StationEvents/Events/MouseMigration.cs new file mode 100644 index 0000000000..ee831de699 --- /dev/null +++ b/Content.Server/StationEvents/Events/MouseMigration.cs @@ -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 SpawnedPrototypeChoices = new List() //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().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); + } + } +} diff --git a/Resources/Locale/en-US/animals/rat-king/rat-king.ftl b/Resources/Locale/en-US/animals/rat-king/rat-king.ftl new file mode 100644 index 0000000000..35354daa08 --- /dev/null +++ b/Resources/Locale/en-US/animals/rat-king/rat-king.ftl @@ -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! \ No newline at end of file diff --git a/Resources/Locale/en-US/station-events/events/mouse-migration.ftl b/Resources/Locale/en-US/station-events/events/mouse-migration.ftl new file mode 100644 index 0000000000..98a86ca153 --- /dev/null +++ b/Resources/Locale/en-US/station-events/events/mouse-migration.ftl @@ -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. \ No newline at end of file diff --git a/Resources/Prototypes/Diseases/infectious.yml b/Resources/Prototypes/Diseases/infectious.yml index 067ce166b6..58f222c1f3 100644 --- a/Resources/Prototypes/Diseases/infectious.yml +++ b/Resources/Prototypes/Diseases/infectious.yml @@ -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 diff --git a/Resources/Prototypes/Entities/Clothing/Head/misc.yml b/Resources/Prototypes/Entities/Clothing/Head/misc.yml index 915c43b47f..cdbba6024d 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/misc.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/misc.yml @@ -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 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml new file mode 100644 index 0000000000..c6aa09c805 --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml @@ -0,0 +1,189 @@ +- type: entity + name: Rat King + id: MobRatKing + parent: SimpleMobBase + description: He's da rat. He make da roolz. + components: + - type: CombatMode + - type: MovementSpeedModifier + baseWalkSpeed : 3.75 + baseSprintSpeed : 3.75 + - type: UtilityAI + behaviorSets: + - Idle + - UnarmedAttackHostiles + - type: Reactive + groups: + Flammable: [Touch] + Extinguish: [Touch] + - type: AiFactionTag + factions: + - SimpleHostile + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Animals/regalrat.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: regalrat + - type: Physics + bodyType: KinematicController + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.25 + mass: 120 + mask: + - MobMask + layer: + - MobLayer + - type: MobState + thresholds: + 0: !type:NormalMobState {} + 150: !type:CriticalMobState {} + 200: !type:DeadMobState {} + - type: MeleeWeapon + range: 1 + arcwidth: 0 + arc: claw + damage: + types: + Slash: 12 + Piercing: 8 + - type: Appearance + visuals: + - type: DamageStateVisualizer + rotate: true + normal: regalrat + crit: dead + dead: dead + - type: Puller + - type: GhostTakeoverAvailable + makeSentient: true + name: Rat King + description: You are the Rat King, scavenge food in order to produce rat minions to do your bidding. + rules: You are an antagonist, scavenge, attack, and grow your hoarde! + - type: Tag + tags: + - CannotSuicide + - DoorBumpOpener + - FootstepSound + - type: NoSlip + - type: RatKing + actionRaiseArmy: + useDelay: 4 + icon: Interface/Actions/ratKingArmy.png + name: rat-king-raise-army-name + description: rat-king-raise-army-description + itemIconStyle: NoItem + event: !type:RatKingRaiseArmyActionEvent + hungerPerArmyUse: 25 + actionDomain: + useDelay: 10 + icon: Interface/Actions/ratKingDomain.png + name: rat-king-domain-name + description: rat-king-domain-description + itemIconStyle: NoItem + event: !type:RatKingDomainActionEvent + hungerPerDomainUse: 50 + - type: Access #he's so baller he gets his own access. NT got nothing on him + tags: + - Maintenance + - Service + - type: Butcherable + spawned: + - id: ClothingHeadHatFancyCrown #how did that get there? + amount: 1 + - type: DiseaseCarrier + carrierDiseases: + - Plague + - type: SlowOnDamage + speedModifierThresholds: + 50: 0.9 + 75: 0.8 + 100: 0.7 + - type: MobPrice + price: 2500 # rat wealth + +- type: entity + name: Rat Servant + id: MobRatServant + parent: SimpleMobBase + description: He's da mini rat. He don't make da roolz. + components: + - type: CombatMode + - type: MovementSpeedModifier + baseWalkSpeed : 4 + baseSprintSpeed : 4 + - type: UtilityAI + behaviorSets: + - Idle + - UnarmedAttackHostiles + - type: Reactive + groups: + Flammable: [Touch] + Extinguish: [Touch] + - type: AiFactionTag + factions: + - SimpleHostile + - type: Sprite + drawdepth: SmallMobs + sprite: Mobs/Animals/mouse.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: mouse-3 + - type: Physics + bodyType: KinematicController + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.2 + mass: 10 + mask: + - SmallMobMask + layer: + - SmallMobLayer + - type: MobState + thresholds: + 0: !type:NormalMobState {} + 25: !type:CriticalMobState {} + 50: !type:DeadMobState {} + - type: MeleeWeapon + range: 1 + arcwidth: 0 + arc: claw + damage: + types: + Slash: 5 + Piercing: 2 + - type: Appearance + visuals: + - type: DamageStateVisualizer + rotate: true + normal: mouse-3 + crit: dead-3 + dead: splat-3 + - type: Puller + - type: DiseaseCarrier + carrierDiseases: + - Plague + - type: Vocal + # mice are gender neutral who cares + maleScream: /Audio/Animals/mouse_squeak.ogg + femaleScream: /Audio/Animals/mouse_squeak.ogg + wilhelmProbability: 0.001 + - type: GhostTakeoverAvailable + makeSentient: true + name: Rat Servant + description: You are a Rat Servant. You must follow your king's orders. + rules: You are an antagonist, scavenge, attack, and serve your king! + - type: Tag + tags: + - CannotSuicide + - DoorBumpOpener + - FootstepSound + - type: NoSlip + - type: MobPrice + price: 500 # rat wealth + diff --git a/Resources/Textures/Clothing/Head/Misc/fancycrown.rsi/equipped-HELMET.png b/Resources/Textures/Clothing/Head/Misc/fancycrown.rsi/equipped-HELMET.png new file mode 100644 index 0000000000000000000000000000000000000000..e44fd7e7e2be2a1bd9d6352919d32aef4fcb07d8 GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|wtBiahE&XX zduyR!tAmL1Mf3ffSNL=j7Ak8wT{!ryVTqtl5_g24O!GejmxBJtqbh7u#S5KvBg^;g zKRqknJ1lZ?jOv=7leU~+yY7AZC)G^v=4s1rT)kkX}z$KbLh*2~7ajMP`)% literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Head/Misc/fancycrown.rsi/icon.png b/Resources/Textures/Clothing/Head/Misc/fancycrown.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f656459ea61b9aebd350703169ef8439fb1e24f6 GIT binary patch literal 598 zcmV-c0;&CpP)Px%5J^NqR9J=Wm9cBvKorJ*HgyNn455QbsIWa0Oon2-wT40`8%|It8Tu~-G8CM_ zv~w3jp+m3-uN{mDfr1LnU^;2_&_M*Ulp2!3gd1u+#HQCF+;OT?OKD=V=!4^-?@sr< z`|jxp5+q1)1Jp|eb*JJp*;jXxgcg^+qsHC*jgmLM#Vr)hTCBK8EJjdLw+Gv%k}5DFDUI+kJfit*rq60076w073r%i9!>#RT+((wYazdr?t$gssNpx z0FjXZe=`8$WAf<$0004WQchC4}r-&B#ap6?r7*{$Knq?Vj53k@ZA!RQo+ynfe`utfMkVmESf05?6E8a z%Nk%2v@Ey)cs|Xun1Gk+0A`|Wr!!PF>Lz>2+q>ZG^@SXx(i(f~0=X6EcN#W%NryoI9} zq*3uGO^X$x84<;7Ra<@UGqCAL#YOY+mrTyR%Cl6;fW7JO`LG?p^!PMy0mFX)=QveE iRs+>Q_WW-nebFBxrx4r=Q{prL00006TB<^TWBb~3tZEwIGUp0K;?d??hZGymjx|L&;h zg*gBA)Tq11lvE=U&a8|80004WQchCmDPcN3#$)I0Uc9^B z+;u13hi&>(jD5$_Z^0bE%ys9UZ8*L^^{37NfFOjA(#^y zhAaRQMKRU~IYK0)3nl1RlEm>aUsA>?4cT`<(*(#R$ySaNWM;gl6b4~4FFMqfTQkUJYZy(=Q2$q4e~+&C_!WZph6Kwq}<6}8fh8i zrD`aJDE2`35(puwOl6Wr*}f1EDF6>>5mi-lzLa^M14*Nz8;ic7Y)a8ob=6h~$zLE* z)O5qH;cyf+h+2JbDSxZ_m>*Ctx`wvT5mHrs!=WE+jt%YUw`-3Lo6|tu(wz4Djz*mK sJ5e;^DhDB&;&45<``E1v|Iml$4~nQd;i1%iN&o-=07*qoM6N<$f+`I#M*si- literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Animals/mouse.rsi/dead-3.png b/Resources/Textures/Mobs/Animals/mouse.rsi/dead-3.png new file mode 100644 index 0000000000000000000000000000000000000000..63c0d553acf74db1e0bd709cecbbc44e494be331 GIT binary patch literal 431 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Animals/regalrat.rsi/meta.json b/Resources/Textures/Mobs/Animals/regalrat.rsi/meta.json new file mode 100644 index 0000000000..98a5d7e891 --- /dev/null +++ b/Resources/Textures/Mobs/Animals/regalrat.rsi/meta.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from https://github.com/tgstation/tgstation/commit/53d1f1477d22a11a99c6c6924977cd431075761b", + "states": [ + { + "name": "dead" + }, + { + "name": "icon" + }, + { + "name": "regalrat", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Mobs/Animals/regalrat.rsi/regalrat.png b/Resources/Textures/Mobs/Animals/regalrat.rsi/regalrat.png new file mode 100644 index 0000000000000000000000000000000000000000..340c0b46dd4a5a6fe0913226bb4d030cf4f09706 GIT binary patch literal 3397 zcmV-L4Z8A)P)0J_zyboi$Pz>ddT)bH~0^5n?T59HZhI~9cA{{Dn~=b112ZE^*I@gErIm!_s> zDJdyY7nq)&mcG7oY4J}Q06Jd1x>3=dn3#~~zWt;WMn-?{x4t4{BO}_5Hai}dtb+jm zHEY(Y+wsRBR8&-`@_^9M(J3J>K5(B3|D*tbd3}9@B95tncDWaE%gW01{mjgaT)A>t z+S=BuU~AX5@HlHA82H7-#me`=g9kD>IjJ$gSH!c#nwlCJ@dhFl{z+RvWo4yQS69pM z@UY$^z^mWfEq^`PEhj$yNS_fG03a8H;{46d&ME*SBg3+4RlSb*=;(+nTUMu*P+MCo zQ&Uq(_q!kfpx@ZoB&DULI?@P15F`i@kw?ZS!LSO;_gy4^RiHrjCcdEI8eFOjI z<~2Io04~biyg8(8P#&KAUc5LcSgA7g+VahgB&;AQ3&7MtosRK8nBof69ZmAZ_B{D_ zf4c&MAjAaBkv7>P6vzFLf&Oc1YLyp*!n2ABtg}GDK@Qp^Yl%q#z=)#w>C>mw&+$c+ zJoKxh%E+CPh|X12Rcfj(rD6q^*1G&r3J@#^a?OAMG_GmK*aAq?LbMU)PcuRrs% zU&aLiU39eO3SV!yh5!GV*U?>CcHtaR;$2bu$HV%gLL%R zwi$J**49={dqMuxsZ&zr31R-nwE^+*zpnVqZDgMwro^%SrAkPx#%tcTXxx9xVrVK2euc&`k&c!ViyK_mYgIYSuH; zGg0Oa)zvLmp%{h9(4@92D=(AsigFKxIc1hqmd*3)#2_42i{V?Yc~0=f?-_aW68KeC zR>|_9MSWeZ0&d?X;u{wLl&8a82M(xj!BCMNn=`li`c+I#o_w6$}; z1&Db3V*(KLSw@urbm#VM@48qjD@r6Z5%SW`8qf4bWqNAbj{~>>%A0>KWcGuW=Ss0DE&!O6A;*1xf4=}i zZS7LMrgMT5@9et1p+POc-bfQ;o4qiU<_Jxi`%aQ2A_ zKrk9(ZZJWy=H_Ob1;R(X_<)rV?063I-rnAQzT;T=VkQn%;T!ps=fTlwQ zs=O(_(Cib}0xTMHZ9shQ;6a^(NqM1iZ!zL`RQTzX7?8oNV0K#knZOi>(wYULKRm3{ zVP|Kj-VyO3i|&jDL6Cf)qeFL!!`Ze1crYC^6&imVBnHQ(TQ?|XoCg?Vl<(^5(nxP< zFlJ^9P`0?ZNUen|aqHHtT>9}rG9WW`GEn$myLMIFe%;x^sBTrI^!4@m$ylQP;{sre zQN}X7lP6C)3SEe5Z>i_>^h|jB_U*D|%NAP^rUiuYrytyl1yOf*cg%j=k>*CHI^GU}>sbvR+6b_q|&RPqdAeDdp4x+>&)HK-{)Lg?Z+d!gEC#0bs>S z$lZeC`NY(1Iq>#zIrzeEea8JlHGET;wrp^4O&{C`i=Od#r%Gu7V9crhkfcOXQ(qvf z60vgo^`HJMHFc#@SGZQo*C-atoNW^XW!ZJ6PrhwjTjwQV%WeG;#Usc&9UxK$0OeuM zCJ9v-GDL*q8L29D0kSr(*-9rHqz#)Crf9srtrW(-Ki}EXmu+tQzNMvAc~ccKkf~Bd zHe|v%KOaCD8fL5tZNJ{CHgk)iPTioSNNMli`OW+C{b#>wM{42wg8m3f+W8PfKWW=nU$`n9`hVQQJ#_H`9fst4!-e* zS3#vO>(_V~Z&wyurl&$F9gx_xX|rE+L}9DhojG$_HgEo%jyAiu?9Wp`86O|lN)luv zyAaul4-Q^IRHIPX`ZTaV`Q$&^r)`V#9sMJtNR|&sxWd8Af{&TL5${SPn5pt{Bo1rWRmJVETrqkyVV%D!E3+R463?%&cvMr~~p0!u$Y+ zk@1$qp6M3(!u0ig5SH01vVZ>{U^F zc0cd;L7()^2-}7Tyy1x~_&;q;o{Rw4^VFBZ$KLxeYR=_Q1k8xKR(j^N$dV;X^uUB| zlt5IG#ys=q*o^k)DPkjqOhGH z1$BxG01e%Hi~M#*z?gJ(ZPgJWCIE~9)ZKkX-!EIbRPNlpt9{t241tck`Vn{g&%xyE*>1mG zYwNnG>M?@jF7DP;tWk*d-0G3=9*Yz|=^Mq*pMO-ELk4)*@f`yocs_yt(Ju&s4*)L? zKDS#AymNe>aHhB&inRHccz{p@s>_!zsbEBAtbu1{zUdNfL@c2eXv&%LoJ8RnvM}@T z3kWvV#ycW|jvo0SL|MRG9c@0*DGFi!WN9Qipl*i~P~LnT>%bMv|1;eZqfh$c)QJT@ zJ(zi*LD9|$o6nn@A~UkP(=DTa_}%var}>ZZLt7fv%H&Z4-+KV<)S7SB&!h;94*r{S&+?4A3Y+{gd4C? z6C`voD?mqAHwD0uq7f#8i3CTVYz$?Y=gs6TU0tGACw_e{u!0VJ`KgQ bEyI5S*=LKja|k+G00000NkvXXu0mjf3cHOO literal 0 HcmV?d00001