diff --git a/Content.Server/Polymorph/Components/PolymorphProviderComponent.cs b/Content.Server/Polymorph/Components/PolymorphProviderComponent.cs new file mode 100644 index 00000000000..351f5d24e43 --- /dev/null +++ b/Content.Server/Polymorph/Components/PolymorphProviderComponent.cs @@ -0,0 +1,13 @@ +using Content.Server.Polymorph.Systems; +using Content.Shared.Polymorph; +using Robust.Shared.Prototypes; + +namespace Content.Server.Polymorph.Components; + +[RegisterComponent] +[Access(typeof(PolymorphSystem))] +public sealed partial class PolymorphProviderComponent : Component +{ + [DataField] + public ProtoId Polymorph; +} diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.Provider.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.Provider.cs new file mode 100644 index 00000000000..03921350f27 --- /dev/null +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.Provider.cs @@ -0,0 +1,31 @@ +using Content.Server.Actions; +using Content.Server.Polymorph.Components; +using Content.Shared.Actions; +using Content.Shared.Inventory.Events; +using Content.Shared.Polymorph; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Server.Polymorph.Systems; + +public sealed partial class PolymorphSystem +{ + private void InitializeProvider() + { + SubscribeLocalEvent(OnEquipped); + SubscribeLocalEvent(OnUnEquipped); + } + + private void OnUnEquipped(EntityUid uid, PolymorphProviderComponent component, ref GotUnequippedEvent args) + { + if (TryComp(args.Equipee, out var polymorphable)) + RemovePolymorphAction(component.Polymorph, (args.Equipee, polymorphable)); + } + + private void OnEquipped(EntityUid uid, PolymorphProviderComponent component, ref GotEquippedEvent args) + { + var polymorphable = EnsureComp(args.Equipee); + CreatePolymorphAction(component.Polymorph, (args.Equipee, polymorphable)); + } + +} diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.cs index 5c970b1a748..23f4eb7d7b1 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.cs @@ -64,6 +64,7 @@ public override void Initialize() InitializeCollide(); InitializeMap(); + InitializeProvider(); } public override void Update(float frameTime) @@ -365,8 +366,11 @@ private void OnDestruction(Entity ent, ref Destructi public void CreatePolymorphAction(ProtoId id, Entity target) { target.Comp.PolymorphActions ??= new(); - if (target.Comp.PolymorphActions.ContainsKey(id)) + if (target.Comp.PolymorphActions.TryGetValue(id, out var actionBla)) + { + _actions.AddAction(target, actionBla, target); return; + } if (!_proto.TryIndex(id, out var polyProto)) return; diff --git a/Resources/Prototypes/Floof/Entities/Clothing/Neck/amulet.yml b/Resources/Prototypes/Floof/Entities/Clothing/Neck/amulet.yml new file mode 100644 index 00000000000..a4a3a2edd54 --- /dev/null +++ b/Resources/Prototypes/Floof/Entities/Clothing/Neck/amulet.yml @@ -0,0 +1,144 @@ + +- type: entity + parent: ClothingNeckBase + id: ClothingNeckDragonAmuletPolymorph + name: dragon amulet + description: A beautiful gold amulet, featuring a ruby that shines with an otherworldly glow. + components: + - type: Sprite + sprite: Floof/Clothing/Neck/amulet_dragon.rsi + - type: Clothing + sprite: Floof/Clothing/Neck/amulet_dragon.rsi + - type: PolymorphProvider + polymorph: PolymorphDragonRubyFang + +- type: polymorph + id: PolymorphDragonRubyFang + configuration: + entity: MobDragonRubyFang + forced: false + inventory: None + transferName: true + transferDamage: true + revertOnCrit: true + revertOnDeath: true + +- type: entity + parent: [ SimpleSpaceMobBase, FlyingMobBase ] + id: MobDragonRubyFang + suffix: "" + name: Rubyfang + description: A giant dragon, probably a couple thousand years old. + components: + - type: Bloodstream + bloodMaxVolume: 650 + - type: Speech + speechVerb: LargeMob + - type: CombatMode + - type: MobMover + - type: InputMover + - type: MovementSpeedModifier + baseWalkSpeed: 3 + baseSprintSpeed: 5 + weightlessModifier: 1.5 + - type: Sprite + color: "#cc0000ff" + sprite: Mobs/Aliens/Carps/dragon.rsi + noRot: true + layers: + - map: [ "enum.DamageStateVisualLayers.Base" ] + state: alive + - map: [ "enum.DamageStateVisualLayers.BaseUnshaded" ] + state: alive-unshaded + shader: unshaded + - type: Appearance + - type: DamageStateVisuals + states: + Alive: + Base: alive + BaseUnshaded: alive-unshaded + Critical: + Base: crit + Dead: + Base: dead + BaseUnshaded: dead-unshaded + - type: Physics + bodyType: KinematicController + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 0.40 + density: 100 + mask: + - FlyingMobMask + layer: + - FlyingMobLayer + - type: MobState + - type: MobStateActions + actions: + Critical: + - ActionCritSuccumb + - ActionCritLastWords + - type: MobThresholds + thresholds: + 0: Alive + 450: Critical + 500: Dead + - type: SlowOnDamage + speedModifierThresholds: + 250: 0.7 + 400: 0.5 + # disable taking damage from fire, since its a fire breathing dragon + - type: Flammable + damage: + types: {} + - type: Temperature + heatDamageThreshold: 800 + - type: Metabolizer + solutionOnBody: false + updateInterval: 0.25 + metabolizerTypes: [ Dragon ] + groups: + - id: Medicine + - id: Poison + - type: Butcherable + spawned: + - id: FoodMeatDragon + amount: 2 + - type: InteractionPopup + successChance: 0.25 # It's no goose, but you better smell like carp. + interactSuccessString: petting-success-dragon + interactFailureString: petting-failure-dragon + interactFailureSound: + path: /Audio/Animals/space_dragon_roar.ogg + soundPerceivedByOthers: false # A 75% chance for a loud roar would get old fast. + - type: MeleeWeapon + altDisarm: false + soundHit: + path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg + damage: + types: + Piercing: 15 + Slash: 15 + - type: Devourer + foodPreference: Humanoid + shouldStoreDevoured: true + chemical: Ichor + healRate: 15.0 + whitelist: + components: + - MobState + - Door + tags: + - Wall + - type: Tag + tags: + - CannotSuicide + - DoorBumpOpener + - type: UserInterface + - type: Puller + needsHands: false + - type: Hands + diff --git a/Resources/Textures/Floof/Clothing/Neck/amulet_dragon.rsi/equipped-NECK.png b/Resources/Textures/Floof/Clothing/Neck/amulet_dragon.rsi/equipped-NECK.png new file mode 100644 index 00000000000..c84c03cc2b7 Binary files /dev/null and b/Resources/Textures/Floof/Clothing/Neck/amulet_dragon.rsi/equipped-NECK.png differ diff --git a/Resources/Textures/Floof/Clothing/Neck/amulet_dragon.rsi/icon.png b/Resources/Textures/Floof/Clothing/Neck/amulet_dragon.rsi/icon.png new file mode 100644 index 00000000000..39b120aabbe Binary files /dev/null and b/Resources/Textures/Floof/Clothing/Neck/amulet_dragon.rsi/icon.png differ diff --git a/Resources/Textures/Floof/Clothing/Neck/amulet_dragon.rsi/meta.json b/Resources/Textures/Floof/Clothing/Neck/amulet_dragon.rsi/meta.json new file mode 100644 index 00000000000..e0e89fc46f0 --- /dev/null +++ b/Resources/Textures/Floof/Clothing/Neck/amulet_dragon.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Pire Discord #plazmaspirit", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-NECK", + "directions": 4 + } + ] +}