From 5954d821c5581cba91f29a680cda279f6533bb2e Mon Sep 17 00:00:00 2001 From: HitPanda <104197232+EnefFlow@users.noreply.github.com> Date: Thu, 11 May 2023 21:49:17 +0300 Subject: [PATCH] [Sponsor] Pets summon book + Wanderer_ pet (#44) * Pets summon book ready * fix name --- .../Pets/PetSummonComponent.cs | 28 +++ .../Pets/PetSummonSystem.cs | 172 ++++++++++++++++++ Resources/Prototypes/White/Fluff/fluff.yml | 18 ++ Resources/Prototypes/White/Fluff/sponsor.yml | 6 + Resources/Prototypes/White/Mobs/Pets/pets.yml | 73 ++++++++ .../Textures/Objects/Misc/books.rsi/meta.json | 5 +- .../Objects/Misc/books.rsi/summon_book.png | Bin 0 -> 363 bytes .../Mobs/Pets/Kommandant/spider.rsi/meta.json | 40 ++++ .../Mobs/Pets/Kommandant/spider.rsi/viper.png | Bin 0 -> 3989 bytes .../Pets/Kommandant/spider.rsi/viper_dead.png | Bin 0 -> 806 bytes 10 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 Content.Server/White/Other/CustomFluffSystems/Pets/PetSummonComponent.cs create mode 100644 Content.Server/White/Other/CustomFluffSystems/Pets/PetSummonSystem.cs create mode 100644 Resources/Prototypes/White/Mobs/Pets/pets.yml create mode 100644 Resources/Textures/Objects/Misc/books.rsi/summon_book.png create mode 100644 Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/meta.json create mode 100644 Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/viper.png create mode 100644 Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/viper_dead.png diff --git a/Content.Server/White/Other/CustomFluffSystems/Pets/PetSummonComponent.cs b/Content.Server/White/Other/CustomFluffSystems/Pets/PetSummonComponent.cs new file mode 100644 index 0000000000..65d8bc0a97 --- /dev/null +++ b/Content.Server/White/Other/CustomFluffSystems/Pets/PetSummonComponent.cs @@ -0,0 +1,28 @@ +using Content.Shared.Actions.ActionTypes; +using Robust.Shared.Utility; + +namespace Content.Server.White.Other.CustomFluffSystems.Pets; + +[RegisterComponent] +public sealed class PetSummonComponent : Component +{ + public InstantAction PetSummonAction = new() + { + Icon = new SpriteSpecifier.Texture(new ResPath("Objects/Misc/books.rsi/summon_book.png")), + DisplayName = "Призыв", + Description = "Призыв питомца БЕЗ возможности вселения призрака", + Event = new PetSummonActionEvent() + }; + + public InstantAction PetGhostSummonAction = new() + { + Icon = new SpriteSpecifier.Texture(new ResPath("Mobs/Ghosts/ghost_human.rsi/icon.png")), + DisplayName = "Призрачный призыв", + Description = "Призыв питомца С возможностью вселения призрака", + Event = new PetGhostSummonActionEvent() + }; + + public int UsesLeft = 10; + + public EntityUid? SummonedEntity; +} diff --git a/Content.Server/White/Other/CustomFluffSystems/Pets/PetSummonSystem.cs b/Content.Server/White/Other/CustomFluffSystems/Pets/PetSummonSystem.cs new file mode 100644 index 0000000000..1382e9439e --- /dev/null +++ b/Content.Server/White/Other/CustomFluffSystems/Pets/PetSummonSystem.cs @@ -0,0 +1,172 @@ +using Content.Server.Ghost.Roles.Components; +using Content.Shared.ActionBlocker; +using Content.Shared.Actions; +using Content.Shared.Examine; +using Content.Shared.Item; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Popups; +using Content.Shared.Verbs; +using Robust.Server.GameObjects; + +namespace Content.Server.White.Other.CustomFluffSystems.Pets; + +public sealed class PetSummonSystem : EntitySystem +{ + [Dependency] private readonly ActionBlockerSystem _blocker = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly SharedActionsSystem _actions = default!; + + private IReadOnlyDictionary MobMap = new Dictionary() + { + { "Wanderer_", "KommandantPetSpider" }, + }; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(GetSummonAction); + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent>(AddSummonVerb); + SubscribeLocalEvent(OnSummon); + SubscribeLocalEvent(OnGhostSummon); + } + + private void OnGhostSummon(EntityUid uid, PetSummonComponent component, PetGhostSummonActionEvent args) + { + AttemptSummon(component, args.Performer, true); + } + + private void OnSummon(EntityUid uid, PetSummonComponent component, PetSummonActionEvent args) + { + AttemptSummon(component, args.Performer, false); + } + + private void AddSummonVerb(EntityUid uid, PetSummonComponent component, GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess) + return; + + AlternativeVerb verb = new() + { + Act = () => + { + AttemptSummon(component, args.User, false); + }, + Text = "Призвать питомца", + Priority = 2 + }; + + AlternativeVerb ghostVerb = new() + { + Act = () => + { + AttemptSummon(component, args.User, true); + }, + Text = "Призвать питомца-призрак", + Priority = 2 + }; + + args.Verbs.Add(verb); + args.Verbs.Add(ghostVerb); + } + + private void OnExamine(EntityUid uid, PetSummonComponent component, ExaminedEvent args) + { + args.PushMarkup($"Осталось призывов: {component.UsesLeft}"); + } + + private void AttemptSummon(PetSummonComponent component, EntityUid user, bool ghostRole) + { + if (!_blocker.CanInteract(user, component.Owner)) + return; + + string? mobProto = null; + if (TryComp(user, out var actorComponent)) + { + var userKey = actorComponent.PlayerSession.Name; + + if (!MobMap.TryGetValue(userKey, out var proto)) + { + _popupSystem.PopupEntity("Вы не достойны", user, PopupType.Medium); + return; + } + + mobProto = proto; + } + + if (component.UsesLeft == 0) + { + _popupSystem.PopupEntity("Больше нет зарядов!", user, PopupType.Medium); + return; + } + + if (component.SummonedEntity != null) + { + if (!TryComp(component.SummonedEntity, out var mobState)) + { + component.SummonedEntity = null; + } + else + { + if (mobState.CurrentState is MobState.Dead or MobState.Invalid) + component.SummonedEntity = null; + else + { + _popupSystem.PopupEntity("Ваш питомец уже призван", user, PopupType.Medium); + return; + } + } + + } + + if (mobProto != null) + SummonPet(user, component, mobProto, ghostRole); + } + + private void SummonPet(EntityUid user, PetSummonComponent component, string mobProto, bool ghostRole) + { + var transform = CompOrNull(user)?.Coordinates; + + if (transform == null) + return; + + var entity = _entityManager.SpawnEntity(mobProto, transform.Value); + component.UsesLeft--; + component.SummonedEntity = entity; + + if (ghostRole) + SetupGhostRole(entity, user); + else + RemComp(entity); + } + + private void SetupGhostRole(EntityUid entity, EntityUid user) + { + EnsureComp(entity); + + if (!TryComp(entity, out var ghostRole)) + return; + + var meta = MetaData(user); + ghostRole.RoleName = $"Питомец {meta.EntityName}"; + ghostRole.RoleDescription = $"Следуйте за хозяином - {meta.EntityName} и выполняйте его приказы"; + ghostRole.RoleRules = $"Вы должны до самого конца следовать за своим хозяином - {meta.EntityName} и послушно выполнять его приказы, иначе можете быть уничтожены."; + } + + private void GetSummonAction(EntityUid uid, PetSummonComponent component, GetItemActionsEvent args) + { + args.Actions.Add(component.PetSummonAction); + args.Actions.Add(component.PetGhostSummonAction); + } +} + +public sealed class PetSummonActionEvent : InstantActionEvent +{ +} + +public sealed class PetGhostSummonActionEvent : InstantActionEvent +{ +} diff --git a/Resources/Prototypes/White/Fluff/fluff.yml b/Resources/Prototypes/White/Fluff/fluff.yml index 4243672dda..8af1983198 100644 --- a/Resources/Prototypes/White/Fluff/fluff.yml +++ b/Resources/Prototypes/White/Fluff/fluff.yml @@ -163,3 +163,21 @@ damage: types: Blunt: 0 + +# Pets book +- type: entity + parent: BookBase + id: PetSummonBook + name: странная потрёпанная книга + description: Книга непонятного происхождения. + suffix: Флафф + components: + - type: Sprite + sprite: Objects/Misc/books.rsi + layers: + - state: summon_book + - type: Item + size: 5 + - type: Paper + content: Ego voco electi pet + - type: PetSummon diff --git a/Resources/Prototypes/White/Fluff/sponsor.yml b/Resources/Prototypes/White/Fluff/sponsor.yml index faaecad893..8917dc5d76 100644 --- a/Resources/Prototypes/White/Fluff/sponsor.yml +++ b/Resources/Prototypes/White/Fluff/sponsor.yml @@ -57,3 +57,9 @@ id: OmntnsHammerLoadout entity: OmntnsHammer sponsorOnly: true + +# Pets summon book +- type: loadout + id: PetsSummonBookLoadout + entity: PetSummonBook + sponsorOnly: true diff --git a/Resources/Prototypes/White/Mobs/Pets/pets.yml b/Resources/Prototypes/White/Mobs/Pets/pets.yml new file mode 100644 index 0000000000..00fe88d1bf --- /dev/null +++ b/Resources/Prototypes/White/Mobs/Pets/pets.yml @@ -0,0 +1,73 @@ +# Kommandant +- type: entity + parent: SimpleMobBase + id: KommandantPetSpider + name: паук Валера + description: Любит мух и деньги. + components: + - type: Faction + factions: + - PetsNT + - type: Sprite + drawdepth: Mobs + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: viper + sprite: White/Mobs/Pets/Kommandant/spider.rsi + scale: "0.5, 0.5" + - type: Physics + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 0.35 + density: 130 + mask: + - MobMask + layer: + - MobLayer + - type: Appearance + - type: DamageStateVisuals + states: + Alive: + Base: viper + Critical: + Base: viper_dead + Dead: + Base: viper_dead + - type: MobThresholds + thresholds: + 0: Alive + 90: Critical + 150: Dead + - type: ReplacementAccent + accent: xeno + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-tarantula + interactFailureString: petting-failure-generic + - type: IgnoreSpiderWeb + - type: NoSlip + - type: CanEscapeInventory + - type: Grammar + attributes: + proper: true + gender: female + - type: Bloodstream + bloodMaxVolume: 150 + bloodReagent: SpiderBlood + - type: Pacifist + - type: Tag + tags: + - CannotSuicide + - type: Item + size: 10 + - type: GhostRole + makeSentient: true + allowSpeech: true + allowMovement: true + name: "Питомец" + description: "Следуйте за хозяином" + rules: "Всегда следуйте за хозяином и слушайте его приказы." + diff --git a/Resources/Textures/Objects/Misc/books.rsi/meta.json b/Resources/Textures/Objects/Misc/books.rsi/meta.json index daa28bac2a..6493495363 100644 --- a/Resources/Textures/Objects/Misc/books.rsi/meta.json +++ b/Resources/Textures/Objects/Misc/books.rsi/meta.json @@ -101,6 +101,9 @@ }, { "name": "book_fish" + }, + { + "name": "summon_book" } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Objects/Misc/books.rsi/summon_book.png b/Resources/Textures/Objects/Misc/books.rsi/summon_book.png new file mode 100644 index 0000000000000000000000000000000000000000..8d1350f1adb6ec02fe4e15dba25d0ac24670dad6 GIT binary patch literal 363 zcmV-x0hIoUP);uInnTrws5eISAf+c@C%59)PHc z$lxT0IcfqYIC84?E3*IA&_SM)-Ra>FaUoE@B{>UTsv1%qlf?i002ov JPDHLkV1guckGlW> literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/meta.json b/Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/meta.json new file mode 100644 index 0000000000..36d381f4a4 --- /dev/null +++ b/Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/meta.json @@ -0,0 +1,40 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "https://github.com/frosty-dev/white", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "viper", + "directions": 4, + "delays": [ + [ + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2 + ], + [ + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "viper_dead" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/viper.png b/Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/viper.png new file mode 100644 index 0000000000000000000000000000000000000000..9a53f0f54aa113a1ef95c03118cd2ba91e82b856 GIT binary patch literal 3989 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/viper_dead.png b/Resources/Textures/White/Mobs/Pets/Kommandant/spider.rsi/viper_dead.png new file mode 100644 index 0000000000000000000000000000000000000000..040ab3e49ab549a978e533a6d5d897a24c609583 GIT binary patch literal 806 zcmV+>1KIqEP)II(d%Xet2n*3j~5+n7>T9 zkDJu)v^;kn00`KomJLN1j01!}xZhtN0}MjvjCDr69~68b02UzjJ3n*kEbWvE)UfK5 zh%DLV#)@#rYn1PJ@&s+=-+P$z`|1O*U-Nl_H|qfeoC~MvTYF8|VeNj$Cw zQe#O5)aJw944dMd%TeF02^!%b7|PM!bd}=WS)sEx{fL6y8X0ZFh7NQ&82rK)+xnX^ z$Vk-Yd-d*Fpi=v6$D^~dcGyD~XQ|UEVSF?elbMP2Hj$$zKG+~2g7g03`D?bn86^WM z2&U=COjH=FwBbxAtglk7`WW;Q4m1g2aP#Vt{d9dz^npKn$d_tW-d(?RgI1rf1XSQU z=>s5Z?;v#=iMXKK!1?X@u3}wK>g8KqEd(L9fOc0gJw3tYU^C#~5MYBsBsIva27j)SV z1i&mHi}XTT)Rt*vVE39O$|RCB7c-?D&RB;7p#W^ajT|LrDoj zwb{zkP|*Sa1I>0*3@09?SH2$-R6m^R5Y;;LAliEgcWYImsU9$tBTK#U%R`4}!GQsA z89-sF((7(G%Yucnqi}47ZvP5NeXIdW1piT#*~8ZTH)wxgS_b$9FdNLm#?KZl6rF{` z#I4QO;_QArMf1g7aYt_Uuu-R?F3!+F#D+YEvCmmwDQ`6FY@sOi?iAj5^znLhzu%Dn k_<`v5`|1BRfPX2!0Wt+AFrxb%DF6Tf07*qoM6N<$g3c3i7ytkO literal 0 HcmV?d00001