From: ActiveMammmoth <140334666+ActiveMammmoth@users.noreply.github.com> Date: Sun, 17 Nov 2024 16:46:31 +0000 (-0500) Subject: Wizard Summon Guns/Magic (#32692) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=22987fc77f5ab508604be215cedc8bb59f7fb947;p=space-station-14.git Wizard Summon Guns/Magic (#32692) * mostly done but there's a bug with spawning * RandomGlobalSpawnSpellEvent now actually works * Summon Guns/Magic is working * Added sound, cap gun, and auto pick up * Added all requested changes/fixes from reviews * Halving cooldowns --- diff --git a/Content.Server/Objectives/Systems/KillPersonConditionSystem.cs b/Content.Server/Objectives/Systems/KillPersonConditionSystem.cs index 8dcbf191b3..f662d6a578 100644 --- a/Content.Server/Objectives/Systems/KillPersonConditionSystem.cs +++ b/Content.Server/Objectives/Systems/KillPersonConditionSystem.cs @@ -53,7 +53,7 @@ public sealed class KillPersonConditionSystem : EntitySystem return; // no other humans to kill - var allHumans = _mind.GetAliveHumansExcept(args.MindId); + var allHumans = _mind.GetAliveHumans(args.MindId); if (allHumans.Count == 0) { args.Cancelled = true; @@ -77,14 +77,14 @@ public sealed class KillPersonConditionSystem : EntitySystem return; // no other humans to kill - var allHumans = _mind.GetAliveHumansExcept(args.MindId); + var allHumans = _mind.GetAliveHumans(args.MindId); if (allHumans.Count == 0) { args.Cancelled = true; return; } - var allHeads = new List(); + var allHeads = new HashSet>(); foreach (var person in allHumans) { if (TryComp(person, out var mind) && mind.OwnedEntity is { } ent && HasComp(ent)) diff --git a/Content.Server/Store/Systems/StoreSystem.Ui.cs b/Content.Server/Store/Systems/StoreSystem.Ui.cs index f1c0cb1e90..5af6ce1c97 100644 --- a/Content.Server/Store/Systems/StoreSystem.Ui.cs +++ b/Content.Server/Store/Systems/StoreSystem.Ui.cs @@ -256,6 +256,11 @@ public sealed partial class StoreSystem RaiseLocalEvent(buyer, listing.ProductEvent); } + if (listing.DisableRefund) + { + component.RefundAllowed = false; + } + //log dat shit. _admin.Add(LogType.StorePurchase, LogImpact.Low, diff --git a/Content.Shared/Magic/Events/RandomGlobalSpawnSpellEvent.cs b/Content.Shared/Magic/Events/RandomGlobalSpawnSpellEvent.cs new file mode 100644 index 0000000000..c77607562a --- /dev/null +++ b/Content.Shared/Magic/Events/RandomGlobalSpawnSpellEvent.cs @@ -0,0 +1,23 @@ +using Content.Shared.Actions; +using Content.Shared.Storage; +using Robust.Shared.Audio; + +namespace Content.Shared.Magic.Events; + +public sealed partial class RandomGlobalSpawnSpellEvent : InstantActionEvent, ISpeakSpell +{ + /// + /// The list of prototypes this spell can spawn, will select one randomly + /// + [DataField] + public List Spawns = new(); + + /// + /// Sound that will play globally when cast + /// + [DataField] + public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Magic/staff_animation.ogg"); + + [DataField] + public string? Speech { get; private set; } +} diff --git a/Content.Shared/Magic/SharedMagicSystem.cs b/Content.Shared/Magic/SharedMagicSystem.cs index 02d483c0a3..21e137346e 100644 --- a/Content.Shared/Magic/SharedMagicSystem.cs +++ b/Content.Shared/Magic/SharedMagicSystem.cs @@ -1,4 +1,4 @@ -using System.Numerics; +using System.Numerics; using Content.Shared.Actions; using Content.Shared.Body.Components; using Content.Shared.Body.Systems; @@ -7,12 +7,17 @@ using Content.Shared.Doors.Components; using Content.Shared.Doors.Systems; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; +using Content.Shared.Humanoid; using Content.Shared.Interaction; using Content.Shared.Inventory; using Content.Shared.Lock; using Content.Shared.Magic.Components; using Content.Shared.Magic.Events; using Content.Shared.Maps; +using Content.Shared.Mind; +using Content.Shared.Mind.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Physics; using Content.Shared.Popups; using Content.Shared.Speech.Muting; @@ -20,6 +25,7 @@ using Content.Shared.Storage; using Content.Shared.Tag; using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Systems; +using Robust.Shared.Audio.Systems; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Network; @@ -53,6 +59,9 @@ public abstract class SharedMagicSystem : EntitySystem [Dependency] private readonly LockSystem _lock = default!; [Dependency] private readonly SharedHandsSystem _hands = default!; [Dependency] private readonly TagSystem _tag = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedMindSystem _mind = default!; public override void Initialize() { @@ -67,6 +76,7 @@ public abstract class SharedMagicSystem : EntitySystem SubscribeLocalEvent(OnSmiteSpell); SubscribeLocalEvent(OnKnockSpell); SubscribeLocalEvent(OnChargeSpell); + SubscribeLocalEvent(OnRandomGlobalSpawnSpell); // Spell wishlist // A wishlish of spells that I'd like to implement or planning on implementing in a future PR @@ -501,6 +511,37 @@ public abstract class SharedMagicSystem : EntitySystem _gunSystem.UpdateBasicEntityAmmoCount(wand.Value, basicAmmoComp.Count.Value + ev.Charge, basicAmmoComp); } // End Charge Spells + #endregion + #region Global Spells + + private void OnRandomGlobalSpawnSpell(RandomGlobalSpawnSpellEvent ev) + { + if (!_net.IsServer || ev.Handled || !PassesSpellPrerequisites(ev.Action, ev.Performer) || ev.Spawns is not { } spawns) + return; + + ev.Handled = true; + Speak(ev); + + var allHumans = _mind.GetAliveHumans(); + + foreach (var human in allHumans) + { + if (!human.Comp.OwnedEntity.HasValue) + continue; + + var ent = human.Comp.OwnedEntity.Value; + + var mapCoords = _transform.GetMapCoordinates(ent); + foreach (var spawn in EntitySpawnCollection.GetSpawns(spawns, _random)) + { + var spawned = Spawn(spawn, mapCoords); + _hands.PickupOrDrop(ent, spawned); + } + } + + _audio.PlayGlobal(ev.Sound, ev.Performer); + } + #endregion // End Spells #endregion diff --git a/Content.Shared/Mind/SharedMindSystem.cs b/Content.Shared/Mind/SharedMindSystem.cs index bf0b5f650a..0f5f9172cc 100644 --- a/Content.Shared/Mind/SharedMindSystem.cs +++ b/Content.Shared/Mind/SharedMindSystem.cs @@ -532,22 +532,19 @@ public abstract class SharedMindSystem : EntitySystem /// /// Returns a list of every living humanoid player's minds, except for a single one which is exluded. /// - public List GetAliveHumansExcept(EntityUid exclude) + public HashSet> GetAliveHumans(EntityUid? exclude = null) { - var mindQuery = EntityQuery(); - - var allHumans = new List(); + var allHumans = new HashSet>(); // HumanoidAppearanceComponent is used to prevent mice, pAIs, etc from being chosen - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var mc, out var mobState, out _)) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var mobState, out _)) { - // the player needs to have a mind and not be the excluded one - if (mc.Mind == null || mc.Mind == exclude) + // the player needs to have a mind and not be the excluded one + + // the player has to be alive + if (!TryGetMind(uid, out var mind, out var mindComp) || mind == exclude || !_mobState.IsAlive(uid, mobState)) continue; - // the player has to be alive - if (_mobState.IsAlive(uid, mobState)) - allHumans.Add(mc.Mind.Value); + allHumans.Add(new Entity(mind, mindComp)); } return allHumans; diff --git a/Content.Shared/Store/ListingPrototype.cs b/Content.Shared/Store/ListingPrototype.cs index 05ac5cc4cd..e2339b72c6 100644 --- a/Content.Shared/Store/ListingPrototype.cs +++ b/Content.Shared/Store/ListingPrototype.cs @@ -39,7 +39,8 @@ public partial class ListingData : IEquatable other.Categories, other.OriginalCost, other.RestockTime, - other.DiscountDownTo + other.DiscountDownTo, + other.DisableRefund ) { @@ -63,7 +64,8 @@ public partial class ListingData : IEquatable HashSet> categories, IReadOnlyDictionary, FixedPoint2> originalCost, TimeSpan restockTime, - Dictionary, FixedPoint2> dataDiscountDownTo + Dictionary, FixedPoint2> dataDiscountDownTo, + bool disableRefund ) { Name = name; @@ -84,6 +86,7 @@ public partial class ListingData : IEquatable OriginalCost = originalCost; RestockTime = restockTime; DiscountDownTo = new Dictionary, FixedPoint2>(dataDiscountDownTo); + DisableRefund = disableRefund; } [ViewVariables] @@ -194,6 +197,12 @@ public partial class ListingData : IEquatable [DataField] public Dictionary, FixedPoint2> DiscountDownTo = new(); + /// + /// Whether or not to disable refunding for the store when the listing is purchased from it. + /// + [DataField] + public bool DisableRefund = false; + public bool Equals(ListingData? listing) { if (listing == null) @@ -287,7 +296,8 @@ public sealed partial class ListingDataWithCostModifiers : ListingData listingData.Categories, listingData.OriginalCost, listingData.RestockTime, - listingData.DiscountDownTo + listingData.DiscountDownTo, + listingData.DisableRefund ) { } diff --git a/Resources/Locale/en-US/magic/spells-actions.ftl b/Resources/Locale/en-US/magic/spells-actions.ftl index 40757cd694..21109066d3 100644 --- a/Resources/Locale/en-US/magic/spells-actions.ftl +++ b/Resources/Locale/en-US/magic/spells-actions.ftl @@ -1,5 +1,7 @@ -action-speech-spell-forcewall = TARCOL MINTI ZHERI +action-speech-spell-forcewall = TARCOL MINTI ZHERI action-speech-spell-knock = AULIE OXIN FIERA action-speech-spell-smite = EI NATH! action-speech-spell-summon-magicarp = AIE KHUSE EU action-speech-spell-fireball = ONI'SOMA! +action-speech-spell-summon-guns = YOR'NEE VES-KORFA +action-speech-spell-summon-magic = RYGOIN FEMA-VERECO diff --git a/Resources/Locale/en-US/store/spellbook-catalog.ftl b/Resources/Locale/en-US/store/spellbook-catalog.ftl index 1d970f6e3a..ed62c6fa82 100644 --- a/Resources/Locale/en-US/store/spellbook-catalog.ftl +++ b/Resources/Locale/en-US/store/spellbook-catalog.ftl @@ -1,4 +1,4 @@ -# Spells +# Spells spellbook-fireball-name = Fireball spellbook-fireball-desc = Get most crew exploding with rage when they see this fireball heading toward them! @@ -33,6 +33,12 @@ spellbook-wand-polymorph-carp-description = For when you need a carp filet quick spellbook-event-summon-ghosts-name = Summon Ghosts spellbook-event-summon-ghosts-description = Who ya gonna call? +spellbook-event-summon-guns-name = Summon Guns +spellbook-event-summon-guns-description = AK47s for everyone! Places a random gun in front of everybody. Disables refunds when bought! + +spellbook-event-summon-magic-name = Summon Magic +spellbook-event-summon-magic-description = Places a random magical item in front of everybody. Nothing could go wrong! Disables refunds when bought! + # Upgrades spellbook-upgrade-fireball-name = Upgrade Fireball spellbook-upgrade-fireball-description = Upgrades Fireball to a maximum of level 3! diff --git a/Resources/Prototypes/Catalog/spellbook_catalog.yml b/Resources/Prototypes/Catalog/spellbook_catalog.yml index 805c157f1e..6e9bba87a6 100644 --- a/Resources/Prototypes/Catalog/spellbook_catalog.yml +++ b/Resources/Prototypes/Catalog/spellbook_catalog.yml @@ -1,4 +1,4 @@ -# Offensive +# Offensive - type: listing id: SpellbookFireball name: spellbook-fireball-name @@ -132,6 +132,34 @@ - !type:ListingLimitedStockCondition stock: 1 +- type: listing + id: SpellbookEventSummonGuns + name: spellbook-event-summon-guns-name + description: spellbook-event-summon-guns-description + productAction: ActionSummonGuns + cost: + WizCoin: 2 + categories: + - SpellbookEvents + conditions: + - !type:ListingLimitedStockCondition + stock: 1 + disableRefund: true + +- type: listing + id: SpellbookEventSummonMagic + name: spellbook-event-summon-magic-name + description: spellbook-event-summon-magic-description + productAction: ActionSummonMagic + cost: + WizCoin: 2 + categories: + - SpellbookEvents + conditions: + - !type:ListingLimitedStockCondition + stock: 1 + disableRefund: true + # Upgrades - type: listing id: SpellbookFireballUpgrade diff --git a/Resources/Prototypes/Magic/event_spells.yml b/Resources/Prototypes/Magic/event_spells.yml index 01006b4ffe..5aad8925a6 100644 --- a/Resources/Prototypes/Magic/event_spells.yml +++ b/Resources/Prototypes/Magic/event_spells.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity id: ActionSummonGhosts name: Summon Ghosts description: Makes all current ghosts permanently invisible @@ -10,3 +10,195 @@ sprite: Mobs/Ghosts/ghost_human.rsi state: icon event: !type:ToggleGhostVisibilityToAllEvent + +# TODO: Add Whitelist/Blacklist and Component support to EntitySpawnLists (to avoid making huge hardcoded lists like below). + +- type: entity + id: ActionSummonGuns + name: Summon Guns + description: AK47s for everyone! Places a random gun in front of everybody. + components: + - type: Magic + - type: InstantAction + useDelay: 300 + itemIconStyle: BigAction + icon: + sprite: Objects/Weapons/Guns/Rifles/ak.rsi + state: base + event: !type:RandomGlobalSpawnSpellEvent + spawns: + - id: WeaponPistolViper + orGroup: Guns + - id: WeaponPistolCobra + orGroup: Guns + - id: WeaponPistolMk58 + orGroup: Guns + - id: WeaponPistolN1984 + orGroup: Guns + - id: WeaponRevolverDeckard + orGroup: Guns + - id: WeaponRevolverInspector + orGroup: Guns + - id: WeaponRevolverMateba + orGroup: Guns + - id: WeaponRevolverPython + orGroup: Guns + - id: WeaponRevolverPirate + orGroup: Guns + - id: WeaponRifleAk + orGroup: Guns + - id: WeaponRifleM90GrenadeLauncher + orGroup: Guns + - id: WeaponRifleLecter + orGroup: Guns + - id: WeaponShotgunBulldog + orGroup: Guns + - id: WeaponShotgunDoubleBarreled + orGroup: Guns + - id: WeaponShotgunEnforcer + orGroup: Guns + - id: WeaponShotgunKammerer + orGroup: Guns + - id: WeaponShotgunSawn + orGroup: Guns + - id: WeaponShotgunHandmade + orGroup: Guns + - id: WeaponShotgunBlunderbuss + orGroup: Guns + - id: WeaponShotgunImprovised + orGroup: Guns + - id: WeaponSubMachineGunAtreides + orGroup: Guns + - id: WeaponSubMachineGunC20r + orGroup: Guns + - id: WeaponSubMachineGunDrozd + orGroup: Guns + - id: WeaponSubMachineGunWt550 + orGroup: Guns + - id: WeaponSniperMosin + orGroup: Guns + - id: WeaponSniperHristov + orGroup: Guns + - id: Musket + orGroup: Guns + - id: WeaponPistolFlintlock + orGroup: Guns + - id: WeaponLauncherChinaLake + orGroup: Guns + - id: WeaponLauncherRocket + orGroup: Guns + - id: WeaponLauncherPirateCannon + orGroup: Guns + - id: WeaponTetherGun + orGroup: Guns + - id: WeaponForceGun + orGroup: Guns + - id: WeaponGrapplingGun + orGroup: Guns + - id: WeaponLightMachineGunL6 + orGroup: Guns + - id: WeaponLaserSvalinn + orGroup: Guns + - id: WeaponLaserGun + orGroup: Guns + - id: WeaponMakeshiftLaser + orGroup: Guns + - id: WeaponTeslaGun + orGroup: Guns + - id: WeaponLaserCarbinePractice + orGroup: Guns + - id: WeaponLaserCarbine + orGroup: Guns + - id: WeaponPulsePistol + orGroup: Guns + - id: WeaponPulseCarbine + orGroup: Guns + - id: WeaponPulseRifle + orGroup: Guns + - id: WeaponLaserCannon + orGroup: Guns + - id: WeaponParticleDecelerator + orGroup: Guns + - id: WeaponXrayCannon + orGroup: Guns + - id: WeaponDisablerPractice + orGroup: Guns + - id: WeaponDisabler + orGroup: Guns + - id: WeaponDisablerSMG + orGroup: Guns + - id: WeaponTaser + orGroup: Guns + - id: WeaponAntiqueLaser + orGroup: Guns + - id: WeaponAdvancedLaser + orGroup: Guns + - id: WeaponPistolCHIMP + orGroup: Guns + - id: WeaponBehonkerLaser + orGroup: Guns + - id: WeaponEnergyShotgun + orGroup: Guns + - id: WeaponMinigun + orGroup: Guns + - id: BowImprovised + orGroup: Guns + - id: WeaponFlareGun + orGroup: Guns + - id: WeaponImprovisedPneumaticCannon + orGroup: Guns + - id: WeaponWaterPistol + orGroup: Guns + - id: WeaponWaterBlaster + orGroup: Guns + - id: WeaponWaterBlasterSuper + orGroup: Guns + - id: RevolverCapGun + orGroup: Guns + - id: RevolverCapGunFake + orGroup: Guns + speech: action-speech-spell-summon-guns + +- type: entity + id: ActionSummonMagic + name: Summon Magic + description: Places a random magical item in front of everybody. Nothing could go wrong! + components: + - type: Magic + - type: InstantAction + useDelay: 300 + itemIconStyle: BigAction + icon: + sprite: Objects/Magic/magicactions.rsi + state: magicmissile + event: !type:RandomGlobalSpawnSpellEvent + spawns: + - id: SpawnSpellbook + orGroup: Magics + - id: ForceWallSpellbook + orGroup: Magics + - id: BlinkBook + orGroup: Magics + - id: SmiteBook + orGroup: Magics + - id: KnockSpellbook + orGroup: Magics + - id: FireballSpellbook + orGroup: Magics + - id: WeaponWandPolymorphCarp + orGroup: Magics + - id: WeaponWandPolymorphMonkey + orGroup: Magics + - id: WeaponWandFireball + orGroup: Magics + - id: WeaponWandPolymorphDoor + orGroup: Magics + - id: WeaponWandCluwne + orGroup: Magics + - id: WeaponWandPolymorphBread + orGroup: Magics + - id: WeaponStaffHealing + orGroup: Magics + - id: WeaponStaffPolymorphDoor + orGroup: Magics + speech: action-speech-spell-summon-magic