From 7138d9bbdff2e910b249614cf8af0339ae538cd0 Mon Sep 17 00:00:00 2001 From: BIGZi0348 <118811750+bigzi0348@users.noreply.github.com> Date: Sat, 21 Sep 2024 14:46:38 +0300 Subject: [PATCH] Suhariki (#4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * init * Porting is complete Still WIP * small stuff * SmallStuff * awawawa * Нас рано * Engi * More luck * removed some shit (cherry picked from commit e1d745655b0e7253ea4e4814b82dd56e90153514) --- .../Other/Suhariki/SuharikiComponent.cs | 49 ++++++ .../_White/Other/Suhariki/SuharikiSystem.cs | 149 ++++++++++++++++++ .../Random/Food_Drinks/food_snacks.yml | 1 + .../Objects/Consumable/Food/suhariki.yml | 77 +++++++++ 4 files changed, 276 insertions(+) create mode 100644 Content.Server/_White/Other/Suhariki/SuharikiComponent.cs create mode 100644 Content.Server/_White/Other/Suhariki/SuharikiSystem.cs create mode 100644 Resources/Prototypes/_White/Entities/Objects/Consumable/Food/suhariki.yml diff --git a/Content.Server/_White/Other/Suhariki/SuharikiComponent.cs b/Content.Server/_White/Other/Suhariki/SuharikiComponent.cs new file mode 100644 index 0000000000..f98ad74000 --- /dev/null +++ b/Content.Server/_White/Other/Suhariki/SuharikiComponent.cs @@ -0,0 +1,49 @@ +using Robust.Shared.Prototypes; +using Content.Shared.Damage; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Content.Shared.Chat.Prototypes; +using Robust.Shared.Audio; +// WD Engi Exclusive +namespace Content.Server._White.Other.Suhariki; + +[RegisterComponent, Access(typeof(SuharikiSystem))] +public sealed partial class SuharikiComponent : Component + +{ + /// + /// Amount and type of damage that will be dealt on event. + /// + [DataField(required: true)] + [ViewVariables(VVAccess.ReadWrite)] + public DamageSpecifier Damage = new(); + + /// + /// Chance of event activation. + /// + [DataField] + public float Chance = 0; + + /// + /// Amount of rolls for event. + /// + [DataField] + public int StonesInFood = 1; + + /// + /// The prototype that will be spawned on event. + /// + [DataField("holdingPrototype", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + public string HoldingPrototype = "SuharikiTooth"; + + /// + /// Emote triggered on event. + /// + [DataField("emote", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string EmoteId = "Scream"; + + /// + /// Sound triggered on event. + /// + [DataField] + public SoundSpecifier UseSound { get; set; } = new SoundPathSpecifier("/Audio/White/Object/Misc/Suhariki/tooth_break.ogg"); +} diff --git a/Content.Server/_White/Other/Suhariki/SuharikiSystem.cs b/Content.Server/_White/Other/Suhariki/SuharikiSystem.cs new file mode 100644 index 0000000000..53fa8d5c9b --- /dev/null +++ b/Content.Server/_White/Other/Suhariki/SuharikiSystem.cs @@ -0,0 +1,149 @@ +using Content.Server.Inventory; +using Content.Server.Nutrition.Components; +using Content.Server.Popups; +using Content.Shared.Interaction.Events; +using Content.Shared.Nutrition.EntitySystems; +using Robust.Shared.Random; +using Content.Shared.Damage; +using Content.Server.Effects; +using Robust.Shared.Player; +using Content.Server.Administration.Logs; +using Content.Shared.Database; +using Content.Server.Chat.Systems; +using Content.Server.Nutrition.EntitySystems; +using Timer = Robust.Shared.Timing.Timer; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; +using Content.Shared.Verbs; +using Robust.Shared.Utility; +using Content.Shared.Body.Components; +using Content.Server.Body.Systems; +using Content.Server.Body.Components; +using Content.Server.Speech.EntitySystems; +using Content.Server.Speech.Components; +// WD Engi Exclusive +namespace Content.Server._White.Other.Suhariki; +public sealed class SuharikiSystem : EntitySystem +{ + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly ColorFlashEffectSystem _color = default!; + [Dependency] private readonly IAdminLogManager _adminLogger = default!; + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly FoodSystem _food = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly BodySystem _body = default!; + private EntityQuery _metaQuery; + + public override void Initialize() + { + base.Initialize(); + _metaQuery = GetEntityQuery(); + SubscribeLocalEvent(OnUseInHand, after: new[] { typeof(OpenableSystem), typeof(ServerInventorySystem) }); + SubscribeLocalEvent>(AddEatVerb); + } + + private void OnUseInHand(Entity entity, ref UseInHandEvent ev) + { + if (ev.Handled) + return; + + var result = TryUse(ev.User, ev.User, entity, entity.Comp); + ev.Handled = result.Handled; + } + + private (bool Success, bool Handled) TryUse(EntityUid user, EntityUid target, EntityUid food, SuharikiComponent scomponent) + { + var foodComponents = _metaQuery.GetComponent(food).EntityPrototype; + + if (foodComponents == null) + return (false, false); + + foodComponents.Components.TryGetComponent("Food", out var component); + + if (component == null) + return (false, false); + + // idk what I'm doing but otherwise the owner is "0" and it throws fatal error + component.Owner = food; + + var result = _food.TryFeed(user, target, food, (FoodComponent) component); + + if (result.Success) + Timer.Spawn(300, () => RollEvent(scomponent, user)); + + return (true, true); + } + + private void RollEvent(SuharikiComponent scomponent, EntityUid user) + { + if (scomponent.StonesInFood < 1) + return; + + scomponent.StonesInFood -= 1; + + // Pseudorandom shit + if (!_random.Prob(scomponent.Chance)) + return; + + // Normally slimes don't care about hard food + var whomst = _metaQuery.GetComponent(user).EntityPrototype; + var isUserSlime = whomst!.ID.Contains("slime", StringComparison.OrdinalIgnoreCase); + if (isUserSlime) + return; + + var modifiedDamage = _damageableSystem.TryChangeDamage(user, scomponent.Damage, true); + var deleted = Deleted(user); + if (modifiedDamage is null || !EntityManager.EntityExists(user)) + return; + if (!modifiedDamage.Any() || deleted) + return; + // Damaging the user with appropriate effects + var stringTopopup = Loc.GetString("suhariki-lost", ("user", user)); + _popup.PopupEntity(Name(user) + " " + stringTopopup, user, Shared.Popups.PopupType.LargeCaution); + _color.RaiseEffect(Color.Red, new List { user }, Filter.Pvs(user, entityManager: EntityManager)); + _audio.PlayPvs(scomponent.UseSound, user, AudioParams.Default.WithVolume(-1f)); + _adminLogger.Add(LogType.Damaged, + LogImpact.Medium, + $"This idiot {ToPrettyString(user):user} tried to eat Suhariki and lost tooth, received {modifiedDamage.GetTotal():damage} damage and recieved FrontalLisp accent"); + + // Spawns prototype + var coords = Transform(user).Coordinates; + Spawn(scomponent.HoldingPrototype, coords.Offset(_random.NextVector2(0.2f))); + + // Scream + Timer.Spawn(300, () => _chat.TryEmoteWithChat(user, scomponent.EmoteId)); + + // Adding FrontalLisp accent + EnsureComp(user); + + return; + + } + + private void AddEatVerb(Entity entity, ref GetVerbsEvent ev) + { + if (entity.Owner == ev.User || + !ev.CanInteract || + !ev.CanAccess || + !TryComp(ev.User, out var body) || + !_body.TryGetBodyOrganComponents(ev.User, out var stomachs)) + return; + + var user = ev.User; + AlternativeVerb verb = new() + { + Act = () => + { + TryUse(user, user, entity, entity.Comp); + }, + Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/cutlery.svg.192dpi.png")), + Text = Loc.GetString("food-system-verb-eat"), + Priority = -1 + }; + + ev.Verbs.Add(verb); + } + +} diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/Food_Drinks/food_snacks.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/Food_Drinks/food_snacks.yml index 9f4b3e5983..cf37bfe791 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/Food_Drinks/food_snacks.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/Food_Drinks/food_snacks.yml @@ -45,5 +45,6 @@ - FoodFrozenSnowconeRainbow - FoodSnackPistachios - FoodSnackSemki + - FoodSnackSuhariki # WD chance: 0.8 offset: 0.0 diff --git a/Resources/Prototypes/_White/Entities/Objects/Consumable/Food/suhariki.yml b/Resources/Prototypes/_White/Entities/Objects/Consumable/Food/suhariki.yml new file mode 100644 index 0000000000..6e698e20d4 --- /dev/null +++ b/Resources/Prototypes/_White/Entities/Objects/Consumable/Food/suhariki.yml @@ -0,0 +1,77 @@ +- type: entity # WD Engi Exclusive + parent: BaseItem + id: FoodSnackSuhariki + name: suhariki + description: Old relic of the past, you can barely read the label "Kirieshki". + components: + - type: Food + trash: FoodPacketSuharikiTrash + - type: FlavorProfile + flavors: + - cheap + - bread + - type: Sprite + sprite: White/Objects/Consumable/Food/Suhariki/suhariki.rsi + state: suhariki + - type: Tag + tags: + - FoodSnack + - type: BadFood + - type: Suhariki + chance: 0.25 + damage: + types: + Blunt: 10 + - type: Item + size: Tiny + sprite: White/Objects/Consumable/Food/Suhariki/suhariki.rsi + heldPrefix: suhariki + - type: SolutionContainerManager + solutions: + food: + maxVol: 5 # No extra room for condiments + reagents: + - ReagentId: Nutriment + Quantity: 1 + - ReagentId: Omnizine + Quantity: 4 + - type: SpaceGarbage + - type: StaticPrice + price: 500 + +- type: entity + noSpawn: true + parent: FoodPacketTrash + id: FoodPacketSuharikiTrash + name: suhariki bag + components: + - type: Sprite + sprite: White/Objects/Consumable/Food/Suhariki/suhariki.rsi + state: suhariki-trash + - type: Item + size: Tiny + sprite: White/Objects/Consumable/Food/Suhariki/suhariki.rsi + heldPrefix: suhariki + +- type: entity + noSpawn: true + name: Зуб + parent: BaseItem + id: SuharikiTooth + description: Может быть он твой, а может и не твой. + components: + - type: Sprite + sprite: White/Objects/Consumable/Food/Suhariki/tooth.rsi + state: icon + - type: Item + size: Tiny + - type: EmitSoundOnLand + sound: + path: /Audio/White/Object/Misc/Suhariki/tooth_drop_1.ogg + - type: EmitSoundOnCollide + sound: + path: /Audio/White/Object/Misc/Suhariki/tooth_drop_2.ogg + - type: SpaceGarbage + - type: StaticPrice + price: 100 +