From 0e187aa895cc4754d0423e7eb4e1cb97da49fa89 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:32:44 -0700 Subject: [PATCH 01/21] Update Credits (#923) This is an automated Pull Request. This PR updates the GitHub contributors in the credits section. Co-authored-by: SimpleStation Changelogs --- Resources/Credits/GitHub.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index 1a2d582a05b..22e7aef8a92 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, angelofallars, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, beck-thompson, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlueHNT, Boaz1111, BobdaBiscuit, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, clorl, Clyybber, CodedCrow, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, Deeeeja, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, dootythefrooty, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, Evgencheg, exincore, exp111, Fahasor, FairlySadPanda, Fansana, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, geraeumig, Git-Nivrak, github-actions[bot], gituhabu, gluesniffler, GNF54, Golinth, GoodWheatley, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, HerCoyote23, HoofedEar, Hoolny, hord-brayden, hubismal, Hugal31, Huxellberger, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Mnemotechnician, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, nyeogmi, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, ShadowCommander, Shadowtheprotogen546, ShatteredSwords, SignalWalker, SimpleStation14, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, SleepyScarecrow, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, stalengd, Stealthbomber16, stellar-novas, StrawberryMoses, superjj18, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, Tmanzxd, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, wafehling, WarMechanic, waylon531, weaversam8, whateverusername0, Willhelm53, Winkarst-cpu, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem +0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, angelofallars, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, beck-thompson, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlueHNT, Boaz1111, BobdaBiscuit, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, CilliePaint, clorl, Clyybber, CodedCrow, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, Deeeeja, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, dootythefrooty, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, Evgencheg, exincore, exp111, Fahasor, FairlySadPanda, Fansana, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, geraeumig, Git-Nivrak, github-actions[bot], gituhabu, gluesniffler, GNF54, Golinth, GoodWheatley, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, HerCoyote23, HoofedEar, Hoolny, hord-brayden, hubismal, Hugal31, Huxellberger, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Mnemotechnician, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, notafet, notquitehadouken, noudoit, nuke-haus, NULL882, nyeogmi, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, ShadowCommander, Shadowtheprotogen546, ShatteredSwords, SignalWalker, SimpleStation14, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, SleepyScarecrow, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, stalengd, Stealthbomber16, stellar-novas, StrawberryMoses, superjj18, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, Tmanzxd, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, wafehling, WarMechanic, waylon531, weaversam8, whateverusername0, Willhelm53, Winkarst-cpu, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, ZNixian, ZoldorfTheWizard, Zumorica, Zymem From 49d128c3ae9634e0848c04bfbf2fbe988ed4ba46 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Sat, 21 Sep 2024 18:46:49 -0400 Subject: [PATCH 02/21] Reimplement Part Upgrading (#917) # Description By extremely popular demand(Both internally, and from our downstreams), this PR reimplements Part Upgrading. Since some of the systems that this PR touches were substantially changed since the removal of Parts, I had to do a lot of very in depth by-hand edits of individual systems. Shockingly, the only one that really proved any trouble was Cloning System, so I'm genuinely surprised wizden didn't substantially touch any of these codes since removing parts.. # Changelog :cl: - add: Part Upgrading has returned! --------- Signed-off-by: VMSolidus Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com> --- .../Interaction/MachineConstruction.cs | 1 - .../Interaction/InteractionTest.Constants.cs | 5 +- .../Anomaly/AnomalySystem.Vessel.cs | 7 + .../Binary/Components/GasRecyclerComponent.cs | 25 +- .../Binary/EntitySystems/GasRecyclerSystem.cs | 18 ++ .../Portable/PortableScrubberComponent.cs | 46 +++- .../Atmos/Portable/PortableScrubberSystem.cs | 18 ++ Content.Server/Bed/BedSystem.cs | 19 +- .../Bed/Components/StasisBedComponent.cs | 11 +- .../Components/SeedExtractorComponent.cs | 30 ++- .../Botany/Systems/SeedExtractorSystem.cs | 20 +- .../Cargo/Systems/CargoSystem.Telepad.cs | 15 ++ .../Components/SolutionHeaterComponent.cs | 22 +- .../EntitySystems/SolutionHeaterSystem.cs | 15 ++ Content.Server/Cloning/CloningSystem.cs | 20 ++ .../ConstructionSystem.Machine.cs | 5 +- .../Construction/PartExchangerSystem.cs | 3 +- .../Gravity/GravityGeneratorComponent.cs | 3 + .../Gravity/GravityGeneratorSystem.cs | 8 + .../Kitchen/Components/MicrowaveComponent.cs | 60 ++--- .../Components/ReagentGrinderComponent.cs | 21 +- .../Kitchen/EntitySystems/MicrowaveSystem.cs | 13 ++ .../EntitySystems/ReagentGrinderSystem.cs | 21 ++ .../Materials/MaterialReclaimerSystem.cs | 16 ++ .../BiomassReclaimerComponent.cs | 93 ++++++-- .../BiomassReclaimerSystem.cs | 23 ++ .../Components/MedicalScannerComponent.cs | 12 +- .../Medical/MedicalScannerSystem.cs | 15 ++ .../Components/FatExtractorComponent.cs | 65 ++++-- .../EntitySystems/FatExtractorSystem.cs | 15 ++ .../Components/UpgradeBatteryComponent.cs | 28 +++ .../Components/UpgradePowerDrawComponent.cs | 41 ++++ .../UpgradePowerSupplierComponent.cs | 36 +++ .../UpgradePowerSupplyRampingComponent.cs | 36 +++ .../EntitySystems/UpgradeBatterySystem.cs | 39 ++++ .../Power/EntitySystems/UpgradePowerSystem.cs | 151 ++++++++++++ .../Power/Generator/GeneratorSystem.cs | 7 +- .../Shuttles/Components/ThrusterComponent.cs | 28 ++- .../Shuttles/Systems/ThrusterSystem.cs | 22 ++ .../EntitySystems/EmitterSystem.cs | 17 ++ .../Components/TraversalDistorterComponent.cs | 17 +- .../Systems/TraversalDistorterSystem.cs | 20 +- .../XenoArtifacts/ArtifactSystem.cs | 1 + .../Components/SharedCargoTelepadComponent.cs | 35 ++- Content.Shared/Cloning/CloningPodComponent.cs | 25 ++ .../Construction/MachinePartSystem.cs | 15 ++ .../Materials/MaterialReclaimerComponent.cs | 81 ++++--- .../Components/SharedEmitterComponent.cs | 101 +++++--- Resources/Locale/en-US/anomaly/anomaly.ftl | 1 + .../en-US/atmos/gas-recycler-system.ftl | 3 + .../Locale/en-US/atmos/portable-scrubber.ftl | 3 + .../components/seed-extractor-component.ftl | 2 + .../en-US/cargo/cargo-console-component.ftl | 2 + .../components/solution-heater-component.ftl | 1 + .../components/machine-part-component.ftl | 2 + .../components/microwave-component.ftl | 1 + .../components/reagent-grinder-component.ftl | 3 + Resources/Locale/en-US/machine/machine.ftl | 5 + .../Locale/en-US/materials/materials.ftl | 3 + .../biomass-reclaimer-component.ftl | 3 + .../components/cloning-pod-component.ftl | 2 + .../components/medical-scanner-component.ftl | 2 + .../components/stasis-bed-component.ftl | 1 + .../nutrition/components/fat-extractor.ftl | 2 + Resources/Locale/en-US/shuttles/thruster.ftl | 2 + .../components/emitter-component.ftl | 3 + .../xenoarchaeology/traversal-distorter.ftl | 2 + Resources/Migrations/migration.yml | 22 -- .../Markers/Spawners/Random/salvage.yml | 93 +++++++- .../Entities/Objects/Misc/machine_parts.yml | 219 ++++++++++++++++++ .../Objects/Specific/Research/rped.yml | 3 + .../Entities/Structures/Dispensers/chem.yml | 3 + .../Structures/Machines/anomaly_equipment.yml | 4 +- .../Structures/Machines/anomaly_sync.yml | 5 +- .../Structures/Machines/artifact_analyzer.yml | 3 + .../Entities/Structures/Machines/lathe.yml | 6 + .../Structures/Machines/seed_extractor.yml | 3 + .../Power/Generation/portable_generator.yml | 6 + .../Entities/Structures/Power/smes.yml | 7 +- .../Entities/Structures/Power/substation.yml | 7 +- .../Structures/Shuttles/thrusters.yml | 5 + Resources/Prototypes/Guidebook/science.yml | 6 + Resources/Prototypes/Recipes/Lathes/Parts.yml | 60 +++++ .../Prototypes/Research/experimental.yml | 28 +++ .../XenoArch/Effects/normal_effects.yml | 18 ++ .../Guidebook/Science/MachineUpgrading.xml | 38 +++ 86 files changed, 1704 insertions(+), 220 deletions(-) create mode 100644 Content.Server/Power/Components/UpgradeBatteryComponent.cs create mode 100644 Content.Server/Power/Components/UpgradePowerDrawComponent.cs create mode 100644 Content.Server/Power/Components/UpgradePowerSupplierComponent.cs create mode 100644 Content.Server/Power/Components/UpgradePowerSupplyRampingComponent.cs create mode 100644 Content.Server/Power/EntitySystems/UpgradeBatterySystem.cs create mode 100644 Content.Server/Power/EntitySystems/UpgradePowerSystem.cs create mode 100644 Resources/Locale/en-US/chemistry/components/solution-heater-component.ftl create mode 100644 Resources/Locale/en-US/construction/components/machine-part-component.ftl create mode 100644 Resources/Locale/en-US/medical/components/stasis-bed-component.ftl create mode 100644 Resources/ServerInfo/Guidebook/Science/MachineUpgrading.xml diff --git a/Content.IntegrationTests/Tests/Construction/Interaction/MachineConstruction.cs b/Content.IntegrationTests/Tests/Construction/Interaction/MachineConstruction.cs index f52f820a4ce..cd95a85f205 100644 --- a/Content.IntegrationTests/Tests/Construction/Interaction/MachineConstruction.cs +++ b/Content.IntegrationTests/Tests/Construction/Interaction/MachineConstruction.cs @@ -57,4 +57,3 @@ public async Task ChangeMachine() AssertPrototype("Autolathe"); } } - diff --git a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Constants.cs b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Constants.cs index 11381fb8ccd..a915e5d47d1 100644 --- a/Content.IntegrationTests/Tests/Interaction/InteractionTest.Constants.cs +++ b/Content.IntegrationTests/Tests/Interaction/InteractionTest.Constants.cs @@ -1,3 +1,4 @@ + namespace Content.IntegrationTests.Tests.Interaction; // This partial class contains various constant prototype IDs common to interaction tests. @@ -27,8 +28,6 @@ public abstract partial class InteractionTest // Parts protected const string Bin1 = "MatterBinStockPart"; - protected const string Cap1 = "CapacitorStockPart"; protected const string Manipulator1 = "MicroManipulatorStockPart"; - protected const string Battery1 = "PowerCellSmall"; - protected const string Battery4 = "PowerCellHyper"; } + diff --git a/Content.Server/Anomaly/AnomalySystem.Vessel.cs b/Content.Server/Anomaly/AnomalySystem.Vessel.cs index 35de5c1a646..9a6c99f8208 100644 --- a/Content.Server/Anomaly/AnomalySystem.Vessel.cs +++ b/Content.Server/Anomaly/AnomalySystem.Vessel.cs @@ -1,4 +1,5 @@ using Content.Server.Anomaly.Components; +using Content.Server.Construction; using Content.Server.Power.EntitySystems; using Content.Shared.Anomaly; using Content.Shared.Anomaly.Components; @@ -20,6 +21,7 @@ private void InitializeVessel() { SubscribeLocalEvent(OnVesselShutdown); SubscribeLocalEvent(OnVesselMapInit); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnVesselInteractUsing); SubscribeLocalEvent(OnExamined); SubscribeLocalEvent(OnVesselGetPointsPerSecond); @@ -65,6 +67,11 @@ private void OnVesselMapInit(EntityUid uid, AnomalyVesselComponent component, Ma UpdateVesselAppearance(uid, component); } + private void OnUpgradeExamine(EntityUid uid, AnomalyVesselComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("anomaly-vessel-component-upgrade-output", component.PointMultiplier); + } + private void OnVesselInteractUsing(EntityUid uid, AnomalyVesselComponent component, InteractUsingEvent args) { if (component.Anomaly != null || diff --git a/Content.Server/Atmos/Piping/Binary/Components/GasRecyclerComponent.cs b/Content.Server/Atmos/Piping/Binary/Components/GasRecyclerComponent.cs index e1eb0072b9d..aa7e3e0b360 100644 --- a/Content.Server/Atmos/Piping/Binary/Components/GasRecyclerComponent.cs +++ b/Content.Server/Atmos/Piping/Binary/Components/GasRecyclerComponent.cs @@ -1,11 +1,12 @@ using Content.Shared.Atmos; +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Atmos.Piping.Binary.Components { [RegisterComponent] public sealed partial class GasRecyclerComponent : Component { - [ViewVariables(VVAccess.ReadOnly)] [DataField("reacting")] public Boolean Reacting { get; set; } = false; @@ -17,10 +18,28 @@ public sealed partial class GasRecyclerComponent : Component [DataField("outlet")] public string OutletName { get; set; } = "outlet"; - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public float MinTemp = 300 + Atmospherics.T0C; - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] + public float BaseMinTemp = 300 + Atmospherics.T0C; + + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartMinTemp = "Capacitor"; + + [DataField] + public float PartRatingMinTempMultiplier = 0.95f; + + [ViewVariables(VVAccess.ReadWrite)] public float MinPressure = 30 * Atmospherics.OneAtmosphere; + + [DataField] + public float BaseMinPressure = 30 * Atmospherics.OneAtmosphere; + + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartMinPressure = "Manipulator"; + + [DataField] + public float PartRatingMinPressureMultiplier = 0.8f; } } diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs index 3ebc5094926..40b9d88846f 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs @@ -1,6 +1,7 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Piping.Binary.Components; using Content.Server.Atmos.Piping.Components; +using Content.Server.Construction; using Content.Server.NodeContainer; using Content.Server.NodeContainer.EntitySystems; using Content.Server.NodeContainer.Nodes; @@ -28,6 +29,8 @@ public override void Initialize() SubscribeLocalEvent(OnUpdate); SubscribeLocalEvent(OnDisabled); SubscribeLocalEvent(OnExamined); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); } private void OnEnabled(EntityUid uid, GasRecyclerComponent comp, ref AtmosDeviceEnabledEvent args) @@ -116,5 +119,20 @@ private void UpdateAppearance(EntityUid uid, GasRecyclerComponent? comp = null) _appearance.SetData(uid, PumpVisuals.Enabled, comp.Reacting); } + + private void OnRefreshParts(EntityUid uid, GasRecyclerComponent component, RefreshPartsEvent args) + { + var ratingTemp = args.PartRatings[component.MachinePartMinTemp]; + var ratingPressure = args.PartRatings[component.MachinePartMinPressure]; + + component.MinTemp = component.BaseMinTemp * MathF.Pow(component.PartRatingMinTempMultiplier, ratingTemp - 1); + component.MinPressure = component.BaseMinPressure * MathF.Pow(component.PartRatingMinPressureMultiplier, ratingPressure - 1); + } + + private void OnUpgradeExamine(EntityUid uid, GasRecyclerComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("gas-recycler-upgrade-min-temp", component.MinTemp / component.BaseMinTemp); + args.AddPercentageUpgrade("gas-recycler-upgrade-min-pressure", component.MinPressure / component.BaseMinPressure); + } } } diff --git a/Content.Server/Atmos/Portable/PortableScrubberComponent.cs b/Content.Server/Atmos/Portable/PortableScrubberComponent.cs index ae9a5da9639..fbe2d3f95a0 100644 --- a/Content.Server/Atmos/Portable/PortableScrubberComponent.cs +++ b/Content.Server/Atmos/Portable/PortableScrubberComponent.cs @@ -1,4 +1,6 @@ using Content.Shared.Atmos; +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Atmos.Portable { @@ -37,13 +39,51 @@ public sealed partial class PortableScrubberComponent : Component /// /// Maximum internal pressure before it refuses to take more. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public float MaxPressure = 2500; /// - /// The speed at which gas is scrubbed from the environment. + /// The base amount of maximum internal pressure /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] + public float BaseMaxPressure = 2500; + + /// + /// The machine part that modifies the maximum internal pressure + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartMaxPressure = "MatterBin"; + + /// + /// How much the will affect the pressure. + /// The value will be multiplied by this amount for each increasing part tier. + /// + [DataField] + public float PartRatingMaxPressureModifier = 1.5f; + + /// + /// The speed at which gas is scrubbed from the environment. + /// + [ViewVariables(VVAccess.ReadWrite)] public float TransferRate = 800; + + /// + /// The base speed at which gas is scrubbed from the environment. + /// + [DataField] + public float BaseTransferRate = 800; + + /// + /// The machine part which modifies the speed of + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartTransferRate = "Manipulator"; + + /// + /// How much the will modify the rate. + /// The value will be multiplied by this amount for each increasing part tier. + /// + [DataField] + public float PartRatingTransferRateModifier = 1.4f; } } diff --git a/Content.Server/Atmos/Portable/PortableScrubberSystem.cs b/Content.Server/Atmos/Portable/PortableScrubberSystem.cs index f9043c091a8..f657d713d28 100644 --- a/Content.Server/Atmos/Portable/PortableScrubberSystem.cs +++ b/Content.Server/Atmos/Portable/PortableScrubberSystem.cs @@ -12,6 +12,7 @@ using Content.Server.NodeContainer.NodeGroups; using Content.Server.Audio; using Content.Server.Administration.Logs; +using Content.Server.Construction; using Content.Server.NodeContainer.EntitySystems; using Content.Shared.Database; @@ -38,6 +39,8 @@ public override void Initialize() SubscribeLocalEvent(OnExamined); SubscribeLocalEvent(OnDestroyed); SubscribeLocalEvent(OnScrubberAnalyzed); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); } private bool IsFull(PortableScrubberComponent component) @@ -156,5 +159,20 @@ private void OnScrubberAnalyzed(EntityUid uid, PortableScrubberComponent compone if (_nodeContainer.TryGetNode(uid, component.PortName, out PipeNode? port)) args.GasMixtures.Add(component.PortName, port.Air); } + + private void OnRefreshParts(EntityUid uid, PortableScrubberComponent component, RefreshPartsEvent args) + { + var pressureRating = args.PartRatings[component.MachinePartMaxPressure]; + var transferRating = args.PartRatings[component.MachinePartTransferRate]; + + component.MaxPressure = component.BaseMaxPressure * MathF.Pow(component.PartRatingMaxPressureModifier, pressureRating - 1); + component.TransferRate = component.BaseTransferRate * MathF.Pow(component.PartRatingTransferRateModifier, transferRating - 1); + } + + private void OnUpgradeExamine(EntityUid uid, PortableScrubberComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("portable-scrubber-component-upgrade-max-pressure", component.MaxPressure / component.BaseMaxPressure); + args.AddPercentageUpgrade("portable-scrubber-component-upgrade-transfer-rate", component.TransferRate / component.BaseTransferRate); + } } } diff --git a/Content.Server/Bed/BedSystem.cs b/Content.Server/Bed/BedSystem.cs index f1bd9482e5e..976ef5139c3 100644 --- a/Content.Server/Bed/BedSystem.cs +++ b/Content.Server/Bed/BedSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Bed.Components; using Content.Server.Bed.Sleep; using Content.Server.Body.Systems; +using Content.Server.Construction; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Shared.Bed; @@ -9,6 +10,7 @@ using Content.Shared.Body.Components; using Content.Shared.Buckle.Components; using Content.Shared.Damage; +using Content.Shared.Emag.Components; using Content.Shared.Emag.Systems; using Content.Shared.Mobs.Systems; using Robust.Shared.Timing; @@ -32,6 +34,8 @@ public override void Initialize() SubscribeLocalEvent(OnBuckleChange); SubscribeLocalEvent(OnPowerChanged); SubscribeLocalEvent(OnEmagged); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); } private void ManageUpdateList(EntityUid uid, HealOnBuckleComponent component, ref BuckleChangeEvent args) @@ -66,7 +70,7 @@ public override void Update(float frameTime) foreach (var healedEntity in strapComponent.BuckledEntities) { - if (_mobStateSystem.IsDead(healedEntity) + if (_mobStateSystem.IsDead(healedEntity) || HasComp(healedEntity)) continue; @@ -126,5 +130,18 @@ private void UpdateMetabolisms(EntityUid uid, StasisBedComponent component, bool RaiseLocalEvent(buckledEntity, ref metabolicEvent); } } + + private void OnRefreshParts(EntityUid uid, StasisBedComponent component, RefreshPartsEvent args) + { + var metabolismRating = args.PartRatings[component.MachinePartMetabolismModifier]; + component.Multiplier = component.BaseMultiplier * metabolismRating; // Linear scaling so it's not OP + if (HasComp(uid)) + component.Multiplier = 1f / component.Multiplier; + } + + private void OnUpgradeExamine(EntityUid uid, StasisBedComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("stasis-bed-component-upgrade-stasis", component.Multiplier / component.BaseMultiplier); + } } } diff --git a/Content.Server/Bed/Components/StasisBedComponent.cs b/Content.Server/Bed/Components/StasisBedComponent.cs index e2175d6e646..bb4096a2a5e 100644 --- a/Content.Server/Bed/Components/StasisBedComponent.cs +++ b/Content.Server/Bed/Components/StasisBedComponent.cs @@ -1,12 +1,21 @@ +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + namespace Content.Server.Bed.Components { [RegisterComponent] public sealed partial class StasisBedComponent : Component { + [DataField] + public float BaseMultiplier = 10f; + /// - /// What the metabolic update rate will be multiplied by (higher = slower metabolism) + /// What the metabolic update rate will be multiplied by (higher = slower metabolism) /// [ViewVariables(VVAccess.ReadWrite)] public float Multiplier = 10f; + + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartMetabolismModifier = "Capacitor"; } } diff --git a/Content.Server/Botany/Components/SeedExtractorComponent.cs b/Content.Server/Botany/Components/SeedExtractorComponent.cs index ddb04f213d1..d765e079cec 100644 --- a/Content.Server/Botany/Components/SeedExtractorComponent.cs +++ b/Content.Server/Botany/Components/SeedExtractorComponent.cs @@ -1,4 +1,7 @@ using Content.Server.Botany.Systems; +using Content.Server.Construction; +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Botany.Components; @@ -7,14 +10,33 @@ namespace Content.Server.Botany.Components; public sealed partial class SeedExtractorComponent : Component { /// - /// The minimum amount of seed packets dropped. + /// The minimum amount of seed packets dropped with no machine upgrades. /// - [DataField("baseMinSeeds"), ViewVariables(VVAccess.ReadWrite)] + [DataField] public int BaseMinSeeds = 1; /// - /// The maximum amount of seed packets dropped. + /// The maximum amount of seed packets dropped with no machine upgrades. /// - [DataField("baseMaxSeeds"), ViewVariables(VVAccess.ReadWrite)] + [DataField] public int BaseMaxSeeds = 3; + + /// + /// Modifier to the amount of seeds outputted, set on . + /// + [ViewVariables(VVAccess.ReadWrite)] + public float SeedAmountMultiplier; + + /// + /// Machine part whose rating modifies the amount of seed packets dropped. + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartSeedAmount = "Manipulator"; + + /// + /// How much the machine part quality affects the amount of seeds outputted. + /// Going up a tier will multiply the seed output by this amount. + /// + [DataField] + public float PartRatingSeedAmountMultiplier = 1.5f; } diff --git a/Content.Server/Botany/Systems/SeedExtractorSystem.cs b/Content.Server/Botany/Systems/SeedExtractorSystem.cs index f1ae6c9f11a..4c547b96f09 100644 --- a/Content.Server/Botany/Systems/SeedExtractorSystem.cs +++ b/Content.Server/Botany/Systems/SeedExtractorSystem.cs @@ -1,8 +1,10 @@ using Content.Server.Botany.Components; +using Content.Server.Construction; using Content.Server.Popups; using Content.Server.Power.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Popups; +using Robust.Shared.Player; using Robust.Shared.Random; namespace Content.Server.Botany.Systems; @@ -18,6 +20,8 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnInteractUsing); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); } private void OnInteractUsing(EntityUid uid, SeedExtractorComponent seedExtractor, InteractUsingEvent args) @@ -25,8 +29,7 @@ private void OnInteractUsing(EntityUid uid, SeedExtractorComponent seedExtractor if (!this.IsPowered(uid, EntityManager)) return; - if (!TryComp(args.Used, out ProduceComponent? produce)) - return; + if (!TryComp(args.Used, out ProduceComponent? produce)) return; if (!_botanySystem.TryGetSeed(produce, out var seed) || seed.Seedless) { _popupSystem.PopupCursor(Loc.GetString("seed-extractor-component-no-seeds",("name", args.Used)), @@ -39,7 +42,7 @@ private void OnInteractUsing(EntityUid uid, SeedExtractorComponent seedExtractor QueueDel(args.Used); - var amount = _random.Next(seedExtractor.BaseMinSeeds, seedExtractor.BaseMaxSeeds + 1); + var amount = (int) _random.NextFloat(seedExtractor.BaseMinSeeds, seedExtractor.BaseMaxSeeds + 1) * seedExtractor.SeedAmountMultiplier; var coords = Transform(uid).Coordinates; if (amount > 1) @@ -50,4 +53,15 @@ private void OnInteractUsing(EntityUid uid, SeedExtractorComponent seedExtractor _botanySystem.SpawnSeedPacket(seed, coords, args.User); } } + + private void OnRefreshParts(EntityUid uid, SeedExtractorComponent seedExtractor, RefreshPartsEvent args) + { + var manipulatorQuality = args.PartRatings[seedExtractor.MachinePartSeedAmount]; + seedExtractor.SeedAmountMultiplier = MathF.Pow(seedExtractor.PartRatingSeedAmountMultiplier, manipulatorQuality - 1); + } + + private void OnUpgradeExamine(EntityUid uid, SeedExtractorComponent seedExtractor, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("seed-extractor-component-upgrade-seed-yield", seedExtractor.SeedAmountMultiplier); + } } diff --git a/Content.Server/Cargo/Systems/CargoSystem.Telepad.cs b/Content.Server/Cargo/Systems/CargoSystem.Telepad.cs index 42aabf2578e..1c25b0e79d2 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.Telepad.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.Telepad.cs @@ -1,4 +1,6 @@ using Content.Server.Cargo.Components; +using Content.Server.Construction; +using Content.Server.Paper; using Content.Server.Power.Components; using Content.Shared.Cargo; using Content.Shared.Cargo.Components; @@ -13,6 +15,8 @@ public sealed partial class CargoSystem private void InitializeTelepad() { SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnTelepadPowerChange); // Shouldn't need re-anchored event SubscribeLocalEvent(OnTelepadAnchorChange); @@ -79,6 +83,17 @@ private void OnInit(EntityUid uid, CargoTelepadComponent telepad, ComponentInit _linker.EnsureSinkPorts(uid, telepad.ReceiverPort); } + private void OnRefreshParts(EntityUid uid, CargoTelepadComponent component, RefreshPartsEvent args) + { + var rating = args.PartRatings[component.MachinePartTeleportDelay] - 1; + component.Delay = component.BaseDelay * MathF.Pow(component.PartRatingTeleportDelay, rating); + } + + private void OnUpgradeExamine(EntityUid uid, CargoTelepadComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("cargo-telepad-delay-upgrade", component.Delay / component.BaseDelay); + } + private void SetEnabled(EntityUid uid, CargoTelepadComponent component, ApcPowerReceiverComponent? receiver = null, TransformComponent? xform = null) { diff --git a/Content.Server/Chemistry/Components/SolutionHeaterComponent.cs b/Content.Server/Chemistry/Components/SolutionHeaterComponent.cs index c1841e022c7..bc1d44e82f1 100644 --- a/Content.Server/Chemistry/Components/SolutionHeaterComponent.cs +++ b/Content.Server/Chemistry/Components/SolutionHeaterComponent.cs @@ -4,8 +4,26 @@ namespace Content.Server.Chemistry.Components; public sealed partial class SolutionHeaterComponent : Component { /// - /// How much heat is added per second to the solution, taking upgrades into account. + /// How much heat is added per second to the solution, with no upgrades. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] + public float BaseHeatPerSecond = 120; + + /// + /// How much heat is added per second to the solution, taking upgrades into account. + /// + [ViewVariables(VVAccess.ReadWrite)] public float HeatPerSecond; + + /// + /// The machine part that affects the heat multiplier. + /// + [DataField] + public string MachinePartHeatMultiplier = "Capacitor"; + + /// + /// How much each upgrade multiplies the heat by. + /// + [DataField] + public float PartRatingHeatMultiplier = 1.5f; } diff --git a/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs index 6e6373e10bf..1ef589ab5cb 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionHeaterSystem.cs @@ -1,5 +1,6 @@ using Content.Server.Chemistry.Components; using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Server.Construction; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Shared.Chemistry; @@ -20,6 +21,8 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnPowerChanged); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnItemPlaced); SubscribeLocalEvent(OnItemRemoved); } @@ -61,6 +64,18 @@ private void OnPowerChanged(Entity entity, ref PowerCha } } + private void OnRefreshParts(Entity entity, ref RefreshPartsEvent args) + { + var heatRating = args.PartRatings[entity.Comp.MachinePartHeatMultiplier] - 1; + + entity.Comp.HeatPerSecond = entity.Comp.BaseHeatPerSecond * MathF.Pow(entity.Comp.PartRatingHeatMultiplier, heatRating); + } + + private void OnUpgradeExamine(Entity entity, ref UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("solution-heater-upgrade-heat", entity.Comp.HeatPerSecond / entity.Comp.BaseHeatPerSecond); + } + private void OnItemPlaced(Entity entity, ref ItemPlacedEvent args) { TryTurnOn(entity); diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index 7931fae4778..72104bc381f 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -1,6 +1,7 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.Chat.Systems; using Content.Server.Cloning.Components; +using Content.Server.Construction; using Content.Server.DeviceLinking.Systems; using Content.Server.EUI; using Content.Server.Fluids.EntitySystems; @@ -9,6 +10,10 @@ using Content.Server.Materials; using Content.Server.Popups; using Content.Server.Power.EntitySystems; +using Content.Server.Traits.Assorted; +using Content.Shared.Atmos; +using Content.Shared.CCVar; +using Content.Shared.Chemistry.Components; using Content.Shared.Cloning; using Content.Shared.Damage; using Content.Shared.DeviceLinking.Events; @@ -90,8 +95,23 @@ public override void Initialize() SubscribeLocalEvent(OnExamined); SubscribeLocalEvent(OnEmagged); SubscribeLocalEvent(OnPowerChanged); + SubscribeLocalEvent(OnPartsRefreshed); + SubscribeLocalEvent(OnUpgradeExamine); + } + private void OnPartsRefreshed(EntityUid uid, CloningPodComponent component, RefreshPartsEvent args) + { + var materialRating = args.PartRatings[component.MachinePartMaterialUse]; + var speedRating = args.PartRatings[component.MachinePartCloningSpeed]; + + component.BiomassCostMultiplier = MathF.Pow(component.PartRatingMaterialMultiplier, materialRating - 1); + component.CloningTime = component.CloningTime * MathF.Pow(component.PartRatingSpeedMultiplier, speedRating - 1); } + private void OnUpgradeExamine(EntityUid uid, CloningPodComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("cloning-pod-component-upgrade-speed", component.CloningTime / component.CloningTime); + args.AddPercentageUpgrade("cloning-pod-component-upgrade-biomass-requirement", component.BiomassCostMultiplier); + } private void OnPortDisconnected(EntityUid uid, CloningPodComponent pod, PortDisconnectedEvent args) { pod.ConnectedConsole = null; diff --git a/Content.Server/Construction/ConstructionSystem.Machine.cs b/Content.Server/Construction/ConstructionSystem.Machine.cs index 2e670dbe40d..65b0b704761 100644 --- a/Content.Server/Construction/ConstructionSystem.Machine.cs +++ b/Content.Server/Construction/ConstructionSystem.Machine.cs @@ -5,6 +5,7 @@ using Content.Shared.Construction.Prototypes; using Content.Shared.Verbs; using Robust.Shared.Containers; +using Robust.Shared.Map.Components; using Robust.Shared.Utility; namespace Content.Server.Construction; @@ -143,7 +144,7 @@ private void CreateBoardAndStockParts(EntityUid uid, MachineComponent component) var p = EntityManager.SpawnEntity(partProto.StockPartPrototype, xform.Coordinates); if (!_container.Insert(p, partContainer)) - throw new Exception($"Couldn't insert machine part of type {part} to machine with prototype {partProto.StockPartPrototype}!"); + throw new Exception($"Couldn't insert machine part of type {part} to machine with prototype {partProto.StockPartPrototype ?? "N/A"}!"); } } @@ -183,7 +184,7 @@ public sealed class RefreshPartsEvent : EntityEventArgs { public IReadOnlyList Parts = new List(); - public Dictionary PartRatings = new(); + public Dictionary PartRatings = new Dictionary(); } public sealed class UpgradeExamineEvent : EntityEventArgs diff --git a/Content.Server/Construction/PartExchangerSystem.cs b/Content.Server/Construction/PartExchangerSystem.cs index ee5edcbd0a0..f364d1b547d 100644 --- a/Content.Server/Construction/PartExchangerSystem.cs +++ b/Content.Server/Construction/PartExchangerSystem.cs @@ -10,6 +10,7 @@ using Robust.Shared.Containers; using Robust.Shared.Utility; using Content.Shared.Wires; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Collections; @@ -42,7 +43,7 @@ private void OnDoAfter(EntityUid uid, PartExchangerComponent component, DoAfterE if (args.Handled || args.Args.Target == null) return; - if (!TryComp(uid, out var storage)) + if (!TryComp(uid, out var storage) || storage.Container == null) return; //the parts are stored in here var machinePartQuery = GetEntityQuery(); diff --git a/Content.Server/Gravity/GravityGeneratorComponent.cs b/Content.Server/Gravity/GravityGeneratorComponent.cs index f9462920384..f47d3979391 100644 --- a/Content.Server/Gravity/GravityGeneratorComponent.cs +++ b/Content.Server/Gravity/GravityGeneratorComponent.cs @@ -37,6 +37,9 @@ public sealed partial class GravityGeneratorComponent : SharedGravityGeneratorCo // 0 -> 1 [ViewVariables(VVAccess.ReadWrite)] [DataField("charge")] public float Charge { get; set; } = 1; + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartMaxChargeMultiplier = "Capacitor"; + /// /// Is the gravity generator currently "producing" gravity? /// diff --git a/Content.Server/Gravity/GravityGeneratorSystem.cs b/Content.Server/Gravity/GravityGeneratorSystem.cs index ec5646457e2..b1696e6a713 100644 --- a/Content.Server/Gravity/GravityGeneratorSystem.cs +++ b/Content.Server/Gravity/GravityGeneratorSystem.cs @@ -1,5 +1,6 @@ using Content.Server.Administration.Logs; using Content.Server.Audio; +using Content.Server.Construction; using Content.Server.Power.Components; using Content.Server.Emp; using Content.Shared.Database; @@ -27,6 +28,7 @@ public override void Initialize() SubscribeLocalEvent(OnComponentShutdown); SubscribeLocalEvent(OnParentChanged); // Or just anchor changed? SubscribeLocalEvent(OnInteractHand); + SubscribeLocalEvent(OnRefreshParts); SubscribeLocalEvent( OnSwitchGenerator); @@ -257,6 +259,12 @@ public void UpdateState(Entity ent, AppearanceComponent? appearance) { _ambientSoundSystem.SetAmbience(ent, false); diff --git a/Content.Server/Kitchen/Components/MicrowaveComponent.cs b/Content.Server/Kitchen/Components/MicrowaveComponent.cs index 815ba8f5213..1e343e5e332 100644 --- a/Content.Server/Kitchen/Components/MicrowaveComponent.cs +++ b/Content.Server/Kitchen/Components/MicrowaveComponent.cs @@ -11,95 +11,99 @@ namespace Content.Server.Kitchen.Components [RegisterComponent] public sealed partial class MicrowaveComponent : Component { - [DataField("cookTimeMultiplier"), ViewVariables(VVAccess.ReadWrite)] + [DataField] public float CookTimeMultiplier = 1; - - [DataField("baseHeatMultiplier"), ViewVariables(VVAccess.ReadWrite)] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartCookTimeMultiplier = "Capacitor"; + [DataField] + public float CookTimeScalingConstant = 0.5f; + [DataField] public float BaseHeatMultiplier = 100; - [DataField("objectHeatMultiplier"), ViewVariables(VVAccess.ReadWrite)] + [DataField] public float ObjectHeatMultiplier = 100; - [DataField("failureResult", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string BadRecipeEntityId = "FoodBadRecipe"; #region audio - [DataField("beginCookingSound")] + [DataField] public SoundSpecifier StartCookingSound = new SoundPathSpecifier("/Audio/Machines/microwave_start_beep.ogg"); - [DataField("foodDoneSound")] + [DataField] public SoundSpecifier FoodDoneSound = new SoundPathSpecifier("/Audio/Machines/microwave_done_beep.ogg"); - [DataField("clickSound")] + [DataField] public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"); - [DataField("ItemBreakSound")] + [DataField] public SoundSpecifier ItemBreakSound = new SoundPathSpecifier("/Audio/Effects/clang.ogg"); public EntityUid? PlayingStream; - [DataField("loopingSound")] + [DataField] public SoundSpecifier LoopingSound = new SoundPathSpecifier("/Audio/Machines/microwave_loop.ogg"); #endregion [ViewVariables] public bool Broken; - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public ProtoId OnPort = "On"; /// - /// This is a fixed offset of 5. - /// The cook times for all recipes should be divisible by 5,with a minimum of 1 second. - /// For right now, I don't think any recipe cook time should be greater than 60 seconds. + /// This is a fixed offset of 5. + /// The cook times for all recipes should be divisible by 5,with a minimum of 1 second. + /// For right now, I don't think any recipe cook time should be greater than 60 seconds. /// - [DataField("currentCookTimerTime"), ViewVariables(VVAccess.ReadWrite)] + [DataField] public uint CurrentCookTimerTime = 0; /// - /// Tracks the elapsed time of the current cook timer. + /// Tracks the elapsed time of the current cook timer. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public TimeSpan CurrentCookTimeEnd = TimeSpan.Zero; /// - /// The maximum number of seconds a microwave can be set to. - /// This is currently only used for validation and the client does not check this. + /// The maximum number of seconds a microwave can be set to. + /// This is currently only used for validation and the client does not check this. /// - [DataField("maxCookTime"), ViewVariables(VVAccess.ReadWrite)] + [DataField] public uint MaxCookTime = 30; /// /// The max temperature that this microwave can heat objects to. /// - [DataField("temperatureUpperThreshold")] + [DataField] public float TemperatureUpperThreshold = 373.15f; public int CurrentCookTimeButtonIndex; public Container Storage = default!; - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public int Capacity = 10; - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public ProtoId MaxItemSize = "Normal"; /// - /// How frequently the microwave can malfunction. + /// How frequently the microwave can malfunction. /// [DataField] public float MalfunctionInterval = 1.0f; /// - /// Chance of an explosion occurring when we microwave a metallic object + /// Chance of an explosion occurring when we microwave a metallic object /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public float ExplosionChance = .1f; /// - /// Chance of lightning occurring when we microwave a metallic object - [DataField, ViewVariables(VVAccess.ReadWrite)] + /// Chance of lightning occurring when we microwave a metallic object + /// + [DataField] public float LightningChance = .75f; } diff --git a/Content.Server/Kitchen/Components/ReagentGrinderComponent.cs b/Content.Server/Kitchen/Components/ReagentGrinderComponent.cs index 5bbbe2dc8da..4f4531206c7 100644 --- a/Content.Server/Kitchen/Components/ReagentGrinderComponent.cs +++ b/Content.Server/Kitchen/Components/ReagentGrinderComponent.cs @@ -1,6 +1,8 @@ using Content.Shared.Kitchen; using Content.Server.Kitchen.EntitySystems; +using Content.Shared.Construction.Prototypes; using Robust.Shared.Audio; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Kitchen.Components { @@ -13,15 +15,30 @@ namespace Content.Server.Kitchen.Components [Access(typeof(ReagentGrinderSystem)), RegisterComponent] public sealed partial class ReagentGrinderComponent : Component { - [DataField] + [ViewVariables(VVAccess.ReadWrite)] public int StorageMaxEntities = 6; [DataField] - public TimeSpan WorkTime = TimeSpan.FromSeconds(3.5); // Roughly matches the grind/juice sounds. + public int BaseStorageMaxEntities = 4; + + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartStorageMax = "MatterBin"; + + [DataField] + public int StoragePerPartRating = 4; [DataField] + public TimeSpan WorkTime = TimeSpan.FromSeconds(3.5); // Roughly matches the grind/juice sounds. + + [ViewVariables(VVAccess.ReadWrite)] public float WorkTimeMultiplier = 1; + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartWorkTime = "Manipulator"; + + [DataField] + public float PartRatingWorkTimerMulitplier = 0.6f; + [DataField] public SoundSpecifier ClickSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"); diff --git a/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs b/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs index 212383c463a..3de7051f54d 100644 --- a/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs @@ -76,6 +76,8 @@ public override void Initialize() SubscribeLocalEvent(OnPowerChanged); SubscribeLocalEvent(OnAnchorChanged); SubscribeLocalEvent(OnSuicide); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnSignalReceived); @@ -342,6 +344,17 @@ private void OnAnchorChanged(EntityUid uid, MicrowaveComponent component, ref An _container.EmptyContainer(component.Storage); } + private void OnRefreshParts(Entity ent, ref RefreshPartsEvent args) + { + var cookRating = args.PartRatings[ent.Comp.MachinePartCookTimeMultiplier]; + ent.Comp.CookTimeMultiplier = MathF.Pow(ent.Comp.CookTimeScalingConstant, cookRating - 1); + } + + private void OnUpgradeExamine(Entity ent, ref UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("microwave-component-upgrade-cook-time", ent.Comp.CookTimeMultiplier); + } + private void OnSignalReceived(Entity ent, ref SignalReceivedEvent args) { if (args.Port != ent.Comp.OnPort) diff --git a/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs b/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs index e8ee4539860..aad33fea678 100644 --- a/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/ReagentGrinderSystem.cs @@ -1,4 +1,5 @@ using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Server.Construction; using Content.Server.Kitchen.Components; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; @@ -48,6 +49,8 @@ public override void Initialize() SubscribeLocalEvent((uid, _, _) => UpdateUiState(uid)); SubscribeLocalEvent((EntityUid uid, ReagentGrinderComponent _, ref PowerChangedEvent _) => UpdateUiState(uid)); SubscribeLocalEvent(OnInteractUsing); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnContainerModified); SubscribeLocalEvent(OnContainerModified); @@ -197,6 +200,24 @@ private void OnInteractUsing(Entity entity, ref Interac args.Handled = true; } + /// + /// Gotta be efficient, you know? you're saving a whole extra second here and everything. + /// + private void OnRefreshParts(Entity entity, ref RefreshPartsEvent args) + { + var ratingWorkTime = args.PartRatings[entity.Comp.MachinePartWorkTime]; + var ratingStorage = args.PartRatings[entity.Comp.MachinePartStorageMax]; + + entity.Comp.WorkTimeMultiplier = MathF.Pow(entity.Comp.PartRatingWorkTimerMulitplier, ratingWorkTime - 1); + entity.Comp.StorageMaxEntities = entity.Comp.BaseStorageMaxEntities + (int) (entity.Comp.StoragePerPartRating * (ratingStorage - 1)); + } + + private void OnUpgradeExamine(Entity entity, ref UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("reagent-grinder-component-upgrade-work-time", entity.Comp.WorkTimeMultiplier); + args.AddNumberUpgrade("reagent-grinder-component-upgrade-storage", entity.Comp.StorageMaxEntities - entity.Comp.BaseStorageMaxEntities); + } + private void UpdateUiState(EntityUid uid) { ReagentGrinderComponent? grinderComp = null; diff --git a/Content.Server/Materials/MaterialReclaimerSystem.cs b/Content.Server/Materials/MaterialReclaimerSystem.cs index aa24fde44b7..de82f125985 100644 --- a/Content.Server/Materials/MaterialReclaimerSystem.cs +++ b/Content.Server/Materials/MaterialReclaimerSystem.cs @@ -1,4 +1,6 @@ using Content.Server.Chemistry.Containers.EntitySystems; +using Content.Server.Chemistry.EntitySystems; +using Content.Server.Construction; using Content.Server.Fluids.EntitySystems; using Content.Server.GameTicking; using Content.Server.Popups; @@ -45,6 +47,8 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnPowerChanged); SubscribeLocalEvent(OnInteractUsing, before: new []{typeof(WiresSystem), typeof(SolutionTransferSystem)}); @@ -56,6 +60,18 @@ private void OnStartup(Entity entity, ref ComponentS _solutionContainer.EnsureSolution(entity.Owner, entity.Comp.SolutionContainerId); } + private void OnUpgradeExamine(Entity entity, ref UpgradeExamineEvent args) + { + args.AddPercentageUpgrade(Loc.GetString("material-reclaimer-upgrade-process-rate"), entity.Comp.MaterialProcessRate / entity.Comp.BaseMaterialProcessRate); + } + + private void OnRefreshParts(Entity entity, ref RefreshPartsEvent args) + { + var rating = args.PartRatings[entity.Comp.MachinePartProcessRate] - 1; + entity.Comp.MaterialProcessRate = entity.Comp.BaseMaterialProcessRate * MathF.Pow(entity.Comp.PartRatingProcessRateMultiplier, rating); + Dirty(entity); + } + private void OnPowerChanged(Entity entity, ref PowerChangedEvent args) { AmbientSound.SetAmbience(entity.Owner, entity.Comp.Enabled && args.Powered); diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs index 61d36f98b96..1358bfbcbbc 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs @@ -1,4 +1,8 @@ +using System.Threading; +using Content.Shared.Construction.Prototypes; using Content.Shared.Storage; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Medical.BiomassReclaimer { @@ -6,72 +10,111 @@ namespace Content.Server.Medical.BiomassReclaimer public sealed partial class BiomassReclaimerComponent : Component { /// - /// This gets set for each mob it processes. - /// When it hits 0, there is a chance for the reclaimer to either spill blood or throw an item. + /// This gets set for each mob it processes. + /// When it hits 0, there is a chance for the reclaimer to either spill blood or throw an item. /// [ViewVariables] public float RandomMessTimer = 0f; /// - /// The interval for . + /// The interval for . /// - [ViewVariables(VVAccess.ReadWrite), DataField] + [DataField] public TimeSpan RandomMessInterval = TimeSpan.FromSeconds(5); /// - /// This gets set for each mob it processes. - /// When it hits 0, spit out biomass. + /// This gets set for each mob it processes. + /// When it hits 0, spit out biomass. /// [ViewVariables] - public float ProcessingTimer = default; + public float ProcessingTimer; /// - /// Amount of biomass that the mob being processed will yield. - /// This is calculated from the YieldPerUnitMass. - /// Also stores non-integer leftovers. + /// Amount of biomass that the mob being processed will yield. + /// This is calculated from the YieldPerUnitMass. + /// Also stores non-integer leftovers. /// [ViewVariables] - public float CurrentExpectedYield = 0f; + public float CurrentExpectedYield; /// - /// The reagent that will be spilled while processing a mob. + /// The reagent that will be spilled while processing a mob. /// [ViewVariables] public string? BloodReagent; /// - /// Entities that can be randomly spawned while processing a mob. + /// Entities that can be randomly spawned while processing a mob. /// public List SpawnedEntities = new(); /// - /// How many units of biomass it produces for each unit of mass. + /// How many units of biomass it produces for each unit of mass. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float YieldPerUnitMass = 0.4f; + [ViewVariables(VVAccess.ReadWrite)] + public float YieldPerUnitMass = default; /// - /// How many seconds to take to insert an entity per unit of its mass. + /// The base yield per mass unit when no components are upgraded. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] + public float BaseYieldPerUnitMass = 0.4f; + + /// + /// Machine part whose rating modifies the yield per mass. + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartYieldAmount = "MatterBin"; + + /// + /// How much the machine part quality affects the yield. + /// Going up a tier will multiply the yield by this amount. + /// + [DataField] + public float PartRatingYieldAmountMultiplier = 1.25f; + + /// + /// How many seconds to take to insert an entity per unit of its mass. + /// + [DataField] public float BaseInsertionDelay = 0.1f; /// - /// How much to multiply biomass yield from botany produce. + /// How much to multiply biomass yield from botany produce. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public float ProduceYieldMultiplier = 0.25f; /// - /// The time it takes to process a mob, per mass. + /// The time it takes to process a mob, per mass. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float ProcessingTimePerUnitMass; + + /// + /// The base time per mass unit that it takes to process a mob + /// when no components are upgraded. + /// + [DataField] + public float BaseProcessingTimePerUnitMass = 0.5f; + + /// + /// The machine part that increses the processing speed. + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartProcessingSpeed = "Manipulator"; + + /// + /// How much the machine part quality affects the yield. + /// Going up a tier will multiply the speed by this amount. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public float ProcessingTimePerUnitMass = 0.5f; + [DataField] + public float PartRatingSpeedMultiplier = 1.35f; /// - /// Will this refuse to gib a living mob? + /// Will this refuse to gib a living mob? /// - [ViewVariables(VVAccess.ReadWrite), DataField] + [DataField] public bool SafetyEnabled = true; } } diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs index eaf04d64b2b..97a758a5ed3 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs @@ -1,6 +1,7 @@ using System.Numerics; using Content.Server.Body.Components; using Content.Server.Botany.Components; +using Content.Server.Construction; using Content.Server.Fluids.EntitySystems; using Content.Server.Materials; using Content.Server.Power.Components; @@ -99,6 +100,8 @@ public override void Initialize() SubscribeLocalEvent(OnUnanchorAttempt); SubscribeLocalEvent(OnAfterInteractUsing); SubscribeLocalEvent(OnClimbedOn); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnPowerChanged); SubscribeLocalEvent(OnSuicide); SubscribeLocalEvent(OnDoAfter); @@ -173,6 +176,26 @@ private void OnClimbedOn(Entity reclaimer, ref Climbe StartProcessing(args.Climber, reclaimer); } + private void OnRefreshParts(EntityUid uid, BiomassReclaimerComponent component, RefreshPartsEvent args) + { + var laserRating = args.PartRatings[component.MachinePartProcessingSpeed]; + var manipRating = args.PartRatings[component.MachinePartYieldAmount]; + + // Processing time slopes downwards with part rating. + component.ProcessingTimePerUnitMass = + component.BaseProcessingTimePerUnitMass / MathF.Pow(component.PartRatingSpeedMultiplier, laserRating - 1); + + // Yield slopes upwards with part rating. + component.YieldPerUnitMass = + component.BaseYieldPerUnitMass * MathF.Pow(component.PartRatingYieldAmountMultiplier, manipRating - 1); + } + + private void OnUpgradeExamine(EntityUid uid, BiomassReclaimerComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("biomass-reclaimer-component-upgrade-speed", component.BaseProcessingTimePerUnitMass / component.ProcessingTimePerUnitMass); + args.AddPercentageUpgrade("biomass-reclaimer-component-upgrade-biomass-yield", component.YieldPerUnitMass / component.BaseYieldPerUnitMass); + } + private void OnDoAfter(Entity reclaimer, ref ReclaimerDoAfterEvent args) { if (args.Handled diff --git a/Content.Server/Medical/Components/MedicalScannerComponent.cs b/Content.Server/Medical/Components/MedicalScannerComponent.cs index 96de6499875..15ca6cd2bd7 100644 --- a/Content.Server/Medical/Components/MedicalScannerComponent.cs +++ b/Content.Server/Medical/Components/MedicalScannerComponent.cs @@ -1,5 +1,4 @@ using Content.Shared.Construction.Prototypes; -using Content.Shared.DragDrop; using Content.Shared.MedicalScanner; using Robust.Shared.Containers; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -13,10 +12,15 @@ public sealed partial class MedicalScannerComponent : SharedMedicalScannerCompon public ContainerSlot BodyContainer = default!; public EntityUid? ConnectedConsole; - [DataField, ViewVariables(VVAccess.ReadWrite)] + [ViewVariables(VVAccess.ReadWrite)] public float CloningFailChanceMultiplier = 1f; - - // Nyano, needed for Metem Machine. + public float MetemKarmaBonus = 0.25f; + + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartCloningFailChance = "Capacitor"; + + [DataField] + public float PartRatingFailMultiplier = 0.75f; } } diff --git a/Content.Server/Medical/MedicalScannerSystem.cs b/Content.Server/Medical/MedicalScannerSystem.cs index a6ce43c4081..ab6918e373b 100644 --- a/Content.Server/Medical/MedicalScannerSystem.cs +++ b/Content.Server/Medical/MedicalScannerSystem.cs @@ -7,6 +7,7 @@ using Content.Shared.Verbs; using Robust.Shared.Containers; using Content.Server.Cloning.Components; +using Content.Server.Construction; using Content.Server.DeviceLinking.Systems; using Content.Shared.DeviceLinking.Events; using Content.Server.Power.EntitySystems; @@ -44,6 +45,8 @@ public override void Initialize() SubscribeLocalEvent(OnDragDropOn); SubscribeLocalEvent(OnPortDisconnected); SubscribeLocalEvent(OnAnchorChanged); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnCanDragDropOn); } @@ -220,5 +223,17 @@ public void EjectBody(EntityUid uid, MedicalScannerComponent? scannerComponent) _climbSystem.ForciblySetClimbing(contained, uid); UpdateAppearance(uid, scannerComponent); } + + private void OnRefreshParts(EntityUid uid, MedicalScannerComponent component, RefreshPartsEvent args) + { + var ratingFail = args.PartRatings[component.MachinePartCloningFailChance]; + + component.CloningFailChanceMultiplier = MathF.Pow(component.PartRatingFailMultiplier, ratingFail - 1); + } + + private void OnUpgradeExamine(EntityUid uid, MedicalScannerComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("medical-scanner-upgrade-cloning", component.CloningFailChanceMultiplier); + } } } diff --git a/Content.Server/Nutrition/Components/FatExtractorComponent.cs b/Content.Server/Nutrition/Components/FatExtractorComponent.cs index e23c557236c..fa6edc911e1 100644 --- a/Content.Server/Nutrition/Components/FatExtractorComponent.cs +++ b/Content.Server/Nutrition/Components/FatExtractorComponent.cs @@ -1,4 +1,5 @@ using Content.Server.Nutrition.EntitySystems; +using Content.Shared.Construction.Prototypes; using Content.Shared.Nutrition.Components; using Robust.Shared.Audio; using Robust.Shared.Prototypes; @@ -8,67 +9,87 @@ namespace Content.Server.Nutrition.Components; /// -/// This is used for a machine that extracts hunger from entities and creates meat. Yum! +/// This is used for a machine that extracts hunger from entities and creates meat. Yum! /// [RegisterComponent, Access(typeof(FatExtractorSystem)), AutoGenerateComponentPause] public sealed partial class FatExtractorComponent : Component { /// - /// Whether or not the extractor is currently extracting fat from someone + /// Whether or not the extractor is currently extracting fat from someone /// - [DataField("processing")] + [DataField] public bool Processing = true; /// - /// How much nutrition is extracted per second. + /// How much nutrition is extracted per second. /// - [DataField("nutritionPerSecond"), ViewVariables(VVAccess.ReadWrite)] + [ViewVariables(VVAccess.ReadWrite)] public int NutritionPerSecond = 10; /// - /// An accumulator which tracks extracted nutrition to determine - /// when to spawn a meat. + /// The base rate of extraction /// - [DataField("nutrientAccumulator"), ViewVariables(VVAccess.ReadWrite)] + [DataField] + public int BaseNutritionPerSecond = 10; + + #region Machine Upgrade + /// + /// Which machine part affects the nutrition rate + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartNutritionRate = "Manipulator"; + + /// + /// The increase in rate per each rating above 1. + /// + [DataField] + public float PartRatingRateMultiplier = 10; + #endregion + + /// + /// An accumulator which tracks extracted nutrition to determine + /// when to spawn a meat. + /// + [DataField] public int NutrientAccumulator; /// - /// How high has to be to spawn meat + /// How high has to be to spawn meat /// - [DataField("nutrientPerMeat"), ViewVariables(VVAccess.ReadWrite)] - public int NutrientPerMeat = 30; + [DataField] + public int NutrientPerMeat = 60; /// - /// Meat spawned by the extractor. + /// Meat spawned by the extractor. /// - [DataField("meatPrototype", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string MeatPrototype = "FoodMeat"; /// - /// When the next update will occur + /// When the next update will occur /// - [DataField("nextUpdate", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] [AutoPausedField] public TimeSpan NextUpdate; /// - /// How long each update takes + /// How long each update takes /// - [DataField("updateTime"), ViewVariables(VVAccess.ReadWrite)] + [DataField] public TimeSpan UpdateTime = TimeSpan.FromSeconds(1); /// - /// The sound played when extracting + /// The sound played when extracting /// - [DataField("processSound")] + [DataField] public SoundSpecifier? ProcessSound; public EntityUid? Stream; /// - /// A minium hunger threshold for extracting nutrition. - /// Ignored when emagged. + /// A minium hunger threshold for extracting nutrition. + /// Ignored when emagged. /// - [DataField("minHungerThreshold")] + [DataField] public HungerThreshold MinHungerThreshold = HungerThreshold.Okay; } diff --git a/Content.Server/Nutrition/EntitySystems/FatExtractorSystem.cs b/Content.Server/Nutrition/EntitySystems/FatExtractorSystem.cs index 180e40d1e42..dc1f67c7400 100644 --- a/Content.Server/Nutrition/EntitySystems/FatExtractorSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/FatExtractorSystem.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; +using Content.Server.Construction; using Content.Server.Nutrition.Components; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; @@ -9,6 +10,7 @@ using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; using Content.Shared.Storage.Components; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Timing; @@ -27,12 +29,25 @@ public sealed class FatExtractorSystem : EntitySystem /// public override void Initialize() { + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnGotEmagged); SubscribeLocalEvent(OnClosed); SubscribeLocalEvent(OnOpen); SubscribeLocalEvent(OnPowerChanged); } + private void OnRefreshParts(EntityUid uid, FatExtractorComponent component, RefreshPartsEvent args) + { + var rating = args.PartRatings[component.MachinePartNutritionRate] - 1; + component.NutritionPerSecond = component.BaseNutritionPerSecond + (int) (component.PartRatingRateMultiplier * rating); + } + + private void OnUpgradeExamine(EntityUid uid, FatExtractorComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("fat-extractor-component-rate", (float) component.NutritionPerSecond / component.BaseNutritionPerSecond); + } + private void OnGotEmagged(EntityUid uid, FatExtractorComponent component, ref GotEmaggedEvent args) { args.Handled = true; diff --git a/Content.Server/Power/Components/UpgradeBatteryComponent.cs b/Content.Server/Power/Components/UpgradeBatteryComponent.cs new file mode 100644 index 00000000000..b676883b711 --- /dev/null +++ b/Content.Server/Power/Components/UpgradeBatteryComponent.cs @@ -0,0 +1,28 @@ +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Power.Components +{ + + [RegisterComponent] + public sealed partial class UpgradeBatteryComponent : Component + { + /// + /// The machine part that affects the power capacity. + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartPowerCapacity = "PowerCell"; + + /// + /// The machine part rating is raised to this power when calculating power gain + /// + [DataField] + public float MaxChargeMultiplier = 2f; + + /// + /// Power gain scaling + /// + [DataField] + public float BaseMaxCharge = 8000000; + } +} diff --git a/Content.Server/Power/Components/UpgradePowerDrawComponent.cs b/Content.Server/Power/Components/UpgradePowerDrawComponent.cs new file mode 100644 index 00000000000..23db4905cc5 --- /dev/null +++ b/Content.Server/Power/Components/UpgradePowerDrawComponent.cs @@ -0,0 +1,41 @@ +using Content.Server.Construction.Components; +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Power.Components; + +/// +/// This is used for machines whose power draw +/// can be decreased through machine part upgrades. +/// +[RegisterComponent] +public sealed partial class UpgradePowerDrawComponent : Component +{ + /// + /// The base power draw of the machine. + /// Prioritizes hv/mv draw over lv draw. + /// Value is initializezd on map init from + /// + [ViewVariables(VVAccess.ReadWrite)] + public float BaseLoad; + + /// + /// The machine part that affects the power draw. + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + public string MachinePartPowerDraw = "Capacitor"; + + /// + /// The multiplier used for scaling the power draw. + /// + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public float PowerDrawMultiplier = 1f; + + /// + /// What type of scaling is being used? + /// + [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] + public MachineUpgradeScalingType Scaling; +} + + diff --git a/Content.Server/Power/Components/UpgradePowerSupplierComponent.cs b/Content.Server/Power/Components/UpgradePowerSupplierComponent.cs new file mode 100644 index 00000000000..012c38a6b90 --- /dev/null +++ b/Content.Server/Power/Components/UpgradePowerSupplierComponent.cs @@ -0,0 +1,36 @@ +using Content.Server.Construction.Components; +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Power.Components; + +[RegisterComponent] +public sealed partial class UpgradePowerSupplierComponent : Component +{ + [ViewVariables(VVAccess.ReadWrite)] + public float BaseSupplyRate; + + /// + /// The machine part that affects the power supplu. + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartPowerSupply = "Capacitor"; + + /// + /// The multiplier used for scaling the power supply. + /// + [DataField(required: true)] + public float PowerSupplyMultiplier = 1f; + + /// + /// What type of scaling is being used? + /// + [DataField(required: true)] + public MachineUpgradeScalingType Scaling; + + /// + /// The current value that the power supply is being scaled by, + /// + [DataField] + public float ActualScalar = 1f; +} diff --git a/Content.Server/Power/Components/UpgradePowerSupplyRampingComponent.cs b/Content.Server/Power/Components/UpgradePowerSupplyRampingComponent.cs new file mode 100644 index 00000000000..61a654b383b --- /dev/null +++ b/Content.Server/Power/Components/UpgradePowerSupplyRampingComponent.cs @@ -0,0 +1,36 @@ +using Content.Server.Construction.Components; +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Power.Components; + +[RegisterComponent] +public sealed partial class UpgradePowerSupplyRampingComponent : Component +{ + [ViewVariables(VVAccess.ReadWrite)] + public float BaseRampRate; + + /// + /// The machine part that affects the power supply ramping + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartRampRate = "Capacitor"; + + /// + /// The multiplier used for scaling the power supply ramping + /// + [DataField] + public float SupplyRampingMultiplier = 1f; + + /// + /// What type of scaling is being used? + /// + [DataField(required: true)] + public MachineUpgradeScalingType Scaling; + + /// + /// The current value that the power supply is being scaled by + /// + [DataField] + public float ActualScalar = 1f; +} diff --git a/Content.Server/Power/EntitySystems/UpgradeBatterySystem.cs b/Content.Server/Power/EntitySystems/UpgradeBatterySystem.cs new file mode 100644 index 00000000000..734cf9d89ce --- /dev/null +++ b/Content.Server/Power/EntitySystems/UpgradeBatterySystem.cs @@ -0,0 +1,39 @@ +using Content.Server.Construction; +using Content.Server.Power.Components; +using JetBrains.Annotations; + +namespace Content.Server.Power.EntitySystems +{ + [UsedImplicitly] + public sealed class UpgradeBatterySystem : EntitySystem + { + [Dependency] private readonly BatterySystem _batterySystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); + } + + public void OnRefreshParts(EntityUid uid, UpgradeBatteryComponent component, RefreshPartsEvent args) + { + var powerCellRating = args.PartRatings[component.MachinePartPowerCapacity]; + + if (TryComp(uid, out var batteryComp)) + { + _batterySystem.SetMaxCharge(uid, MathF.Pow(component.MaxChargeMultiplier, powerCellRating - 1) * component.BaseMaxCharge, batteryComp); + } + } + + private void OnUpgradeExamine(EntityUid uid, UpgradeBatteryComponent component, UpgradeExamineEvent args) + { + // UpgradeBatteryComponent.MaxChargeMultiplier is not the actual multiplier, so we have to do this. + if (TryComp(uid, out var batteryComp)) + { + args.AddPercentageUpgrade("upgrade-max-charge", batteryComp.MaxCharge / component.BaseMaxCharge); + } + } + } +} diff --git a/Content.Server/Power/EntitySystems/UpgradePowerSystem.cs b/Content.Server/Power/EntitySystems/UpgradePowerSystem.cs new file mode 100644 index 00000000000..d2f6ee4f568 --- /dev/null +++ b/Content.Server/Power/EntitySystems/UpgradePowerSystem.cs @@ -0,0 +1,151 @@ +using Content.Server.Construction; +using Content.Server.Construction.Components; +using Content.Server.Power.Components; + +namespace Content.Server.Power.EntitySystems; + +/// +/// This handles using upgraded machine parts +/// to modify the power supply/generation of a machine. +/// +public sealed class UpgradePowerSystem : EntitySystem +{ + /// + public override void Initialize() + { + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); + + SubscribeLocalEvent(OnSupplierMapInit); + SubscribeLocalEvent(OnSupplierRefreshParts); + SubscribeLocalEvent(OnSupplierUpgradeExamine); + + SubscribeLocalEvent(OnSupplyRampingMapInit); + SubscribeLocalEvent(OnSupplyRampingRefreshParts); + SubscribeLocalEvent(OnSupplyRampingUpgradeExamine); + } + + private void OnMapInit(EntityUid uid, UpgradePowerDrawComponent component, MapInitEvent args) + { + if (TryComp(uid, out var powa)) + component.BaseLoad = powa.DrawRate; + else if (TryComp(uid, out var powa2)) + component.BaseLoad = powa2.Load; + } + + private void OnRefreshParts(EntityUid uid, UpgradePowerDrawComponent component, RefreshPartsEvent args) + { + var load = component.BaseLoad; + var rating = args.PartRatings[component.MachinePartPowerDraw]; + switch (component.Scaling) + + { + case MachineUpgradeScalingType.Linear: + load += component.PowerDrawMultiplier * (rating - 1); + break; + case MachineUpgradeScalingType.Exponential: + load *= MathF.Pow(component.PowerDrawMultiplier, rating - 1); + break; + default: + Log.Error($"invalid power scaling type for {ToPrettyString(uid)}."); + load = 0; + break; + } + + if (TryComp(uid, out var powa)) + powa.Load = load; + if (TryComp(uid, out var powa2)) + powa2.DrawRate = load; + } + + private void OnUpgradeExamine(EntityUid uid, UpgradePowerDrawComponent component, UpgradeExamineEvent args) + { + // UpgradePowerDrawComponent.PowerDrawMultiplier is not the actual multiplier, so we have to do this. + var powerDrawMultiplier = CompOrNull(uid)?.Load / component.BaseLoad + ?? CompOrNull(uid)?.DrawRate / component.BaseLoad; + + if (powerDrawMultiplier is not null) + args.AddPercentageUpgrade("upgrade-power-draw", powerDrawMultiplier.Value); + } + + private void OnSupplierMapInit(EntityUid uid, UpgradePowerSupplierComponent component, MapInitEvent args) + { + if (!TryComp(uid, out var supplier)) + return; + + component.BaseSupplyRate = supplier.MaxSupply; + } + + private void OnSupplierRefreshParts(EntityUid uid, UpgradePowerSupplierComponent component, RefreshPartsEvent args) + { + var supply = component.BaseSupplyRate; + var rating = args.PartRatings[component.MachinePartPowerSupply]; + switch (component.Scaling) + + { + case MachineUpgradeScalingType.Linear: + supply += component.PowerSupplyMultiplier * component.BaseSupplyRate * (rating - 1); + break; + case MachineUpgradeScalingType.Exponential: + supply *= MathF.Pow(component.PowerSupplyMultiplier, rating - 1); + break; + default: + Log.Error($"invalid power scaling type for {ToPrettyString(uid)}."); + supply = component.BaseSupplyRate; + break; + } + + component.ActualScalar = supply / component.BaseSupplyRate; + + if (!TryComp(uid, out var powa)) + return; + + powa.MaxSupply = supply; + } + + private void OnSupplierUpgradeExamine(EntityUid uid, UpgradePowerSupplierComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("upgrade-power-supply", component.ActualScalar); + } + + private void OnSupplyRampingMapInit(EntityUid uid, UpgradePowerSupplyRampingComponent component, MapInitEvent args) + { + if (!TryComp(uid, out var battery)) + return; + + component.BaseRampRate = battery.SupplyRampRate; + } + + private void OnSupplyRampingRefreshParts(EntityUid uid, UpgradePowerSupplyRampingComponent component, RefreshPartsEvent args) + { + var rampRate = component.BaseRampRate; + var rating = args.PartRatings[component.MachinePartRampRate]; + switch (component.Scaling) + + { + case MachineUpgradeScalingType.Linear: + rampRate += component.SupplyRampingMultiplier * component.BaseRampRate * (rating - 1); + break; + case MachineUpgradeScalingType.Exponential: + rampRate *= MathF.Pow(component.SupplyRampingMultiplier, rating - 1); + break; + default: + Log.Error($"invalid power supply ramping type for {ToPrettyString(uid)}."); + rampRate = component.BaseRampRate; + break; + } + + component.ActualScalar = rampRate / component.BaseRampRate; + + if (!TryComp(uid, out var battery)) + return; + + battery.SupplyRampRate = rampRate; + } + + private void OnSupplyRampingUpgradeExamine(EntityUid uid, UpgradePowerSupplyRampingComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("upgrade-power-supply-ramping", component.ActualScalar); + } +} diff --git a/Content.Server/Power/Generator/GeneratorSystem.cs b/Content.Server/Power/Generator/GeneratorSystem.cs index a75d1e4113d..721a959820b 100644 --- a/Content.Server/Power/Generator/GeneratorSystem.cs +++ b/Content.Server/Power/Generator/GeneratorSystem.cs @@ -26,8 +26,11 @@ public sealed class GeneratorSystem : SharedGeneratorSystem [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly PuddleSystem _puddle = default!; + private EntityQuery _upgradeQuery; + public override void Initialize() { + _upgradeQuery = GetEntityQuery(); UpdatesBefore.Add(typeof(PowerNetSystem)); @@ -225,7 +228,9 @@ public override void Update(float frameTime) supplier.Enabled = true; - supplier.MaxSupply = gen.TargetPower; + var upgradeMultiplier = _upgradeQuery.CompOrNull(uid)?.ActualScalar ?? 1f; + + supplier.MaxSupply = gen.TargetPower * upgradeMultiplier; var eff = 1 / CalcFuelEfficiency(gen.TargetPower, gen.OptimalPower, gen); var consumption = gen.OptimalBurnRate * frameTime * eff; diff --git a/Content.Server/Shuttles/Components/ThrusterComponent.cs b/Content.Server/Shuttles/Components/ThrusterComponent.cs index 3bba9b5a7f0..f64d9bdcbf0 100644 --- a/Content.Server/Shuttles/Components/ThrusterComponent.cs +++ b/Content.Server/Shuttles/Components/ThrusterComponent.cs @@ -1,8 +1,10 @@ using System.Numerics; using Content.Server.Shuttles.Systems; +using Content.Shared.Construction.Prototypes; using Content.Shared.Damage; using Robust.Shared.GameStates; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Shuttles.Components { @@ -13,7 +15,7 @@ public sealed partial class ThrusterComponent : Component /// /// Whether the thruster has been force to be enabled / disabled (e.g. VV, interaction, etc.) /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public bool Enabled { get; set; } = true; /// @@ -22,9 +24,12 @@ public sealed partial class ThrusterComponent : Component public bool IsOn; // Need to serialize this because RefreshParts isn't called on Init and this will break post-mapinit maps! - [ViewVariables(VVAccess.ReadWrite), DataField("thrust")] + [DataField] public float Thrust = 100f; + [DataField] + public float BaseThrust = 100f; + [DataField("thrusterType")] public ThrusterType Type = ThrusterType.Linear; @@ -37,24 +42,31 @@ public sealed partial class ThrusterComponent : Component }; /// - /// How much damage is done per second to anything colliding with our thrust. + /// How much damage is done per second to anything colliding with our thrust. /// - [DataField("damage")] public DamageSpecifier? Damage = new(); + [DataField] + public DamageSpecifier? Damage = new(); - [DataField("requireSpace")] + [DataField] public bool RequireSpace = true; // Used for burns public List Colliding = new(); - public bool Firing = false; + public bool Firing; /// - /// Next time we tick damage for anyone colliding. + /// Next time we tick damage for anyone colliding. /// - [ViewVariables(VVAccess.ReadWrite), DataField("nextFire", customTypeSerializer:typeof(TimeOffsetSerializer))] + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] public TimeSpan NextFire; + + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartThrust = "Capacitor"; + + [DataField] + public float PartRatingThrustMultiplier = 1.5f; } public enum ThrusterType diff --git a/Content.Server/Shuttles/Systems/ThrusterSystem.cs b/Content.Server/Shuttles/Systems/ThrusterSystem.cs index be55cd9a62a..ee131d7857a 100644 --- a/Content.Server/Shuttles/Systems/ThrusterSystem.cs +++ b/Content.Server/Shuttles/Systems/ThrusterSystem.cs @@ -1,5 +1,6 @@ using System.Numerics; using Content.Server.Audio; +using Content.Server.Construction; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Server.Shuttles.Components; @@ -51,6 +52,9 @@ public override void Initialize() SubscribeLocalEvent(OnThrusterExamine); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); + SubscribeLocalEvent(OnShuttleTileChange); } @@ -580,6 +584,24 @@ public void SetAngularThrust(ShuttleComponent component, bool on) } } + private void OnRefreshParts(EntityUid uid, ThrusterComponent component, RefreshPartsEvent args) + { + if (component.IsOn) // safely disable thruster to prevent negative thrust + DisableThruster(uid, component); + + var thrustRating = args.PartRatings[component.MachinePartThrust]; + + component.Thrust = component.BaseThrust * MathF.Pow(component.PartRatingThrustMultiplier, thrustRating - 1); + + if (component.Enabled && CanEnable(uid, component)) + EnableThruster(uid, component); + } + + private void OnUpgradeExamine(EntityUid uid, ThrusterComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("thruster-comp-upgrade-thrust", component.Thrust / component.BaseThrust); + } + #endregion private int GetFlagIndex(DirectionFlag flag) diff --git a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs index a9763b64d90..652ca236e44 100644 --- a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs +++ b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs @@ -1,6 +1,7 @@ using System.Numerics; using System.Threading; using Content.Server.Administration.Logs; +using Content.Server.Construction; using Content.Server.DeviceLinking.Events; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; @@ -47,6 +48,8 @@ public override void Initialize() SubscribeLocalEvent(OnInteractHand); SubscribeLocalEvent>(OnGetVerb); SubscribeLocalEvent(OnExamined); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnAnchorStateChanged); SubscribeLocalEvent(OnSignalReceived); } @@ -176,6 +179,20 @@ private void OnApcChanged(EntityUid uid, EmitterComponent component, ref PowerCh } } + private void OnRefreshParts(EntityUid uid, EmitterComponent component, RefreshPartsEvent args) + { + var fireRateRating = args.PartRatings[component.MachinePartFireRate]; + + component.FireInterval = component.BaseFireInterval * MathF.Pow(component.FireRateMultiplier, fireRateRating - 1); + component.FireBurstDelayMin = component.BaseFireBurstDelayMin * MathF.Pow(component.FireRateMultiplier, fireRateRating - 1); + component.FireBurstDelayMax = component.BaseFireBurstDelayMax * MathF.Pow(component.FireRateMultiplier, fireRateRating - 1); + } + + private void OnUpgradeExamine(EntityUid uid, EmitterComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("emitter-component-upgrade-fire-rate", (float) (component.BaseFireInterval.TotalSeconds / component.FireInterval.TotalSeconds)); + } + public void SwitchOff(EntityUid uid, EmitterComponent component) { component.IsOn = false; diff --git a/Content.Server/Xenoarchaeology/Equipment/Components/TraversalDistorterComponent.cs b/Content.Server/Xenoarchaeology/Equipment/Components/TraversalDistorterComponent.cs index ec16083c538..d6a39fe4f40 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Components/TraversalDistorterComponent.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Components/TraversalDistorterComponent.cs @@ -1,4 +1,7 @@ -namespace Content.Server.Xenoarchaeology.Equipment.Components; +using Content.Shared.Construction.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Xenoarchaeology.Equipment.Components; /// /// This is used for a machine that biases @@ -7,6 +10,18 @@ [RegisterComponent] public sealed partial class TraversalDistorterComponent : Component { + [ViewVariables(VVAccess.ReadWrite)] + public float BiasChance; + + [DataField] + public float BaseBiasChance = 0.7f; + + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartBiasChance = "Manipulator"; + + [DataField] + public float PartRatingBiasChance = 1.1f; + [ViewVariables(VVAccess.ReadWrite)] public BiasDirection BiasDirection = BiasDirection.In; diff --git a/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs b/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs index 230e639af49..bb662925a92 100644 --- a/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs +++ b/Content.Server/Xenoarchaeology/Equipment/Systems/TraversalDistorterSystem.cs @@ -1,9 +1,12 @@ -using Content.Server.Popups; +using Content.Server.Construction; +using Content.Server.Popups; using Content.Server.Power.EntitySystems; using Content.Server.Xenoarchaeology.Equipment.Components; +using Content.Server.Xenoarchaeology.XenoArtifacts; using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.Placeable; +using Robust.Shared.Player; using Robust.Shared.Timing; namespace Content.Server.Xenoarchaeology.Equipment.Systems; @@ -20,6 +23,8 @@ public override void Initialize() SubscribeLocalEvent(OnInteract); SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); SubscribeLocalEvent(OnItemPlaced); SubscribeLocalEvent(OnItemRemoved); @@ -68,10 +73,21 @@ private void OnExamine(EntityUid uid, TraversalDistorterComponent component, Exa examine = Loc.GetString("traversal-distorter-desc-out"); break; } - args.PushMarkup(examine); } + private void OnRefreshParts(EntityUid uid, TraversalDistorterComponent component, RefreshPartsEvent args) + { + var biasRating = args.PartRatings[component.MachinePartBiasChance]; + + component.BiasChance = component.BaseBiasChance * MathF.Pow(component.PartRatingBiasChance, biasRating - 1); + } + + private void OnUpgradeExamine(EntityUid uid, TraversalDistorterComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("traversal-distorter-upgrade-bias", component.BiasChance / component.BaseBiasChance); + } + private void OnItemPlaced(EntityUid uid, TraversalDistorterComponent component, ref ItemPlacedEvent args) { var bias = EnsureComp(args.OtherEntity); diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs index 955fe827d72..a7948aa7ff9 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs @@ -206,6 +206,7 @@ public void ForceActivateArtifact(EntityUid uid, EntityUid? user = null, Artifac if (TryComp(uid, out var bias) && TryComp(bias.Provider, out var trav) && + _random.Prob(trav.BiasChance) && this.IsPowered(bias.Provider, EntityManager)) { switch (trav.BiasDirection) diff --git a/Content.Shared/Cargo/Components/SharedCargoTelepadComponent.cs b/Content.Shared/Cargo/Components/SharedCargoTelepadComponent.cs index 911ea41cca5..7c8a3625227 100644 --- a/Content.Shared/Cargo/Components/SharedCargoTelepadComponent.cs +++ b/Content.Shared/Cargo/Components/SharedCargoTelepadComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.Construction.Prototypes; using Content.Shared.DeviceLinking; using Robust.Shared.Audio; using Robust.Shared.GameStates; @@ -13,29 +14,47 @@ namespace Content.Shared.Cargo.Components; public sealed partial class CargoTelepadComponent : Component { /// - /// The actual amount of time it takes to teleport from the telepad + /// The base amount of time it takes to teleport from the telepad /// - [DataField("delay"), ViewVariables(VVAccess.ReadWrite)] + [DataField] + public float BaseDelay = 10f; + + /// + /// The actual amount of time it takes to teleport from the telepad + /// + [DataField] public float Delay = 10f; /// - /// How much time we've accumulated until next teleport. + /// The machine part that affects + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + public string MachinePartTeleportDelay = "Capacitor"; + + /// + /// A multiplier applied to for each level of + /// + [DataField] + public float PartRatingTeleportDelay = 0.8f; + + /// + /// How much time we've accumulated until next teleport. /// - [DataField("accumulator"), ViewVariables(VVAccess.ReadWrite)] + [DataField] public float Accumulator; - [DataField("currentState")] + [DataField] public CargoTelepadState CurrentState = CargoTelepadState.Unpowered; - [DataField("teleportSound")] + [DataField] public SoundSpecifier TeleportSound = new SoundPathSpecifier("/Audio/Machines/phasein.ogg"); /// /// The paper-type prototype to spawn with the order information. /// - [DataField("printerOutput", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] public string PrinterOutput = "PaperCargoInvoice"; - [DataField("receiverPort", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] public string ReceiverPort = "OrderReceiver"; } diff --git a/Content.Shared/Cloning/CloningPodComponent.cs b/Content.Shared/Cloning/CloningPodComponent.cs index 082b92e8b14..c9a6fd4500b 100644 --- a/Content.Shared/Cloning/CloningPodComponent.cs +++ b/Content.Shared/Cloning/CloningPodComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.Construction.Prototypes; using Content.Shared.DeviceLinking; using Content.Shared.Materials; using Content.Shared.Random; @@ -38,6 +39,18 @@ public sealed partial class CloningPodComponent : Component [DataField] public ProtoId RequiredMaterial = "Biomass"; + /// + /// The multiplier for cloning duration + /// + [DataField] + public float PartRatingSpeedMultiplier = 0.75f; + + /// + /// The machine part that affects cloning speed + /// + [DataField] + public ProtoId MachinePartCloningSpeed = "Manipulator"; + /// /// The current amount of time it takes to clone a body /// @@ -66,6 +79,18 @@ public sealed partial class CloningPodComponent : Component Params = AudioParams.Default.WithVolume(4), }; + /// + /// The machine part that affects how much biomass is needed to clone a body. + /// + [DataField] + public float PartRatingMaterialMultiplier = 0.85f; + + /// + /// The machine part that decreases the amount of material needed for cloning + /// + [DataField] + public ProtoId MachinePartMaterialUse = "MatterBin"; + [ViewVariables(VVAccess.ReadWrite)] public CloningPodStatus Status; diff --git a/Content.Shared/Construction/MachinePartSystem.cs b/Content.Shared/Construction/MachinePartSystem.cs index 1a19040b410..01db7fbade3 100644 --- a/Content.Shared/Construction/MachinePartSystem.cs +++ b/Content.Shared/Construction/MachinePartSystem.cs @@ -21,6 +21,7 @@ public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnMachineBoardExamined); + SubscribeLocalEvent(OnMachinePartExamined); } private void OnMachineBoardExamined(EntityUid uid, MachineBoardComponent component, ExaminedEvent args) @@ -61,6 +62,20 @@ private void OnMachineBoardExamined(EntityUid uid, MachineBoardComponent compone } } + private void OnMachinePartExamined(EntityUid uid, MachinePartComponent component, ExaminedEvent args) + { + if (!args.IsInDetailsRange) + return; + + using (args.PushGroup(nameof(MachinePartComponent))) + { + args.PushMarkup(Loc.GetString("machine-part-component-on-examine-rating-text", + ("rating", component.Rating))); + args.PushMarkup(Loc.GetString("machine-part-component-on-examine-type-text", ("type", + Loc.GetString(_prototype.Index(component.PartType).Name)))); + } + } + public Dictionary GetMachineBoardMaterialCost(Entity entity, int coefficient = 1) { var (_, comp) = entity; diff --git a/Content.Shared/Materials/MaterialReclaimerComponent.cs b/Content.Shared/Materials/MaterialReclaimerComponent.cs index 3e72baf6041..2fd6cd6fc82 100644 --- a/Content.Shared/Materials/MaterialReclaimerComponent.cs +++ b/Content.Shared/Materials/MaterialReclaimerComponent.cs @@ -1,100 +1,121 @@ -using Content.Shared.Whitelist; +using Content.Shared.Construction.Prototypes; +using Content.Shared.Whitelist; using Robust.Shared.Audio; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Shared.Materials; /// -/// This is a machine that handles converting entities -/// into the raw materials and chemicals that make them up. +/// This is a machine that handles converting entities +/// into the raw materials and chemicals that make them up. /// [RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause] [Access(typeof(SharedMaterialReclaimerSystem))] public sealed partial class MaterialReclaimerComponent : Component { /// - /// Whether or not the machine has power. We put it here - /// so we can network and predict it. + /// Whether or not the machine has power. We put it here + /// so we can network and predict it. /// - [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] + [DataField, AutoNetworkedField] public bool Powered; /// - /// An "enable" toggle for things like interfacing with machine linking + /// An "enable" toggle for things like interfacing with machine linking /// - [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] + [DataField, AutoNetworkedField] public bool Enabled = true; /// - /// How efficiently the materials are reclaimed. - /// In practice, a multiplier per material when calculating the output of the reclaimer. + /// How efficiently the materials are reclaimed. + /// In practice, a multiplier per material when calculating the output of the reclaimer. /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public float Efficiency = 1f; /// - /// Whether or not the process - /// speed scales with the amount of materials being processed - /// or if it's just + /// Whether or not the process + /// speed scales with the amount of materials being processed + /// or if it's just /// [DataField] public bool ScaleProcessSpeed = true; /// - /// How quickly it takes to consume X amount of materials per second. - /// For example, with a rate of 50, an entity with 100 total material takes 2 seconds to process. + /// How quickly it takes to consume X amount of materials per second. + /// For example, with a rate of 50, an entity with 100 total material takes 2 seconds to process. /// - [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] + [DataField] + public float BaseMaterialProcessRate = 100f; + + /// + /// How quickly it takes to consume X amount of materials per second. + /// For example, with a rate of 50, an entity with 100 total material takes 2 seconds to process. + /// + [DataField, AutoNetworkedField] public float MaterialProcessRate = 100f; /// - /// The minimum amount fo time it can take to process an entity. - /// this value supercedes the calculated one using + /// Machine part whose rating modifies + /// + [DataField] + public ProtoId MachinePartProcessRate = "Manipulator"; + + /// + /// How much the machine part quality affects the /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] + public float PartRatingProcessRateMultiplier = 1.5f; + + /// + /// The minimum amount fo time it can take to process an entity. + /// this value supercedes the calculated one using + /// + [DataField] public TimeSpan MinimumProcessDuration = TimeSpan.FromSeconds(0.5f); /// - /// The id of our output solution + /// The id of our output solution /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public string SolutionContainerId = "output"; /// - /// a whitelist for what entities can be inserted into this reclaimer + /// a whitelist for what entities can be inserted into this reclaimer /// [DataField] public EntityWhitelist? Whitelist; /// - /// a blacklist for what entities cannot be inserted into this reclaimer + /// a blacklist for what entities cannot be inserted into this reclaimer /// [DataField] public EntityWhitelist? Blacklist; /// - /// The sound played when something is being processed. + /// The sound played when something is being processed. /// [DataField] public SoundSpecifier? Sound; /// - /// whether or not we cut off the sound early when the reclaiming ends. + /// whether or not we cut off the sound early when the reclaiming ends. /// [DataField] public bool CutOffSound = true; /// - /// When the next sound will be allowed to be played. Used to prevent spam. + /// When the next sound will be allowed to be played. Used to prevent spam. /// [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] [AutoPausedField] public TimeSpan NextSound; /// - /// Minimum time inbetween each + /// Minimum time inbetween each /// [DataField] public TimeSpan SoundCooldown = TimeSpan.FromSeconds(0.8f); @@ -102,10 +123,10 @@ public sealed partial class MaterialReclaimerComponent : Component public EntityUid? Stream; /// - /// A counter of how many items have been processed + /// A counter of how many items have been processed /// /// - /// I saw this on the recycler and i'm porting it because it's cute af + /// I saw this on the recycler and i'm porting it because it's cute af /// [DataField, AutoNetworkedField] public int ItemsProcessed; diff --git a/Content.Shared/Singularity/Components/SharedEmitterComponent.cs b/Content.Shared/Singularity/Components/SharedEmitterComponent.cs index c2e7af717b1..cc6e8aeede2 100644 --- a/Content.Shared/Singularity/Components/SharedEmitterComponent.cs +++ b/Content.Shared/Singularity/Components/SharedEmitterComponent.cs @@ -1,4 +1,5 @@ using System.Threading; +using Content.Shared.Construction.Prototypes; using Content.Shared.DeviceLinking; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -14,90 +15,130 @@ public sealed partial class EmitterComponent : Component { public CancellationTokenSource? TimerCancel; - // whether the power switch is in "on" - [ViewVariables] public bool IsOn; - // Whether the power switch is on AND the machine has enough power (so is actively firing) - [ViewVariables] public bool IsPowered; + /// + /// Whether the power switch is on + /// + [ViewVariables] + public bool IsOn; /// - /// counts the number of consecutive shots fired. + /// Whether the power switch is on AND the machine has enough power (so is actively firing) + /// + [ViewVariables] + public bool IsPowered; + + /// + /// counts the number of consecutive shots fired. /// [ViewVariables] public int FireShotCounter; /// - /// The entity that is spawned when the emitter fires. + /// The entity that is spawned when the emitter fires. /// - [DataField("boltType", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string BoltType = "EmitterBolt"; - [DataField("selectableTypes", customTypeSerializer: typeof(PrototypeIdListSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdListSerializer))] public List SelectableTypes = new(); /// - /// The current amount of power being used. + /// The current amount of power being used. /// - [DataField("powerUseActive")] + [DataField] public int PowerUseActive = 600; /// - /// The amount of shots that are fired in a single "burst" + /// The amount of shots that are fired in a single "burst" /// - [DataField("fireBurstSize")] + [DataField] public int FireBurstSize = 3; /// - /// The time between each shot during a burst. + /// The time between each shot during a burst. /// - [DataField("fireInterval")] + [DataField] public TimeSpan FireInterval = TimeSpan.FromSeconds(2); /// - /// The current minimum delay between bursts. + /// The base amount of time between each shot during a burst. /// - [DataField("fireBurstDelayMin")] + [DataField] + public TimeSpan BaseFireInterval = TimeSpan.FromSeconds(2); + + /// + /// The current minimum delay between bursts. + /// + [DataField] public TimeSpan FireBurstDelayMin = TimeSpan.FromSeconds(4); /// - /// The current maximum delay between bursts. + /// The current maximum delay between bursts. /// - [DataField("fireBurstDelayMax")] + [DataField] public TimeSpan FireBurstDelayMax = TimeSpan.FromSeconds(10); /// - /// The visual state that is set when the emitter is turned on + /// The base minimum delay between shot bursts. + /// Used for machine part rating calculations. + /// + [DataField] + public TimeSpan BaseFireBurstDelayMin = TimeSpan.FromSeconds(4); + + /// + /// The base maximum delay between shot bursts. + /// Used for machine part rating calculations. + /// + [DataField] + public TimeSpan BaseFireBurstDelayMax = TimeSpan.FromSeconds(10); + + /// + /// The multiplier for the base delay between shot bursts as well as + /// the fire interval + /// + [DataField] + public float FireRateMultiplier = 0.8f; + + /// + /// The machine part that affects burst delay. + /// + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartFireRate = "Capacitor"; + + /// + /// The visual state that is set when the emitter is turned on /// - [DataField("onState")] + [DataField] public string? OnState = "beam"; /// - /// The visual state that is set when the emitter doesn't have enough power. + /// The visual state that is set when the emitter doesn't have enough power. /// - [DataField("underpoweredState")] + [DataField] public string? UnderpoweredState = "underpowered"; /// - /// Signal port that turns on the emitter. + /// Signal port that turns on the emitter. /// - [DataField("onPort", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string OnPort = "On"; /// - /// Signal port that turns off the emitter. + /// Signal port that turns off the emitter. /// - [DataField("offPort", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string OffPort = "Off"; /// - /// Signal port that toggles the emitter on or off. + /// Signal port that toggles the emitter on or off. /// - [DataField("togglePort", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string TogglePort = "Toggle"; /// - /// Map of signal ports to entity prototype IDs of the entity that will be fired. + /// Map of signal ports to entity prototype IDs of the entity that will be fired. /// - [DataField("setTypePorts", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] public Dictionary SetTypePorts = new(); } diff --git a/Resources/Locale/en-US/anomaly/anomaly.ftl b/Resources/Locale/en-US/anomaly/anomaly.ftl index da5882fa62f..1609d77d914 100644 --- a/Resources/Locale/en-US/anomaly/anomaly.ftl +++ b/Resources/Locale/en-US/anomaly/anomaly.ftl @@ -3,6 +3,7 @@ anomaly-component-contact-damage = The anomaly sears off your skin! anomaly-vessel-component-anomaly-assigned = Anomaly assigned to vessel. anomaly-vessel-component-not-assigned = This vessel is not assigned to any anomaly. Try using a scanner on it. anomaly-vessel-component-assigned = This vessel is currently assigned to an anomaly. +anomaly-vessel-component-upgrade-output = point output anomaly-particles-delta = Delta particles anomaly-particles-epsilon = Epsilon particles diff --git a/Resources/Locale/en-US/atmos/gas-recycler-system.ftl b/Resources/Locale/en-US/atmos/gas-recycler-system.ftl index cc527adf5c8..a72e137732c 100644 --- a/Resources/Locale/en-US/atmos/gas-recycler-system.ftl +++ b/Resources/Locale/en-US/atmos/gas-recycler-system.ftl @@ -1,3 +1,6 @@ gas-recycler-reacting = It is [color=green]converting[/color] waste gases. gas-recycler-low-pressure = The input pressure is [color=darkred]too low[/color]. gas-recycler-low-temperature = The input temperature is [color=darkred]too low[/color]. + +gas-recycler-upgrade-min-temp = Minimum temperature +gas-recycler-upgrade-min-pressure = Minimum pressure diff --git a/Resources/Locale/en-US/atmos/portable-scrubber.ftl b/Resources/Locale/en-US/atmos/portable-scrubber.ftl index c4071b4acce..8aadf076d96 100644 --- a/Resources/Locale/en-US/atmos/portable-scrubber.ftl +++ b/Resources/Locale/en-US/atmos/portable-scrubber.ftl @@ -1 +1,4 @@ portable-scrubber-fill-level = It's at about [color=yellow]{$percent}%[/color] of its maximum internal pressure. + +portable-scrubber-component-upgrade-max-pressure = max pressure +portable-scrubber-component-upgrade-transfer-rate = transfer rate diff --git a/Resources/Locale/en-US/botany/components/seed-extractor-component.ftl b/Resources/Locale/en-US/botany/components/seed-extractor-component.ftl index 84d5a5ed283..c586a594a9a 100644 --- a/Resources/Locale/en-US/botany/components/seed-extractor-component.ftl +++ b/Resources/Locale/en-US/botany/components/seed-extractor-component.ftl @@ -2,3 +2,5 @@ seed-extractor-component-interact-message = You extract some seeds from the { THE($name) }. seed-extractor-component-no-seeds = { CAPITALIZE(THE($name)) } has no seeds! + +seed-extractor-component-upgrade-seed-yield = seed yield diff --git a/Resources/Locale/en-US/cargo/cargo-console-component.ftl b/Resources/Locale/en-US/cargo/cargo-console-component.ftl index b56f4730ccd..1caa810f1b7 100644 --- a/Resources/Locale/en-US/cargo/cargo-console-component.ftl +++ b/Resources/Locale/en-US/cargo/cargo-console-component.ftl @@ -45,3 +45,5 @@ cargo-shuttle-console-station-unknown = Unknown cargo-shuttle-console-shuttle-not-found = Not found cargo-shuttle-console-organics = Detected organic lifeforms on the shuttle cargo-no-shuttle = No cargo shuttle found! + +cargo-telepad-delay-upgrade = Teleport delay diff --git a/Resources/Locale/en-US/chemistry/components/solution-heater-component.ftl b/Resources/Locale/en-US/chemistry/components/solution-heater-component.ftl new file mode 100644 index 00000000000..cecf15550c7 --- /dev/null +++ b/Resources/Locale/en-US/chemistry/components/solution-heater-component.ftl @@ -0,0 +1 @@ +solution-heater-upgrade-heat = Heat strength diff --git a/Resources/Locale/en-US/construction/components/machine-part-component.ftl b/Resources/Locale/en-US/construction/components/machine-part-component.ftl new file mode 100644 index 00000000000..0613f505161 --- /dev/null +++ b/Resources/Locale/en-US/construction/components/machine-part-component.ftl @@ -0,0 +1,2 @@ +machine-part-component-on-examine-rating-text = [color=white]Rating:[/color] [color=cyan]{$rating}[/color] +machine-part-component-on-examine-type-text = [color=white]Type:[/color] [color=cyan]{$type}[/color] diff --git a/Resources/Locale/en-US/kitchen/components/microwave-component.ftl b/Resources/Locale/en-US/kitchen/components/microwave-component.ftl index 0603b3c8463..12346ee75dc 100644 --- a/Resources/Locale/en-US/kitchen/components/microwave-component.ftl +++ b/Resources/Locale/en-US/kitchen/components/microwave-component.ftl @@ -9,6 +9,7 @@ microwave-component-suicide-multi-head-others-message = {$victim} is trying to c microwave-component-suicide-others-message = {$victim} is trying to cook their head! microwave-component-suicide-multi-head-message = You cook your heads! microwave-component-suicide-message = You cook your head! +microwave-component-upgrade-cook-time = cook time microwave-component-interact-full = It's full. microwave-component-interact-item-too-big = { CAPITALIZE(THE($item)) } is too big to fit in the microwave! diff --git a/Resources/Locale/en-US/kitchen/components/reagent-grinder-component.ftl b/Resources/Locale/en-US/kitchen/components/reagent-grinder-component.ftl index 8a3ca9eef85..34951282745 100644 --- a/Resources/Locale/en-US/kitchen/components/reagent-grinder-component.ftl +++ b/Resources/Locale/en-US/kitchen/components/reagent-grinder-component.ftl @@ -4,6 +4,9 @@ reagent-grinder-bound-user-interface-instant-button = INSTANT reagent-grinder-bound-user-interface-cook-time-label = COOK TIME reagent-grinder-component-cannot-put-entity-message = You can't put this in the reagent grinder! +reagent-grinder-component-upgrade-work-time = Work time +reagent-grinder-component-upgrade-storage = Storage + grinder-menu-title = All-In-One Grinder 3000 grinder-menu-grind-button = Grind grinder-menu-juice-button = Juice diff --git a/Resources/Locale/en-US/machine/machine.ftl b/Resources/Locale/en-US/machine/machine.ftl index ce8873df6f8..26059505160 100644 --- a/Resources/Locale/en-US/machine/machine.ftl +++ b/Resources/Locale/en-US/machine/machine.ftl @@ -13,6 +13,11 @@ machine-part-name-manipulator = Manipulator machine-part-name-matter-bin = Matter Bin machine-part-name-power-cell = Power Cell +upgrade-power-draw = power draw +upgrade-max-charge = max charge +upgrade-power-supply = power supply +upgrade-power-supply-ramping = power ramp rate + two-way-lever-left = push left two-way-lever-right = push right two-way-lever-cant = can't push the lever that way! diff --git a/Resources/Locale/en-US/materials/materials.ftl b/Resources/Locale/en-US/materials/materials.ftl index dca520b5b49..5a4413348e8 100644 --- a/Resources/Locale/en-US/materials/materials.ftl +++ b/Resources/Locale/en-US/materials/materials.ftl @@ -35,3 +35,6 @@ materials-raw-plasma = raw plasma materials-raw-uranium = raw uranium materials-raw-bananium = raw bananium materials-raw-salt = raw salt + +# Material Reclaimer +material-reclaimer-upgrade-process-rate = process rate diff --git a/Resources/Locale/en-US/medical/components/biomass-reclaimer-component.ftl b/Resources/Locale/en-US/medical/components/biomass-reclaimer-component.ftl index 443429c1ef3..0c0b8faf59e 100644 --- a/Resources/Locale/en-US/medical/components/biomass-reclaimer-component.ftl +++ b/Resources/Locale/en-US/medical/components/biomass-reclaimer-component.ftl @@ -1 +1,4 @@ biomass-reclaimer-suicide-others = {CAPITALIZE(THE($victim))} threw themselves into the biomass reclaimer! + +biomass-reclaimer-component-upgrade-speed = speed +biomass-reclaimer-component-upgrade-biomass-yield = biomass yield diff --git a/Resources/Locale/en-US/medical/components/cloning-pod-component.ftl b/Resources/Locale/en-US/medical/components/cloning-pod-component.ftl index b222d707a0a..e92ac86a1e4 100644 --- a/Resources/Locale/en-US/medical/components/cloning-pod-component.ftl +++ b/Resources/Locale/en-US/medical/components/cloning-pod-component.ftl @@ -1,3 +1,5 @@ cloning-pod-biomass = It currently has [color=red]{$number}[/color] units of biomass. +cloning-pod-component-upgrade-speed = cloning speed +cloning-pod-component-upgrade-biomass-requirement = biomass requirement cloning-pod-component-upgrade-emag-requirement = The card zaps something inside the cloning pod. diff --git a/Resources/Locale/en-US/medical/components/medical-scanner-component.ftl b/Resources/Locale/en-US/medical/components/medical-scanner-component.ftl index c4b19426545..da4dc7a3847 100644 --- a/Resources/Locale/en-US/medical/components/medical-scanner-component.ftl +++ b/Resources/Locale/en-US/medical/components/medical-scanner-component.ftl @@ -2,3 +2,5 @@ medical-scanner-verb-enter = Enter medical-scanner-verb-noun-occupant = occupant + +medical-scanner-upgrade-cloning = Cloning fail chance diff --git a/Resources/Locale/en-US/medical/components/stasis-bed-component.ftl b/Resources/Locale/en-US/medical/components/stasis-bed-component.ftl new file mode 100644 index 00000000000..2d8a18c263e --- /dev/null +++ b/Resources/Locale/en-US/medical/components/stasis-bed-component.ftl @@ -0,0 +1 @@ +stasis-bed-component-upgrade-stasis = stasis effect diff --git a/Resources/Locale/en-US/nutrition/components/fat-extractor.ftl b/Resources/Locale/en-US/nutrition/components/fat-extractor.ftl index 20a31cd8c40..611b8ef5406 100644 --- a/Resources/Locale/en-US/nutrition/components/fat-extractor.ftl +++ b/Resources/Locale/en-US/nutrition/components/fat-extractor.ftl @@ -1,3 +1,5 @@ +fat-extractor-component-rate = extraction rate + fat-extractor-fact-1 = Fats are triglycerides made up of a combination of different building blocks; glycerol and fatty acids. fat-extractor-fact-2 = Adults should get a recommended 20-35% of their energy intake from fat. fat-extractor-fact-3 = Being overweight or obese puts you at an increased risk of chronic diseases, such as cardiovascular diseases, metabolic syndrome, type 2 diabetes, and some types of cancers. diff --git a/Resources/Locale/en-US/shuttles/thruster.ftl b/Resources/Locale/en-US/shuttles/thruster.ftl index 94035811c73..faed6e8dd28 100644 --- a/Resources/Locale/en-US/shuttles/thruster.ftl +++ b/Resources/Locale/en-US/shuttles/thruster.ftl @@ -3,3 +3,5 @@ thruster-comp-disabled = The thruster is turned [color=red]off[/color]. thruster-comp-nozzle-direction = The nozzle is facing [color=yellow]{$direction}[/color]. thruster-comp-nozzle-exposed = The nozzle [color=green]exposed[/color] to space. thruster-comp-nozzle-not-exposed = The nozzle [color=red]is not exposed[/color] to space. + +thruster-comp-upgrade-thrust = Thrust strength diff --git a/Resources/Locale/en-US/singularity/components/emitter-component.ftl b/Resources/Locale/en-US/singularity/components/emitter-component.ftl index c71b3d6bdfd..c7db1a93bba 100644 --- a/Resources/Locale/en-US/singularity/components/emitter-component.ftl +++ b/Resources/Locale/en-US/singularity/components/emitter-component.ftl @@ -11,5 +11,8 @@ comp-emitter-turned-off = The {$target} turns off. # Shows if the user attempts to activate the emitter while it's un-anchored. comp-emitter-not-anchored = The {$target} isn't anchored to the ground! +# Upgrades +emitter-component-upgrade-fire-rate = fire rate + emitter-component-current-type = The current selected type is: {$type}. emitter-component-type-set = Type set to: {$type} diff --git a/Resources/Locale/en-US/xenoarchaeology/traversal-distorter.ftl b/Resources/Locale/en-US/xenoarchaeology/traversal-distorter.ftl index 5c9eac57a5d..af3039e864e 100644 --- a/Resources/Locale/en-US/xenoarchaeology/traversal-distorter.ftl +++ b/Resources/Locale/en-US/xenoarchaeology/traversal-distorter.ftl @@ -3,3 +3,5 @@ traversal-distorter-set-out = Traversal bias set to "out" traversal-distorter-desc-in = The affected artifact's traversal now favors moving inwards to the beginning. traversal-distorter-desc-out = The affected artifact's traversal now favors moving outwards towards more dangerous nodes. + +traversal-distorter-upgrade-bias = Bias effectiveness diff --git a/Resources/Migrations/migration.yml b/Resources/Migrations/migration.yml index 7f19699ad8a..3b4a7178cf8 100644 --- a/Resources/Migrations/migration.yml +++ b/Resources/Migrations/migration.yml @@ -126,28 +126,6 @@ DrinkGoldschlagerGlass: DrinkGildlagerGlass ClosetBase: ClosetSteelBase MonkeyCubeBox: VariantCubeBox -# 2024-01-08 -SalvagePartsT4Spawner: SalvageLootSpawner -SalvagePartsT3Spawner: SalvageLootSpawner -SalvagePartsT3T4Spawner: SalvageLootSpawner -SalvagePartsT2Spawner: SalvageLootSpawner -AdvancedCapacitorStockPart: CapacitorStockPart -SuperCapacitorStockPart: CapacitorStockPart -QuadraticCapacitorStockPart: CapacitorStockPart -NanoManipulatorStockPart: MicroManipulatorStockPart -PicoManipulatorStockPart: MicroManipulatorStockPart -FemtoManipulatorStockPart: MicroManipulatorStockPart -AdvancedMatterBinStockPart: MatterBinStockPart -SuperMatterBinStockPart: MatterBinStockPart -BluespaceMatterBinStockPart: MatterBinStockPart -AnsibleSubspaceStockPart: null -FilterSubspaceStockPart: null -AmplifierSubspaceStockPart: null -TreatmentSubspaceStockPart: null -AnalyzerSubspaceStockPart: null -CrystalSubspaceStockPart: null -TransmitterSubspaceStockPart: null - # 2024-01-10 ClothingHeadHatHoodRad: null diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/salvage.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/salvage.yml index 34bf32d8d7b..4beffbc9c22 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/salvage.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/salvage.yml @@ -63,23 +63,78 @@ offset: 0.0 - type: entity - name: salvage loot spawner - id: SalvageLootSpawner + name: Salvage T2 Machine Parts Spawner + id: SalvagePartsT2Spawner parent: MarkerBase components: - type: Sprite layers: - state: red - - sprite: Objects/Weapons/Melee/crusher.rsi - state: icon + - sprite: Objects/Misc/stock_parts.rsi + state: advanced_matter_bin - type: RandomSpawner prototypes: - - WeaponCrusher - - WeaponCrusherDagger - - WeaponCrusherGlaive - - MiningDrill + - AdvancedCapacitorStockPart + - NanoManipulatorStockPart + - AdvancedMatterBinStockPart offset: 0.0 +- type: entity + parent: MarkerBase + id: SalvagePartsT3T4Spawner + name: tier 3/4 machine part + components: + - type: Sprite + layers: + - sprite: Objects/Misc/stock_parts.rsi + state: super_matter_bin + - type: RandomSpawner + rarePrototypes: + - QuadraticCapacitorStockPart + - FemtoManipulatorStockPart + - BluespaceMatterBinStockPart + rareChance: 0.05 + prototypes: + - SuperCapacitorStockPart + - PicoManipulatorStockPart + - SuperMatterBinStockPart + chance: 0.95 + offset: 0.0 + +- type: entity + parent: MarkerBase + id: SalvagePartsT3Spawner + name: tier 3 machine part + suffix: Spawner + components: + - type: Sprite + layers: + - sprite: Objects/Misc/stock_parts.rsi + state: super_matter_bin + - type: RandomSpawner + prototypes: + - SuperCapacitorStockPart + - PicoManipulatorStockPart + - SuperMatterBinStockPart + offset: 0.0 + +- type: entity + parent: MarkerBase + id: SalvagePartsT4Spawner + name: tier 4 machine part + suffix: Spawner + components: + - type: Sprite + layers: + - sprite: Objects/Misc/stock_parts.rsi + state: bluespace_matter_bin + - type: RandomSpawner + prototypes: + - QuadraticCapacitorStockPart + - PicoManipulatorStockPart + - BluespaceMatterBinStockPart + offset: 0.0 + - type: entity name: Salvage Mob Spawner id: SalvageMobSpawner @@ -228,3 +283,25 @@ - MobFleshLoverSalvage chance: 1 offset: 0.2 + +- type: entity + name: Salvage Loot Spawner + id: SalvageLootSpawner + parent: MarkerBase + components: + - type: Sprite + layers: + - state: red + - sprite: Structures/Storage/Crates/generic.rsi + state: icon + - type: RandomSpawner + rarePrototypes: + - SalvagePartsT2Spawner + - SalvagePartsT3Spawner + - SalvagePartsT3T4Spawner + - SalvagePartsT4Spawner + rareChance: 0.4 + prototypes: + - CrateSalvageAssortedGoodies + chance: 0.9 + offset: 0.2 diff --git a/Resources/Prototypes/Entities/Objects/Misc/machine_parts.yml b/Resources/Prototypes/Entities/Objects/Misc/machine_parts.yml index 341acb52f0b..d90b03528e5 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/machine_parts.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/machine_parts.yml @@ -16,6 +16,10 @@ sound: /Audio/SimpleStation14/Items/Handling/component_drop.ogg - type: EmitSoundOnLand sound: /Audio/SimpleStation14/Items/Handling/component_drop.ogg +# Rating 1 + - type: GuideHelp + guides: + - MachineUpgrading # Rating 1 @@ -69,3 +73,218 @@ - type: ReverseEngineering # Nyano recipes: - MatterBinStockPart + +# Rating 2 + +- type: entity + id: AdvancedCapacitorStockPart + name: advanced capacitor + parent: CapacitorStockPart + description: An advanced capacitor used in the construction of a variety of devices. + suffix: Rating 2 + components: + - type: Sprite + state: adv_capacitor + - type: MachinePart + rating: 2 + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - AdvancedCapacitorStockPart + +- type: entity + id: NanoManipulatorStockPart + name: advanced manipulator + parent: MicroManipulatorStockPart + description: An advanced manipulator used in the construction of a variety of devices. + suffix: Rating 2 + components: + - type: Sprite + state: nano_mani + - type: MachinePart + rating: 2 + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - NanoManipulatorStockPart + +- type: entity + id: AdvancedMatterBinStockPart + name: advanced matter bin + parent: MatterBinStockPart + description: An advanced matter bin used in the construction of a variety of devices. + suffix: Rating 2 + components: + - type: Sprite + state: advanced_matter_bin + - type: MachinePart + rating: 2 + - type: ReverseEngineering # Nyano + difficulty: 2 + recipes: + - AdvancedMatterBinStockPart + +# Rating 3 + +- type: entity + id: SuperCapacitorStockPart + name: super capacitor + parent: CapacitorStockPart + description: A super capacitor used in the construction of a variety of devices. + suffix: Rating 3 + components: + - type: Sprite + state: super_capacitor + - type: MachinePart + rating: 3 + - type: ReverseEngineering # Nyano + difficulty: 3 + recipes: + - SuperCapacitorStockPart + +- type: entity + id: PicoManipulatorStockPart + name: super manipulator + parent: MicroManipulatorStockPart + description: A super manipulator used in the construction of a variety of devices. + suffix: Rating 3 + components: + - type: Sprite + state: pico_mani + - type: MachinePart + rating: 3 + - type: ReverseEngineering # Nyano + difficulty: 3 + recipes: + - PicoManipulatorStockPart + +- type: entity + id: SuperMatterBinStockPart + name: super matter bin + parent: MatterBinStockPart + description: A super matter bin used in the construction of a variety of devices. + suffix: Rating 3 + components: + - type: Sprite + state: super_matter_bin + - type: MachinePart + rating: 3 + - type: ReverseEngineering # Nyano + difficulty: 3 + recipes: + - SuperMatterBinStockPart + +# Rating 4 + +- type: entity + id: QuadraticCapacitorStockPart + name: bluespace capacitor + parent: CapacitorStockPart + description: A bluespace capacitor used in the construction of a variety of devices. + suffix: Rating 4 + components: + - type: Sprite + state: quadratic_capacitor + - type: MachinePart + rating: 4 + - type: ReverseEngineering # Nyano + difficulty: 4 + recipes: + - QuadraticCapacitorStockPart + +- type: entity + id: FemtoManipulatorStockPart + name: bluespace manipulator + parent: MicroManipulatorStockPart + description: A bluespace manipulator used in the construction of a variety of devices. + suffix: Rating 4 + components: + - type: Sprite + state: femto_mani + - type: MachinePart + rating: 4 + - type: ReverseEngineering # Nyano + difficulty: 4 + recipes: + - FemtoManipulatorStockPart + +- type: entity + id: BluespaceMatterBinStockPart + name: bluespace matter bin + parent: MatterBinStockPart + description: A bluespace matter bin used in the construction of a variety of devices. + suffix: Rating 4 + components: + - type: Sprite + state: bluespace_matter_bin + - type: MachinePart + rating: 4 + - type: ReverseEngineering # Nyano + difficulty: 4 + recipes: + - BluespaceMatterBinStockPart + +# Subspace stock parts (REMOVE THESE) + +- type: entity + id: AnsibleSubspaceStockPart + name: subspace ansible + parent: BaseStockPart + description: A compact module capable of sensing extradimensional activity. + components: + - type: Sprite + state: subspace_ansible + +- type: entity + id: FilterSubspaceStockPart + name: hyperwave filter + parent: BaseStockPart + description: A tiny device capable of filtering and converting super-intense radiowaves. + components: + - type: Sprite + state: hyperwave_filter + +- type: entity + id: AmplifierSubspaceStockPart + name: subspace amplifier + parent: BaseStockPart + description: A compact micro-machine capable of amplifying weak subspace transmissions. + components: + - type: Sprite + state: subspace_amplifier + +- type: entity + id: TreatmentSubspaceStockPart + name: subspace treatment disk + parent: BaseStockPart + description: A compact micro-machine capable of stretching out hyper-compressed radio waves. + components: + - type: Sprite + state: treatment_disk + +- type: entity + id: AnalyzerSubspaceStockPart + name: subspace wavelength analyzer + parent: BaseStockPart + description: A sophisticated analyzer capable of analyzing cryptic subspace wavelengths. + components: + - type: Sprite + state: wavelength_analyzer + +- type: entity + id: CrystalSubspaceStockPart + name: ansible crystal + parent: BaseStockPart + description: A crystal made from pure glass used to transmit laser databursts to subspace. + components: + - type: Sprite + state: ansible_crystal + +- type: entity + id: TransmitterSubspaceStockPart + name: subspace transmitter + parent: BaseStockPart + description: A large piece of equipment used to open a window into the subspace dimension. + components: + - type: Sprite + state: subspace_transmitter diff --git a/Resources/Prototypes/Entities/Objects/Specific/Research/rped.yml b/Resources/Prototypes/Entities/Objects/Specific/Research/rped.yml index 84a51b4f345..fca8c8ae85f 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Research/rped.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Research/rped.yml @@ -10,6 +10,9 @@ - type: Item sprite: Objects/Specific/Research/rped.rsi size: Normal + - type: GuideHelp + guides: + - MachineUpgrading - type: PartExchanger - type: Storage grid: diff --git a/Resources/Prototypes/Entities/Structures/Dispensers/chem.yml b/Resources/Prototypes/Entities/Structures/Dispensers/chem.yml index 681f0a390c8..6e331a13a8c 100644 --- a/Resources/Prototypes/Entities/Structures/Dispensers/chem.yml +++ b/Resources/Prototypes/Entities/Structures/Dispensers/chem.yml @@ -31,6 +31,9 @@ acts: ["Destruction"] - type: Machine board: ChemDispenserMachineCircuitboard + - type: UpgradePowerDraw + powerDrawMultiplier: 0.75 + scaling: Exponential - type: GuideHelp guides: - Chemicals diff --git a/Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml b/Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml index ab09a03fef7..e6f08fe8467 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/anomaly_equipment.yml @@ -176,8 +176,8 @@ SetParticleZeta: AnomalousParticleZeta SetParticleSigma: AnomalousParticleSigma fireBurstSize: 1 - fireBurstDelayMin: 2 - fireBurstDelayMax: 6 + baseFireBurstDelayMin: 2 + baseFireBurstDelayMax: 6 - type: ApcPowerReceiver powerLoad: 100 - type: GuideHelp diff --git a/Resources/Prototypes/Entities/Structures/Machines/anomaly_sync.yml b/Resources/Prototypes/Entities/Structures/Machines/anomaly_sync.yml index 3019b8adf83..eeaae611c37 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/anomaly_sync.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/anomaly_sync.yml @@ -41,7 +41,7 @@ bounds: "-0.35,-0.35,0.35,0.35" density: 100 mask: - - ItemMask + - ItemMask hard: True - type: Transform anchored: true @@ -49,6 +49,9 @@ - type: ApcPowerReceiver powerLoad: 2500 needsPower: true + - type: UpgradePowerDraw + powerDrawMultiplier: 0.80 + scaling: Exponential - type: ItemPlacer whitelist: components: diff --git a/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml b/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml index 18999a6ab2a..2bea530e908 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/artifact_analyzer.yml @@ -107,6 +107,9 @@ hard: False - type: Transform noRot: false + - type: UpgradePowerDraw + powerDrawMultiplier: 0.80 + scaling: Exponential - type: TraversalDistorter - type: ItemPlacer # don't limit the number of artifacts that can be biased diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index e5a9cb35417..52e9096791b 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -294,6 +294,12 @@ - Implanter - PillCanister - ChemistryEmptyBottle01 + - AdvancedCapacitorStockPart + - AdvancedMatterBinStockPart + - NanoManipulatorStockPart + - SuperCapacitorStockPart + - SuperMatterBinStockPart + - PicoManipulatorStockPart - AdvMopItem - WeaponSprayNozzle - ClothingBackpackWaterTank diff --git a/Resources/Prototypes/Entities/Structures/Machines/seed_extractor.yml b/Resources/Prototypes/Entities/Structures/Machines/seed_extractor.yml index ec07294bfb1..4ecd1c29e27 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/seed_extractor.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/seed_extractor.yml @@ -35,3 +35,6 @@ - type: SeedExtractor - type: Machine board: SeedExtractorMachineCircuitboard + - type: UpgradePowerDraw + powerDrawMultiplier: 0.75 + scaling: Exponential diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml index 4fa1bcbd918..35d65ffe87a 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml @@ -171,6 +171,9 @@ materialWhiteList: [Plasma] - type: PortableGenerator startChance: 0.8 + - type: UpgradePowerSupplier + powerSupplyMultiplier: 1.25 + scaling: Exponential - type: GeneratorExhaustGas gasType: CarbonDioxide # 2 moles of gas for every sheet of plasma. @@ -228,6 +231,9 @@ storageLimit: 3000 materialWhiteList: [Uranium] - type: PortableGenerator + - type: UpgradePowerSupplier + powerSupplyMultiplier: 1.25 + scaling: Exponential - type: PowerMonitoringDevice group: Generator loadNodes: diff --git a/Resources/Prototypes/Entities/Structures/Power/smes.yml b/Resources/Prototypes/Entities/Structures/Power/smes.yml index 1e3559e5a95..762e8d375f6 100644 --- a/Resources/Prototypes/Entities/Structures/Power/smes.yml +++ b/Resources/Prototypes/Entities/Structures/Power/smes.yml @@ -29,10 +29,15 @@ state: "smes-op1" shader: unshaded - type: Smes + - type: UpgradeBattery + maxChargeMultiplier: 2 + baseMaxCharge: 8000000 + - type: UpgradePowerSupplyRamping + scaling: Linear + supplyRampingMultiplier: 1 - type: Appearance - type: Battery startingCharge: 0 - maxCharge: 8000000 - type: ExaminableBattery - type: NodeContainer examinable: true diff --git a/Resources/Prototypes/Entities/Structures/Power/substation.yml b/Resources/Prototypes/Entities/Structures/Power/substation.yml index 347b18ecaee..489cfff6597 100644 --- a/Resources/Prototypes/Entities/Structures/Power/substation.yml +++ b/Resources/Prototypes/Entities/Structures/Power/substation.yml @@ -17,8 +17,13 @@ shader: unshaded - state: full shader: unshaded + - type: UpgradeBattery + maxChargeMultiplier: 2 + baseMaxCharge: 2500000 + - type: UpgradePowerSupplyRamping + scaling: Linear + supplyRampingMultiplier: 1 - type: Battery - maxCharge: 2500000 startingCharge: 0 - type: ExaminableBattery - type: PointLight diff --git a/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml b/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml index f87be426598..eb299e3f3a6 100644 --- a/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml +++ b/Resources/Prototypes/Entities/Structures/Shuttles/thrusters.yml @@ -143,6 +143,7 @@ - type: Thruster thrusterType: Angular requireSpace: false + baseThrust: 2000 thrust: 2000 machinePartThrust: Manipulator - type: Sprite @@ -192,6 +193,9 @@ collection: MetalBreak - !type:ChangeConstructionNodeBehavior node: machineFrame + - type: UpgradePowerDraw + powerDrawMultiplier: 0.75 + scaling: Exponential - type: Damageable damageContainer: Inorganic damageModifierSet: Electronic @@ -216,6 +220,7 @@ - type: Thruster thrusterType: Angular requireSpace: false + baseThrust: 100 thrust: 100 - type: ApcPowerReceiver needsPower: false diff --git a/Resources/Prototypes/Guidebook/science.yml b/Resources/Prototypes/Guidebook/science.yml index a21be1678ce..c73b666f687 100644 --- a/Resources/Prototypes/Guidebook/science.yml +++ b/Resources/Prototypes/Guidebook/science.yml @@ -7,6 +7,7 @@ - AnomalousResearch - Xenoarchaeology - Robotics + - MachineUpgrading - Psionics # Nyanotrasen - Psionics guidebook # - AltarsGolemancy # When it's added # Nyanotrasen - Golemancy guidebook - ReverseEngineering # Nyanotrasen - Reverse Engineering guidebook @@ -60,6 +61,11 @@ name: guide-entry-traversal-distorter text: "/ServerInfo/Guidebook/Science/TraversalDistorter.xml" +- type: guideEntry + id: MachineUpgrading + name: guide-entry-machine-upgrading + text: "/ServerInfo/Guidebook/Science/MachineUpgrading.xml" + - type: guideEntry id: Cyborgs name: guide-entry-cyborgs diff --git a/Resources/Prototypes/Recipes/Lathes/Parts.yml b/Resources/Prototypes/Recipes/Lathes/Parts.yml index 90cff2174d6..496bc3a8a48 100644 --- a/Resources/Prototypes/Recipes/Lathes/Parts.yml +++ b/Resources/Prototypes/Recipes/Lathes/Parts.yml @@ -1,3 +1,4 @@ +#Rating 1 - type: latheRecipe id: CapacitorStockPart result: CapacitorStockPart @@ -24,3 +25,62 @@ materials: Steel: 50 Plastic: 50 + +#Rating 2 +- type: latheRecipe + id: AdvancedCapacitorStockPart + result: AdvancedCapacitorStockPart + completetime: 3 + materials: + Steel: 80 + Plastic: 80 + Plasma: 75 + +- type: latheRecipe + id: AdvancedMatterBinStockPart + result: AdvancedMatterBinStockPart + completetime: 3 + materials: + Steel: 80 + Plastic: 80 + Plasma: 75 + +- type: latheRecipe + id: NanoManipulatorStockPart + result: NanoManipulatorStockPart + completetime: 3 + materials: + Steel: 80 + Plastic: 80 + Plasma: 75 + +#Rating 3 +- type: latheRecipe + id: SuperCapacitorStockPart + result: SuperCapacitorStockPart + completetime: 3 + materials: + Steel: 150 + Plastic: 150 + Plasma: 75 + Gold: 75 + +- type: latheRecipe + id: SuperMatterBinStockPart + result: SuperMatterBinStockPart + completetime: 3 + materials: + Steel: 150 + Plastic: 150 + Plasma: 75 + Gold: 75 + +- type: latheRecipe + id: PicoManipulatorStockPart + result: PicoManipulatorStockPart + completetime: 3 + materials: + Steel: 150 + Plastic: 150 + Plasma: 75 + Gold: 75 diff --git a/Resources/Prototypes/Research/experimental.yml b/Resources/Prototypes/Research/experimental.yml index d46e1db144e..85523033f86 100644 --- a/Resources/Prototypes/Research/experimental.yml +++ b/Resources/Prototypes/Research/experimental.yml @@ -84,6 +84,20 @@ # Tier 2 +- type: technology + id: AdvancedParts + name: research-technology-advanced-parts + icon: + sprite: Objects/Misc/stock_parts.rsi + state: advanced_matter_bin + discipline: Experimental + tier: 2 + cost: 10000 + recipeUnlocks: + - AdvancedCapacitorStockPart + - AdvancedMatterBinStockPart + - NanoManipulatorStockPart + - type: technology id: AbnormalArtifactManipulation name: research-technology-abnormal-artifact-manipulation @@ -155,6 +169,20 @@ # Tier 3 +- type: technology + id: SuperParts + name: research-technology-super-parts + icon: + sprite: Objects/Misc/stock_parts.rsi + state: super_matter_bin + discipline: Experimental + tier: 3 + cost: 15000 + recipeUnlocks: + - SuperCapacitorStockPart + - SuperMatterBinStockPart + - PicoManipulatorStockPart + #- type: technology # DeltaV - LRP # id: GravityManipulation # name: research-technology-gravity-manipulation diff --git a/Resources/Prototypes/XenoArch/Effects/normal_effects.yml b/Resources/Prototypes/XenoArch/Effects/normal_effects.yml index b9564c0366b..0a0b9bcbcc3 100644 --- a/Resources/Prototypes/XenoArch/Effects/normal_effects.yml +++ b/Resources/Prototypes/XenoArch/Effects/normal_effects.yml @@ -584,6 +584,24 @@ messages: - shuffle-artifact-popup +- type: artifactEffect + id: EffectT4PartsSpawn + targetDepth: 3 + effectHint: artifact-effect-hint-creation + components: + - type: SpawnArtifact + maxSpawns: 10 + spawns: + - id: QuadraticCapacitorStockPart + prob: 0.5 + maxAmount: 3 + - id: FemtoManipulatorStockPart + prob: 0.5 + maxAmount: 3 + - id: BluespaceMatterBinStockPart + prob: 0.5 + maxAmount: 3 + - type: artifactEffect id: EffectFoamDangerous targetDepth: 3 diff --git a/Resources/ServerInfo/Guidebook/Science/MachineUpgrading.xml b/Resources/ServerInfo/Guidebook/Science/MachineUpgrading.xml new file mode 100644 index 00000000000..286219b4d9e --- /dev/null +++ b/Resources/ServerInfo/Guidebook/Science/MachineUpgrading.xml @@ -0,0 +1,38 @@ + +# Machine Upgrading + +Machines help the station run smoothly, and as a scientist, you can help them run even better! + +## Parts +Stock Parts: + + + + + +You can examine each machine part to see both the type and the rating, which range from 1 to 4. + +Parts of higher levels can be researched as well as found through artifacts or salvage. + + + + + + +## Upgrading +To know if a machine can be upgraded, you can examine it and check for the [color=#a4885c]lightning bolt[/color] icon in the lower right corner. Clicking on it will allow you to see what kinds of upgrades the machine has. + +To check what parts a machine needs, you can examine its board. Try it here: + + + + + + +You can use any rating part for any part requirement. Using higher rated parts will increase how effective the machine is. + +If you want to upgrade an existing machine, simply deconstruct it with a screwdriver and crowbar, and replace the existing parts with parts of a higher level. + +You can also quickly upgrade machines by using an RPED, loading it with machine parts, and then clicking on a machine. It will quickly be upgraded with whatever parts were inserted. + + From f126bb4149d01050760818211bcec10d0a418f2f Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Sat, 21 Sep 2024 18:46:59 -0400 Subject: [PATCH 03/21] [Port] Uplink Discounts From White Dream (#930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This is a port of https://github.com/WWhiteDreamProject/wwdpublic/pull/11 from White Dream. This feature selects random items in the traitor uplink each round to be discounted and moved to the Discount tab, which are the same for every traitor. This in theory helps encourage players to be spontaneous, and use items that they otherwise might not normally consider using, which helps mix things up from round to round.

Media

> # Описание PR > Порт скидок в аплинке. > > # Изменения > 🆑 Spatison > > * add: Added discounts in uplink / Добавлены скидки в аплинк

# Changelog :cl: Spatison add: Added discounts in uplink / Добавлены скидки в аплинк --------- Signed-off-by: VMSolidus Co-authored-by: Spatison <137375981+Spatison@users.noreply.github.com> Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com> --- Content.Client/Store/Ui/StoreMenu.xaml.cs | 5 ++ .../Store/Systems/StoreSystem.Ui.cs | 6 ++ Content.Server/Store/Systems/StoreSystem.cs | 6 +- .../StoreDiscount/StoreDiscountSystem.cs | 55 +++++++++++++++++++ .../Store/ListingLocalisationHelpers.cs | 5 ++ Content.Shared/Store/ListingPrototype.cs | 18 ++++++ Content.Shared/Store/StorePresetPrototype.cs | 4 ++ .../StoreDiscount/SalesSpecifier.cs | 38 +++++++++++++ Resources/Locale/en-US/store/sales.ftl | 2 + Resources/Locale/ru-RU/store/sales.ftl | 2 + .../Prototypes/Catalog/uplink_catalog.yml | 38 ++++++++++++- Resources/Prototypes/Store/presets.yml | 8 +++ .../Prototypes/_White/Store/categories.yml | 4 ++ 13 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 Content.Server/StoreDiscount/StoreDiscountSystem.cs create mode 100644 Content.Shared/StoreDiscount/SalesSpecifier.cs create mode 100644 Resources/Locale/en-US/store/sales.ftl create mode 100644 Resources/Locale/ru-RU/store/sales.ftl create mode 100644 Resources/Prototypes/_White/Store/categories.yml diff --git a/Content.Client/Store/Ui/StoreMenu.xaml.cs b/Content.Client/Store/Ui/StoreMenu.xaml.cs index b7a2c285fe5..7eb597f2f39 100644 --- a/Content.Client/Store/Ui/StoreMenu.xaml.cs +++ b/Content.Client/Store/Ui/StoreMenu.xaml.cs @@ -3,6 +3,7 @@ using Content.Client.Message; using Content.Shared.FixedPoint; using Content.Shared.Store; +using Content.Client.Stylesheets; using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.Graphics; @@ -147,6 +148,10 @@ private void AddListingGui(ListingData listing) } var newListing = new StoreListingControl(listing, GetListingPriceString(listing), hasBalance, texture); + + if (listing.DiscountValue > 0) + newListing.StoreItemBuyButton.AddStyleClass(StyleNano.ButtonColorDangerDefault.ToString()); + newListing.StoreItemBuyButton.OnButtonDown += args => OnListingButtonPressed?.Invoke(args, listing); diff --git a/Content.Server/Store/Systems/StoreSystem.Ui.cs b/Content.Server/Store/Systems/StoreSystem.Ui.cs index 25f64ba4b64..7187a704768 100644 --- a/Content.Server/Store/Systems/StoreSystem.Ui.cs +++ b/Content.Server/Store/Systems/StoreSystem.Ui.cs @@ -265,6 +265,12 @@ private void OnBuyRequest(EntityUid uid, StoreComponent component, StoreBuyListi listing.PurchaseAmount++; //track how many times something has been purchased _audio.PlayEntity(component.BuySuccessSound, msg.Session, uid); //cha-ching! + if (listing.SaleLimit != 0 && listing.DiscountValue > 0 && listing.PurchaseAmount >= listing.SaleLimit) + { + listing.DiscountValue = 0; + listing.Cost = listing.OldCost; + } + UpdateUserInterface(buyer, uid, component); } diff --git a/Content.Server/Store/Systems/StoreSystem.cs b/Content.Server/Store/Systems/StoreSystem.cs index 72aeb29d195..a86dffef633 100644 --- a/Content.Server/Store/Systems/StoreSystem.cs +++ b/Content.Server/Store/Systems/StoreSystem.cs @@ -10,6 +10,7 @@ using Robust.Server.GameObjects; using Robust.Shared.Prototypes; using System.Linq; +using Content.Server.StoreDiscount; using Robust.Shared.Utility; namespace Content.Server.Store.Systems; @@ -22,6 +23,7 @@ public sealed partial class StoreSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly StoreDiscountSystem _storeDiscount = default!; public override void Initialize() { @@ -199,6 +201,8 @@ public void InitializeFromPreset(StorePresetPrototype preset, EntityUid uid, Sto if (component.Balance == new Dictionary() && preset.InitialBalance != null) //if we don't have a value stored, use the preset TryAddCurrency(preset.InitialBalance, uid, component); + _storeDiscount.ApplyDiscounts(component.Listings, preset); + var ui = _ui.GetUiOrNull(uid, StoreUiKey.Key); if (ui != null) { @@ -225,7 +229,7 @@ public CurrencyInsertAttemptEvent(EntityUid user, EntityUid target, EntityUid us /// -/// Nyano/DeltaV Code. For penguin bombs and what not. +/// Nyano/DeltaV Code. For penguin bombs and what not. /// Raised on an item when it is purchased. /// An item may need to set it upself up for its purchaser. /// For example, to make sure it isn't hostile to them or diff --git a/Content.Server/StoreDiscount/StoreDiscountSystem.cs b/Content.Server/StoreDiscount/StoreDiscountSystem.cs new file mode 100644 index 00000000000..8f77eba7801 --- /dev/null +++ b/Content.Server/StoreDiscount/StoreDiscountSystem.cs @@ -0,0 +1,55 @@ +using System.Linq; +using Content.Shared.FixedPoint; +using Content.Shared.Store; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.StoreDiscount; + +public sealed class StoreDiscountSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + + public void ApplyDiscounts(IEnumerable listings, StorePresetPrototype store) + { + if (!store.Sales.Enabled) + return; + + var count = _random.Next(store.Sales.MinItems, store.Sales.MaxItems + 1); + + listings = listings + .Where(l => + !l.SaleBlacklist + && l.Cost.Any(x => x.Value > 1) + && store.Categories.Overlaps(ChangedFormatCategories(l.Categories))) + .OrderBy(_ => _random.Next()).Take(count).ToList(); + + foreach (var listing in listings) + { + var sale = GetDiscount(store.Sales.MinMultiplier, store.Sales.MaxMultiplier); + var newCost = listing.Cost.ToDictionary(x => x.Key, + x => FixedPoint2.New(Math.Max(1, (int) MathF.Round(x.Value.Float() * sale)))); + + if (listing.Cost.All(x => x.Value.Int() == newCost[x.Key].Int())) + continue; + + var key = listing.Cost.First(x => x.Value > 0).Key; + listing.OldCost = listing.Cost; + listing.DiscountValue = 100 - (newCost[key] / listing.Cost[key] * 100).Int(); + listing.Cost = newCost; + listing.Categories = new() {store.Sales.SalesCategory}; + } + } + + private IEnumerable ChangedFormatCategories(List> categories) + { + var modified = from p in categories select p.Id; + + return modified; + } + + private float GetDiscount(float minMultiplier, float maxMultiplier) + { + return _random.NextFloat() * (maxMultiplier - minMultiplier) + minMultiplier; + } +} diff --git a/Content.Shared/Store/ListingLocalisationHelpers.cs b/Content.Shared/Store/ListingLocalisationHelpers.cs index 882300109ce..19cd029488f 100644 --- a/Content.Shared/Store/ListingLocalisationHelpers.cs +++ b/Content.Shared/Store/ListingLocalisationHelpers.cs @@ -18,6 +18,11 @@ public static string GetLocalisedNameOrEntityName(ListingData listingData, IProt else if (listingData.ProductEntity != null) name = prototypeManager.Index(listingData.ProductEntity.Value).Name; + if (listingData.DiscountValue > 0) + name += " " + Loc.GetString("store-sales-amount", ("amount", listingData.DiscountValue)); + else if (listingData.OldCost.Count > 0) + name += " " + Loc.GetString("store-sales-over"); + return name; } diff --git a/Content.Shared/Store/ListingPrototype.cs b/Content.Shared/Store/ListingPrototype.cs index d3d2e13cdfd..0b59ab48cb6 100644 --- a/Content.Shared/Store/ListingPrototype.cs +++ b/Content.Shared/Store/ListingPrototype.cs @@ -109,6 +109,19 @@ public partial class ListingData : IEquatable, ICloneable [DataField] public TimeSpan RestockTime = TimeSpan.Zero; + [DataField] + public int SaleLimit = 3; + + [DataField] + public bool SaleBlacklist; + + public int DiscountValue; + + public Dictionary, FixedPoint2> OldCost = new(); + + [DataField] + public List Components = new(); + public bool Equals(ListingData? listing) { if (listing == null) @@ -166,6 +179,11 @@ public object Clone() ProductEvent = ProductEvent, PurchaseAmount = PurchaseAmount, RestockTime = RestockTime, + SaleLimit = SaleLimit, + SaleBlacklist = SaleBlacklist, + DiscountValue = DiscountValue, + OldCost = OldCost, + Components = Components, }; } } diff --git a/Content.Shared/Store/StorePresetPrototype.cs b/Content.Shared/Store/StorePresetPrototype.cs index ce7f0312b60..41ee510bd8e 100644 --- a/Content.Shared/Store/StorePresetPrototype.cs +++ b/Content.Shared/Store/StorePresetPrototype.cs @@ -1,3 +1,4 @@ +using Content.Shared.StoreDiscount; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; @@ -38,4 +39,7 @@ public sealed partial class StorePresetPrototype : IPrototype /// [DataField("currencyWhitelist", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] public HashSet CurrencyWhitelist { get; private set; } = new(); + + [DataField] + public SalesSpecifier Sales { get; private set; } = new(); } diff --git a/Content.Shared/StoreDiscount/SalesSpecifier.cs b/Content.Shared/StoreDiscount/SalesSpecifier.cs new file mode 100644 index 00000000000..21539f85d41 --- /dev/null +++ b/Content.Shared/StoreDiscount/SalesSpecifier.cs @@ -0,0 +1,38 @@ +namespace Content.Shared.StoreDiscount; + +[DataDefinition] +public sealed partial class SalesSpecifier +{ + [DataField] + public bool Enabled { get; private set; } + + [DataField] + public float MinMultiplier { get; private set; } + + [DataField] + public float MaxMultiplier { get; private set; } + + [DataField] + public int MinItems { get; private set; } + + [DataField] + public int MaxItems { get; private set; } + + [DataField] + public string SalesCategory { get; private set; } = string.Empty; + + public SalesSpecifier() + { + } + + public SalesSpecifier(bool enabled, float minMultiplier, float maxMultiplier, int minItems, int maxItems, + string salesCategory) + { + Enabled = enabled; + MinMultiplier = minMultiplier; + MaxMultiplier = maxMultiplier; + MinItems = minItems; + MaxItems = maxItems; + SalesCategory = salesCategory; + } +} diff --git a/Resources/Locale/en-US/store/sales.ftl b/Resources/Locale/en-US/store/sales.ftl new file mode 100644 index 00000000000..7223a8a0dcd --- /dev/null +++ b/Resources/Locale/en-US/store/sales.ftl @@ -0,0 +1,2 @@ +store-sales-amount = [DISCOUNT] { $amount }%! +store-sales-over = [The sale is over] diff --git a/Resources/Locale/ru-RU/store/sales.ftl b/Resources/Locale/ru-RU/store/sales.ftl new file mode 100644 index 00000000000..93f1798fe79 --- /dev/null +++ b/Resources/Locale/ru-RU/store/sales.ftl @@ -0,0 +1,2 @@ +store-sales-amount = [СКИДКА] { $amount }%! +store-sales-over = [Скидка закончилась] diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index a1a60e3fef0..bdd27e83a89 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -10,6 +10,7 @@ Telecrystal: 3 categories: - UplinkWeapons + saleLimit: 1 - type: listing id: UplinkRevolverPython @@ -20,6 +21,7 @@ Telecrystal: 8 # Originally was 13 TC but was not used due to high cost categories: - UplinkWeapons + saleLimit: 1 # Inbuilt suppressor so it's sneaky + more expensive. - type: listing @@ -31,6 +33,7 @@ Telecrystal: 4 categories: - UplinkWeapons + saleLimit: 1 # Poor accuracy, slow to fire, cheap option - type: listing @@ -42,6 +45,7 @@ Telecrystal: 1 categories: - UplinkWeapons + saleLimit: 1 - type: listing id: UplinkEsword @@ -53,6 +57,7 @@ Telecrystal: 8 categories: - UplinkWeapons + saleLimit: 2 - type: listing id: UplinkEnergyDagger @@ -64,6 +69,7 @@ Telecrystal: 2 categories: - UplinkWeapons + saleLimit: 1 - type: listing id: UplinkThrowingKnivesKit @@ -85,6 +91,7 @@ Telecrystal: 8 categories: - UplinkWeapons + saleLimit: 1 - type: listing id: UplinkDisposableTurret @@ -100,6 +107,7 @@ blacklist: tags: - NukeOpsUplink + saleLimit: 2 - type: listing id: BaseBallBatHomeRun @@ -112,6 +120,7 @@ Telecrystal: 16 categories: - UplinkWeapons + saleLimit: 1 # Explosives @@ -214,6 +223,7 @@ whitelist: tags: - NukeOpsUplink + saleLimit: 1 - type: listing id: UplinkC4Bundle @@ -224,6 +234,7 @@ Telecrystal: 12 #you're buying bulk so its a 25% discount categories: - UplinkExplosives + saleLimit: 1 - type: listing id: UplinkEmpGrenade @@ -261,6 +272,7 @@ blacklist: tags: - NukeOpsUplink + saleLimit: 1 - type: listing id: UplinkSyndicateBombNukie @@ -276,6 +288,7 @@ whitelist: tags: - NukeOpsUplink + saleLimit: 1 - type: listing id: UplinkClusterGrenade @@ -451,6 +464,7 @@ blacklist: tags: - NukeOpsUplink + saleLimit: 1 - type: listing id: UplinkReinforcementRadioSyndicateNukeops # Version for Nukeops that spawns an agent with the NukeOperative component. @@ -467,6 +481,7 @@ whitelist: tags: - NukeOpsUplink + saleLimit: 1 - type: listing id: UplinkReinforcementRadioSyndicateCyborgAssault @@ -483,6 +498,7 @@ whitelist: tags: - NukeOpsUplink + saleLimit: 1 - type: listing id: UplinkReinforcementRadioSyndicateMonkey @@ -515,6 +531,7 @@ whitelist: tags: - NukeOpsUplink + saleLimit: 1 - type: listing id: UplinkStealthBox @@ -545,7 +562,6 @@ productEntity: EncryptionKeyBinary cost: Telecrystal: 1 - categories: - UplinkUtility @@ -748,6 +764,7 @@ blacklist: tags: - NukeOpsUplink + saleBlacklist: true - type: listing id: UplinkDeathRattle @@ -821,6 +838,7 @@ blacklist: components: - SurplusBundle + saleLimit: 1 - type: listing id: UplinkChemistryKitBundle @@ -862,6 +880,7 @@ blacklist: components: - SurplusBundle + saleLimit: 1 - type: listing id: UplinkSniperBundle @@ -873,6 +892,7 @@ Telecrystal: 12 categories: - UplinkBundles + saleLimit: 1 - type: listing id: UplinkC20RBundle @@ -884,6 +904,7 @@ Telecrystal: 17 categories: - UplinkBundles + saleLimit: 1 - type: listing id: UplinkBulldogBundle @@ -895,6 +916,7 @@ Telecrystal: 20 categories: - UplinkBundles + saleLimit: 1 - type: listing id: UplinkGrenadeLauncherBundle @@ -906,6 +928,7 @@ Telecrystal: 25 categories: - UplinkBundles + saleLimit: 1 - type: listing id: UplinkL6SawBundle @@ -917,6 +940,7 @@ Telecrystal: 30 categories: - UplinkBundles + saleLimit: 1 - type: listing id: UplinkZombieBundle @@ -937,6 +961,7 @@ blacklist: components: - SurplusBundle + saleLimit: 1 - type: listing id: UplinkSurplusBundle @@ -956,6 +981,7 @@ blacklist: components: - SurplusBundle + saleBlacklist: true - type: listing id: UplinkSuperSurplusBundle @@ -975,6 +1001,7 @@ blacklist: components: - SurplusBundle + saleBlacklist: true # Tools @@ -1113,6 +1140,7 @@ - !type:BuyerJobCondition whitelist: - Chaplain + saleLimit: 1 - type: listing id: uplinkRevolverCapGunFake @@ -1128,6 +1156,7 @@ whitelist: - Mime - Clown + saleLimit: 1 - type: listing id: uplinkBananaPeelExplosive @@ -1172,6 +1201,7 @@ - !type:BuyerJobCondition whitelist: - Clown + saleLimit: 1 - type: listing id: uplinkHotPotato @@ -1335,6 +1365,7 @@ Telecrystal: 8 categories: - UplinkArmor + saleLimit: 1 - type: listing id: UplinkHardsuitSyndieElite @@ -1346,6 +1377,7 @@ Telecrystal: 10 categories: - UplinkArmor + saleLimit: 1 - type: listing id: UplinkClothingOuterHardsuitJuggernaut @@ -1357,6 +1389,7 @@ Telecrystal: 12 categories: - UplinkArmor + saleLimit: 1 # Misc @@ -1425,6 +1458,7 @@ whitelist: tags: - NukeOpsUplink + saleLimit: 1 - type: listing id: UplinkSoapSyndie @@ -1515,6 +1549,7 @@ Telecrystal: 12 categories: - UplinkMisc + saleLimit: 1 - type: listing id: UplinkBribe @@ -1541,6 +1576,7 @@ whitelist: tags: - NukeOpsUplink + saleLimit: 1 - type: listing id: UplinkBackpackSyndicate diff --git a/Resources/Prototypes/Store/presets.yml b/Resources/Prototypes/Store/presets.yml index e623f4c8cd6..bbf96997956 100644 --- a/Resources/Prototypes/Store/presets.yml +++ b/Resources/Prototypes/Store/presets.yml @@ -13,5 +13,13 @@ - UplinkJob - UplinkArmor - UplinkPointless + - UplinkSales currencyWhitelist: - Telecrystal + sales: + enabled: true + minMultiplier: 0.2 + maxMultiplier: 0.8 + minItems: 3 + maxItems: 8 + salesCategory: UplinkSales diff --git a/Resources/Prototypes/_White/Store/categories.yml b/Resources/Prototypes/_White/Store/categories.yml new file mode 100644 index 00000000000..cb9cfbc88f8 --- /dev/null +++ b/Resources/Prototypes/_White/Store/categories.yml @@ -0,0 +1,4 @@ +- type: storeCategory + id: UplinkSales + name: Sales + priority: 10 From 331d68d0681fba2fddda866fd63f5fc0ad4ae488 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 21 Sep 2024 22:47:34 +0000 Subject: [PATCH 04/21] Automatic Changelog Update (#917) --- Resources/Changelog/Changelog.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f4bc13c1173..bbb35f6773e 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -6576,3 +6576,10 @@ Entries: id: 6381 time: '2024-09-20T21:47:16.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/940 +- author: VMSolidus + changes: + - type: Add + message: Part Upgrading has returned! + id: 6382 + time: '2024-09-21T22:46:49.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/917 From 1b431230b14a978da5d7230ec09277d57857095a Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 21 Sep 2024 22:48:59 +0000 Subject: [PATCH 05/21] Automatic Changelog Update (#930) --- Resources/Changelog/Changelog.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index bbb35f6773e..2477a35b914 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -6583,3 +6583,10 @@ Entries: id: 6382 time: '2024-09-21T22:46:49.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/917 +- author: Spatison + changes: + - type: Add + message: Added discounts in uplink / Добавлены скидки в аплинк + id: 6383 + time: '2024-09-21T22:46:59.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/930 From 61e1c8cc97c1d129c273b852c53206df333a52d0 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Sat, 21 Sep 2024 18:50:00 -0400 Subject: [PATCH 06/21] Psionic "Heal Other" Powers (#942) # Description This PR introduces two new Psionic Powers, Healing Word, and Breath of Life, both utilizing a new PsionicHealOtherSystem, which operates on datafield event arguments rather than a "hardcoded" component. Thus, any number of powers can be created which share this system. Healing Word is a power that features a short cast time, and heals a small amount of each damage type to a target(while reducing the target's rot timer slightly). It has a relatively short cooldown, and a low glimmer cost. Breath of Life by contrast, is an extremely rare power with a longer cast time, healing a much larger amount of each damage type to a target, reduces rot significantly, and attempts to revive the target. It has a 2 minute cooldown, and a high glimmer cost.

Media

![image](https://github.com/user-attachments/assets/ba01ccce-639f-4b03-84bb-55f96b5aeda3)

# Changelog :cl: - add: Healing Word has been added as a new Psionic Power. When cast on another person, it heals a small amount of every damage type(scaling with Casting Stats), while also reducing rot timers. Healing Word has a very short cooldown, and a fairly low Glimmer cost. - add: Breath of Life has been added as a new extremely rare Psionic Power. When cast on another person, it heals a large amount of damage(scaling with Casting Stats), while also substantially reducing rot timers. Additionally, it will revive the target if it is possible to do so. Breath of Life has an incredibly long cooldown, a long interuptable cast time, and an extraordinarily high glimmer cost(A typical Psion will spike glimmer by more than 50 points when casting it). - add: The Chaplain now starts with the Healing Word power. --------- Signed-off-by: VMSolidus Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com> --- .../Abilities/HealOtherPowerSystem.cs | 152 ++++++++++++++++++ .../PsionicHealOtherPowerActionEvent.cs | 59 +++++++ Content.Shared/Psionics/Events.cs | 61 +++++-- Content.Shared/Psionics/PsionicComponent.cs | 11 +- .../Locale/en-US/psionics/psionic-powers.ftl | 23 +++ Resources/Prototypes/Actions/psionics.yml | 73 +++++++++ .../Prototypes/Nyanotrasen/psionicPowers.yml | 2 + Resources/Prototypes/Psionics/psionics.yml | 22 +++ .../Roles/Jobs/Civilian/chaplain.yml | 9 +- .../Actions/psionics.rsi/healing_word.png | Bin 0 -> 2189 bytes .../Interface/Actions/psionics.rsi/meta.json | 17 ++ .../Actions/psionics.rsi/revivify.png | Bin 0 -> 1977 bytes .../Interface/VerbIcons/ATTRIBUTION.txt | 3 + 13 files changed, 412 insertions(+), 20 deletions(-) create mode 100644 Content.Server/Abilities/Psionics/Abilities/HealOtherPowerSystem.cs create mode 100644 Content.Shared/Actions/Events/PsionicHealOtherPowerActionEvent.cs create mode 100644 Resources/Textures/Interface/Actions/psionics.rsi/healing_word.png create mode 100644 Resources/Textures/Interface/Actions/psionics.rsi/meta.json create mode 100644 Resources/Textures/Interface/Actions/psionics.rsi/revivify.png diff --git a/Content.Server/Abilities/Psionics/Abilities/HealOtherPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/HealOtherPowerSystem.cs new file mode 100644 index 00000000000..85bae78dc6b --- /dev/null +++ b/Content.Server/Abilities/Psionics/Abilities/HealOtherPowerSystem.cs @@ -0,0 +1,152 @@ +using Robust.Shared.Player; +using Content.Server.DoAfter; +using Content.Shared.Abilities.Psionics; +using Content.Shared.Damage; +using Content.Shared.DoAfter; +using Content.Shared.Popups; +using Content.Shared.Psionics.Events; +using Content.Shared.Examine; +using static Content.Shared.Examine.ExamineSystemShared; +using Robust.Shared.Timing; +using Content.Shared.Actions.Events; +using Robust.Server.Audio; +using Content.Server.Atmos.Rotting; +using Content.Shared.Mobs.Systems; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Psionics.Glimmer; + +namespace Content.Server.Abilities.Psionics; + +public sealed class RevivifyPowerSystem : EntitySystem +{ + [Dependency] private readonly AudioSystem _audioSystem = default!; + [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly SharedPsionicAbilitiesSystem _psionics = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly ExamineSystemShared _examine = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly RottingSystem _rotting = default!; + [Dependency] private readonly MobThresholdSystem _mobThreshold = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly GlimmerSystem _glimmer = default!; + + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnPowerUsed); + SubscribeLocalEvent(OnDispelled); + SubscribeLocalEvent(OnDoAfter); + } + + + private void OnPowerUsed(EntityUid uid, PsionicComponent component, PsionicHealOtherPowerActionEvent args) + { + if (component.DoAfter is not null) + return; + + if (!args.Immediate) + AttemptDoAfter(uid, component, args); + else ActivatePower(uid, component, args); + + if (args.PopupText is not null + && _glimmer.Glimmer > args.GlimmerObviousPopupThreshold * component.CurrentDampening) + _popupSystem.PopupEntity(Loc.GetString(args.PopupText, ("entity", uid)), uid, + Filter.Pvs(uid).RemoveWhereAttachedEntity(entity => !_examine.InRangeUnOccluded(uid, entity, ExamineRange, null)), + true, + args.PopupType); + + if (args.PlaySound + && _glimmer.Glimmer > args.GlimmerObviousSoundThreshold * component.CurrentDampening) + _audioSystem.PlayPvs(args.SoundUse, uid, args.AudioParams); + + // Sanitize the Glimmer inputs because otherwise the game will crash if someone makes MaxGlimmer lower than MinGlimmer. + var minGlimmer = (int) Math.Round(MathF.MinMagnitude(args.MinGlimmer, args.MaxGlimmer) + + component.CurrentAmplification - component.CurrentDampening); + var maxGlimmer = (int) Math.Round(MathF.MaxMagnitude(args.MinGlimmer, args.MaxGlimmer) + + component.CurrentAmplification - component.CurrentDampening); + + _psionics.LogPowerUsed(uid, args.PowerName, minGlimmer, maxGlimmer); + args.Handled = true; + } + + private void AttemptDoAfter(EntityUid uid, PsionicComponent component, PsionicHealOtherPowerActionEvent args) + { + var ev = new PsionicHealOtherDoAfterEvent(_gameTiming.CurTime); + ev.HealingAmount = args.HealingAmount; + ev.RotReduction = args.RotReduction; + ev.DoRevive = args.DoRevive; + var doAfterArgs = new DoAfterArgs(EntityManager, uid, args.UseDelay, ev, uid, target: args.Target) + { + BreakOnUserMove = args.BreakOnUserMove, + BreakOnTargetMove = args.BreakOnTargetMove, + }; + + if (!_doAfterSystem.TryStartDoAfter(doAfterArgs, out var doAfterId)) + return; + + component.DoAfter = doAfterId; + } + + private void OnDispelled(EntityUid uid, PsionicComponent component, DispelledEvent args) + { + if (component.DoAfter is null) + return; + + _doAfterSystem.Cancel(component.DoAfter); + component.DoAfter = null; + args.Handled = true; + } + + private void OnDoAfter(EntityUid uid, PsionicComponent component, PsionicHealOtherDoAfterEvent args) + { + // It's entirely possible for the caster to stop being Psionic(due to mindbreaking) mid cast + if (component is null) + return; + component.DoAfter = null; + + // The target can also cease existing mid-cast + if (args.Target is null) + return; + + _rotting.ReduceAccumulator(args.Target.Value, TimeSpan.FromSeconds(args.RotReduction * component.CurrentAmplification)); + + if (!TryComp(args.Target.Value, out var damageableComponent)) + return; + + _damageable.TryChangeDamage(args.Target.Value, args.HealingAmount * component.CurrentAmplification, true, false, damageableComponent, uid); + + if (!args.DoRevive + || !TryComp(args.Target, out var mob) + || !_mobThreshold.TryGetThresholdForState(args.Target.Value, MobState.Dead, out var threshold) + || damageableComponent.TotalDamage > threshold) + return; + + _mobState.ChangeMobState(args.Target.Value, MobState.Critical, mob, uid); + } + + // This would be the same thing as OnDoAfter, except that here the target isn't nullable, so I have to reuse code with different arguments. + private void ActivatePower(EntityUid uid, PsionicComponent component, PsionicHealOtherPowerActionEvent args) + { + if (component is null) + return; + + _rotting.ReduceAccumulator(args.Target, TimeSpan.FromSeconds(args.RotReduction * component.CurrentAmplification)); + + if (!TryComp(args.Target, out var damageableComponent)) + return; + + _damageable.TryChangeDamage(args.Target, args.HealingAmount * component.CurrentAmplification, true, false, damageableComponent, uid); + + if (!args.DoRevive + || !TryComp(args.Target, out var mob) + || !_mobThreshold.TryGetThresholdForState(args.Target, MobState.Dead, out var threshold) + || damageableComponent.TotalDamage > threshold) + return; + + _mobState.ChangeMobState(args.Target, MobState.Critical, mob, uid); + } +} diff --git a/Content.Shared/Actions/Events/PsionicHealOtherPowerActionEvent.cs b/Content.Shared/Actions/Events/PsionicHealOtherPowerActionEvent.cs new file mode 100644 index 00000000000..8cf11b9e66d --- /dev/null +++ b/Content.Shared/Actions/Events/PsionicHealOtherPowerActionEvent.cs @@ -0,0 +1,59 @@ +using Robust.Shared.Audio; +using Content.Shared.Damage; +using Content.Shared.Popups; + +namespace Content.Shared.Actions.Events; +public sealed partial class PsionicHealOtherPowerActionEvent : EntityTargetActionEvent +{ + [DataField] + public DamageSpecifier HealingAmount = default!; + + [DataField] + public string PowerName; + + /// Controls whether or not a power fires immediately and with no DoAfter + [DataField] + public bool Immediate; + + [DataField] + public string? PopupText; + + [DataField] + public float RotReduction; + + [DataField] + public bool DoRevive; + + [DataField] + public bool BreakOnUserMove = true; + + [DataField] + public bool BreakOnTargetMove = false; + + [DataField] + public float UseDelay = 8f; + + [DataField] + public int MinGlimmer = 8; + + [DataField] + public int MaxGlimmer = 12; + + [DataField] + public int GlimmerObviousSoundThreshold; + + [DataField] + public int GlimmerObviousPopupThreshold; + + [DataField] + public PopupType PopupType = PopupType.Medium; + + [DataField] + public AudioParams AudioParams = default!; + + [DataField] + public bool PlaySound; + + [DataField] + public SoundSpecifier SoundUse = new SoundPathSpecifier("/Audio/Psionics/heartbeat_fast.ogg"); +} diff --git a/Content.Shared/Psionics/Events.cs b/Content.Shared/Psionics/Events.cs index cf9a50c6e18..f110c9c405f 100644 --- a/Content.Shared/Psionics/Events.cs +++ b/Content.Shared/Psionics/Events.cs @@ -1,28 +1,59 @@ using Robust.Shared.Serialization; +using Content.Shared.Damage; using Content.Shared.DoAfter; -namespace Content.Shared.Psionics.Events +namespace Content.Shared.Psionics.Events; + +[Serializable, NetSerializable] +public sealed partial class PsionicRegenerationDoAfterEvent : DoAfterEvent { - [Serializable, NetSerializable] - public sealed partial class PsionicRegenerationDoAfterEvent : DoAfterEvent + [DataField("startedAt", required: true)] + public TimeSpan StartedAt; + + public PsionicRegenerationDoAfterEvent(TimeSpan startedAt) { - [DataField("startedAt", required: true)] - public TimeSpan StartedAt; + StartedAt = startedAt; + } + + public override DoAfterEvent Clone() => this; +} - private PsionicRegenerationDoAfterEvent() - { - } +[Serializable, NetSerializable] +public sealed partial class GlimmerWispDrainDoAfterEvent : SimpleDoAfterEvent { } - public PsionicRegenerationDoAfterEvent(TimeSpan startedAt) - { - StartedAt = startedAt; - } +[Serializable, NetSerializable] +public sealed partial class HealingWordDoAfterEvent : DoAfterEvent +{ + [DataField(required: true)] + public TimeSpan StartedAt; - public override DoAfterEvent Clone() => this; + public HealingWordDoAfterEvent(TimeSpan startedAt) + { + StartedAt = startedAt; } - [Serializable, NetSerializable] - public sealed partial class GlimmerWispDrainDoAfterEvent : SimpleDoAfterEvent + public override DoAfterEvent Clone() => this; +} + +[Serializable, NetSerializable] +public sealed partial class PsionicHealOtherDoAfterEvent : DoAfterEvent +{ + [DataField(required: true)] + public TimeSpan StartedAt; + + [DataField] + public DamageSpecifier HealingAmount = default!; + + [DataField] + public float RotReduction; + + [DataField] + public bool DoRevive; + + public PsionicHealOtherDoAfterEvent(TimeSpan startedAt) { + StartedAt = startedAt; } + + public override DoAfterEvent Clone() => this; } diff --git a/Content.Shared/Psionics/PsionicComponent.cs b/Content.Shared/Psionics/PsionicComponent.cs index 85b7e380fea..37d0a9a7ef4 100644 --- a/Content.Shared/Psionics/PsionicComponent.cs +++ b/Content.Shared/Psionics/PsionicComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.DoAfter; using Content.Shared.Psionics; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -166,6 +167,14 @@ private set /// unneccesary subs for unique psionic entities like e.g. Oracle. ///
[DataField] - public List? PsychognomicDescriptors = null; + public List? PsychognomicDescriptors = null; + + /// Used for tracking what spell a Psion is actively casting + [DataField] + public DoAfterId? DoAfter; + + /// Popup to play if a Psion attempts to start casting a power while already casting one + [DataField] + public string AlreadyCasting = "already-casting"; } } diff --git a/Resources/Locale/en-US/psionics/psionic-powers.ftl b/Resources/Locale/en-US/psionics/psionic-powers.ftl index c68bb2a4968..01b50cce326 100644 --- a/Resources/Locale/en-US/psionics/psionic-powers.ftl +++ b/Resources/Locale/en-US/psionics/psionic-powers.ftl @@ -1,4 +1,5 @@ generic-power-initialization-feedback = I Awaken. +arleady-casting = I cannot channel more than one power at a time. # Dispel dispel-power-description = Dispel summoned entities such as familiars or forcewalls. @@ -48,6 +49,28 @@ psionic-regeneration-power-initialization-feedback = I look within myself, finding a wellspring of life. psionic-regeneration-power-metapsionic-feedback = {CAPITALIZE($entity)} possesses an overwhelming will to live +# Healing Word +action-name-healing-word = Healing Word +action-description-healing-word = Speak the Lesser Secret Of Life, and restore health to another. +healing-word-power-description = Speak the Lesser Secret Of Life, and restore health to another. +healing-word-power-initialization-feedback = + At the beginning of time, a word was spoken that brought life into the Spheres. + Though it taxes my mind to know it, this Secret is known to me now. + I need only speak it. +healing-word-power-metapsionic-feedback = {CAPITALIZE($entity)} bears the Lesser Secret of Life. +healing-word-begin = {CAPITALIZE($entity)} mutters a word that brings both joy and pain alike to those who hear it. + +# Revivify +action-name-revivify = Breath of Life +action-description-revivify = Speak the Greater Secret of Life, and restore another to life. +revivify-power-description = Speak the Greater Secret of Life, and restore another to life. +revivify-power-initialization-feedback = + For a moment, my soul journeys across time and space to the beginning of it all, there I hear it. + The Secret of Life in its fullness. I feel my entire existence burning out from within, merely by knowing it. + Power flows through me as a mighty river, begging to be released with a simple spoken word. +revivify-power-metapsionic-feedback = {CAPITALIZE($entity)} bears the Greater Secret of Life. +revivify-word-begin = {CAPITALIZE($entity)} enunciates a word of such divine power, that those who hear it weep from joy. + # Telegnosis telegnosis-power-description = Create a telegnostic projection to remotely observe things. telegnosis-power-initialization-feedback = diff --git a/Resources/Prototypes/Actions/psionics.yml b/Resources/Prototypes/Actions/psionics.yml index 981d53884ea..d38608a469b 100644 --- a/Resources/Prototypes/Actions/psionics.yml +++ b/Resources/Prototypes/Actions/psionics.yml @@ -146,3 +146,76 @@ icon: Interface/VerbIcons/psionic_invisibility_off.png event: !type:RemovePsionicInvisibilityOffPowerActionEvent +- type: entity + id: ActionHealingWord + name: action-name-healing-word + description: action-description-healing-word + noSpawn: true + components: + - type: EntityTargetAction + icon: { sprite : Interface/Actions/psionics.rsi, state: healing_word } + useDelay: 10 + checkCanAccess: false + range: 6 + itemIconStyle: BigAction + canTargetSelf: true + blacklist: + components: + - PsionicInsulation + - Mindbroken + event: !type:PsionicHealOtherPowerActionEvent + healingAmount: + groups: # These all get divided by the number of damage types in the group. So they're all -2.5. + Genetic: -2.5 + Toxin: -5 + Airloss: -5 + Brute: -7.5 + Burn: -10 + rotReduction: 10 + useDelay: 1 + doRevive: true + powerName: Healing Word + popupText: healing-word-begin + playSound: true + minGlimmer: 2 + maxGlimmer: 4 + glimmerObviousSoundThreshold: 100 + glimmerObviousPopupThreshold: 200 + +- type: entity + id: ActionRevivify + name: action-name-revivify + description: action-description-revivify + noSpawn: true + components: + - type: EntityTargetAction + icon: { sprite : Interface/Actions/psionics.rsi, state: revivify } + useDelay: 120 + checkCanAccess: false + range: 2 + itemIconStyle: BigAction + canTargetSelf: false + blacklist: + components: + - PsionicInsulation + - Mindbroken + event: !type:PsionicHealOtherPowerActionEvent + healingAmount: + # These all get divided by the number of damage types in the group. So they're all -15 + # Additionally, they're multiplied by the caster's Amplification, which, + # assuming this is the only power they have, the multiplier is between 2.9-3.9 + groups: + Genetic: -15 + Toxin: -30 + Airloss: -60 # Except airloss, which heals 30 per type + Brute: -45 + Burn: -60 + rotReduction: 60 + doRevive: true + powerName: Revivify + popupText: revivify-begin + playSound: true + minGlimmer: 10 # These also get multiplied by caster stats. So, + maxGlimmer: 15 # keeping in mind the ~3.5x multiplier, this spikes glimmer by as much as 60 points. + glimmerObviousSoundThreshold: 50 + glimmerObviousPopupThreshold: 100 diff --git a/Resources/Prototypes/Nyanotrasen/psionicPowers.yml b/Resources/Prototypes/Nyanotrasen/psionicPowers.yml index 0781122b8ec..2aee2273a18 100644 --- a/Resources/Prototypes/Nyanotrasen/psionicPowers.yml +++ b/Resources/Prototypes/Nyanotrasen/psionicPowers.yml @@ -11,3 +11,5 @@ # PsionicInvisibilityPower: 0.15 MindSwapPower: 0.15 TelepathyPower: 1 + HealingWordPower: 0.85 + RevivifyPower: 0.1 diff --git a/Resources/Prototypes/Psionics/psionics.yml b/Resources/Prototypes/Psionics/psionics.yml index 461098eab21..b881f1f11fb 100644 --- a/Resources/Prototypes/Psionics/psionics.yml +++ b/Resources/Prototypes/Psionics/psionics.yml @@ -140,3 +140,25 @@ initializationFeedback: telepathy-power-initialization-feedback metapsionicFeedback: psionic-language-power-feedback # Reuse for telepathy, clairaudience, etc powerSlotCost: 0 + +- type: psionicPower + id: HealingWordPower + name: HealingWord + description: healing-word-power-description + actions: + - ActionHealingWord + initializationFeedback: healing-word-power-initialization-feedback + metapsionicFeedback: healing-word-power-feedback + amplificationModifier: 0.5 + dampeningModifier: 0.5 + +- type: psionicPower + id: RevivifyPower + name: Revivify + description: revivify-power-description + actions: + - ActionRevivify + initializationFeedback: revivify-power-initialization-feedback + metapsionicFeedback: revivify-power-feedback + amplificationModifier: 2.5 # An extremely rare and dangerous power + powerSlotCost: 2 diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml index c7395ff3e2d..d4f8bdb0671 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml @@ -5,8 +5,8 @@ playTimeTracker: JobChaplain requirements: - !type:CharacterDepartmentTimeRequirement - department: Epistemics # DeltaV - Epistemics Department replacing Science - min: 14400 #DeltaV 4 hours + department: Epistemics # Chaplain is now one of the station's "Crew-Aligned Wizards" + min: 14400 # 4 hours - !type:CharacterLogicOrRequirement requirements: - !type:CharacterSpeciesRequirement @@ -21,7 +21,7 @@ supervisors: job-supervisors-rd access: - Chapel - - Research # DeltaV - Move Chaplain into Epistemics + - Research - Maintenance special: - !type:AddComponentSpecial @@ -32,6 +32,7 @@ - type: InnatePsionicPowers powersToAdd: - TelepathyPower + - HealingWordPower - type: startingGear id: ChaplainGear @@ -40,7 +41,7 @@ back: ClothingBackpackChaplainFilled shoes: ClothingShoesColorBlack id: ChaplainPDA - ears: ClothingHeadsetScience # DeltaV - Move Chaplain into Epistemics + ears: ClothingHeadsetScience innerClothingSkirt: ClothingUniformJumpskirtChaplain satchel: ClothingBackpackSatchelChaplainFilled duffelbag: ClothingBackpackDuffelChaplainFilled diff --git a/Resources/Textures/Interface/Actions/psionics.rsi/healing_word.png b/Resources/Textures/Interface/Actions/psionics.rsi/healing_word.png new file mode 100644 index 0000000000000000000000000000000000000000..800e2a46e6139ae17b21fb4509242b317c6445c5 GIT binary patch literal 2189 zcmV;82y*v{P)9?Ncm1Y5zzB48of z_$vGd+6uM`f}jW@me#%+k@Zd@BuJcP_I{k1bD22<_Fz`anJqrZ<%>or;CC-Ym)*`6 z+8CyfL3}aI)aS!<5&j*Yci2?D^{QU~?`t|b6G>A8Tf6X-rW-}!8R6i1QCGYz+^c0` z3E@NGaYGI$e5Lewjh_{#Yy7U*h=gXru6nxD4IFP^Eo0<_$Amq(Y)Sh)kGe@$GQSv> zIv{fhlMn&?xQSC@jVwjHQuC5obDyv3Tc98wP5wG%3~{8%h<9Anl5|ZO^grk^BUY6hGVQ4pyq-dL6nbu;W2KhW?>Z;<5ZRC?x`w@d7?u65)gMjJXf8H>^ zJath878q+2OxT#PaA736l+>sT;>L|8mc+g3LXC|kE)X>?T-3NRv9S>CqFB2iEmR{5 zH9oMZ#UDs2t@k^(=l0xrbARUNzG8Wk-0|#Luf3U?cIb_ln{7riUuCT8tBe&kfoDrV!dj@H5(Vf$0nQ}* zyk(dDt0X2k0Wkda!9n%MzpL;d`7cJ^Rds9I(X(y2k~a{zTonmzRXHDk%J#(3 z7n860Gx^=*CLq*SL1l4OLO|Q%&osXTmIa#cKX9y88OS^`f)apL0uVGwf)1Vy;``he z_p#c|Y(WWN!)Jc_s{zBOGasjj;SLhKPK>UiDu@YAz{2HuHMR7;0tpOGf*k&KgzobN zP@nvGRxM87Abb}u&Lr+*Qb=eLf)mhx&tWA=03ZOwJ+v)zcPNk`8$ZiZg-KDNhzOnr zVc7Bh7gDKi;hRzQ%U5->8L6XUobLZ&0zK;N*CkF?e3#Fh0U`4TFPw(za z5g>h-pX(&a7oZ%FKy6Q~rit@00eZiNo0d0%xd7&cA7jO&gaLl+w^5QiuPA2-&IIs# z6F7FEqEu;#In_O=0x&XwE~tnE75gy=i34C91o3=KjYgji(|3SJpDijT2w6kAhYtR( z<@3~UNv*n>43M^DI4J;uhc7uH3_(Bx$lkVx=)z~*=LVG!36Uxi@FEM~K1h&tf^?x% zpMOn5@pCS)Y=LusYXy|qsUgbOcHO=*$AJd_WD(cvN z|HedN{LF;}s{;{$Kl$o$it=(x%O^Tm=`{G*B&^^^r{hu>4gCNB3V{kx1xgZFN!(x7 z3H&aCBx1ySWABin@V?8I*~tZ9nB3s#smZhw><0T^>Q-C(7S-mi>*_-1IQ@(7xQ`2s z-Gmh($-%v+YR8iKQDgWtYZs7{l{wsy{QU*P1rJb?7?1#0fod>@ z-k>g&+j`0Eq5xY0HlV6Q+LF>kb$0r*4{3e`tSXPSI2O2oHN9i)0vH4IW$a=_0FOY`*!GQ7kWfV!1$?AHQ=TtQd)cPr-LWt08j&4D0tLos zi)^Y5Y{+mT0J(UZ>ZEx%4KjEiz$U{R$HT6&Lq(+lmEG);HlSr+Cju}4R-fCM`JvKz zzO12H^@2>1k9D3<2UiAkRe}=%GVrjkW2InpR-P{dyy#uj3bIZ(GdZO8skm%*ZMJDJ znFlpMNbqF|~qz?yXB+!#WYbyFzk^t zpr&S8c~|*+5uh66@E@B(uU*UOp;iC@01jnXNoGw=04e|g00;m8000000Mb*F P00000NkvXXu0mjf%9`?P literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/Actions/psionics.rsi/meta.json b/Resources/Textures/Interface/Actions/psionics.rsi/meta.json new file mode 100644 index 00000000000..085cc412814 --- /dev/null +++ b/Resources/Textures/Interface/Actions/psionics.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by leonardo_dabepis (discord)", + "size": { + "x": 64, + "y": 64 + }, + "states": [ + { + "name": "healing_word" + }, + { + "name": "revivify" + } + ] +} diff --git a/Resources/Textures/Interface/Actions/psionics.rsi/revivify.png b/Resources/Textures/Interface/Actions/psionics.rsi/revivify.png new file mode 100644 index 0000000000000000000000000000000000000000..087f40b4c98a073de7c2e0258f6128a1c3ff755b GIT binary patch literal 1977 zcmV;q2S)gbP)9?Ncm1Y5zzB48of z_$vGd+6uM`f}jW@me#%+k@Zd@BuJcP_I{k1bD22<_Fz`anJqrZ<%>or;CC-Ym)*`6 z+8CyfL3}aI)aS!<5&j*Yci2?D^{QU~?`t|b6G>A8Tf6X-rW-}!8R6i1QCGYz+^c0` z3E@NGaYGI$e5Lewjh_{#Yy7U*h=gXru6nxD4IFP^Eo0<_$Amq(Y)Sh)kGe@$GQSv> zIv{fhlMn&?xQSC@jVwjHQuC5obDyv3Tc98wP5wG%3~{8%h<9Anl5|ZO^grk^BUY6hGVQ4pyq-dL6nbu;W2KhW?>Z;<5ZRC?x`w@d7?u65)gMjJXf8h;(q6Rd$W6&-JQwJYU2(Zm%E+YdEd{xdGp?Eh@ut|hzLXk zA_5VC|1E(_!cboK`hsblaZ*p6HE!QL9m7<91M#gbi&TDM_l?uUv}p)N0kHVhl*K3O3?H&ir-jyO~R zEWD$mGbgm4XzL5FiqAbepA8*^G60>zMizeS&1FL5O-o`~2o?Zt0I}!Ioy7giuV~2g z2*2@FlO-hpI)#l}ye-_4cIh)!)Z6^7L*$kxx6tl4cGLN@=P8{@kPIP6QKect1O_mh z!UisnnU}@SwAiQqx|$dQWpcd&7gUP1L!eYxx3Ec{OAxR3_WSN~XvXaCeW=&|4#MSD zHt!ee?&_vY<~N5I_(jRMV(sAT0lK+8T)%DIT48VH!pjTV?H29sG=IT-f)@Z}kR1Z` z11e9ID$+9%(iJZYNsbPRkKc|Z?H6CiEW2l&Kc6^}5^+GKan%V3STcwienHdM15^y~ z>MO5*z^JDx(Org6a$$tZE+b;ksJL-4jelo3fwc@wHKPDBS6)N+-?B{D-uLn6wg!#| z5X>z#%n>gozB)emC8bYKn$m6G*C+rUW%Q>%sI#*}5@YQO+mh6}YX|L!Ws{%x4<2&N zbZO~Tl=XnqbnT*YksAbw1FFP~6hkm}b^9h^OTKt=z*ty)yXePm4&iw5X9U7kEAFM2 zpMTs=kW@u_^)~{52aHuNbgC z$i4TwRSa!ANShC=7eQ~s#`R*>PbN;%ZFF9~D z&u}D1xc2ZPo9%1x0zhC-fCsE?dQfDAuk`FSA|5w25(M{s_ztamV55LQR2V{R#qvB+ zfWVa@wnunI$%VmxykW5s2u1)*jQvPRfDi*10<0gib_28}uFQ~g0nP(hDZcO9pLKmK zjf-LzfRVqRnWV3e9}y7H06`WnyFQDBc(^*}26)Gda{&|Lm6rf=?H~_1U~D3lJ@pyb z7pFgeKS!^1_vE=SPJ?b6t|jWqZi6)qHKGqgK;TnNhgH{!@)D3ASa=PFI({T&<>XdA zfTi&Cb6e@XJ-xyc_?_O$?f($pxO5pEJvB_rtFvh`W?v-@4r-fhw=w_~!hq1<_cq0( zBd{-y9HzFGHH7z-)Mn2*#LLY+`#R!+*y?*8pnDd;gQJvXFL0*AMDl?s`m+~IPXA2D zKK)AM189Yg#=OL-oC)~m0XSpBgGup#(mHI=X$XjD$O&*pfOm+;fyhhSx7#m7dbCqR zKiF&Eqj5lS=SU27If5qF28acm9pXf&x#Vt}XLbGcV(p_U{Al14$LyNBM&+CIU_Zc3%002-H<9rb30qtw*HaV)_)kN{87YmAq`_FU^2yuSR=&?9M@G`>h2^MGq3CL0&Iz0u}+cJx*LS^o{zq!wmtW_p#i|a5VqmW6XHFQ$UPrq zqfDi{UK0~40NId#Lu?@szIniG-2P(tZ3MvdEQJ-!bajLh1OCep0;j?%glAho$z!P$ zHYzr9Un2l;^I||SEgp6n1K@_BGdrqdSO literal 0 HcmV?d00001 diff --git a/Resources/Textures/Interface/VerbIcons/ATTRIBUTION.txt b/Resources/Textures/Interface/VerbIcons/ATTRIBUTION.txt index 0b8ae856bd8..69aa4650b32 100644 --- a/Resources/Textures/Interface/VerbIcons/ATTRIBUTION.txt +++ b/Resources/Textures/Interface/VerbIcons/ATTRIBUTION.txt @@ -7,3 +7,6 @@ https://game-icons.net/1x1/lorc/padlock.html unlock.svg by Delapouite under CC BY 3.0 https://game-icons.net/1x1/delapouite/padlock-open.html + +healing_word.png by LeonardoDaBepis under CC BY 3.0 +revivify.png by LeonardoDaBepis under CC BY 3.0 \ No newline at end of file From 272b4ece2f952d7d14a4ce531a62f5e311ebe597 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 21 Sep 2024 22:51:07 +0000 Subject: [PATCH 07/21] Automatic Changelog Update (#942) --- Resources/Changelog/Changelog.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 2477a35b914..ad3de9ce823 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -6590,3 +6590,25 @@ Entries: id: 6383 time: '2024-09-21T22:46:59.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/930 +- author: VMSolidus + changes: + - type: Add + message: >- + Healing Word has been added as a new Psionic Power. When cast on another + person, it heals a small amount of every damage type(scaling with + Casting Stats), while also reducing rot timers. Healing Word has a very + short cooldown, and a fairly low Glimmer cost. + - type: Add + message: >- + Breath of Life has been added as a new extremely rare Psionic Power. + When cast on another person, it heals a large amount of damage(scaling + with Casting Stats), while also substantially reducing rot timers. + Additionally, it will revive the target if it is possible to do so. + Breath of Life has an incredibly long cooldown, a long interuptable cast + time, and an extraordinarily high glimmer cost(A typical Psion will + spike glimmer by more than 50 points when casting it). + - type: Add + message: The Chaplain now starts with the Healing Word power. + id: 6384 + time: '2024-09-21T22:50:01.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/942 From 5bf5d5718a58eadf1989ef30e1ff32515a7bdd4e Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Sat, 21 Sep 2024 19:22:42 -0400 Subject: [PATCH 08/21] More Objects Hit By Projectiles (#943) # Description This PR is a follow up to https://github.com/Simple-Station/Einstein-Engines/pull/939 By increasing the number of items that are struck by bullets, or can be targeted by bullets. To add to the "Cinematic" experience of a gunfight, Bottles, Cups, and Plates of all kinds are automatically struck by bullets when fired over, and *probably* destroyed given that they only have 5 hit points. This also serves to aid in limiting the amount of things that can be hidden underneath when crawling under a table, since the station's bar counter will likely explode into a ton of glass and spilled booze when a gunfight gets near it. I also added Chairs to the "RequireProjectileTarget" feature, so that if you click on a chair, you'll shoot the chair and (probably) destroy it. # Changelog :cl: - add: Bottles, Drink Glasses, Plates, and all liquid containers are now struck by bullets(and most likely destroyed in the process). We hope that this will offer both a small tactical advantage/disadvantage, as well as contribute to making gunfights around the bar more "Cinematic". - add: Chairs are now hit by projectiles if a shooter clicks on them, in addition to Tables. --- .../Objects/Consumable/Drinks/drinks.yml | 25 +++++++++++++++++++ .../Consumable/Drinks/drinks_bottles.yml | 3 +++ .../Consumable/Food/Containers/plate.yml | 11 ++++++++ .../Entities/Structures/Furniture/chairs.yml | 3 ++- 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml index 93d4b957fe7..743d9a17925 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml @@ -48,6 +48,31 @@ path: /Audio/SimpleStation14/Items/Handling/drinkglass_drop.ogg params: volume: -2 + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + density: 30 + mask: + - ItemMask + layer: + - BulletImpassable # Ever seen a John Woo movie? + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 5 + behaviors: + - !type:PlaySoundBehavior + sound: + collection: MetalBreak + params: + volume: -6 + - !type:SpillBehavior { } + - !type:DoActsBehavior + acts: [ "Destruction" ] - type: entity parent: DrinkBase diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml index a6752286dd2..b2489325e0a 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml @@ -31,6 +31,9 @@ !type:DamageTrigger damage: 5 behaviors: + - !type:PlaySoundBehavior + sound: + collection: GlassBreak - !type:SpillBehavior { } - !type:DoActsBehavior acts: [ "Destruction" ] diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/plate.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/plate.yml index 63c47df67e7..3bd66e8a481 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/plate.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/plate.yml @@ -54,6 +54,17 @@ materialComposition: Glass: 60 - type: SpaceGarbage + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + density: 25 + mask: + - ItemMask + layer: + - BulletImpassable # Ever seen a John Woo movie? - type: entity name: broken plate diff --git a/Resources/Prototypes/Entities/Structures/Furniture/chairs.yml b/Resources/Prototypes/Entities/Structures/Furniture/chairs.yml index 0fb69b4fdbd..14b3270ba88 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/chairs.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/chairs.yml @@ -33,7 +33,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 100 + damage: 25 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -48,6 +48,7 @@ collection: MetalBreak - type: StaticPrice price: 10 + - type: RequireProjectileTarget #Starts unanchored, cannot be rotated while anchored - type: entity From 900630cafd30a53ad04a1ed55257b23dc840c8e2 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sat, 21 Sep 2024 23:23:09 +0000 Subject: [PATCH 09/21] Automatic Changelog Update (#943) --- Resources/Changelog/Changelog.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index ad3de9ce823..f85816dfafa 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -6612,3 +6612,18 @@ Entries: id: 6384 time: '2024-09-21T22:50:01.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/942 +- author: VMSolidus + changes: + - type: Add + message: >- + Bottles, Drink Glasses, Plates, and all liquid containers are now struck + by bullets(and most likely destroyed in the process). We hope that this + will offer both a small tactical advantage/disadvantage, as well as + contribute to making gunfights around the bar more "Cinematic". + - type: Add + message: >- + Chairs are now hit by projectiles if a shooter clicks on them, in + addition to Tables. + id: 6385 + time: '2024-09-21T23:22:43.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/943 From 89860b40f54663a512c696af6d121c46c53df8bc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:38:48 -0700 Subject: [PATCH 10/21] Update Credits (#946) This is an automated Pull Request. This PR updates the GitHub contributors in the credits section. Co-authored-by: SimpleStation Changelogs --- Resources/Credits/GitHub.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index 22e7aef8a92..aeed9636628 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, angelofallars, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, beck-thompson, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlueHNT, Boaz1111, BobdaBiscuit, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, CilliePaint, clorl, Clyybber, CodedCrow, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, Deeeeja, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, dootythefrooty, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, Evgencheg, exincore, exp111, Fahasor, FairlySadPanda, Fansana, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, geraeumig, Git-Nivrak, github-actions[bot], gituhabu, gluesniffler, GNF54, Golinth, GoodWheatley, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, HerCoyote23, HoofedEar, Hoolny, hord-brayden, hubismal, Hugal31, Huxellberger, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Mnemotechnician, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, notafet, notquitehadouken, noudoit, nuke-haus, NULL882, nyeogmi, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, ShadowCommander, Shadowtheprotogen546, ShatteredSwords, SignalWalker, SimpleStation14, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, SleepyScarecrow, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, stalengd, Stealthbomber16, stellar-novas, StrawberryMoses, superjj18, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, Tmanzxd, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, wafehling, WarMechanic, waylon531, weaversam8, whateverusername0, Willhelm53, Winkarst-cpu, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, ZNixian, ZoldorfTheWizard, Zumorica, Zymem +0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, angelofallars, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, beck-thompson, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlueHNT, Boaz1111, BobdaBiscuit, brainfood1183, BramvanZijp, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, CilliePaint, clorl, Clyybber, CodedCrow, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, Deeeeja, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, dootythefrooty, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, Evgencheg, exincore, exp111, Fahasor, FairlySadPanda, Fansana, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Froffy025, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, geraeumig, Git-Nivrak, github-actions[bot], gituhabu, gluesniffler, GNF54, Golinth, GoodWheatley, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, HerCoyote23, HoofedEar, Hoolny, hord-brayden, hubismal, Hugal31, Huxellberger, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, Interrobang01, IProduceWidgets, ItsMeThom, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTrotter, KaiShibaa, kalane15, kalanosh, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Ko4ergaPunk, komunre, koteq, Krunklehorn, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, Lgibb18, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Mnemotechnician, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, notafet, notquitehadouken, noudoit, nuke-haus, NULL882, nyeogmi, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, osjarw, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, ShadowCommander, Shadowtheprotogen546, ShatteredSwords, SignalWalker, SimpleStation14, Simyon264, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, SleepyScarecrow, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, stalengd, Stealthbomber16, stellar-novas, StrawberryMoses, superjj18, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, Tmanzxd, tmtmtl30, TokenStyle, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UltimateJester, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Vermidia, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, wafehling, WarMechanic, waylon531, weaversam8, whateverusername0, Willhelm53, Winkarst-cpu, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zerorulez, zionnBE, ZNixian, ZoldorfTheWizard, Zumorica, Zymem From 99ee3122f244ebede2d8e3960475f79240ca07c3 Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Mon, 23 Sep 2024 20:56:34 -0400 Subject: [PATCH 11/21] Fix HealingWord & Revivify Bugs (#949) # Description Playtesting uncovered a few bugs with the HealOtherSystem, these are luckily pretty simple to fix. I also made a few of the functions in this system nullable as a performance optimization. # Changelog :cl: - fix: Fixed a bug where Breath of Life and Healing Word would set living people to crit, which would knock them down. - fix: Fixed a bug where Breath of Life could revive people who were rotten(It will still heal them and reduce the rot timer as intended, but will not revive unless said rot timer reduction brings them below the 10 minute threshold). - add: The Do-After bar for Breath of Life and Healing Word is now hidden if glimmer is low enough. The threshold for which scales with your Dampening stat. More Dampening = stealthier casting. --- .../Abilities/HealOtherPowerSystem.cs | 32 +++++++++++++------ .../PsionicHealOtherPowerActionEvent.cs | 11 ++++--- Content.Shared/Psionics/Events.cs | 4 +-- Resources/Prototypes/Actions/psionics.yml | 10 +++--- 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/Content.Server/Abilities/Psionics/Abilities/HealOtherPowerSystem.cs b/Content.Server/Abilities/Psionics/Abilities/HealOtherPowerSystem.cs index 85bae78dc6b..35b5e6a2381 100644 --- a/Content.Server/Abilities/Psionics/Abilities/HealOtherPowerSystem.cs +++ b/Content.Server/Abilities/Psionics/Abilities/HealOtherPowerSystem.cs @@ -53,14 +53,14 @@ private void OnPowerUsed(EntityUid uid, PsionicComponent component, PsionicHealO else ActivatePower(uid, component, args); if (args.PopupText is not null - && _glimmer.Glimmer > args.GlimmerObviousPopupThreshold * component.CurrentDampening) + && _glimmer.Glimmer > args.GlimmerPopupThreshold * component.CurrentDampening) _popupSystem.PopupEntity(Loc.GetString(args.PopupText, ("entity", uid)), uid, Filter.Pvs(uid).RemoveWhereAttachedEntity(entity => !_examine.InRangeUnOccluded(uid, entity, ExamineRange, null)), true, args.PopupType); if (args.PlaySound - && _glimmer.Glimmer > args.GlimmerObviousSoundThreshold * component.CurrentDampening) + && _glimmer.Glimmer > args.GlimmerSoundThreshold * component.CurrentDampening) _audioSystem.PlayPvs(args.SoundUse, uid, args.AudioParams); // Sanitize the Glimmer inputs because otherwise the game will crash if someone makes MaxGlimmer lower than MinGlimmer. @@ -76,13 +76,16 @@ private void OnPowerUsed(EntityUid uid, PsionicComponent component, PsionicHealO private void AttemptDoAfter(EntityUid uid, PsionicComponent component, PsionicHealOtherPowerActionEvent args) { var ev = new PsionicHealOtherDoAfterEvent(_gameTiming.CurTime); - ev.HealingAmount = args.HealingAmount; - ev.RotReduction = args.RotReduction; + if (args.HealingAmount is not null) + ev.HealingAmount = args.HealingAmount; + if (args.RotReduction is not null) + ev.RotReduction = args.RotReduction.Value; ev.DoRevive = args.DoRevive; var doAfterArgs = new DoAfterArgs(EntityManager, uid, args.UseDelay, ev, uid, target: args.Target) { BreakOnUserMove = args.BreakOnUserMove, BreakOnTargetMove = args.BreakOnTargetMove, + Hidden = _glimmer.Glimmer > args.GlimmerDoAfterVisibilityThreshold * component.CurrentDampening, }; if (!_doAfterSystem.TryStartDoAfter(doAfterArgs, out var doAfterId)) @@ -104,7 +107,8 @@ private void OnDispelled(EntityUid uid, PsionicComponent component, DispelledEve private void OnDoAfter(EntityUid uid, PsionicComponent component, PsionicHealOtherDoAfterEvent args) { // It's entirely possible for the caster to stop being Psionic(due to mindbreaking) mid cast - if (component is null) + if (component is null + || args.Cancelled) return; component.DoAfter = null; @@ -112,15 +116,19 @@ private void OnDoAfter(EntityUid uid, PsionicComponent component, PsionicHealOth if (args.Target is null) return; - _rotting.ReduceAccumulator(args.Target.Value, TimeSpan.FromSeconds(args.RotReduction * component.CurrentAmplification)); + if (args.RotReduction is not null) + _rotting.ReduceAccumulator(args.Target.Value, TimeSpan.FromSeconds(args.RotReduction.Value * component.CurrentAmplification)); if (!TryComp(args.Target.Value, out var damageableComponent)) return; - _damageable.TryChangeDamage(args.Target.Value, args.HealingAmount * component.CurrentAmplification, true, false, damageableComponent, uid); + if (args.HealingAmount is not null) + _damageable.TryChangeDamage(args.Target.Value, args.HealingAmount * component.CurrentAmplification, true, false, damageableComponent, uid); if (!args.DoRevive - || !TryComp(args.Target, out var mob) + || _rotting.IsRotten(args.Target.Value) + || !TryComp(args.Target.Value, out var mob) + || !_mobState.IsDead(args.Target.Value, mob) || !_mobThreshold.TryGetThresholdForState(args.Target.Value, MobState.Dead, out var threshold) || damageableComponent.TotalDamage > threshold) return; @@ -134,15 +142,19 @@ private void ActivatePower(EntityUid uid, PsionicComponent component, PsionicHea if (component is null) return; - _rotting.ReduceAccumulator(args.Target, TimeSpan.FromSeconds(args.RotReduction * component.CurrentAmplification)); + if (args.RotReduction is not null) + _rotting.ReduceAccumulator(args.Target, TimeSpan.FromSeconds(args.RotReduction.Value * component.CurrentAmplification)); if (!TryComp(args.Target, out var damageableComponent)) return; - _damageable.TryChangeDamage(args.Target, args.HealingAmount * component.CurrentAmplification, true, false, damageableComponent, uid); + if (args.HealingAmount is not null) + _damageable.TryChangeDamage(args.Target, args.HealingAmount * component.CurrentAmplification, true, false, damageableComponent, uid); if (!args.DoRevive + || _rotting.IsRotten(args.Target) || !TryComp(args.Target, out var mob) + || !_mobState.IsDead(args.Target, mob) || !_mobThreshold.TryGetThresholdForState(args.Target, MobState.Dead, out var threshold) || damageableComponent.TotalDamage > threshold) return; diff --git a/Content.Shared/Actions/Events/PsionicHealOtherPowerActionEvent.cs b/Content.Shared/Actions/Events/PsionicHealOtherPowerActionEvent.cs index 8cf11b9e66d..0001c7842d7 100644 --- a/Content.Shared/Actions/Events/PsionicHealOtherPowerActionEvent.cs +++ b/Content.Shared/Actions/Events/PsionicHealOtherPowerActionEvent.cs @@ -6,7 +6,7 @@ namespace Content.Shared.Actions.Events; public sealed partial class PsionicHealOtherPowerActionEvent : EntityTargetActionEvent { [DataField] - public DamageSpecifier HealingAmount = default!; + public DamageSpecifier? HealingAmount = default!; [DataField] public string PowerName; @@ -19,7 +19,7 @@ public sealed partial class PsionicHealOtherPowerActionEvent : EntityTargetActio public string? PopupText; [DataField] - public float RotReduction; + public float? RotReduction; [DataField] public bool DoRevive; @@ -40,10 +40,13 @@ public sealed partial class PsionicHealOtherPowerActionEvent : EntityTargetActio public int MaxGlimmer = 12; [DataField] - public int GlimmerObviousSoundThreshold; + public int GlimmerSoundThreshold; [DataField] - public int GlimmerObviousPopupThreshold; + public int GlimmerPopupThreshold; + + [DataField] + public int GlimmerDoAfterVisibilityThreshold; [DataField] public PopupType PopupType = PopupType.Medium; diff --git a/Content.Shared/Psionics/Events.cs b/Content.Shared/Psionics/Events.cs index f110c9c405f..744dd3b6ea2 100644 --- a/Content.Shared/Psionics/Events.cs +++ b/Content.Shared/Psionics/Events.cs @@ -42,10 +42,10 @@ public sealed partial class PsionicHealOtherDoAfterEvent : DoAfterEvent public TimeSpan StartedAt; [DataField] - public DamageSpecifier HealingAmount = default!; + public DamageSpecifier? HealingAmount = default!; [DataField] - public float RotReduction; + public float? RotReduction; [DataField] public bool DoRevive; diff --git a/Resources/Prototypes/Actions/psionics.yml b/Resources/Prototypes/Actions/psionics.yml index d38608a469b..82e356a11f5 100644 --- a/Resources/Prototypes/Actions/psionics.yml +++ b/Resources/Prototypes/Actions/psionics.yml @@ -179,8 +179,9 @@ playSound: true minGlimmer: 2 maxGlimmer: 4 - glimmerObviousSoundThreshold: 100 - glimmerObviousPopupThreshold: 200 + glimmerSoundThreshold: 100 + glimmerPopupThreshold: 200 + glimmerDoAfterVisibilityThreshold: 70 - type: entity id: ActionRevivify @@ -217,5 +218,6 @@ playSound: true minGlimmer: 10 # These also get multiplied by caster stats. So, maxGlimmer: 15 # keeping in mind the ~3.5x multiplier, this spikes glimmer by as much as 60 points. - glimmerObviousSoundThreshold: 50 - glimmerObviousPopupThreshold: 100 + glimmerSoundThreshold: 50 + glimmerPopupThreshold: 100 + glimmerDoAfterVisibilityThreshold: 35 From 7c7619c40c6162f6d3a6a74c24757f38fe481afc Mon Sep 17 00:00:00 2001 From: gluesniffler <159397573+gluesniffler@users.noreply.github.com> Date: Mon, 23 Sep 2024 20:56:45 -0400 Subject: [PATCH 12/21] More Quick Construction Recipes And Upgrades (#945) # Description This PR adds a few new recipes to Quick Construction (accessed by pressing Z on commonly used construction materials/items, such as rods, glass, steel, plasma, etc etc). Along with simple nesting for grouping items up under categories, akin to how the RCD works. Which allows engineers to massively speed up pipe laying work, disposal rebuilding, setting up the supermatter, etc etc. First time doing UI code, apologies for the shitcode in advance :godo: ---

Media

https://github.com/user-attachments/assets/9d540d7f-7e4f-4a43-874d-5ea069011a37

--- # Considerations Is this powergamey? Probably. Is it fucking awesome? Hell yeah. Some servers might question the fact that everyone can build stuff this fast now that they dont have to deal too much with the construction menu for the most common things... And might want to lock it behind traits or given as a job freebie, like CPR for doctors. Other servers might appreciate it if they are looking for more action to happen over the round, and giving everyone the ability to deal with breaches and repairs quicker is probably a step into that direction. I'll be observing for feedback and adjust accordingly. It also shouldn't invalidate any eventual RPDs, or other devices of the kind since this is just a shortcut for construction, you still require materials and a doafter for most of them. --- # Changelog :cl: Mocho - add: Added a lot of recipes to the quick construction menus. Give it a shot by pressing Z with different construction materials in your hand! --------- Signed-off-by: gluesniffler <159397573+gluesniffler@users.noreply.github.com> Co-authored-by: VMSolidus --- .../UI/ShortConstructionMenuBUI.cs | 95 +++++++++++-------- .../ShortConstructionComponent.cs | 26 ++++- .../Objects/Materials/Sheets/glass.yml | 63 +++++++++++- .../Objects/Materials/Sheets/metal.yml | 84 ++++++++++++++-- .../Objects/Materials/Sheets/other.yml | 31 ++++++ .../Entities/Objects/Materials/parts.yml | 26 ++++- .../Graphs/structures/windowdirectional.yml | 2 + .../Recipes/Construction/structures.yml | 36 +++++++ 8 files changed, 308 insertions(+), 55 deletions(-) diff --git a/Content.Client/ShortConstruction/UI/ShortConstructionMenuBUI.cs b/Content.Client/ShortConstruction/UI/ShortConstructionMenuBUI.cs index 4d50d91e168..95da2e0a336 100644 --- a/Content.Client/ShortConstruction/UI/ShortConstructionMenuBUI.cs +++ b/Content.Client/ShortConstruction/UI/ShortConstructionMenuBUI.cs @@ -12,6 +12,7 @@ using Robust.Client.UserInterface.Controls; using Robust.Shared.Enums; using Robust.Shared.Prototypes; +using Robust.Shared.Utility; // ReSharper disable InconsistentNaming @@ -30,7 +31,6 @@ public sealed class ShortConstructionMenuBUI : BoundUserInterface private readonly SpriteSystem _spriteSystem; private RadialMenu? _menu; - public ShortConstructionMenuBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey) { _construction = _entManager.System(); @@ -39,8 +39,17 @@ public ShortConstructionMenuBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey protected override void Open() { - _menu = FormMenu(); - _menu.OnClose += Close; + _menu = new RadialMenu + { + HorizontalExpand = true, + VerticalExpand = true, + BackButtonStyleClass = "RadialMenuBackButton", + CloseButtonStyleClass = "RadialMenuCloseButton" + }; + + if (_entManager.TryGetComponent(Owner, out var crafting)) + CreateMenu(crafting.Entries); + _menu.OpenCenteredAt(_inputManager.MouseScreenPosition.Position / _displayManager.ScreenSize); } @@ -51,56 +60,58 @@ protected override void Dispose(bool disposing) _menu?.Dispose(); } - private RadialMenu FormMenu() + private void CreateMenu(List entries, string? parentCategory = null) { - var menu = new RadialMenu - { - HorizontalExpand = true, - VerticalExpand = true, - BackButtonStyleClass = "RadialMenuBackButton", - CloseButtonStyleClass = "RadialMenuCloseButton" - }; - - if (!_entManager.TryGetComponent(Owner, out var crafting)) - return menu; + if (_menu == null) + return; - var mainContainer = new RadialContainer + var container = new RadialContainer { - Radius = 36f / MathF.Sin(MathF.PI / 2f / crafting.Prototypes.Count) + Name = parentCategory ?? "Main", + Radius = 48f + 24f * MathF.Log(entries.Count), }; - foreach (var protoId in crafting.Prototypes) - { - if (!_protoManager.TryIndex(protoId, out var proto)) - continue; + _menu.AddChild(container); - var button = new RadialMenuTextureButton + foreach (var entry in entries) + { + if (entry.Category != null) { - ToolTip = Loc.GetString(proto.Name), - StyleClasses = { "RadialMenuButton" }, - SetSize = new Vector2(48f, 48f) - }; - - var texture = new TextureRect + var button = CreateButton(entry.Category.Name, entry.Category.Icon); + button.TargetLayer = entry.Category.Name; + CreateMenu(entry.Category.Entries, entry.Category.Name); + container.AddChild(button); + } + else if (entry.Prototype != null + && _protoManager.TryIndex(entry.Prototype, out var proto)) { - VerticalAlignment = Control.VAlignment.Center, - HorizontalAlignment = Control.HAlignment.Center, - Texture = _spriteSystem.Frame0(proto.Icon), - TextureScale = new Vector2(1.5f, 1.5f) - }; + var button = CreateButton(proto.Name, proto.Icon); + button.OnButtonUp += _ => ConstructItem(proto); + container.AddChild(button); + } + } - button.AddChild(texture); + } - button.OnButtonUp += _ => - { - ConstructItem(proto); - }; + private RadialMenuTextureButton CreateButton(string name, SpriteSpecifier icon) + { + var button = new RadialMenuTextureButton + { + ToolTip = Loc.GetString(name), + StyleClasses = { "RadialMenuButton" }, + SetSize = new Vector2(64f, 64f), + }; - mainContainer.AddChild(button); - } + var texture = new TextureRect + { + VerticalAlignment = Control.VAlignment.Center, + HorizontalAlignment = Control.HAlignment.Center, + Texture = _spriteSystem.Frame0(icon), + TextureScale = new Vector2(2f, 2f) + }; - menu.AddChild(mainContainer); - return menu; + button.AddChild(texture); + return button; } /// @@ -121,6 +132,6 @@ private void ConstructItem(ConstructionPrototype prototype) }, new ConstructionPlacementHijack(_construction, prototype)); // Should only close the menu if we're placing a construction hijack. - _menu!.Close(); + // Theres not much point to closing it though. _menu!.Close(); } } diff --git a/Content.Shared/ShortConstruction/ShortConstructionComponent.cs b/Content.Shared/ShortConstruction/ShortConstructionComponent.cs index 4ca40638668..dedf8605bdb 100644 --- a/Content.Shared/ShortConstruction/ShortConstructionComponent.cs +++ b/Content.Shared/ShortConstruction/ShortConstructionComponent.cs @@ -2,6 +2,7 @@ using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; +using Robust.Shared.Utility; namespace Content.Shared.ShortConstruction; @@ -9,7 +10,30 @@ namespace Content.Shared.ShortConstruction; public sealed partial class ShortConstructionComponent : Component { [DataField(required: true)] - public List> Prototypes = new(); + public List Entries = new(); +} + +[DataDefinition] +public sealed partial class ShortConstructionEntry +{ + [DataField] + public ProtoId? Prototype { get; set; } + + [DataField] + public ShortConstructionCategory? Category { get; set; } +} + +[DataDefinition] +public sealed partial class ShortConstructionCategory +{ + [DataField] + public string Name { get; set; } = string.Empty; + + [DataField] + public SpriteSpecifier Icon { get; set; } = default!; + + [DataField] + public List Entries { get; set; } = new(); } [NetSerializable, Serializable] diff --git a/Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml b/Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml index 91ba1abff93..59c9a8fc46f 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml @@ -98,8 +98,13 @@ - type: ActivatableUI key: enum.ShortConstructionUiKey.Key - type: ShortConstruction - prototypes: - - Window + entries: + - prototype: Window + - prototype: WindowDirectional + - prototype: WindowDiagonal + - prototype: SheetRGlass + - prototype: SheetPGlass + - prototype: SheetUGlass - type: entity parent: SheetGlass @@ -193,8 +198,12 @@ - type: ActivatableUI key: enum.ShortConstructionUiKey.Key - type: ShortConstruction - prototypes: - - ReinforcedWindow + entries: + - prototype: SheetRPGlass1 + - prototype: SheetRUGlass1 + - prototype: ReinforcedWindow + - prototype: ReinforcedWindowDiagonal + - prototype: WindowReinforcedDirectional - type: entity parent: SheetRGlass @@ -272,6 +281,18 @@ max: 1 - !type:DoActsBehavior acts: [ "Destruction" ] + - type: UserInterface + interfaces: + - key: enum.ShortConstructionUiKey.Key + type: ShortConstructionMenuBUI + - type: ActivatableUI + key: enum.ShortConstructionUiKey.Key + - type: ShortConstruction + entries: + - prototype: SheetRPGlass0 + - prototype: PlasmaWindow + - prototype: PlasmaWindowDiagonal + - prototype: PlasmaWindowDirectional - type: entity parent: SheetPGlass @@ -338,6 +359,17 @@ - ReagentId: Carbon Quantity: 0.5 canReact: false + - type: UserInterface + interfaces: + - key: enum.ShortConstructionUiKey.Key + type: ShortConstructionMenuBUI + - type: ActivatableUI + key: enum.ShortConstructionUiKey.Key + - type: ShortConstruction + entries: + - prototype: ReinforcedPlasmaWindow + - prototype: ReinforcedPlasmaWindowDiagonal + - prototype: PlasmaReinforcedWindowDirectional - type: entity parent: SheetRPGlass @@ -413,6 +445,18 @@ - ReagentId: Uranium Quantity: 10 canReact: false + - type: UserInterface + interfaces: + - key: enum.ShortConstructionUiKey.Key + type: ShortConstructionMenuBUI + - type: ActivatableUI + key: enum.ShortConstructionUiKey.Key + - type: ShortConstruction + entries: + - prototype: SheetRUGlass0 + - prototype: UraniumWindow + - prototype: UraniumWindowDiagonal + - prototype: UraniumWindowDirectional - type: entity parent: SheetUGlass @@ -467,6 +511,17 @@ - ReagentId: Carbon Quantity: 0.5 canReact: false + - type: UserInterface + interfaces: + - key: enum.ShortConstructionUiKey.Key + type: ShortConstructionMenuBUI + - type: ActivatableUI + key: enum.ShortConstructionUiKey.Key + - type: ShortConstruction + entries: + - prototype: ReinforcedUraniumWindow + - prototype: ReinforcedUraniumWindowDiagonal + - prototype: UraniumReinforcedWindowDirectional - type: entity parent: SheetRUGlass diff --git a/Resources/Prototypes/Entities/Objects/Materials/Sheets/metal.yml b/Resources/Prototypes/Entities/Objects/Materials/Sheets/metal.yml index 83982474d2a..427ae362a7a 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/Sheets/metal.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/Sheets/metal.yml @@ -76,12 +76,75 @@ - type: ActivatableUI key: enum.ShortConstructionUiKey.Key - type: ShortConstruction - prototypes: - - Girder - - MetalRod - - TileSteel - - TileWhite - - TileDark + entries: + - prototype: Girder + - prototype: MetalRod + - category: + name: Tiles + icon: + sprite: Objects/Tiles/tile.rsi + state: steel + entries: + - prototype: TileSteel + - prototype: TileWhite + - prototype: TileDark + - category: + name: Electronics + icon: + sprite: Structures/Machines/computers.rsi + state: computer-datatheory + entries: + - prototype: MachineFrame + - prototype: Computer + - prototype: Windoor + - prototype: LightTubeFixture + - prototype: APC + - prototype: AirAlarmFixture + - prototype: AirSensor + - prototype: FireAlarm + - category: + name: Atmospherics + icon: + sprite: Structures/Piping/Atmospherics/vent.rsi + state: vent_out + entries: + - prototype: GasPort + - prototype: GasOutletInjector + - prototype: GasVentScrubber + - prototype: GasPassiveVent + - prototype: GasVentPump + - prototype: GasMixer + - prototype: GasFilter + - prototype: GasVolumePump + - prototype: GasPressurePump + - prototype: GasValve + - category: + name: Piping + icon: + sprite: Structures/Piping/Atmospherics/pipe.rsi + state: pipeFourway + entries: + - prototype: HeatExchanger + - prototype: GasPipeBend + - prototype: GasPipeFourway + - prototype: GasPipeHalf + - prototype: GasPipeStraight + - prototype: GasPipeTJunction + - category: + name: Disposals + icon: + sprite: Structures/Piping/disposal.rsi + state: disposal + entries: + - prototype: DisposalPipe + - prototype: DisposalBend + - prototype: DisposalJunction + - prototype: DisposalYJunction + - prototype: DisposalRouter + - prototype: DisposalTagger + - prototype: DisposalTrunk + - prototype: DisposalUnit + - prototype: CrateGenericSteel - type: entity parent: SheetSteel @@ -218,6 +281,15 @@ - ReagentId: Carbon Quantity: 1 canReact: false + - type: UserInterface + interfaces: + - key: enum.ShortConstructionUiKey.Key + type: ShortConstructionMenuBUI + - type: ActivatableUI + key: enum.ShortConstructionUiKey.Key + - type: ShortConstruction + entries: + - prototype: SecureWindoor - type: entity parent: SheetPlasteel diff --git a/Resources/Prototypes/Entities/Objects/Materials/Sheets/other.yml b/Resources/Prototypes/Entities/Objects/Materials/Sheets/other.yml index dfb51336289..ab8597d02a5 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/Sheets/other.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/Sheets/other.yml @@ -110,6 +110,17 @@ - type: Tag tags: - Sheet + - type: UserInterface + interfaces: + - key: enum.ShortConstructionUiKey.Key + type: ShortConstructionMenuBUI + - type: ActivatableUI + key: enum.ShortConstructionUiKey.Key + - type: ShortConstruction + entries: + - prototype: SheetPGlass + - prototype: SheetRPGlass + - prototype: SheetRPGlass1 - type: entity parent: SheetPlasma @@ -162,6 +173,15 @@ - ReagentId: Phosphorus Quantity: 5 canReact: false + - type: UserInterface + interfaces: + - key: enum.ShortConstructionUiKey.Key + type: ShortConstructionMenuBUI + - type: ActivatableUI + key: enum.ShortConstructionUiKey.Key + - type: ShortConstruction + entries: + - prototype: CratePlastic - type: entity parent: SheetPlastic @@ -224,6 +244,17 @@ - ReagentId: Radium Quantity: 2 canReact: false + - type: UserInterface + interfaces: + - key: enum.ShortConstructionUiKey.Key + type: ShortConstructionMenuBUI + - type: ActivatableUI + key: enum.ShortConstructionUiKey.Key + - type: ShortConstruction + entries: + - prototype: SheetUGlass + - prototype: SheetRUGlass + - prototype: SheetRUGlass1 - type: entity parent: SheetUranium diff --git a/Resources/Prototypes/Entities/Objects/Materials/parts.yml b/Resources/Prototypes/Entities/Objects/Materials/parts.yml index 8b916f2e2be..e0547b3dc48 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/parts.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/parts.yml @@ -75,8 +75,30 @@ - type: ActivatableUI key: enum.ShortConstructionUiKey.Key - type: ShortConstruction - prototypes: - - Grille + entries: + - prototype: Grille + - prototype: GrilleDiagonal + - category: + name: Railings + icon: + sprite: Structures/Walls/railing.rsi + state: side + entries: + - prototype: Railing + - prototype: RailingCorner + - prototype: RailingRound + - prototype: RailingCornerSmall + - category: + name: Glass + icon: + sprite: Objects/Materials/Sheets/glass.rsi + state: rglass_3 + entries: + - prototype: SheetRPGlass + - prototype: SheetRPGlass0 + - prototype: SheetRUGlass + - prototype: SheetRUGlass0 + - prototype: SheetRGlass - type: entity parent: PartRodMetal diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/structures/windowdirectional.yml b/Resources/Prototypes/Recipes/Construction/Graphs/structures/windowdirectional.yml index 96f009fabb7..effddd7ca39 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/structures/windowdirectional.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/structures/windowdirectional.yml @@ -28,6 +28,7 @@ - material: ReinforcedPlasmaGlass amount: 1 doAfter: 3 + - to: uraniumWindowDirectional steps: - material: UraniumGlass @@ -136,6 +137,7 @@ doAfter: 2 - tool: Anchoring doAfter: 3 + - node: uraniumWindowDirectional entity: UraniumWindowDirectional edges: diff --git a/Resources/Prototypes/Recipes/Construction/structures.yml b/Resources/Prototypes/Recipes/Construction/structures.yml index b152e827e6a..52b43872561 100644 --- a/Resources/Prototypes/Recipes/Construction/structures.yml +++ b/Resources/Prototypes/Recipes/Construction/structures.yml @@ -688,6 +688,42 @@ objectType: Structure placementMode: SnapgridCenter +- type: construction + name: directional uranium window + id: UraniumWindowDirectional + graph: WindowDirectional + startNode: start + targetNode: uraniumWindowDirectional + category: construction-category-structures + canBuildInImpassable: true + description: Clear and tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. + conditions: + - !type:EmptyOrWindowValidInTile + - !type:NoWindowsInTile + icon: + sprite: Structures/Windows/directional.rsi + state: uranium_window + objectType: Structure + placementMode: SnapgridCenter + +- type: construction + name: directional reinforced uranium window + id: UraniumReinforcedWindowDirectional + graph: WindowDirectional + startNode: start + targetNode: uraniumReinforcedWindowDirectional + category: construction-category-structures + canBuildInImpassable: true + description: Clear and much tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. + conditions: + - !type:EmptyOrWindowValidInTile + - !type:NoWindowsInTile + icon: + sprite: Structures/Windows/directional.rsi + state: uranium_reinforced_window + objectType: Structure + placementMode: SnapgridCenter + - type: construction name: firelock id: Firelock From 5b9f28ca3cfa6b0c3ba89eb420adfbfbe9b0de4f Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 24 Sep 2024 00:56:59 +0000 Subject: [PATCH 13/21] Automatic Changelog Update (#949) --- Resources/Changelog/Changelog.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f85816dfafa..67ebde8ea6a 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -6627,3 +6627,23 @@ Entries: id: 6385 time: '2024-09-21T23:22:43.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/943 +- author: VMSolidus + changes: + - type: Fix + message: >- + Fixed a bug where Breath of Life and Healing Word would set living + people to crit, which would knock them down. + - type: Fix + message: >- + Fixed a bug where Breath of Life could revive people who were rotten(It + will still heal them and reduce the rot timer as intended, but will not + revive unless said rot timer reduction brings them below the 10 minute + threshold). + - type: Add + message: >- + The Do-After bar for Breath of Life and Healing Word is now hidden if + glimmer is low enough. The threshold for which scales with your + Dampening stat. More Dampening = stealthier casting. + id: 6386 + time: '2024-09-24T00:56:34.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/949 From 08248fff936374e49e9d42ec949ff865fd61a722 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 24 Sep 2024 00:57:25 +0000 Subject: [PATCH 14/21] Automatic Changelog Update (#945) --- Resources/Changelog/Changelog.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 67ebde8ea6a..d5a5a174f3f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -6647,3 +6647,12 @@ Entries: id: 6386 time: '2024-09-24T00:56:34.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/949 +- author: Mocho + changes: + - type: Add + message: >- + Added a lot of recipes to the quick construction menus. Give it a shot + by pressing Z with different construction materials in your hand! + id: 6387 + time: '2024-09-24T00:56:45.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/945 From 42871bc6a030cd3cae8aa5991a2075fefd1e630a Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Wed, 25 Sep 2024 01:09:06 -0400 Subject: [PATCH 15/21] IPCs Don't Weigh 5kg (#959) # Description The people who made IPC apparently never setup a fixture for them, so they were using the BaseMob default fixture, which provides a mass of 5kg. I've swapped it out for a standard human fixture for the time being. # Changelog :cl: - fix: IPC now weigh 71kg by default instead of 5kg. Seriously who the fuck made the BeepBoops out of feathers!?! --- Resources/Prototypes/Entities/Mobs/Player/ipc.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Resources/Prototypes/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/Entities/Mobs/Player/ipc.yml index 0e1e1a1ae7d..452062f2af3 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/ipc.yml @@ -115,6 +115,18 @@ whitelist: types: - Shard + - type: Fixtures + fixtures: # TODO: This needs a second fixture just for mob collisions. + fix1: + shape: + !type:PhysShapeCircle + radius: 0.35 + density: 185 + restitution: 0.0 + mask: + - MobMask + layer: + - MobLayer - type: entity save: false From b53b555612fc2c74a978007b5e46affbdaf36794 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 25 Sep 2024 05:09:36 +0000 Subject: [PATCH 16/21] Automatic Changelog Update (#959) --- Resources/Changelog/Changelog.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index d5a5a174f3f..e3ebd4d835f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -6656,3 +6656,12 @@ Entries: id: 6387 time: '2024-09-24T00:56:45.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/945 +- author: VMSolidus + changes: + - type: Fix + message: >- + IPC now weigh 71kg by default instead of 5kg. Seriously who the fuck + made the BeepBoops out of feathers!?! + id: 6388 + time: '2024-09-25T05:09:06.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/959 From af0c9327225f23b98d0f1f6caa079ce4e885847f Mon Sep 17 00:00:00 2001 From: fenndragon Date: Thu, 26 Sep 2024 09:06:54 -0600 Subject: [PATCH 17/21] Enemies and Allies Content Port (#956) # Description This is a batch of changes I made for Floof station being ported over to the upstream branch --- # Changelog :cl: - add: Added new neutral xenos, events, and reagent slimes --------- Signed-off-by: fenndragon Signed-off-by: SleepyScarecrow <136123749+SleepyScarecrow@users.noreply.github.com> Co-authored-by: FoxxoTrystan <45297731+FoxxoTrystan@users.noreply.github.com> Co-authored-by: SleepyScarecrow <136123749+SleepyScarecrow@users.noreply.github.com> --- .../station-events/events/vent-critters.ftl | 9 +- .../Prototypes/Body/Organs/Friendstomach.yml | 15 + .../Body/Prototypes/Friendshaped.yml | 24 + .../Prototypes/Entities/Mobs/NPCs/Rslimes.yml | 289 ++++++++++ .../Entities/Mobs/NPCs/elemental.yml | 15 +- .../Prototypes/Entities/Mobs/NPCs/xeno.yml | 34 +- .../Prototypes/Entities/Mobs/NPCs/xenopet.yml | 540 ++++++++++++++++++ .../Mobs/Aliens/Xenos/rouny.rsi/crit.png | Bin 3967 -> 5308 bytes .../Mobs/Aliens/Xenos/rouny.rsi/dead.png | Bin 5646 -> 5646 bytes .../Mobs/Aliens/Xenos/rouny.rsi/meta.json | 2 +- .../Mobs/Aliens/Xenos/rouny.rsi/running.png | Bin 11054 -> 14050 bytes .../Mobs/Aliens/Xenos/rouny.rsi/sleeping.png | Bin 2887 -> 2685 bytes .../Mobs/Animals/patriarch.rsi/meta.json | 24 + .../Mobs/Animals/patriarch.rsi/patriarch.png | Bin 0 -> 6815 bytes .../Animals/patriarch.rsi/patriarch_crit.png | Bin 0 -> 2183 bytes .../Animals/patriarch.rsi/patriarch_dead.png | Bin 0 -> 2644 bytes .../patriarch.rsi/patriarch_sleeping.png | Bin 0 -> 1941 bytes .../Mobs/Animals/subject7355.rsi/glow.png | Bin 0 -> 1977 bytes .../Mobs/Animals/subject7355.rsi/meta.json | 28 + .../Animals/subject7355.rsi/subject7355.png | Bin 0 -> 5421 bytes .../subject7355.rsi/subject7355_crit.png | Bin 0 -> 1851 bytes .../subject7355.rsi/subject7355_dead.png | Bin 0 -> 2760 bytes .../subject7355.rsi/subject7355_sleeping.png | Bin 0 -> 1549 bytes 23 files changed, 967 insertions(+), 13 deletions(-) create mode 100644 Resources/Prototypes/Body/Organs/Friendstomach.yml create mode 100644 Resources/Prototypes/Body/Prototypes/Friendshaped.yml create mode 100644 Resources/Prototypes/Entities/Mobs/NPCs/Rslimes.yml create mode 100644 Resources/Prototypes/Entities/Mobs/NPCs/xenopet.yml create mode 100644 Resources/Textures/Mobs/Animals/patriarch.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Animals/patriarch.rsi/patriarch.png create mode 100644 Resources/Textures/Mobs/Animals/patriarch.rsi/patriarch_crit.png create mode 100644 Resources/Textures/Mobs/Animals/patriarch.rsi/patriarch_dead.png create mode 100644 Resources/Textures/Mobs/Animals/patriarch.rsi/patriarch_sleeping.png create mode 100644 Resources/Textures/Mobs/Animals/subject7355.rsi/glow.png create mode 100644 Resources/Textures/Mobs/Animals/subject7355.rsi/meta.json create mode 100644 Resources/Textures/Mobs/Animals/subject7355.rsi/subject7355.png create mode 100644 Resources/Textures/Mobs/Animals/subject7355.rsi/subject7355_crit.png create mode 100644 Resources/Textures/Mobs/Animals/subject7355.rsi/subject7355_dead.png create mode 100644 Resources/Textures/Mobs/Animals/subject7355.rsi/subject7355_sleeping.png diff --git a/Resources/Locale/en-US/station-events/events/vent-critters.ftl b/Resources/Locale/en-US/station-events/events/vent-critters.ftl index 04b124d8245..d99906be4a3 100644 --- a/Resources/Locale/en-US/station-events/events/vent-critters.ftl +++ b/Resources/Locale/en-US/station-events/events/vent-critters.ftl @@ -2,7 +2,14 @@ station-event-slimes-spawn-announcement = Attention. A large influx of unknown life forms have been detected residing within the station's ventilation systems. Please be rid of these creatures before it begins to affect productivity. station-event-vent-critters-announcement = Attention. A large influx of unknown life forms have been detected residing within the station's ventilation systems. Please be rid of these creatures before it begins to affect productivity. station-event-spider-spawn-announcement = Attention. A large influx of unknown life forms have been detected residing within the station's ventilation systems. Please be rid of these creatures before it begins to affect productivity. - +station-event-reagentslime-vents-announcement = Attention. A large influx of unknown life forms have been detected residing within the station's ventilation systems. Please be rid of these creatures before it begins to affect productivity. +station-event-meat-vents-announcement = Attention. A large influx of unknown life forms have been detected residing within the station's ventilation systems. Please be rid of these creatures before it begins to affect productivity. +station-event-neutral-xeno-vents-announcement = Confirmed sightings of alien wildlife on the station. Personnel are advised to arm themselves, barricade doors, and defend themselves if necessary. Security is advised to investigate the threat as soon as possible. +station-event-tick-vents-announcement = Confirmed sightings of hostile alien wildlife on the station. Personnel are advised to arm themselves, barricade doors, and defend themselves if necessary. Security is advised to eradicate the threat as soon as possible. +station-event-argocyte-vents-announcement = Confirmed sightings of hostile alien wildlife on the station. Personnel are advised to arm themselves, barricade doors, and defend themselves if necessary. Security is advised to eradicate the threat as soon as possible. +station-event-light-vents-announcement = Confirmed sightings of hostile alien wildlife on the station. Personnel are advised to arm themselves, barricade doors, and defend themselves if necessary. Security is advised to eradicate the threat as soon as possible. +station-event-carp-vents-announcement = Confirmed sightings of hostile alien wildlife on the station. Personnel are advised to arm themselves, barricade doors, and defend themselves if necessary. Security is advised to eradicate the threat as soon as possible. +station-event-space-vents-announcement = Confirmed sightings of hostile wildlife on the station. Personnel are advised to arm themselves, barricade doors, and defend themselves if necessary. Security is advised to eradicate the threat as soon as possible. # Weak station-event-slimes-spawn-weak-announcement = Attention. A moderate influx of unknown life forms have been detected residing within the station's ventilation systems. Please be rid of these creatures before it begins to affect productivity. station-event-spider-spawn-weak-announcement = Attention. A moderate influx of unknown life forms have been detected residing within the station's ventilation systems. Please be rid of these creatures before it begins to affect productivity. diff --git a/Resources/Prototypes/Body/Organs/Friendstomach.yml b/Resources/Prototypes/Body/Organs/Friendstomach.yml new file mode 100644 index 00000000000..a20bbbe75bc --- /dev/null +++ b/Resources/Prototypes/Body/Organs/Friendstomach.yml @@ -0,0 +1,15 @@ +- type: entity + id: OrganFriendStomach + parent: OrganAnimalStomach + noSpawn: true + components: + - type: Stomach + - type: SolutionContainerManager + solutions: + stomach: + maxVol: 100 + food: + maxVol: 50 + reagents: + - ReagentId: UncookedAnimalProteins + Quantity: 5 diff --git a/Resources/Prototypes/Body/Prototypes/Friendshaped.yml b/Resources/Prototypes/Body/Prototypes/Friendshaped.yml new file mode 100644 index 00000000000..0ab85a03433 --- /dev/null +++ b/Resources/Prototypes/Body/Prototypes/Friendshaped.yml @@ -0,0 +1,24 @@ +- type: body + id: Friendshaped + name: "Friend-Shaped" + root: torso + slots: + torso: + part: TorsoAnimal + connections: + - hands + - legs + organs: + lungs: OrganAnimalLungs + stomach: OrganFriendStomach + liver: OrganAnimalLiver + heart: OrganAnimalHeart + kidneys: OrganAnimalKidneys + hands: + part: HandsAnimal + legs: + part: LegsAnimal + connections: + - feet + feet: + part: FeetAnimal diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/Rslimes.yml b/Resources/Prototypes/Entities/Mobs/NPCs/Rslimes.yml new file mode 100644 index 00000000000..03ce5a04e6e --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/NPCs/Rslimes.yml @@ -0,0 +1,289 @@ +- type: entity + id: ReagentSlimeIchor + parent: ReagentSlime + suffix: Ichor + components: + - type: Bloodstream + bloodReagent: Ichor + - type: PointLight + color: "#f4692e" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#f4692e" + +- type: entity + id: ReagentSlimeBleach + parent: ReagentSlime + suffix: Bleach + components: + - type: Bloodstream + bloodReagent: Bleach + - type: PointLight + color: "#a1000b" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#a1000b" + +- type: entity + id: ReagentSlimeSoap + parent: ReagentSlime + suffix: Soap + components: + - type: Bloodstream + bloodReagent: SoapReagent + - type: PointLight + color: "#c8dfc9" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#c8dfc9" + +- type: entity + id: ReagentSlimeSpacelube + parent: ReagentSlime + suffix: Spacelube + components: + - type: Bloodstream + bloodReagent: SpaceLube + - type: PointLight + color: "#77b58e" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#77b58e" + +- type: entity + id: ReagentSlimeBuzzachloricbees + parent: ReagentSlime + suffix: Buzzachloricbees + components: + - type: Bloodstream + bloodReagent: BuzzochloricBees + - type: PointLight + color: "#FFD35D" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#FFD35D" + +- type: entity + id: ReagentSlimeWehjuice + parent: ReagentSlime + suffix: Wehjuice + components: + - type: Bloodstream + bloodReagent: JuiceThatMakesYouWeh + - type: PointLight + color: "#59b23a" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#59b23a" + +- type: entity + id: ReagentCognizine + parent: ReagentSlime + suffix: Cognizine + components: + - type: Bloodstream + bloodReagent: Cognizine + - type: PointLight + color: "#b50ee8" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#b50ee8" + +- type: entity + id: ReagentSlimeNecrosol + parent: ReagentSlime + suffix: Necrosol + components: + - type: Bloodstream + bloodReagent: Necrosol + - type: PointLight + color: "#86a5bd" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#86a5bd" + +- type: entity + id: ReagentSlimeSpaceDrugs + parent: ReagentSlime + suffix: SpaceDrugs + components: + - type: Bloodstream + bloodReagent: SpaceDrugs + - type: PointLight + color: "#63806e" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#63806e" + +- type: entity + id: ReagentSlimeUnstableMutagen + parent: ReagentSlime + suffix: UnstableMutagen + components: + - type: Bloodstream + bloodReagent: UnstableMutagen + - type: PointLight + color: "#00ff5f" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#00ff5f" + +- type: entity + id: ReagentSlimeLead + parent: ReagentSlime + suffix: Lead + components: + - type: Bloodstream + bloodReagent: Lead + - type: PointLight + color: "#5C6274" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#5C6274" + +- type: entity + id: ReagentSlimechlorinetriflouride + parent: ReagentSlime + suffix: chlorinetriflouride + components: + - type: Bloodstream + bloodReagent: ChlorineTrifluoride + - type: PointLight + color: "#FFC8C8" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#FFC8C8" + +- type: entity + id: ReagentSlimePotassium + parent: ReagentSlime + suffix: Potassium + components: + - type: Bloodstream + bloodReagent: Potassium + - type: PointLight + color: "#c6c8cc" + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/elemental.rsi + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + color: "#c6c8cc" + +- type: entity + id: reagentslimeVents + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + startAnnouncement: true + earliestStart: 20 + reoccurrenceDelay: 12 + minimumPlayers: 1 + weight: 6 # Really weak compared to other critters + duration: 60 + - type: VentCrittersRule + entries: + - id: ReagentSlime + prob: 0.01 + - id: ReagentSlimeBeer + prob: 0.01 + - id: ReagentSlimePax + prob: 0.01 + - id: ReagentSlimeNocturine + prob: 0.01 + - id: ReagentSlimeTHC + prob: 0.01 + - id: ReagentSlimeBicaridine + prob: 0.01 + - id: ReagentSlimeToxin + prob: 0.01 + - id: ReagentSlimeNapalm + prob: 0.01 + - id: ReagentSlimeOmnizine + prob: 0.01 + - id: ReagentSlimeMuteToxin + prob: 0.01 + - id: ReagentSlimeNorepinephricAcid + prob: 0.01 + - id: ReagentSlimeEphedrine + prob: 0.01 + - id: ReagentSlimeRobustHarvest + prob: 0.01 + - id: ReagentSlimeIchor + prob: 0.01 + - id: ReagentSlimeBleach + prob: 0.01 + - id: ReagentSlimeSoap + prob: 0.01 + - id: ReagentSlimeSpacelube + prob: 0.01 + - id: ReagentSlimeBuzzachloricbees + prob: 0.01 + - id: ReagentSlimeWehjuice + prob: 0.01 + - id: ReagentCognizine + prob: 0.01 + - id: ReagentSlimeNecrosol + prob: 0.01 + - id: ReagentSlimeSpaceDrugs + prob: 0.01 + - id: ReagentSlimeUnstableMutagen + prob: 0.01 + - id: ReagentSlimeLead + prob: 0.01 + - id: ReagentSlimechlorinetriflouride + prob: 0.01 + - id: ReagentSlimePotassium + prob: 0.01 + - id: ReagentSlimeLotophagoiOil + prob: 0.01 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml index 11c6f926ba6..69a8b0e44a9 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml @@ -329,6 +329,19 @@ - ReagentSlimeNorepinephricAcid - ReagentSlimeEphedrine - ReagentSlimeRobustHarvest + - ReagentSlimeIchor + - ReagentSlimeBleach + - ReagentSlimeSoap + - ReagentSlimeSpacelube + - ReagentSlimeBuzzachloricbees + - ReagentSlimeWehjuice + - ReagentCognizine + - ReagentSlimeNecrosol + - ReagentSlimeSpaceDrugs + - ReagentSlimeUnstableMutagen + - ReagentSlimeLead + - ReagentSlimechlorinetriflouride + - ReagentSlimePotassium - ReagentSlimeLotophagoiOil chance: 1 @@ -560,4 +573,4 @@ color: "#3e901c" - type: GhostRole prob: 1 #it's significantly more psionic than the others - description: ghost-role-information-angry-slimes-description \ No newline at end of file + description: ghost-role-information-angry-slimes-description diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index fc0f879b1ce..66115b46e4c 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -58,13 +58,18 @@ layer: - MobLayer - type: MobState - allowedStates: - - Alive - - Dead + - type: Deathgasp + - type: MobStateActions + actions: + Critical: + - ActionCritSuccumb + - ActionCritFakeDeath + - ActionCritLastWords - type: MobThresholds thresholds: 0: Alive - 50: Dead + 50: Critical + 100: Dead - type: SlowOnDamage speedModifierThresholds: 25: 0.5 @@ -92,6 +97,7 @@ Dead: Base: dead - type: Puller + needsHands: false - type: Butcherable butcheringType: Spike spawned: @@ -121,8 +127,11 @@ molsPerSecondPerUnitMass: 0.0005 - type: Speech speechVerb: LargeMob - - type: Psionic #Nyano - Summary: makes psionic by default. + - type: Psionic removable: false + - type: InnatePsionicPowers + powersToAdd: + - TelepathyPower - type: LanguageKnowledge speaks: - Xeno @@ -144,7 +153,8 @@ - type: MobThresholds thresholds: 0: Alive - 100: Dead + 100: Critical + 150: Dead - type: Stamina critThreshold: 300 - type: SlowOnDamage @@ -177,7 +187,8 @@ - type: MobThresholds thresholds: 0: Alive - 80: Dead + 80: Critical + 130: Dead - type: SlowOnDamage speedModifierThresholds: 40: 0.7 @@ -214,7 +225,8 @@ - type: MobThresholds thresholds: 0: Alive - 300: Dead + 300: Critical + 350: Dead - type: SlowOnDamage speedModifierThresholds: 150: 0.7 @@ -260,7 +272,8 @@ - type: MobThresholds thresholds: 0: Alive - 100: Dead + 100: Critical + 150: Dead - type: MovementSpeedModifier baseSprintSpeed: 4 - type: MeleeWeapon @@ -299,7 +312,7 @@ - type: MeleeWeapon damage: groups: - Brute: 5 + Brute: 10 - type: Fixtures fixtures: fix1: @@ -321,6 +334,7 @@ drawdepth: Mobs sprite: Mobs/Aliens/Xenos/rouny.rsi offset: 0,0.6 + scale: 0.7, 0.7 - type: Butcherable butcheringType: Spike spawned: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xenopet.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xenopet.yml new file mode 100644 index 00000000000..09dd78c6c0d --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xenopet.yml @@ -0,0 +1,540 @@ +- type: entity + name: Neutral Rouny + id: MobXenoNeutralRouny + parent: MobXenoRounyNPC + description: They mostly come at night. Mostly. + components: + - type: NpcFactionMember + factions: + - Passive + - type: PointLight + radius: 2 + energy: 1 + color: "#B85E5E" + - type: MovementAlwaysTouching + - type: GhostRole + name: ghost-role-information-friendlyxeno-name + description: ghost-role-information-friendlyxeno-description + rules: ghost-role-information-friendlyxeno-rules + - type: GhostTakeoverAvailable + - type: LanguageKnowledge + speaks: + - Xeno + understands: + - Xeno + - TauCetiBasic + +- type: entity + name: Neutral Praetorian + id: MobXenoNeutralPraetorian + parent: MobXenoPraetorianNPC + description: They mostly come at night. Mostly. + components: + - type: NpcFactionMember + factions: + - Passive + - type: PointLight + radius: 2 + energy: 1 + color: "#62B85E" + - type: GhostRole + name: ghost-role-information-friendlyxeno-name + description: ghost-role-information-friendlyxeno-description + rules: ghost-role-information-friendlyxeno-rules + - type: GhostTakeoverAvailable + - type: LanguageKnowledge + speaks: + - Xeno + understands: + - Xeno + - TauCetiBasic + +- type: entity + name: Neutral Drone + id: MobXenoNeutralDrone + parent: MobXenoDroneNPC + description: They mostly come at night. Mostly. + components: + - type: NpcFactionMember + factions: + - Passive + - type: PointLight + radius: 2 + energy: 1 + color: "#8B5EB8" + - type: GhostRole + name: ghost-role-information-friendlyxeno-name + description: ghost-role-information-friendlyxeno-description + rules: ghost-role-information-friendlyxeno-rules + - type: GhostTakeoverAvailable + - type: LanguageKnowledge + speaks: + - Xeno + understands: + - Xeno + - TauCetiBasic + +- type: entity + name: Neutral Ravager + id: MobXenoNeutralRavager + parent: MobXenoRavagerNPC + description: They mostly come at night. Mostly. + components: + - type: NpcFactionMember + factions: + - Passive + - type: PointLight + radius: 2 + energy: 1 + color: "#E3954D" + - type: GhostRole + name: ghost-role-information-friendlyxeno-name + description: ghost-role-information-friendlyxeno-description + rules: ghost-role-information-friendlyxeno-rules + - type: GhostTakeoverAvailable + - type: LanguageKnowledge + speaks: + - Xeno + understands: + - Xeno + - TauCetiBasic + +- type: inventoryTemplate + id: friendxeno + slots: + - name: id + slotTexture: id + slotFlags: IDCARD + slotGroup: SecondHotbar + stripTime: 6 + uiWindowPos: 2,1 + strippingWindowPos: 2,4 + displayName: ID + - name: head + slotTexture: head + slotFlags: HEAD + uiWindowPos: 1,2 + strippingWindowPos: 0,0 + displayName: Head + - name: mask + slotTexture: mask + slotFlags: MASK + uiWindowPos: 0,1 + strippingWindowPos: 1,1 + displayName: Mask + +- type: entity + name: Friend-Shaped + parent: MobXenoNeutralRouny + id: MobXenoFriendShaped + description: A very clearly friend-shaped Xeno. + components: + - type: NpcFactionMember + factions: + - PetsNT + - type: Tool + speed: 3 + qualities: + - Prying + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Aliens/Xenos/rouny.rsi + scale: 0.5, 0.5 + - type: GhostRole + - type: GhostTakeoverAvailable + - type: Inventory + templateId: friendxeno + - type: IdExaminable + - type: InventorySlots + - type: Stripping + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - type: Grammar + attributes: + proper: true + gender: male + - type: Body + prototype: Friendshaped + requiredLegs: 1 # TODO: More than 1 leg + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-reptile + interactFailureString: petting-failure-generic + interactSuccessSpawn: EffectHearts + interactSuccessSound: + path: /Audio/Animals/lizard_happy.ogg + +- type: entity + name: Patriach + parent: MobXenoNeutralPraetorian + id: MobXenoPatriarch + description: A not entirely clearly friend-shaped Xeno. + components: + - type: NpcFactionMember + factions: + - PetsNT + - type: Tool + speed: 3 + qualities: + - Prying + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Animals/patriarch.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: patriarch + - type: DamageStateVisuals + states: + Alive: + Base: patriarch + Critical: + Base: patriarch_crit + Dead: + Base: patriarch_dead + - type: Inventory + templateId: friendxeno + - type: IdExaminable + - type: InventorySlots + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - type: Grammar + attributes: + proper: true + gender: male + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-reptile + interactFailureString: petting-failure-generic + interactSuccessSpawn: EffectHearts + interactSuccessSound: + path: /Audio/Animals/lizard_happy.ogg + +- type: entity + name: FXES + parent: MobXenoNeutralDrone + id: MobXenoFXES + description: A very clearly friend-shaped Xeno. + components: + - type: NpcFactionMember + factions: + - PetsNT + - type: Tool + speed: 3 + qualities: + - Prying + - type: Inventory + templateId: friendxeno + - type: IdExaminable + - type: InventorySlots + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - type: Grammar + attributes: + proper: true + gender: male + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-reptile + interactFailureString: petting-failure-generic + interactSuccessSpawn: EffectHearts + interactSuccessSound: + path: /Audio/Animals/lizard_happy.ogg + +- type: entity + name: Hell-Shaped + parent: MobXenoNeutralRavager + id: MobXenoHellShaped + description: A very clearly friend-shaped Xeno. + components: + - type: NpcFactionMember + factions: + - PetsNT + - type: Tool + speed: 3 + qualities: + - Prying + - type: Inventory + templateId: friendxeno + - type: IdExaminable + - type: InventorySlots + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - type: Grammar + attributes: + proper: true + gender: male + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-reptile + interactFailureString: petting-failure-generic + interactSuccessSpawn: EffectHearts + interactSuccessSound: + path: /Audio/Animals/lizard_happy.ogg + +- type: entity + name: FXE Subject 7355 + parent: MobXenoNeutralRavager + id: MobXenoSubjectTess + description: An extremely oddly coloured xeno, with glowing stripes. An odd mutation. + components: + - type: NpcFactionMember + factions: + - PetsNT + - type: Tool + speed: 3 + qualities: + - Prying + - type: Sprite + drawdepth: Mobs + sprite: Mobs/Animals/subject7355.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: subject7355 + - map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ] + state: glow + shader: unshaded + - type: PointLight + radius: 2 + energy: 1 + color: "#639fff" + - type: DamageStateVisuals + states: + Alive: + Base: subject7355 + Critical: + Base: subject7355_crit + Dead: + Base: subject7355_dead + - type: Inventory + templateId: friendxeno + - type: IdExaminable + - type: InventorySlots + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - type: Grammar + attributes: + proper: true + gender: male + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-reptile + interactFailureString: petting-failure-generic + interactSuccessSpawn: EffectHearts + interactSuccessSound: + path: /Audio/Animals/lizard_happy.ogg + +- type: entity + id: neutralXenoVents + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + startAnnouncement: true + earliestStart: 20 + reoccurrenceDelay: 12 + minimumPlayers: 1 + weight: 6 # Really weak compared to other critters + duration: 60 + - type: VentCrittersRule + entries: + - id: MobXeno + prob: 0.01 + - id: MobXenoNeutralRouny + prob: 0.005 + - id: MobXenoNeutralDrone + prob: 0.005 + - id: MobXenoNeutralPraetorian + prob: 0.005 + - id: MobXenoNeutralRavager + prob: 0.005 + +- type: entity + id: ArgocyteVents + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + startAnnouncement: true + earliestStart: 20 + reoccurrenceDelay: 12 + minimumPlayers: 12 + weight: 6 # Really weak compared to other critters + duration: 60 + - type: VentCrittersRule + entries: + - id: BaseMobArgocyte + prob: 0.01 + - id: MobArgocyteSlurva + prob: 0.005 + - id: MobArgocyteBarrier + prob: 0.005 + - id: MobArgocyteSkitter + prob: 0.005 + - id: MobArgocyteSwiper + prob: 0.005 + - id: MobArgocyteMolder + prob: 0.01 + - id: MobArgocytePouncer + prob: 0.005 + - id: MobArgocyteGlider + prob: 0.005 + - id: MobArgocyteHarvester + prob: 0.005 + - id: MobArgocyteCrawler + prob: 0.005 + - id: MobArgocyteEnforcer + prob: 0.005 + - id: MobArgocyteFounder + prob: 0.005 + - id: MobArgocyteLeviathing + prob: 0.005 + +- type: entity + id: MeatVents + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + startAnnouncement: true + earliestStart: 20 + reoccurrenceDelay: 12 + minimumPlayers: 12 + weight: 6 # Really weak compared to other critters + duration: 60 + - type: VentCrittersRule + entries: + - id: BaseMobFlesh + prob: 0.01 + - id: MobFleshJared + prob: 0.005 + - id: MobFleshGolem + prob: 0.005 + - id: MobFleshClamp + prob: 0.005 + - id: MobFleshLover + prob: 0.005 + - id: MobAbomination + prob: 0.005 + +- type: entity + id: TickVents + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + startAnnouncement: true + earliestStart: 20 + reoccurrenceDelay: 12 + minimumPlayers: 1 + weight: 6 # Really weak compared to other critters + duration: 60 + - type: VentCrittersRule + entries: + - id: MobTick + prob: 0.01 + +- type: entity + id: CarpVents + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + startAnnouncement: true + earliestStart: 20 + reoccurrenceDelay: 12 + minimumPlayers: 12 + weight: 6 # Really weak compared to other critters + duration: 60 + - type: VentCrittersRule + entries: + - id: MobCarp + prob: 0.01 + - id: MobCarpMagic + prob: 0.01 + - id: MobCarpHolo + prob: 0.01 + - id: MobCarpRainbow + prob: 0.01 + - id: MobShark + prob: 0.01 + - id: MobCarpDragon + prob: 0.01 + +- type: entity + id: SpaceVents + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + startAnnouncement: true + earliestStart: 20 + reoccurrenceDelay: 12 + minimumPlayers: 12 + weight: 6 # Really weak compared to other critters + duration: 60 + - type: VentCrittersRule + entries: + - id: MobBearSpace + prob: 0.01 + - id: MobKangarooSpace + prob: 0.01 + - id: MobSpiderSpace + prob: 0.01 + - id: MobCobraSpace + prob: 0.01 + +- type: entity + id: LightVents + parent: BaseGameRule + noSpawn: true + components: + - type: StationEvent + startAnnouncement: true + earliestStart: 20 + reoccurrenceDelay: 12 + minimumPlayers: 12 + weight: 6 # Really weak compared to other critters + duration: 60 + - type: VentCrittersRule + entries: + - id: MobLivingLight + prob: 0.01 + - id: MobLuminousPerson + prob: 0.01 + - id: MobLuminousObject + prob: 0.01 + - id: MobLuminousEntity + prob: 0.01 + +- type: entity + name: Friendly Xeno spawner + id: friendlyxenoSpawner + parent: MarkerBase + components: + - type: Sprite + layers: + - state: green + - sprite: Mobs/Aliens/Xenos/drone.rsi + state: sleeping + - type: RandomSpawner + prototypes: + - MobXenoNeutralRouny + - MobXenoNeutralPraetorian + - MobXenoNeutralDrone + - MobXenoNeutralRavager + chance: 1 diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/crit.png b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/crit.png index 23a7ec0af6ce506eb43bb5cea68bc2adc5a96e93..72f56385f584a743197460d5597a09e4342f127f 100644 GIT binary patch delta 5261 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 TO1iTE0000;jZd?r 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 TtZpSK00000NkvXXu0mjfHa~}e diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/dead.png b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/dead.png index cd355b615291e1846feb8518cc3c8b2091a11f6a..8e8464328125328660dbf0268047d764aacd7320 100644 GIT binary patch delta 5591 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 delta 5591 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 diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/meta.json b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/meta.json index cc020d01c46..f238edbb198 100644 --- a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/meta.json +++ b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "DakoDragon, discord ID: 56038550335922176", + "copyright": "Created by Fenndragon, discord ID: 190763499276861440", "size": { "x": 64, "y": 64 diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/running.png b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/running.png index 1438285113f2ade192e11385efe9fecfc529ede8..556dc97d7e95a0fc88cb2e0342a5500dffcfd105 100644 GIT binary patch literal 14050 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 G@c#i~XE{s& literal 11054 zcmcIqWmg=}(_P%%-8I48A-E>Ed$8c{PH+jq-Q9y*a0#}ACAci^y0||3`+tY$#mw}X zIcK`MyZZL6TNU#~O&$Z46cqpfU??icXh5GK|6Rz4(EE_M`6Tp#;-aAM4gg>d{dd8P zIahv#z9jRI)$`DFw)XHgce4UWTRFJIX=0|Lh(h##K5rBLhh*DllMAFk;6_#}7yhWo1XNZ=CIWe?NwwR7zr}<$%6$&tbO_*dDamd64gZ-dmh% zfzQOT3!x5)uC$LEy>8FzRwO*Tu^ze~aBUbqfKMrBp{oU^Xlhyr|x8tQWrM@*(Hs~G=axgQCWF^<7_nty=*Qj zuQR%fkB%s3xZbwBtjy*9&e0S#4~*NbtoqN46N4p(H__fC81jG%wWB?+bJsQ&C1tY1 zZ+Tn`%pFxfnv)>q3FzO|tj@fj`^6y&Q}5m}F9-uidn}&(MbD%^;iA|31qB-)bdc|f zYU+FZXs%1WYB4SJfej+r^oRJS+sj5+Vx{E~jRT?HvqP(@f6z~0%P)k;?@$^=@oKHx z83~PC`1>Bh+S68Sn{|P}k6?8JZcezJP5!qm5BBHP; z9tQEu64%QZ?ZI$f%*+@q*7i%AfTKiS(vzGJpdG3LXVyRC85KbJbnb92Q961zED53g zmDLf+>U!iCCvFAuuZeV3(Lp91OXnIOKHE>W+OdPBKIf}_;c*VaAYPx!jcFjc@Qe!C zyJ2sEGTR@mnM&|A!(f3*=d$2E_Na+nJ+ZV7k^ z>{f*#|C#s+OT51fhQTE-tXk6kG>iXysfRLzO2|V4)=rr2?N#I=C`edR z!;SX-Y(Z+m>>sT{G30THde{~{Yf&c{IAmkD1ZdnrFW?8ZQB*=IB(2I7CLcb zS4{nRBtrC)<1>Ab+%8gQ?n?d$WAOw{w%?hjFqb1t(4Df(PmvK~oLCPl1Fx%2iL@T| zm$#^<1Py0^)OjF1Sxv_T>hlI}Yvp~|Fu!-E7z`l|i^{CA9b0uxJhd&jmrg;I zJP}-s;Q@6Gs?-Wy1=jl!Z^4IVw?yesAN}pT_~+*#KLCd&n~ITvEvwthQHY%$y9|HX zIu0`5QadDt2ibU~PyYv8Hl0@62Me)&OZ-&hwGK zPCHnCauv_$gS-(%LWe%ndNg%v_2dYvK_ZO82&@(^7nZ_u29rnCGiD}GT2IbhjjUZR z_@|CB+2*XQA`*ykvn&_QD958=bgW|M7Dr>*D}AyMo!~q?JcNBQRY4l0I>r=R21DLl zDltUzkw?{xY!+G0`BaQ0D@uf9us!Y z^!cyJT)(iqc!k8gw#dm48)gIR+5DeHn{AdlEGPZme4dU1c3$u0bK!B|J~_GWTO<|M z^%%wCfgA~;i>ABbwP3sLNMb6=hc((}faXh`{F#AM}hVn={nG64hkf(eax}d*` ziA2;(9cZ4Oo>EoZYU21o;F3R7RthcovPUGJrskC~k&@p)ZDA3O`~->TI8 zARR;W(1XiYhoRY2FTeo>5O{Er$&EW;(fUQu34O8ekv%w*FU2{yF>ICFO_50Nf`FZQ zVt+ra0G5-5=6mbebkRK(JMko(zZXPOhaHPbxW73gcWker$L|xKl*~K@W}e4OctD&n z6P+Yt2m+?qjdve>bh}&dEju8;Adn`bw*@~0iN~n4lmW6skpneL`YZ7t@fcD(pH5I& zY)d}ssw8KKyuE$LqIO7UbBYs!eE?&5R-mYXAsn{BNtC6!BL?ggaEgX~W8wmfVmHUm zYc!4MI>B39&|Hz4_Bgb^UmTzK@Hv;g);w?p^Hht|JcPw;y9!V5{*N4bL1?*MX(cnX#7+STv!+{Ycq=FOTd5n_H0Oij|>+XVYMsBg&zJS zoln`vL_ewtMf1@vKf-zwX>|iq5mK@wF&Kb`N_p8q>4DJ~Gj4?#jophAEFM0-a93*@ zHlGzpYkSJGgn^J7jepZA8a9q+l^9k=d83{D>vP;U`;LKR zsrDItx1CDRb8vCRbM)5o7@?1yGc&XQ zqgaZexFLl)3HqP~pC(sXs&8CIk^88M~6tIkX0TxMGBb~j(&p% zxy17Ed3?mbB62d!6sA*&b={X<_nwrYrb5|$HuqQVIkA-rP!@981jBZf(?k@?tij0S9#_l0`}e2z-9;>KeIs)&XPS|s>0pcbBa7K){i{!Ja+zde{s>z^z0jSwJC0|LG1YATCYdyippv_To2>eq*KoXH=IUDU-m z?%hWD9`L+=f5aOQUVT)E;!-88yT=$Vc-8z8jVp@Sf@Cd^(DPSslAsOUjZOhY71W6A z@r3@iakzEt;XmxQLhw?3PVIi$sR#F%{e>P)u%!f-k%lY(+51Ac9KPdkJ&#uiF8(Ym zx%w9@(F@n8!9FCz&R>6aI__@UAJUD-7~fbxpWbU?a$i0=nLv&T%eD%Up+FNw(pies z@-7|ugZ#_!U<~CA%G%*n0x=x&<)R#xX%hE?s*=z4CCvT`gqW(_p1IIaD(~kHDMgtF zd-;>-Z22J?+GE6SHFI=$ALgkm2pSNE{nt_IpZ@ZjjmA;^%wRL`!*{9`&!0$~OhnrF zE<66=-b7<6033BVlAtgsbsY-K5)#!h9Fn~goluoi$?hAZ;=LXd4h}giULh^+EFVh# zfen1=9kW&>uE?5CYg@}q4@Ns#7u!D{Fn}FW*U%pJbnYEW^U8}Q-Y5{QiG7^hRNI*S zyCR(FX2FkOdN6M35RXZbg8WA+=9Qiz8d3wfN0qN2jXHL~@t(p!KeBXh3S^Y|k3&G9D0@Gx=Smoco7M{}NY zoKcC0o{G)|IHdLuoL&cZ{T)ifk$HAL{w8GckeQh(XJW){taJ$zd3~i;vZ?)|YQyf= z(6A2R_vcfxxKv7jE0n&W9nwidZ24!*evkqsS zf!h)a5?=73>s7$*ra($<$Pt!x=*w1Jw}tCZNx%pf_i*qiqn;VcDDCs>9ALBTq1N>9 zw1g5SJR&K@`iDhvt=%1IRN-k-cK$P*>8+&ls=U}gqi>Uz0sV^e2roSw(~talnvsR* zgMXt7L({)Q8NJIZOdloivQ{}$2L>zYtc7iw&0V9-L zn?*a_#+I$aw#Ejeo+#;1x=A&;`jovIe(q6xeau*7yz&ezKTEqlcqr#$vvC^UGs52L z_K}q_-Wf0H|7teqd<(h^7TP*e+QuziS-sV%0eV~e=x@62yY*vtrGByHZnO{jdBeVQ z9-mv8tdu20vi7#zmF$`}+5r#W_i)jm62+iqoR+1^Gsx`z`Ezn;oG~klZk{J-X5v zUI*4-De~{`JUuF^2ebpWKfH#(hi`uS-Bzz36^#*m11@&bh8QJ3Lf*{~C6IB{-Qnu@ zw({Xh>_|z3Fx}98WsyZQQsTfyM|Z7M@uH6*GLV&C8e&+ktE;d$_$vdcxy`@b-AS+*phwVAmtr=%-Jn-h0`Yx|Op*mZCSSSood?Z18%x|$aN zL!Ja}k>yiet|DNa0{jojR5;u_v|8AVrD_Uz#s(b85S>F}BB`%9RDjZWH0u2*rKoyW z$}xIq+*vC42^`?A_6>6*jk&y41B0OTiXH{SAwTX^wUJzwK!#EuNiwlfl3WqDZ)Ex9FYaT4hrOlyu(KV1-m|S5f zy5xZE2CVX0mXpLdc8DMi7UEWynh6k5Y0&9x;lfzplgSnxRN-d4M2 zpROLZ!i(H4X2y%q`b4_=Pm}U4&X3EDaoohSR7g2ITbsIOczi@Uqo2x+nItZ)FVJ5^ zvbKnZ<`FEakot|f)$Gg~34%l>OG1Brzyq-)eP-09{{H(bHcl)PzT4}nSV@(CE|yCj zT~cwsu61+8)ef6s$6)f9U`pufY-YOU!DW%~HJazSe&-Wr(&BSYBW%26&{zauwmrPT zuh0!hdMnYa{J9zhkhWnau@>=A?d~A70WTMX^0RI@^$JqmvGP9Qox-yA>hs0faR>Jb1S}7+j8b!Juz|`f-tcOSSQNOP@^b8b z;sGI|akB2-p0}Ca^)AQN^IyO4I-%c2iM@C{-<_)sHByFqVUX&=Cl;?>;Eh%c^8^Fy ze?yGSsD|S52iO$*(4kb^vmXnmeo||O*=BlzEfE`r`ia~t4OFHyjmQE$a(Ke-k>laR z#@3!gP@7}@y7Y3(tJurbD!ZsYM@OS(AWB`BPr=aKTkTyhq4)(ka~d2;oM6URet4LK zh6MxCA7vu`RH#NL0IC=v?b#TcRBFQmSQgYQ{HPN2r-&&r6{89v>H(dcz%7k5*qw^> zL|pJ!8J7wW320Id#pTzwQk1f>K#f}}fa!y^h|#fClK+3r-|Ang-&zDlt-#E`10MEt ze;1zz-5ZlI^eaYRGC-JN)ILQ=AMc=(j{FI|9Eehf&AlOpeoKTlcK?4G90V|aR8@#W z5*%Q?U0>QQWhp2*!m=SUOK66=S!nc+pZQZA6Q3v_z<3Mu((tiBB9UsAN*19-(T^??#XE(c(+DNUoJDMr0va^HRdm_AwobQQ; z0#)x?vQ=vxY^@>@M+huCuX^th9de>8CGuPmMflJ5@!-l=e=1x***c#^Xa2@}@0HYc zjd3`2;PFo*eegH~q9l*%gAY|dw_7Kbu`Y7$#ziL~?Uz|qDaEBZqADR(njZ~Ym~6Hn zea^^;flcFKeR%q{C@g|OC$8}%sCx2nf^aZe_x=^HfThuJI-ssNq^{uXusyd9RSAB< z+xyB0G<%a^iGicuSHPX%iFE9H4gRal@|;T$P-Dy_uo3LO7b6FYqka#M>FlHhCI>HI zK=m=}xU39;i!w>-b&Kub6|$w}CH$+_;u~I1&9H<~Cn|q@BLi_n=k|+FlV+7@%fmud%=Qy} z1mP|?!AdiS2#Cv&`j>5s)wWj$WTQRGvsmrELy5e+oV&)A5ERnX)Q+WQ$Kd%M472vI z(|(v4Mze}A34b+mTqyHUl_j{1672!4j~MpSYYp#ghr6HL@G!Zb#7!Pt9GwT;_~;1Z z(o(GdZrqrLN*y!a2`AxRzC&y7vssG;_Gdn2fNKYCe;S`t19Ro-FG}t z2OYYwRFL;hzRB25@nL4Lo@mFxPY(+hGynqw5I_??zGs-%UA;@g?`3Vw3TUM{P#*8g z!G^-N2~|@&mx-G8!#x4KEDD$k>4*sb2zfHpSgnE8Y+@73^@S5(i`NgU?j6-HwO;!( zzEapj2cNO+mdMMiSpjaxImS;02nZTgE4+-w>0WkCurdOxp=_ zy}fDhOZ-&eXa_qcXzTq?9NE41cevwc!Ej&qggUL(S12oD-~Ip5V`?vcpW|g&YOoVE zY)|UT^<-RKyrA!CKsQ7BM8jH|6tQ^5k${xJ_t3>be)O9dJ>8V&bKuP=YpTYn)@5)L zF7?Z=Qq7sHiNylny><-o3&*jZQFZK~*`{(k`ZC7r?27Lip_@KyQ*B2ou`YZyBj3s$ zG*EOu2Bv*D72bhE*~YD1yV&>_4oEuw?$PEA)2KecLn#0>@}V?ba4PAZT%|KbsO1Bf zAqupwdbY6&F6OJ8B=e&W6(T%j0DVatv!*`3+{P*gJzS9$z&7d(pf%xwQKOVqk?AP} zihi7I`rcocOy(eCa4`Ud*0?r1^XIsj zf17K8^cXrl6O#*Y<4g?s@*&f;rKM#DfwIOM;vPD4K}62?ze0ESby)!5nDzjSKRmh@~@#WaEKki&+NlU2piuzY|PKY2kHDN zIajoywBF5~926|r4RCIMKbcb@O;jP%uUGkKjpuG^g4homm53!sKHD};h(}oSonV^c zA*2dsxew~xBmD1dn~$*8eo7JFZ=Lp+jeGuj{ODGme6(9am6w?>j%5w%^yE1xwSwf@ z1Y?b``-n}7?=7Mb3Xp5Ri1WRyyicY2bai)Kc|8kOQq#GJ2VZ{cBx3IkacW4Cezvb_ zaO}T)bhhR)oPy%-=iwkSrveGCAX-nP6PTrPvytQ#-|lXaf{SGKIaaV?XbzjX?P7A| z9>by_B%$K?4(9TJr%$QwnKO?f&z3QP*Pm6qA!7yZHhBX9dAeIk}Ae9fiE>L zaPQy1w1*q*J`Mc+^kEujxmj7Vmd2Wu^~ozZiBm>MjLlh$KpgY}DWd@LEI-7>zE?~D z)HL5}r-JfGvj!rZ+qfo%7RoE-rdQNAk-=+TS{SGH6Po9CzKsdsH?N&r66r4I1M#RC z%UdUl&cGT853p$%R5N_sifqlbhr~fhaN+@3zG_a!?ff_I2r%4B2<0jqJJ3)>)?pGv zlwYIMuolL|c{n-f^d9u<8*Zz)k_C1FanRAFL3qxlTITRpcGnlJ38?VpNkav`W3?!S_+j%aKbMsb0g=S>Tp=qBE$c(;sdiA4Xs+Tk_%P4+ z{h!ukN2-e2-)Ntv=IBc^W1xtKCSP-d{v&TRyFs|7c5G%mUF0JE+jF>@?r=i~#lup_ z*>r1w02|)-;0fa6vLyJ8%?dM>!gT4*e6Op$=6}an3tNyU26eK_Nxf4*FABir38CV; zRYHQo9bpjZ{U9H1s%=jLXX^~?SO9(>BufiE*Lmm*V=UAj_<-Rw({@CUqCzNGTu3s0 zQX#iv0}akHG7_Q*-)_o?Dic2N%LSU$z38@@JZcAqRDt*@OlL(? z0Rg{Dh(y_Iy&-|!YF?=VOe!2UCr^1E-X7*)rcX5*yw5#{*2)Ssi?xKLBl1cW19Avy za2_Lw{^UT1RW4fij^a{1)k}}N9P8e&E7)mQ(xZupzyB~EbTOQq1y~q)6lsglDA}%b zls?2QHM+SEzhJUH^j1`){rx)kpnulCxET}ubfNj#>f)|Mb4d!}9rR^=&W@NxY);N% zQ#49h`#V8V7B68=_d`b)WA$NAZDYuvX+-gogSrjGAXQ&K{48c#tvro^o{`CCX1!hz z1N{i3T^dP9ge4)hk|pWe0<3DJ#?dQ11$MSVNm$DzfigWWoO2t$tD_G8SsevV-!V1e zLbvbvHbnpas=V?@hxCm=?ZS!2j?`X*H-D2rjP@wChupJik<`ErP^)=qROu+RnBU}3^szAn$Axn;F~6%rym=|$=irdpH< zKy5KiQ!U(bu}pfQyww6Z-e~WZY*14E#zm&(5(<5>$Q$03F-U50a|vdXC(U`b66yCB z4`*RaC=Hs^+y023o@hSVMM3;Pw$a_Dm>tvJiwJ5R-?Pge4I6sa1JC}UNSVIZZGesR z?iK03s8HGI-w1~q*UU*rRg#g4W>H3yYqwx~wnz2_`i~rXKN^L+GO|U< zwfWKC*S-vWKN6zRbl}}hnBMZQ(Q&gji^-t-g1vuktal-YeeS+1+wy=Q`wkm5lM1TQ zgADjhFedCgEpCb~)oH0k=oSysYCsMe^74AE&b**$x39O)Cwh7pj4N8R7@|6+37@`~ zX2P7Re<^vH*j&YMdUId#sP(q>W~EK-t0(W*JP`f4wf;H~W0O1RT>QxU!$ZnJWm6@^ z67D5YZq|?NR~<(JT)%v}Erd>nZ$u6Mpx}$Tm2x6+*8opu{Ja)j*`z5f=0uG=Pmlbx+2Q4j;ze<(T9p=_nrJoE7liO$abT+2(X;TBz%5AOFYC0 z?41x*dG96b_#C1>;C{-kO*jI^MRDx6h7)(Jt0=F@vp*9i>}R-C=*_7)6YhO|+G?~} z>9B-6MVA|dJi^3ndogs#Bm?Nn=&w@53_C$ZDXBll>HOPnzcAwc#Ov^OKGofbjedHB zvX7|gGN?E_#lc+E+L>VbulrF}iluJ4t_AKnjZ+O@{KYZiw_j9rrD=xlc2z>{$8d>6 z@CBs+ghKc^Eg0~=@0wz%YWD4CxLX2c=>?V)3cl)1)GHEF~$gr#IT4VdKSlw~4V zcvyXQr|&C7a2-A{$<6XvB)Fm{6`{!!U1q`Do?(Cv3Id-d{uSI958VrF#zr640Z1R% zf`EQ&D$1^IMSQ=3zc`knsK^@Un@v?{rxEEh7)p7>X-L?9lq)};*p8YhN}qa*V%b?n zE6R{ac3Hnw4lIf_-$R5jGqTCc9-waJ)OsQ~vI#Sr0@%}3(z~3AHFZ96=;oPw-Wp)t z$`q~nDa65!GTlzJ`T|pG2NM(D&$k-v0Z)bDc`HgXsjeD zWItM_eBu1n^uEW4?(UO21>Y0G6X$%v_tRDJXIsm0I-=@ey*!g#_a@X)EX1u5j&h`G z|KP}aW7Id`&b|$1Z<5buDL5?>?#wZgLx+!=F`gNkWHSB+$|5g6vVU0QLOZ^LV05bu z0LY=($IntmYiIy#6%pl)z-6aH08K$h@J^rF-+1Q8(jN(TZ)lLGvx`WiP}RmbQQ+g; zQl(V5xR^Q~wo{-&t3sGQlo^0j37u26_{1chX&3HjB{}0A0I;@b;{Mrq8Z+FY4&8_a)}YrZI6r@jgRE$|*-qf`@w13t^lYc?n@7 zY2;@jOa4N5$iNyk3gBK`1|H=G;t!|KI|Xgd@f~XK?XEj^H@x42&?42v z{I4EspDUe3CD9tSQ5t+A7Zaf+1$_F+ry}@%p3Wb($qgSs8D&=LPb)1u^HA*U%gO^lp2}J0h$u{cY48& z)5ljM>fpp)%}hO+KjX{MqvE_boo{uJh_e*TOj~_V$Q1$&awJxM$N0kdOADg>)J%Ce zGI_7xl(met6PhFS+aGH1lsIsOH0-e2Uf+n)({?a8&>z2^#IlN-^G6kOKOV0s3+>u{ zJt!BWF}7?DA0{#Qj{SRGX)zFm2C;F4(`Q6e>~!FLtn;AJ^>$&_`K;f1$V`7nijsrH4E8R-G$w_D_e6bE z>1Qn4PkSxg^?Fa)UCa3?&mx~yRn3jKt^RnW&tH^qvS%6Rv8_1(|2*bZ?Dz8!<$pNQ zb%ZH#-gMBpOfpCRkEK-TaLI00E&DghJ4m^pAiLy9+q6qnVws`{Mo;YEwy07#((&7l z?L`wq{|C>i~eya0TpFNoz>V`d?C2*-vI)w>R<&-^T?D=PMU=CU5+BhFOd&Ki&Pt& zOWgbPBBQ~$?}eSL>JjxA+G6rJ;g*17@|Wz}Tr IKbeL7AJieO4*&oF diff --git a/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/sleeping.png b/Resources/Textures/Mobs/Aliens/Xenos/rouny.rsi/sleeping.png index 9221665dd85702cba7aca495d9740ff71327e884..3bb814f467e329e83081a9769752ab8d19bc6757 100644 GIT binary patch delta 2616 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Animals/patriarch.rsi/patriarch_crit.png b/Resources/Textures/Mobs/Animals/patriarch.rsi/patriarch_crit.png new file mode 100644 index 0000000000000000000000000000000000000000..add264b5b5c3c95dc1af9c35b5d4ef8ba14e11de GIT binary patch literal 2183 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 R91*-!U~O^Eyvo!g_Fsz@l)eA} literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Animals/subject7355.rsi/glow.png b/Resources/Textures/Mobs/Animals/subject7355.rsi/glow.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc359cf0c2f32ebbbb36c07ac06a02a216bfb84 GIT binary patch literal 1977 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 As{jB1 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Animals/subject7355.rsi/subject7355_crit.png b/Resources/Textures/Mobs/Animals/subject7355.rsi/subject7355_crit.png new file mode 100644 index 0000000000000000000000000000000000000000..d400295959fbc956a96fea78abdaf912d2250c89 GIT binary patch literal 1851 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 KCUxgLss96U+Yj3S literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Animals/subject7355.rsi/subject7355_sleeping.png b/Resources/Textures/Mobs/Animals/subject7355.rsi/subject7355_sleeping.png new file mode 100644 index 0000000000000000000000000000000000000000..10600583256f3fdda6e1630b0eb54956df199e20 GIT binary patch literal 1549 zcmV+o2J-odP)pF8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT000G; zNklF;C zVn(VuGE`j{5fem2AO(>UkgG6I%Sx5H*daKT(>v#!_>x%Y80_EkyURHxlF#JSdy9SV zuYaHS`+eW<*%nOG#EV=6AAk?Q2jBzn0r&uX06qX8fDgb2-~;dh_yBwWJ^&wp55NcD z1MmU(0DJ&G0M{2zU1STJd+R#~B}u zMp>Pzs>ecj-khfjKu}i9>A86nSC)@_VBUCDRarefJ3$ytPMVpSt5{uJKvS!F7XZb4 zIFrT5$Ov|JcGwtt){BKBn&3GA1R(@IL!Lf zGixsvV3wZoK3_!J90sy>z<^wF9 z{kH4+w%6JHYxwQ(YXAU^^E3d0aOK16FltW`SPDXZX&m1KzO;(r<_6wxeFW{FO|)j4 z5M$?X|Eqhh8}E817?c$g0N(xl3)Fu80fD6;UKU@&J@d1!7v5u(6YXM6h!L@PaugA#}|Hrsw8aEQ^waNHm6Oxdc&?pb9Ok2-Y=3cMo7R z8cx$oU88BRF(i%vSU(Dzx>|GfLgYFCiu*`3 zX4z#iD6%m|)3A64K_f5l9DwP$c~sZdEW6JGptGF{>h zuR;JQL_7n4Ts)FUTH5Lx6#%fPJE=Y2Mt!NCLgdr~;CG+IjW2wCB$34G;sU1U=9!WF z7^7)G42qU|H@u+l07$q1SmK^9;i2}L`hj41@8tgcTyA(l-vKz)r{WQ4n#K&y<#JeG zUx%h?kYyPY6BEei^Q>K#Wt6w-j%%E10DKrk5=pH8^c`}!9P;@*T4%yA8V!VpOx(J8 z1NT?{Kt7*GE|}la+&wV> z8aI}{%;r1Q8bI!!&ScxEZs#hyU3$oj=Z$j$VDC4UzRc#KIb8)1kH<{_*xK3>PHH?| zeJPpY^LZ!Z?Hb?&fxk!4oUQ|)*gFXX{udlklG?`@m;d)NzNTu3Mdf25&@0X9Iso21 z|Eo8QCMQik@8+n!0%8oxC zg1wMu^b>-k2=WkqTz+7QWqxr!?JX4xP*Q2^Z9Qhf2EbxC0Jif(q3-_!2u3U_1Aqkt z&5_UN5sF{xyAJd`1>*6zNyn0Mp_|k5mltwPUaabB&Cv_&E>Cs*dwaWm_ua?_k39zM zH@nQtRrc*Je~;(C#C+Zjkk1Tx5$u)u*;C_z0^rYg{s#))K>9F2Sux2YsPMVG Date: Thu, 26 Sep 2024 15:07:20 +0000 Subject: [PATCH 18/21] Automatic Changelog Update (#956) --- Resources/Changelog/Changelog.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index e3ebd4d835f..9fb3476e8d4 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -6665,3 +6665,10 @@ Entries: id: 6388 time: '2024-09-25T05:09:06.0000000+00:00' url: https://github.com/Simple-Station/Einstein-Engines/pull/959 +- author: fenndragon + changes: + - type: Add + message: Added new neutral xenos, events, and reagent slimes + id: 6389 + time: '2024-09-26T15:06:54.0000000+00:00' + url: https://github.com/Simple-Station/Einstein-Engines/pull/956 From f50c29e8f4a920cd044e8ebba0fa545e4b157669 Mon Sep 17 00:00:00 2001 From: fox Date: Thu, 26 Sep 2024 19:47:47 +0300 Subject: [PATCH 19/21] Remove obsolete prototypes --- .../Floof/Body/Prototypes/Friendshaped.yml | 24 -- .../Floof/Entities/Mobs/NPCs/slimes.yml | 204 ----------- .../Floof/Entities/Mobs/NPCs/xenopet.yml | 340 ------------------ .../Floof/body/Organs/Friendstomach.yml | 15 - .../Mobs/Animals/patriarch.rsi/meta.json | 24 -- .../Mobs/Animals/patriarch.rsi/patriarch.png | Bin 6815 -> 0 bytes .../Animals/patriarch.rsi/patriarch_crit.png | Bin 2183 -> 0 bytes .../Animals/patriarch.rsi/patriarch_dead.png | Bin 2644 -> 0 bytes .../patriarch.rsi/patriarch_sleeping.png | Bin 1941 -> 0 bytes .../Mobs/Animals/subject7355.rsi/glow.png | Bin 1977 -> 0 bytes .../Mobs/Animals/subject7355.rsi/meta.json | 28 -- .../Animals/subject7355.rsi/subject7355.png | Bin 5421 -> 0 bytes .../subject7355.rsi/subject7355_crit.png | Bin 1851 -> 0 bytes .../subject7355.rsi/subject7355_dead.png | Bin 2760 -> 0 bytes .../subject7355.rsi/subject7355_sleeping.png | Bin 1549 -> 0 bytes 15 files changed, 635 deletions(-) delete mode 100644 Resources/Prototypes/Floof/Body/Prototypes/Friendshaped.yml delete mode 100644 Resources/Prototypes/Floof/Entities/Mobs/NPCs/xenopet.yml delete mode 100644 Resources/Prototypes/Floof/body/Organs/Friendstomach.yml delete mode 100644 Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/meta.json delete mode 100644 Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/patriarch.png delete mode 100644 Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/patriarch_crit.png delete mode 100644 Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/patriarch_dead.png delete mode 100644 Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/patriarch_sleeping.png delete mode 100644 Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/glow.png delete mode 100644 Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/meta.json delete mode 100644 Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/subject7355.png delete mode 100644 Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/subject7355_crit.png delete mode 100644 Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/subject7355_dead.png delete mode 100644 Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/subject7355_sleeping.png diff --git a/Resources/Prototypes/Floof/Body/Prototypes/Friendshaped.yml b/Resources/Prototypes/Floof/Body/Prototypes/Friendshaped.yml deleted file mode 100644 index 0ab85a03433..00000000000 --- a/Resources/Prototypes/Floof/Body/Prototypes/Friendshaped.yml +++ /dev/null @@ -1,24 +0,0 @@ -- type: body - id: Friendshaped - name: "Friend-Shaped" - root: torso - slots: - torso: - part: TorsoAnimal - connections: - - hands - - legs - organs: - lungs: OrganAnimalLungs - stomach: OrganFriendStomach - liver: OrganAnimalLiver - heart: OrganAnimalHeart - kidneys: OrganAnimalKidneys - hands: - part: HandsAnimal - legs: - part: LegsAnimal - connections: - - feet - feet: - part: FeetAnimal diff --git a/Resources/Prototypes/Floof/Entities/Mobs/NPCs/slimes.yml b/Resources/Prototypes/Floof/Entities/Mobs/NPCs/slimes.yml index 71b6161f2b4..3446badc703 100644 --- a/Resources/Prototypes/Floof/Entities/Mobs/NPCs/slimes.yml +++ b/Resources/Prototypes/Floof/Entities/Mobs/NPCs/slimes.yml @@ -66,40 +66,6 @@ state: alive color: "#c90084" -- type: entity - id: ReagentSlimeIchor - parent: ReagentSlime - suffix: Ichor - components: - - type: Bloodstream - bloodReagent: Ichor - - type: PointLight - color: "#f4692e" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#f4692e" - -- type: entity - id: ReagentSlimeBleach - parent: ReagentSlime - suffix: Bleach - components: - - type: Bloodstream - bloodReagent: Bleach - - type: PointLight - color: "#a1000b" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#a1000b" - - type: entity id: ReagentSlimeSoap parent: ReagentSlime @@ -117,74 +83,6 @@ state: alive color: "#c8dfc9" -- type: entity - id: ReagentSlimeSpacelube - parent: ReagentSlime - suffix: Spacelube - components: - - type: Bloodstream - bloodReagent: SpaceLube - - type: PointLight - color: "#77b58e" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#77b58e" - -- type: entity - id: ReagentSlimeBuzzachloricbees - parent: ReagentSlime - suffix: Buzzachloricbees - components: - - type: Bloodstream - bloodReagent: BuzzochloricBees - - type: PointLight - color: "#FFD35D" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#FFD35D" - -- type: entity - id: ReagentSlimeWehjuice - parent: ReagentSlime - suffix: Wehjuice - components: - - type: Bloodstream - bloodReagent: JuiceThatMakesYouWeh - - type: PointLight - color: "#59b23a" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#59b23a" - -- type: entity - id: ReagentCognizine - parent: ReagentSlime - suffix: Cognizine - components: - - type: Bloodstream - bloodReagent: Cognizine - - type: PointLight - color: "#b50ee8" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#b50ee8" - - type: entity id: ReagentSlimeOpporozidone parent: ReagentSlime @@ -201,105 +99,3 @@ - map: [ "enum.DamageStateVisualLayers.Base" ] state: alive color: "#b5e36d" - -- type: entity - id: ReagentSlimeNecrosol - parent: ReagentSlime - suffix: Necrosol - components: - - type: Bloodstream - bloodReagent: Necrosol - - type: PointLight - color: "#86a5bd" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#86a5bd" - -- type: entity - id: ReagentSlimeSpaceDrugs - parent: ReagentSlime - suffix: SpaceDrugs - components: - - type: Bloodstream - bloodReagent: SpaceDrugs - - type: PointLight - color: "#63806e" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#63806e" - -- type: entity - id: ReagentSlimeUnstableMutagen - parent: ReagentSlime - suffix: UnstableMutagen - components: - - type: Bloodstream - bloodReagent: UnstableMutagen - - type: PointLight - color: "#00ff5f" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#00ff5f" - -- type: entity - id: ReagentSlimeLead - parent: ReagentSlime - suffix: Lead - components: - - type: Bloodstream - bloodReagent: Lead - - type: PointLight - color: "#5C6274" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#5C6274" - -- type: entity - id: ReagentSlimechlorinetriflouride - parent: ReagentSlime - suffix: chlorinetriflouride - components: - - type: Bloodstream - bloodReagent: ChlorineTrifluoride - - type: PointLight - color: "#FFC8C8" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#FFC8C8" - -- type: entity - id: ReagentSlimePotassium - parent: ReagentSlime - suffix: Potassium - components: - - type: Bloodstream - bloodReagent: Potassium - - type: PointLight - color: "#c6c8cc" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#c6c8cc" diff --git a/Resources/Prototypes/Floof/Entities/Mobs/NPCs/xenopet.yml b/Resources/Prototypes/Floof/Entities/Mobs/NPCs/xenopet.yml deleted file mode 100644 index 049dc27c56d..00000000000 --- a/Resources/Prototypes/Floof/Entities/Mobs/NPCs/xenopet.yml +++ /dev/null @@ -1,340 +0,0 @@ -- type: entity - name: Neutral Rouny - id: MobXenoNeutralRouny - parent: MobXenoRounyNPC - description: They mostly come at night. Mostly. - components: - - type: NpcFactionMember - factions: - - Passive - - type: PointLight - radius: 2 - energy: 1 - color: "#B85E5E" - - type: MovementAlwaysTouching - - type: GhostRole - name: ghost-role-information-friendlyxeno-name - description: ghost-role-information-friendlyxeno-description - rules: ghost-role-information-friendlyxeno-rules - - type: GhostTakeoverAvailable - - type: LanguageKnowledge - speaks: - - Xeno - understands: - - Xeno - - TauCetiBasic - -- type: entity - name: Neutral Praetorian - id: MobXenoNeutralPraetorian - parent: MobXenoPraetorianNPC - description: They mostly come at night. Mostly. - components: - - type: NpcFactionMember - factions: - - Passive - - type: PointLight - radius: 2 - energy: 1 - color: "#62B85E" - - type: GhostRole - name: ghost-role-information-friendlyxeno-name - description: ghost-role-information-friendlyxeno-description - rules: ghost-role-information-friendlyxeno-rules - - type: GhostTakeoverAvailable - - type: LanguageKnowledge - speaks: - - Xeno - understands: - - Xeno - - TauCetiBasic - -- type: entity - name: Neutral Drone - id: MobXenoNeutralDrone - parent: MobXenoDroneNPC - description: They mostly come at night. Mostly. - components: - - type: NpcFactionMember - factions: - - Passive - - type: PointLight - radius: 2 - energy: 1 - color: "#8B5EB8" - - type: GhostRole - name: ghost-role-information-friendlyxeno-name - description: ghost-role-information-friendlyxeno-description - rules: ghost-role-information-friendlyxeno-rules - - type: GhostTakeoverAvailable - - type: LanguageKnowledge - speaks: - - Xeno - understands: - - Xeno - - TauCetiBasic - -- type: entity - name: Neutral Ravager - id: MobXenoNeutralRavager - parent: MobXenoRavagerNPC - description: They mostly come at night. Mostly. - components: - - type: NpcFactionMember - factions: - - Passive - - type: PointLight - radius: 2 - energy: 1 - color: "#E3954D" - - type: GhostRole - name: ghost-role-information-friendlyxeno-name - description: ghost-role-information-friendlyxeno-description - rules: ghost-role-information-friendlyxeno-rules - - type: GhostTakeoverAvailable - - type: LanguageKnowledge - speaks: - - Xeno - understands: - - Xeno - - TauCetiBasic - -- type: inventoryTemplate - id: friendxeno - slots: - - name: id - slotTexture: id - slotFlags: IDCARD - slotGroup: SecondHotbar - stripTime: 6 - uiWindowPos: 2,1 - strippingWindowPos: 2,4 - displayName: ID - - name: head - slotTexture: head - slotFlags: HEAD - uiWindowPos: 1,2 - strippingWindowPos: 0,0 - displayName: Head - - name: mask - slotTexture: mask - slotFlags: MASK - uiWindowPos: 0,1 - strippingWindowPos: 1,1 - displayName: Mask - -- type: entity - name: Friend-Shaped - parent: MobXenoNeutralRouny - id: MobXenoFriendShaped - description: A very clearly friend-shaped Xeno. - components: - - type: NpcFactionMember - factions: - - PetsNT - - type: Tool - speed: 3 - qualities: - - Prying - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/Xenos/rouny.rsi - scale: 0.7, 0.7 - - type: GhostRole - - type: GhostTakeoverAvailable - - type: Inventory - templateId: friendxeno - - type: IdExaminable - - type: InventorySlots - - type: Stripping - - type: Strippable - - type: UserInterface - interfaces: - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface - - type: Grammar - attributes: - proper: true - gender: male - - type: Body - prototype: Friendshaped - requiredLegs: 1 # TODO: More than 1 leg - - type: InteractionPopup - successChance: 0.5 - interactSuccessString: petting-success-reptile - interactFailureString: petting-failure-generic - interactSuccessSpawn: EffectHearts - interactSuccessSound: - path: /Audio/Animals/lizard_happy.ogg - - type: LeashAnchor # Floofstation - -- type: entity - name: Patriach - parent: MobXenoNeutralPraetorian - id: MobXenoPatriarch - description: A not entirely clearly friend-shaped Xeno. - components: - - type: NpcFactionMember - factions: - - PetsNT - - type: Tool - speed: 3 - qualities: - - Prying - - type: Sprite - drawdepth: Mobs - sprite: Floof/Mobs/Animals/patriarch.rsi - layers: - - map: ["enum.DamageStateVisualLayers.Base"] - state: patriarch - - type: DamageStateVisuals - states: - Alive: - Base: patriarch - Critical: - Base: patriarch_crit - Dead: - Base: patriarch_dead - - type: Inventory - templateId: friendxeno - - type: IdExaminable - - type: InventorySlots - - type: Strippable - - type: UserInterface - interfaces: - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface - - type: Grammar - attributes: - proper: true - gender: male - - type: InteractionPopup - successChance: 0.5 - interactSuccessString: petting-success-reptile - interactFailureString: petting-failure-generic - interactSuccessSpawn: EffectHearts - interactSuccessSound: - path: /Audio/Animals/lizard_happy.ogg - -- type: entity - name: FXES - parent: MobXenoNeutralDrone - id: MobXenoFXES - description: A very clearly friend-shaped Xeno. - components: - - type: NpcFactionMember - factions: - - PetsNT - - type: Tool - speed: 3 - qualities: - - Prying - - type: Inventory - templateId: friendxeno - - type: IdExaminable - - type: InventorySlots - - type: Strippable - - type: UserInterface - interfaces: - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface - - type: Grammar - attributes: - proper: true - gender: male - - type: InteractionPopup - successChance: 0.5 - interactSuccessString: petting-success-reptile - interactFailureString: petting-failure-generic - interactSuccessSpawn: EffectHearts - interactSuccessSound: - path: /Audio/Animals/lizard_happy.ogg - -- type: entity - name: Hell-Shaped - parent: MobXenoNeutralRavager - id: MobXenoHellShaped - description: A very clearly friend-shaped Xeno. - components: - - type: NpcFactionMember - factions: - - PetsNT - - type: Tool - speed: 3 - qualities: - - Prying - - type: Inventory - templateId: friendxeno - - type: IdExaminable - - type: InventorySlots - - type: Strippable - - type: UserInterface - interfaces: - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface - - type: Grammar - attributes: - proper: true - gender: male - - type: InteractionPopup - successChance: 0.5 - interactSuccessString: petting-success-reptile - interactFailureString: petting-failure-generic - interactSuccessSpawn: EffectHearts - interactSuccessSound: - path: /Audio/Animals/lizard_happy.ogg - -- type: entity - name: FXE Subject 7355 - parent: MobXenoNeutralRavager - id: MobXenoSubjectTess - description: An extremely oddly coloured xeno, with glowing stripes. An odd mutation. - components: - - type: NpcFactionMember - factions: - - PetsNT - - type: Tool - speed: 3 - qualities: - - Prying - - type: Sprite - drawdepth: Mobs - sprite: Floof/Mobs/Animals/subject7355.rsi - layers: - - map: ["enum.DamageStateVisualLayers.Base"] - state: subject7355 - - map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ] - state: glow - shader: unshaded - - type: PointLight - radius: 2 - energy: 1 - color: "#639fff" - - type: DamageStateVisuals - states: - Alive: - Base: subject7355 - Critical: - Base: subject7355_crit - Dead: - Base: subject7355_dead - - type: Inventory - templateId: friendxeno - - type: IdExaminable - - type: InventorySlots - - type: Strippable - - type: UserInterface - interfaces: - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface - - type: Grammar - attributes: - proper: true - gender: male - - type: InteractionPopup - successChance: 0.5 - interactSuccessString: petting-success-reptile - interactFailureString: petting-failure-generic - interactSuccessSpawn: EffectHearts - interactSuccessSound: - path: /Audio/Animals/lizard_happy.ogg diff --git a/Resources/Prototypes/Floof/body/Organs/Friendstomach.yml b/Resources/Prototypes/Floof/body/Organs/Friendstomach.yml deleted file mode 100644 index a20bbbe75bc..00000000000 --- a/Resources/Prototypes/Floof/body/Organs/Friendstomach.yml +++ /dev/null @@ -1,15 +0,0 @@ -- type: entity - id: OrganFriendStomach - parent: OrganAnimalStomach - noSpawn: true - components: - - type: Stomach - - type: SolutionContainerManager - solutions: - stomach: - maxVol: 100 - food: - maxVol: 50 - reagents: - - ReagentId: UncookedAnimalProteins - Quantity: 5 diff --git a/Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/meta.json b/Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/meta.json deleted file mode 100644 index 9eaca141c97..00000000000 --- a/Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/meta.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "version": 1, - "license": "CC-BY-SA-3.0", - "copyright": "https://gitlab.com/cmdevs/colonial-warfare/-/blob/dev/icons/mob/xenonids/praetorian.dmi edited by Fenndragon", - "size": { - "x": 64, - "y": 64 - }, - "states": [ - { - "name": "patriarch", - "directions": 4 - }, - { - "name": "patriarch_sleeping" - }, - { - "name": "patriarch_crit" - }, - { - "name": "patriarch_dead" - } - ] -} diff --git a/Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/patriarch.png b/Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/patriarch.png deleted file mode 100644 index 34cb16d5552da799173e6665ef70b247d1a6d78d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6815 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 diff --git a/Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/patriarch_crit.png b/Resources/Textures/Floof/Mobs/Animals/patriarch.rsi/patriarch_crit.png deleted file mode 100644 index add264b5b5c3c95dc1af9c35b5d4ef8ba14e11de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2183 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 R91*-!U~O^Eyvo!g_Fsz@l)eA} diff --git a/Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/glow.png b/Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/glow.png deleted file mode 100644 index 9fc359cf0c2f32ebbbb36c07ac06a02a216bfb84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1977 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 As{jB1 diff --git a/Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/subject7355_crit.png b/Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/subject7355_crit.png deleted file mode 100644 index d400295959fbc956a96fea78abdaf912d2250c89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1851 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 KCUxgLss96U+Yj3S diff --git a/Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/subject7355_sleeping.png b/Resources/Textures/Floof/Mobs/Animals/subject7355.rsi/subject7355_sleeping.png deleted file mode 100644 index 10600583256f3fdda6e1630b0eb54956df199e20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1549 zcmV+o2J-odP)pF8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT000G; zNklF;C zVn(VuGE`j{5fem2AO(>UkgG6I%Sx5H*daKT(>v#!_>x%Y80_EkyURHxlF#JSdy9SV zuYaHS`+eW<*%nOG#EV=6AAk?Q2jBzn0r&uX06qX8fDgb2-~;dh_yBwWJ^&wp55NcD z1MmU(0DJ&G0M{2zU1STJd+R#~B}u zMp>Pzs>ecj-khfjKu}i9>A86nSC)@_VBUCDRarefJ3$ytPMVpSt5{uJKvS!F7XZb4 zIFrT5$Ov|JcGwtt){BKBn&3GA1R(@IL!Lf zGixsvV3wZoK3_!J90sy>z<^wF9 z{kH4+w%6JHYxwQ(YXAU^^E3d0aOK16FltW`SPDXZX&m1KzO;(r<_6wxeFW{FO|)j4 z5M$?X|Eqhh8}E817?c$g0N(xl3)Fu80fD6;UKU@&J@d1!7v5u(6YXM6h!L@PaugA#}|Hrsw8aEQ^waNHm6Oxdc&?pb9Ok2-Y=3cMo7R z8cx$oU88BRF(i%vSU(Dzx>|GfLgYFCiu*`3 zX4z#iD6%m|)3A64K_f5l9DwP$c~sZdEW6JGptGF{>h zuR;JQL_7n4Ts)FUTH5Lx6#%fPJE=Y2Mt!NCLgdr~;CG+IjW2wCB$34G;sU1U=9!WF z7^7)G42qU|H@u+l07$q1SmK^9;i2}L`hj41@8tgcTyA(l-vKz)r{WQ4n#K&y<#JeG zUx%h?kYyPY6BEei^Q>K#Wt6w-j%%E10DKrk5=pH8^c`}!9P;@*T4%yA8V!VpOx(J8 z1NT?{Kt7*GE|}la+&wV> z8aI}{%;r1Q8bI!!&ScxEZs#hyU3$oj=Z$j$VDC4UzRc#KIb8)1kH<{_*xK3>PHH?| zeJPpY^LZ!Z?Hb?&fxk!4oUQ|)*gFXX{udlklG?`@m;d)NzNTu3Mdf25&@0X9Iso21 z|Eo8QCMQik@8+n!0%8oxC zg1wMu^b>-k2=WkqTz+7QWqxr!?JX4xP*Q2^Z9Qhf2EbxC0Jif(q3-_!2u3U_1Aqkt z&5_UN5sF{xyAJd`1>*6zNyn0Mp_|k5mltwPUaabB&Cv_&E>Cs*dwaWm_ua?_k39zM zH@nQtRrc*Je~;(C#C+Zjkk1Tx5$u)u*;C_z0^rYg{s#))K>9F2Sux2YsPMVG Date: Thu, 26 Sep 2024 20:03:50 +0300 Subject: [PATCH 20/21] Begone --- .../Floof/Entities/Mobs/NPCs/slimes.yml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Resources/Prototypes/Floof/Entities/Mobs/NPCs/slimes.yml b/Resources/Prototypes/Floof/Entities/Mobs/NPCs/slimes.yml index 3446badc703..01d35a0042d 100644 --- a/Resources/Prototypes/Floof/Entities/Mobs/NPCs/slimes.yml +++ b/Resources/Prototypes/Floof/Entities/Mobs/NPCs/slimes.yml @@ -66,23 +66,6 @@ state: alive color: "#c90084" -- type: entity - id: ReagentSlimeSoap - parent: ReagentSlime - suffix: Soap - components: - - type: Bloodstream - bloodReagent: SoapReagent - - type: PointLight - color: "#c8dfc9" - - type: Sprite - drawdepth: Mobs - sprite: Mobs/Aliens/elemental.rsi - layers: - - map: [ "enum.DamageStateVisualLayers.Base" ] - state: alive - color: "#c8dfc9" - - type: entity id: ReagentSlimeOpporozidone parent: ReagentSlime From 5c92c52a5a41b798c61643fc4514ad3ff7bb6050 Mon Sep 17 00:00:00 2001 From: fox Date: Thu, 26 Sep 2024 20:22:25 +0300 Subject: [PATCH 21/21] Fix dead IPCs not having a startup button --- .../Silicon/DeadStartupButtonSystem/DeadStartupButtonSystem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Server/Silicon/DeadStartupButtonSystem/DeadStartupButtonSystem.cs b/Content.Server/Silicon/DeadStartupButtonSystem/DeadStartupButtonSystem.cs index 1c43a3cff91..d932abb8f84 100644 --- a/Content.Server/Silicon/DeadStartupButtonSystem/DeadStartupButtonSystem.cs +++ b/Content.Server/Silicon/DeadStartupButtonSystem/DeadStartupButtonSystem.cs @@ -28,6 +28,7 @@ public sealed class DeadStartupButtonSystem : SharedDeadStartupButtonSystem /// public override void Initialize() { + base.Initialize(); // Floofstation - remove the comment after this call is added upstream SubscribeLocalEvent(OnDoAfter); SubscribeLocalEvent(OnElectrocuted); SubscribeLocalEvent(OnMobStateChanged);