From 7bb39bce25df3a6a383f09648f8072c03651ed97 Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Wed, 13 Mar 2024 02:09:49 +0400 Subject: [PATCH 01/13] =?UTF-8?q?=D0=9C=D0=B8=D0=BD=D0=B8-=D0=B0=D0=BF?= =?UTF-8?q?=D0=B4=D0=B5=D0=B9=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChangelingSystem.Abilities.cs | 9 ++ .../EntitySystems/ChangelingSystem.cs | 7 ++ .../ComponentalActions.Abilities.cs | 87 ++++++++++++++++++- .../EntitySystems/ComponentalActions.cs | 27 ++++++ .../Components/ChangelingComponent.cs | 3 + .../Components/InvisibilityActComponent.cs | 30 +++++++ .../Components/StasisHealActComponent.cs | 40 +++++++++ .../SharedComponentalActions.cs | 8 ++ .../Stealth/Components/StealthComponent.cs | 1 - .../Locale/ru-RU/ADT/componental-actions.ftl | 6 ++ .../ADT/Actions/componental_actions.yml | 30 +++++++ .../Weapons/Guns/Projectiles/projectiles.yml | 22 +++++ Resources/Prototypes/ADT/ling_unturnable.yml | 78 +++++++++++++++++ 13 files changed, 345 insertions(+), 3 deletions(-) create mode 100644 Content.Shared/ADT/ComponentalActions/Components/InvisibilityActComponent.cs create mode 100644 Content.Shared/ADT/ComponentalActions/Components/StasisHealActComponent.cs create mode 100644 Resources/Prototypes/ADT/ling_unturnable.yml diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs index 1c329e05bbc..0f51133c1ef 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs @@ -29,6 +29,7 @@ using Content.Shared.Eye.Blinding.Systems; using Content.Server.Destructible; using Content.Shared.Polymorph; +using Content.Server.Ghost.Components; namespace Content.Server.Changeling.EntitySystems; @@ -694,6 +695,8 @@ private void OnStasisDeathAction(EntityUid uid, ChangelingComponent component, S args.Handled = true; + RemComp(uid); + var damage_burn = new DamageSpecifier(_proto.Index(BurnDamageGroup), component.StasisDeathDamageAmount); _damageableSystem.TryChangeDamage(uid, damage_burn); /// Самоопиздюливание @@ -723,6 +726,9 @@ private void OnStasisDeathAction(EntityUid uid, ChangelingComponent component, S _mobState.ChangeMobState(uid, MobState.Critical); /// Переходим в крит, если повреждений окажется меньше нужных для крита, поднимемся в MobState.Alive сами _damageableSystem.TryChangeDamage(uid, damage_burn); component.StasisDeathActive = false; + EnsureComp(uid); + var ghostOnMove = EnsureComp(uid); + ghostOnMove.MustBeDead = true; } } @@ -961,6 +967,9 @@ private void OnLastResort(EntityUid uid, ChangelingComponent component, LastReso if (!TryUseAbility(uid, component, component.ChemicalsCostFree)) return; + if (component.LastResortUsed) + return; + if (SpawnLingSlug(uid, component)) { var damage_brute = new DamageSpecifier(_proto.Index(BruteDamageGroup), component.GibDamage); diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs index f0eec8c1b4d..0794ed0a677 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs @@ -33,6 +33,7 @@ using Content.Shared.Gibbing.Systems; using Content.Shared.Mind; using Content.Shared.Sirena.NightVision.Components; +using Content.Shared.CombatMode; namespace Content.Server.Changeling.EntitySystems; @@ -56,6 +57,8 @@ public sealed partial class ChangelingSystem : EntitySystem [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly GibbingSystem _gibbingSystem = default!; [Dependency] private readonly SharedMindSystem _mindSystem = default!; + [Dependency] private readonly SharedCombatModeSystem _combat = default!; + public override void Initialize() { base.Initialize(); @@ -332,6 +335,7 @@ public void OnTransform(EntityUid uid, ChangelingComponent component, Changeling newLingComponent.ChameleonSkinActive = component.ChameleonSkinActive; newLingComponent.LingArmorActive = component.LingArmorActive; newLingComponent.CanRefresh = component.CanRefresh; + newLingComponent.LastResortUsed = component.LastResortUsed; RemComp(uid, component); if (TryComp(uid, out StoreComponent? storeComp)) @@ -612,6 +616,7 @@ public bool LesserForm(EntityUid uid, ChangelingComponent component) newLingComponent.LingArmorActive = component.LingArmorActive; newLingComponent.CanRefresh = component.CanRefresh; newLingComponent.LesserFormActive = !component.LesserFormActive; + newLingComponent.LastResortUsed = component.LastResortUsed; RemComp(uid, component); if (TryComp(uid, out StoreComponent? storeComp)) @@ -670,6 +675,7 @@ public bool LesserForm(EntityUid uid, ChangelingComponent component) newLingComponent.LingArmorActive = component.LingArmorActive; newLingComponent.CanRefresh = component.CanRefresh; newLingComponent.LesserFormActive = !component.LesserFormActive; + newLingComponent.LastResortUsed = component.LastResortUsed; RemComp(uid, component); if (TryComp(uid, out StoreComponent? storeComp)) @@ -734,6 +740,7 @@ public bool SpawnLingMonkey(EntityUid uid, ChangelingComponent component) newLingComponent.LingArmorActive = component.LingArmorActive; newLingComponent.CanRefresh = component.CanRefresh; newLingComponent.LesserFormActive = !component.LesserFormActive; + newLingComponent.LastResortUsed = true; _action.AddAction(uid, ref component.ChangelingLesserFormActionEntity, component.ChangelingLesserFormAction); diff --git a/Content.Server/ADT/ComponentalActions/EntitySystems/ComponentalActions.Abilities.cs b/Content.Server/ADT/ComponentalActions/EntitySystems/ComponentalActions.Abilities.cs index b62a69902bf..d80cb1c4b68 100644 --- a/Content.Server/ADT/ComponentalActions/EntitySystems/ComponentalActions.Abilities.cs +++ b/Content.Server/ADT/ComponentalActions/EntitySystems/ComponentalActions.Abilities.cs @@ -50,8 +50,8 @@ using Content.Shared.Physics; using Content.Shared.Storage; using Robust.Server.GameObjects; -using Robust.Shared.Serialization.Manager; -using Robust.Shared.Spawners; +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; using Content.Shared.Throwing; namespace Content.Server.ComponentalActions.EntitySystems; @@ -83,8 +83,34 @@ private void InitializeCompAbilities() SubscribeLocalEvent(OnProjectile); SubscribeLocalEvent(OnHeal); SubscribeLocalEvent(OnJump); + SubscribeLocalEvent(OnStasisHeal); + SubscribeLocalEvent(OnInvisibility); } + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var stasis)) + { + if (stasis.Active) + { + var damage_brute = new DamageSpecifier(_proto.Index(BruteDamageGroup), stasis.RegenerateBruteHealAmount); + var damage_burn = new DamageSpecifier(_proto.Index(BurnDamageGroup), stasis.RegenerateBurnHealAmount); + var damage_airloss = new DamageSpecifier(_proto.Index(AirlossDamageGroup), stasis.RegenerateBurnHealAmount); + var damage_toxin = new DamageSpecifier(_proto.Index(ToxinDamageGroup), stasis.RegenerateBurnHealAmount); + var damage_genetic = new DamageSpecifier(_proto.Index(GeneticDamageGroup), stasis.RegenerateBurnHealAmount); + _damageableSystem.TryChangeDamage(uid, damage_brute); + _damageableSystem.TryChangeDamage(uid, damage_burn); + _damageableSystem.TryChangeDamage(uid, damage_airloss); + _damageableSystem.TryChangeDamage(uid, damage_toxin); + _damageableSystem.TryChangeDamage(uid, damage_genetic); + _bloodstreamSystem.TryModifyBloodLevel(uid, stasis.RegenerateBloodVolumeHealAmount); // give back blood and remove bleeding + _bloodstreamSystem.TryModifyBleedAmount(uid, stasis.RegenerateBleedReduceAmount); + } + } + } private List GetSpawnPositions(TransformComponent casterXform, ComponentalActionsSpawnData data) { switch (data) @@ -188,6 +214,9 @@ private void OnProjectile(EntityUid uid, ProjectileActComponent component, CompP public ProtoId BruteDamageGroup = "Brute"; public ProtoId BurnDamageGroup = "Burn"; + public ProtoId AirlossDamageGroup = "Airloss"; + public ProtoId ToxinDamageGroup = "Toxin"; + public ProtoId GeneticDamageGroup = "Genetic"; private void OnHeal(EntityUid uid, HealActComponent component, CompHealActionEvent args) { @@ -220,4 +249,58 @@ private void OnJump(EntityUid uid, JumpActComponent component, CompJumpActionEve args.Handled = true; } + private void OnStasisHeal(EntityUid uid, StasisHealActComponent component, CompStasisHealActionEvent args) + { + if (args.Handled) + return; + + if (component.Active) + { + var movementSpeed = EnsureComp(uid); + var sprintSpeed = component.BaseSprintSpeed; + var walkSpeed = component.BaseWalkSpeed; + _movementSpeedModifierSystem?.ChangeBaseSpeed(uid, walkSpeed, sprintSpeed, movementSpeed.Acceleration, movementSpeed); + } + + if (!component.Active) + { + var movementSpeed = EnsureComp(uid); + var sprintSpeed = component.SpeedModifier; + var walkSpeed = component.SpeedModifier; + _movementSpeedModifierSystem?.ChangeBaseSpeed(uid, walkSpeed, sprintSpeed, movementSpeed.Acceleration, movementSpeed); + } + + component.Active = !component.Active; + + args.Handled = true; + } + + private void OnInvisibility(EntityUid uid, InvisibilityActComponent component, CompInvisibilityActionEvent args) + { + if (args.Handled) + return; + + var stealth = EnsureComp(uid); // cant remove the armor + var stealthonmove = EnsureComp(uid); // cant remove the armor + + var message = Loc.GetString(!component.Active ? "changeling-chameleon-toggle-on" : "changeling-chameleon-toggle-off"); + _popup.PopupEntity(message, uid, uid); + + if (!component.Active) + { + stealthonmove.PassiveVisibilityRate = component.PassiveVisibilityRate; + stealthonmove.MovementVisibilityRate = component.MovementVisibilityRate; + stealth.MinVisibility = component.MinVisibility; + stealth.MaxVisibility = component.MaxVisibility; + } + else + { + RemCompDeferred(uid, stealth); + RemCompDeferred(uid, stealthonmove); + } + + component.Active = !component.Active; + + args.Handled = true; + } } diff --git a/Content.Server/ADT/ComponentalActions/EntitySystems/ComponentalActions.cs b/Content.Server/ADT/ComponentalActions/EntitySystems/ComponentalActions.cs index afea788fd4e..b99b8eb9523 100644 --- a/Content.Server/ADT/ComponentalActions/EntitySystems/ComponentalActions.cs +++ b/Content.Server/ADT/ComponentalActions/EntitySystems/ComponentalActions.cs @@ -72,6 +72,12 @@ public override void Initialize() SubscribeLocalEvent(OnJumpInit); SubscribeLocalEvent(OnJumpShutdown); + SubscribeLocalEvent(OnStasisHealInit); + SubscribeLocalEvent(OnStasisHealShutdown); + + SubscribeLocalEvent(OnStealthInit); + SubscribeLocalEvent(OnStealthShutdown); + InitializeCompAbilities(); } @@ -110,4 +116,25 @@ private void OnJumpShutdown(EntityUid uid, JumpActComponent component, Component _action.RemoveAction(uid, component.ActionEntity); } + private void OnStasisHealInit(EntityUid uid, StasisHealActComponent component, MapInitEvent args) + { + var movementSpeed = EnsureComp(uid); + component.BaseSprintSpeed = movementSpeed.BaseSprintSpeed; + component.BaseWalkSpeed = movementSpeed.BaseWalkSpeed; + _action.AddAction(uid, ref component.ActionEntity, component.Action); + } + private void OnStasisHealShutdown(EntityUid uid, StasisHealActComponent component, ComponentShutdown args) + { + _action.RemoveAction(uid, component.ActionEntity); + } + + private void OnStealthInit(EntityUid uid, InvisibilityActComponent component, MapInitEvent args) + { + _action.AddAction(uid, ref component.ActionEntity, component.Action); + } + private void OnStealthShutdown(EntityUid uid, InvisibilityActComponent component, ComponentShutdown args) + { + _action.RemoveAction(uid, component.ActionEntity); + } + } diff --git a/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs b/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs index cd7abd9d4e4..566c2f43cf8 100644 --- a/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs +++ b/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs @@ -437,4 +437,7 @@ public sealed partial class ChangelingComponent : Component [DataField] public bool EggsReady = false; + [DataField] + public bool LastResortUsed = false; + } diff --git a/Content.Shared/ADT/ComponentalActions/Components/InvisibilityActComponent.cs b/Content.Shared/ADT/ComponentalActions/Components/InvisibilityActComponent.cs new file mode 100644 index 00000000000..7a6a9da97d9 --- /dev/null +++ b/Content.Shared/ADT/ComponentalActions/Components/InvisibilityActComponent.cs @@ -0,0 +1,30 @@ +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; + +namespace Content.Shared.ComponentalActions.Components; + +[RegisterComponent] +[AutoGenerateComponentState(true)] +public sealed partial class InvisibilityActComponent : Component +{ + [DataField] + public bool Active = false; + + [DataField("passiveVisibilityRate")] + public float PassiveVisibilityRate = -0.10f; + + [DataField("movementVisibilityRate")] + public float MovementVisibilityRate = 0.10f; + + [DataField("minVisibility")] + public float MinVisibility = -1f; + + [DataField("maxVisibility")] + public float MaxVisibility = 1.5f; + + [DataField("stealthAction")] + public EntProtoId Action = "CompActionStealth"; + + [DataField, AutoNetworkedField] + public EntityUid? ActionEntity; +} diff --git a/Content.Shared/ADT/ComponentalActions/Components/StasisHealActComponent.cs b/Content.Shared/ADT/ComponentalActions/Components/StasisHealActComponent.cs new file mode 100644 index 00000000000..06f2fd45ae6 --- /dev/null +++ b/Content.Shared/ADT/ComponentalActions/Components/StasisHealActComponent.cs @@ -0,0 +1,40 @@ +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; + +namespace Content.Shared.ComponentalActions.Components; + +[RegisterComponent] +[AutoGenerateComponentState(true)] +public sealed partial class StasisHealActComponent : Component +{ + [DataField] + public bool Active = false; + + [DataField] + public float SpeedModifier = 1f; + + [DataField] + public float BaseSprintSpeed = 3f; + + [DataField] + public float BaseWalkSpeed = 3f; + + [DataField] + public float RegenerateBurnHealAmount = -0.05f; + + [DataField] + public float RegenerateBruteHealAmount = -0.1f; + + [DataField] + public float RegenerateBloodVolumeHealAmount = 0.25f; + + [DataField] + public float RegenerateBleedReduceAmount = -0.01f; + + [DataField("healAction")] + public EntProtoId Action = "CompActionStasisHeal"; + + [DataField, AutoNetworkedField] + public EntityUid? ActionEntity; + +} diff --git a/Content.Shared/ADT/ComponentalActions/SharedComponentalActions.cs b/Content.Shared/ADT/ComponentalActions/SharedComponentalActions.cs index f8482a4e397..d88dc86744a 100644 --- a/Content.Shared/ADT/ComponentalActions/SharedComponentalActions.cs +++ b/Content.Shared/ADT/ComponentalActions/SharedComponentalActions.cs @@ -20,3 +20,11 @@ public sealed partial class CompJumpActionEvent : WorldTargetActionEvent public sealed partial class CompHealActionEvent : InstantActionEvent { } + +public sealed partial class CompStasisHealActionEvent : InstantActionEvent +{ +} + +public sealed partial class CompInvisibilityActionEvent : InstantActionEvent +{ +} diff --git a/Content.Shared/Stealth/Components/StealthComponent.cs b/Content.Shared/Stealth/Components/StealthComponent.cs index 1a8a647768a..74f210d75de 100644 --- a/Content.Shared/Stealth/Components/StealthComponent.cs +++ b/Content.Shared/Stealth/Components/StealthComponent.cs @@ -10,7 +10,6 @@ namespace Content.Shared.Stealth.Components; /// Use other components (like StealthOnMove) to modify this component's visibility based on certain conditions. /// [RegisterComponent, NetworkedComponent] -[Access(typeof(SharedStealthSystem))] public sealed partial class StealthComponent : Component { /// diff --git a/Resources/Locale/ru-RU/ADT/componental-actions.ftl b/Resources/Locale/ru-RU/ADT/componental-actions.ftl index dd68c553834..8fa7ac4f0a6 100644 --- a/Resources/Locale/ru-RU/ADT/componental-actions.ftl +++ b/Resources/Locale/ru-RU/ADT/componental-actions.ftl @@ -10,6 +10,12 @@ action-heal-desc = Исцелите часть своих ран. action-jump = Прыжок action-jump-desc = Прыгните в указанную точку. +action-stasis-heal = Стазисная регенерация +action-stasis-heal-desc = Замедлитесь донельзя и начните регенерировать свои раны. + +action-stealth-heal = Невидимость +action-stealth-heal-desc = Исчезните из виду остальных. И себя в том числе. + teleport-act = Телепорт teleport-act-desc = Моментально перенеситесь в произвольную точку в радиусе вашего обзора. diff --git a/Resources/Prototypes/ADT/Actions/componental_actions.yml b/Resources/Prototypes/ADT/Actions/componental_actions.yml index aa33e597a18..5c2cfbb86c4 100644 --- a/Resources/Prototypes/ADT/Actions/componental_actions.yml +++ b/Resources/Prototypes/ADT/Actions/componental_actions.yml @@ -66,3 +66,33 @@ sprite: Clothing/Shoes/Boots/combatboots.rsi state: icon event: !type:CompJumpActionEvent + +- type: entity + id: CompActionStasisHeal + name: action-stasis-heal + description: action-stasis-heal-desc + noSpawn: true + components: + - type: InstantAction + icon: + sprite: Interface/Actions/actions_ling.rsi + state: fleshmend + itemIconStyle: BigAction + checkCanInteract: false + event: !type:CompStasisHealActionEvent + useDelay: 5 + +- type: entity + id: CompActionStealth + name: action-stealth + description: action-stealth-desc + noSpawn: true + components: + - type: InstantAction + icon: + sprite: Interface/Actions/actions_ling.rsi + state: chameleon + itemIconStyle: BigAction + checkCanInteract: false + event: !type:CompInvisibilityActionEvent + useDelay: 1 diff --git a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml index 753e2445150..7bcd7935117 100644 --- a/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml +++ b/Resources/Prototypes/ADT/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml @@ -7,3 +7,25 @@ sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi layers: - state: syringeproj + +- type: entity + id: ADTBulletLingGas + name: acid spit + parent: BaseBulletTrigger + noSpawn: true + components: + - type: Projectile + damage: + types: + Caustic: 5 + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/xeno_toxic.rsi + layers: + - state: xeno_toxic + - type: SmokeOnTrigger + duration: 15 + spreadAmount: 50 + solution: + reagents: + - ReagentId: TearGas + Quantity: 50 diff --git a/Resources/Prototypes/ADT/ling_unturnable.yml b/Resources/Prototypes/ADT/ling_unturnable.yml new file mode 100644 index 00000000000..39aefbab51c --- /dev/null +++ b/Resources/Prototypes/ADT/ling_unturnable.yml @@ -0,0 +1,78 @@ +- type: entity + id: LingUntActionStealth + name: action-stealth + description: action-stealth-desc + noSpawn: true + components: + - type: InstantAction + icon: + sprite: Interface/Actions/actions_ling.rsi + state: chameleon + itemIconStyle: BigAction + checkCanInteract: false + event: !type:CompInvisibilityActionEvent + useDelay: 30 + +- type: entity + id: LingUntActionStasisHeal + name: action-stasis-heal + description: action-stasis-heal-desc + noSpawn: true + components: + - type: InstantAction + icon: + sprite: Interface/Actions/actions_ling.rsi + state: fleshmend + itemIconStyle: BigAction + checkCanInteract: false + event: !type:CompStasisHealActionEvent + useDelay: 5 + +- type: entity + id: LingUntActionJump + name: action-jump + description: action-jump-desc + noSpawn: true + components: + - type: WorldTargetAction + useDelay: 75 + range: 16 # default examine-range. + # ^ should probably add better validation that the clicked location is on the users screen somewhere, + itemIconStyle: BigAction + checkCanAccess: false + repeat: true + icon: + sprite: Clothing/Shoes/Boots/combatboots.rsi + state: icon + event: !type:CompJumpActionEvent + +- type: entity + id: LingUntActionShoot + name: action-shoot + description: action-shoot-desc + noSpawn: true + components: + - type: WorldTargetAction + useDelay: 60 + range: 16 # default examine-range. + # ^ should probably add better validation that the clicked location is on the users screen somewhere, + itemIconStyle: BigAction + checkCanAccess: false + repeat: true + icon: + sprite: Objects/Weapons/Guns/Pistols/mk58.rsi + state: icon + event: !type:CompProjectileActionEvent + +- type: entity # Как будут спрайты доделаю. + name: Urist McWeb + parent: BaseMobArachnid + id: ADTMobLingUnt + components: + - type: InvisibilityAct + minVisibility: 0 + - type: JumpAct + jumpAction: LingUntActionJump + - type: ProjectileAct + projAction: LingUntActionShoot + prototype: ADTBulletLingGas From 367014f48204eb53e9b45789ea9009ef3a5fa5b8 Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Wed, 13 Mar 2024 05:45:26 +0400 Subject: [PATCH 02/13] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=BD=D0=BE=D1=80=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D1=83=D1=8E=20?= =?UTF-8?q?=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D1=83=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20LingEggsHolderComponent,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D1=87=D0=B5=D1=80=D0=B2=D1=8F-=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=BE=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8F=20(=D0=BD=D0=B5=20=D0=B7=D0=B0=D0=B1?= =?UTF-8?q?=D0=B5=D1=80=D1=91=D1=82=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=20=D0=BD=D0=B0=D0=B4=20=D0=BD=D0=BE=D0=B2=D1=8B?= =?UTF-8?q?=D0=BC=20=D0=B3=D0=B5=D0=BD=D0=BE=D0=BA=D1=80=D0=B0=D0=B4=D0=BE?= =?UTF-8?q?=D0=BC),=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=D0=BE=D1=80=D0=B8=D1=82=D0=B5=D1=82=20=D0=B0=D0=BA?= =?UTF-8?q?=D1=88=D0=BE=D0=BD=D0=B0=D0=BC=20=D0=B3=D0=B5=D0=BD=D0=BE=D0=BA?= =?UTF-8?q?=D1=80=D0=B0=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EntitySystems/ChangelingEggSystem.cs | 42 +++++++ .../ChangelingSlugSystem.Abilities.cs | 6 +- .../EntitySystems/ChangelingSlugSystem.cs | 16 ++- .../ChangelingSystem.Abilities.cs | 7 +- .../EntitySystems/ChangelingSystem.cs | 14 +-- Content.Server/Medical/DefibrillatorSystem.cs | 9 +- .../Components/ChangelingComponent.cs | 9 -- .../Changeling/Components/LingEggsHolder.cs | 11 ++ .../Components/LingSlugComponent.cs | 5 + .../ru-RU/game-ticking/preset-changeling.ftl | 1 + .../medical/components/defibrillator.ftl | 3 +- .../prototypes/entities/mobs/npcs/animals.ftl | 4 + Resources/Prototypes/ADT/Actions/language.yml | 1 + .../Prototypes/ADT/changeling/changeling.yml | 40 ++++++- Resources/Prototypes/ADT/changeling/mobs.yml | 110 ++++++++++++++++++ Resources/Prototypes/Actions/types.yml | 2 + 16 files changed, 241 insertions(+), 39 deletions(-) create mode 100644 Content.Server/ADT/Changeling/EntitySystems/ChangelingEggSystem.cs diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingEggSystem.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingEggSystem.cs new file mode 100644 index 00000000000..43a57e738d7 --- /dev/null +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingEggSystem.cs @@ -0,0 +1,42 @@ +using Content.Shared.Changeling.Components; +using Content.Server.Actions; +using Content.Shared.Damage; +using Content.Shared.Damage.Prototypes; +using Content.Shared.Popups; +using Robust.Shared.Prototypes; + +namespace Content.Server.Changeling.EntitySystems; + +public sealed partial class ChangelingEggSystem : EntitySystem +{ + [Dependency] private readonly ActionsSystem _action = default!; + [Dependency] private readonly MetaDataSystem _metaData = default!; + [Dependency] private readonly EntityManager _entityManager = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnShutdown); + + } + public ProtoId BruteDamageGroup = "Brute"; + private void OnInit(EntityUid uid, LingEggsHolderComponent component, MapInitEvent args) + { + var damage_burn = new DamageSpecifier(_proto.Index(BruteDamageGroup), component.DamageAmount); + _damageableSystem.TryChangeDamage(uid, damage_burn); /// To be sure that target is dead + var newLing = EnsureComp(uid); + newLing.EggedBody = true; /// To make egged person into a ling + var selfMessage = Loc.GetString("changeling-eggs-inform"); + _popup.PopupEntity(selfMessage, uid, uid, PopupType.LargeCaution); /// Popup + _action.AddAction(uid, ref component.ChangelingHatchActionEntity, component.ChangelingHatchAction); + } + private void OnShutdown(EntityUid uid, LingEggsHolderComponent component, ComponentShutdown args) + { + _action.RemoveAction(uid, component.ChangelingHatchActionEntity); + } +} diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSlugSystem.Abilities.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSlugSystem.Abilities.cs index f41fe80bd53..d276f80566c 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSlugSystem.Abilities.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSlugSystem.Abilities.cs @@ -27,7 +27,7 @@ private void InitializeLingAbilities() SubscribeLocalEvent(OnLayEggsDoAfter); } - private void OnLayEggs(EntityUid uid, LingSlugComponent component, LingEggActionEvent args) + private void OnLayEggs(EntityUid uid, LingSlugComponent component, LingEggActionEvent args) /// TODO: Заменить на кладку яиц при ударе. { if (args.Handled) return; @@ -89,7 +89,7 @@ private void OnLayEggsDoAfter(EntityUid uid, LingSlugComponent component, LingEg else { - EnsureComp(target); + var holderComp = EnsureComp(target); var selfMessage = Loc.GetString("changeling-eggs-self-success", ("target", Identity.Entity(target, EntityManager))); _popup.PopupEntity(selfMessage, uid, uid, PopupType.MediumCaution); @@ -97,6 +97,8 @@ private void OnLayEggsDoAfter(EntityUid uid, LingSlugComponent component, LingEg component.EggsLaid = true; component.EggLing = target; + holderComp.ChangelingHatchAction = component.HatchAction; + _action.RemoveAction(uid, component.LayEggsActionEntity); /// Яйца откладываются только один раз return; diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSlugSystem.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSlugSystem.cs index 7ac4b9a2cb4..30364905650 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSlugSystem.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSlugSystem.cs @@ -66,17 +66,21 @@ public override void Update(float frameTime) var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var ling)) { - if (ling.EggsLaid) + if (ling.EggsLaid) /// TODO: Зачем я вообще сделал это через Update? { if (ling.EggLing != null) { var oldUid = uid; - var newLing = EnsureComp(ling.EggLing.Value); - newLing.EggedBody = true; - _action.AddAction(ling.EggLing.Value, ref newLing.ChangelingHatchActionEntity, newLing.ChangelingHatchAction); - if (_mindSystem.TryGetMind(uid, out var mindId, out var mind)) - _mindSystem.TransferTo(mindId, ling.EggLing.Value, mind: mind); + if (ling.Spread == false) + { + if (_mindSystem.TryGetMind(uid, out var mindId, out var mind)) + _mindSystem.TransferTo(mindId, ling.EggLing.Value, mind: mind); + } + else + { + continue; + } if (!_entityManager.TryGetComponent(oldUid, out var bloodstream)) return; diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs index 0f51133c1ef..333d2f9750b 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs @@ -967,9 +967,6 @@ private void OnLastResort(EntityUid uid, ChangelingComponent component, LastReso if (!TryUseAbility(uid, component, component.ChemicalsCostFree)) return; - if (component.LastResortUsed) - return; - if (SpawnLingSlug(uid, component)) { var damage_brute = new DamageSpecifier(_proto.Index(BruteDamageGroup), component.GibDamage); @@ -979,7 +976,7 @@ private void OnLastResort(EntityUid uid, ChangelingComponent component, LastReso } } - private void OnHatch(EntityUid uid, ChangelingComponent component, LingHatchActionEvent args) + private void OnHatch(EntityUid uid, ChangelingComponent component, LingHatchActionEvent args) /// TODO: Сделать из акшона автоматическую систему! { if (args.Handled) return; @@ -1006,8 +1003,6 @@ private void OnHatch(EntityUid uid, ChangelingComponent component, LingHatchActi else { - _action.RemoveAction(uid, component.ChangelingHatchActionEntity); - if (SpawnLingMonkey(uid, component)) { args.Handled = true; diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs index 0794ed0a677..4751ab804ad 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs @@ -335,7 +335,6 @@ public void OnTransform(EntityUid uid, ChangelingComponent component, Changeling newLingComponent.ChameleonSkinActive = component.ChameleonSkinActive; newLingComponent.LingArmorActive = component.LingArmorActive; newLingComponent.CanRefresh = component.CanRefresh; - newLingComponent.LastResortUsed = component.LastResortUsed; RemComp(uid, component); if (TryComp(uid, out StoreComponent? storeComp)) @@ -616,7 +615,6 @@ public bool LesserForm(EntityUid uid, ChangelingComponent component) newLingComponent.LingArmorActive = component.LingArmorActive; newLingComponent.CanRefresh = component.CanRefresh; newLingComponent.LesserFormActive = !component.LesserFormActive; - newLingComponent.LastResortUsed = component.LastResortUsed; RemComp(uid, component); if (TryComp(uid, out StoreComponent? storeComp)) @@ -675,7 +673,6 @@ public bool LesserForm(EntityUid uid, ChangelingComponent component) newLingComponent.LingArmorActive = component.LingArmorActive; newLingComponent.CanRefresh = component.CanRefresh; newLingComponent.LesserFormActive = !component.LesserFormActive; - newLingComponent.LastResortUsed = component.LastResortUsed; RemComp(uid, component); if (TryComp(uid, out StoreComponent? storeComp)) @@ -724,11 +721,9 @@ public bool SpawnLingSlug(EntityUid uid, ChangelingComponent component) public bool SpawnLingMonkey(EntityUid uid, ChangelingComponent component) { - _action.RemoveAction(uid, component.ChangelingHatchActionEntity); - var slug = Spawn(LingMonkeyId, Transform(uid).Coordinates); - RemComp(slug); + RemComp(uid); var newLingComponent = EnsureComp(slug); newLingComponent.Chemicals = component.Chemicals; @@ -740,16 +735,11 @@ public bool SpawnLingMonkey(EntityUid uid, ChangelingComponent component) newLingComponent.LingArmorActive = component.LingArmorActive; newLingComponent.CanRefresh = component.CanRefresh; newLingComponent.LesserFormActive = !component.LesserFormActive; - newLingComponent.LastResortUsed = true; - _action.AddAction(uid, ref component.ChangelingLesserFormActionEntity, component.ChangelingLesserFormAction); RemComp(uid, component); - _actionContainer.TransferAllActionsWithNewAttached(uid, slug, slug); - - _action.AddAction(slug, ref newLingComponent.ChangelingLastResortActionEntity, newLingComponent.ChangelingLastResortAction); - _action.RemoveAction(slug, newLingComponent.ChangelingLastResortActionEntity); + _action.AddAction(slug, ref component.ChangelingLesserFormActionEntity, component.ChangelingLesserFormAction); newLingComponent.StoredDNA = new List(); /// Создание нового ДНК списка diff --git a/Content.Server/Medical/DefibrillatorSystem.cs b/Content.Server/Medical/DefibrillatorSystem.cs index b4b96f33167..73d6074547e 100644 --- a/Content.Server/Medical/DefibrillatorSystem.cs +++ b/Content.Server/Medical/DefibrillatorSystem.cs @@ -24,6 +24,7 @@ using Robust.Shared.Player; using Robust.Shared.Timing; using Content.Shared.Atmos.Miasma; +using Content.Shared.Changeling.Components; namespace Content.Server.Medical; @@ -224,8 +225,12 @@ public void Zap(EntityUid uid, EntityUid target, EntityUid user, DefibrillatorCo _chatManager.TrySendInGameICMessage(uid, Loc.GetString("defibrillator-embalmed"), InGameICChatType.Speak, true); } - else - if (_rotting.IsRotten(target)) + else if (HasComp(target)) + { + _chatManager.TrySendInGameICMessage(uid, Loc.GetString("defibrillator-changeling"), + InGameICChatType.Speak, true); + } + else if (_rotting.IsRotten(target)) { _chatManager.TrySendInGameICMessage(uid, Loc.GetString("defibrillator-rotten"), InGameICChatType.Speak, true); diff --git a/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs b/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs index 566c2f43cf8..20b1491fc4a 100644 --- a/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs +++ b/Content.Shared/ADT/Changeling/Components/ChangelingComponent.cs @@ -136,12 +136,6 @@ public sealed partial class ChangelingComponent : Component [DataField, AutoNetworkedField] public EntityUid? ChangelingLastResortActionEntity; - [DataField] - public EntProtoId ChangelingHatchAction = "ActionLingHatch"; - - [DataField, AutoNetworkedField] - public EntityUid? ChangelingHatchActionEntity; - ///[DataField] ///public EntProtoId ChangelingArmBladeAction = "ActionArmBlade"; @@ -437,7 +431,4 @@ public sealed partial class ChangelingComponent : Component [DataField] public bool EggsReady = false; - [DataField] - public bool LastResortUsed = false; - } diff --git a/Content.Shared/ADT/Changeling/Components/LingEggsHolder.cs b/Content.Shared/ADT/Changeling/Components/LingEggsHolder.cs index 5876d5b2648..6e81fd4825f 100644 --- a/Content.Shared/ADT/Changeling/Components/LingEggsHolder.cs +++ b/Content.Shared/ADT/Changeling/Components/LingEggsHolder.cs @@ -1,6 +1,17 @@ +using Robust.Shared.Prototypes; + namespace Content.Shared.Changeling.Components; [RegisterComponent] +[AutoGenerateComponentState(true)] public sealed partial class LingEggsHolderComponent : Component { + [DataField] + public EntProtoId ChangelingHatchAction = "ActionLingHatch"; + + [DataField, AutoNetworkedField] + public EntityUid? ChangelingHatchActionEntity; + + [DataField] + public float DamageAmount = 500f; /// Damage gain to die } diff --git a/Content.Shared/ADT/Changeling/Components/LingSlugComponent.cs b/Content.Shared/ADT/Changeling/Components/LingSlugComponent.cs index 0c1d15d47da..500b6bcca0c 100644 --- a/Content.Shared/ADT/Changeling/Components/LingSlugComponent.cs +++ b/Content.Shared/ADT/Changeling/Components/LingSlugComponent.cs @@ -32,4 +32,9 @@ public sealed partial class LingSlugComponent : Component [DataField] public float LayedDamage = 70; + [DataField("spread")] + public bool Spread = false; + + [DataField("eggsAction")] + public EntProtoId HatchAction = "ActionLingHatch"; } diff --git a/Resources/Locale/ru-RU/game-ticking/preset-changeling.ftl b/Resources/Locale/ru-RU/game-ticking/preset-changeling.ftl index 8fa0ddb1bbe..ca832106a88 100644 --- a/Resources/Locale/ru-RU/game-ticking/preset-changeling.ftl +++ b/Resources/Locale/ru-RU/game-ticking/preset-changeling.ftl @@ -74,3 +74,4 @@ changeling-eggs-self-success = Вы успешно оставили кладку changeling-eggs-interrupted = Кладка была прервана! changeling-egg-others = Личинки в теле {THE($user)} начинают активно шевелиться и разрастаться! changeling-egg-self = Личинки прорастают, готовясь вырваться наружу. +changeling-eggs-inform = Теперь вы генокрад. Вылупляйтесь. diff --git a/Resources/Locale/ru-RU/medical/components/defibrillator.ftl b/Resources/Locale/ru-RU/medical/components/defibrillator.ftl index 99af7fae3de..fed5068f19f 100644 --- a/Resources/Locale/ru-RU/medical/components/defibrillator.ftl +++ b/Resources/Locale/ru-RU/medical/components/defibrillator.ftl @@ -2,4 +2,5 @@ defibrillator-not-on = Дефибриллятор не включён. defibrillator-no-mind = Не удалось обнаружить паттерны мозговой активности пациента. Дальнейшие попытки бесполезны... defibrillator-ghosted = Реанимация не удалась - Ошибка ментального интерфейса. Дальнейшие попытки могут увенчаться успехом. defibrillator-rotten = Обнаружено разложение тела: реанимация невозможна. -defibrillator-embalmed = Обнаружено бальзамирование тела: реанимация невозможна. \ No newline at end of file +defibrillator-embalmed = Обнаружено бальзамирование тела: реанимация невозможна. +defibrillator-changeling = Неизвестная форма жизни обнаружена в теле. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/animals.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/animals.ftl index d68182f63fa..f328deb7cc6 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/animals.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/animals.ftl @@ -109,6 +109,10 @@ ent-MobMonkeyChangeling = обезьяна .desc = Новая церковь неодарвинистов действительно верит, что КАЖДОЕ животное произошло от обезьяны. На вкус они как свинина, а убивать их весело и приятно. ent-ChangelingHeadslug = червь генокрада .desc = Отвратительное нечто, оставшееся от генокрада. Почему вы просто стоите и смотрите?! Убейте это, пока не поздно! + .suffix = Генокрад +ent-ChangelingHeadslugSpread = червь генокрада + .desc = Отвратительное нечто, оставшееся от генокрада. Почему вы просто стоите и смотрите?! Убейте это, пока не поздно! + .suffix = Распространитель ent-MobKobold = кобольд .desc = Двоюродные братья унатхов, сливающиеся со своей средой обитания и являющиеся такими же противными, как макаки. Они готовы вырвать ваши волосы и заколоть вас до смерти. ent-MobMonkeySyndicateAgentNukeops = обезьяна diff --git a/Resources/Prototypes/ADT/Actions/language.yml b/Resources/Prototypes/ADT/Actions/language.yml index 9c92009386f..222a73c9ba0 100644 --- a/Resources/Prototypes/ADT/Actions/language.yml +++ b/Resources/Prototypes/ADT/Actions/language.yml @@ -9,3 +9,4 @@ icon: _NF/Interface/Actions/language.png event: !type:LanguageMenuActionEvent useDelay: 2 + priority: -97 diff --git a/Resources/Prototypes/ADT/changeling/changeling.yml b/Resources/Prototypes/ADT/changeling/changeling.yml index 19e5eead34e..a0dc1d335dc 100644 --- a/Resources/Prototypes/ADT/changeling/changeling.yml +++ b/Resources/Prototypes/ADT/changeling/changeling.yml @@ -7,6 +7,7 @@ - type: InstantAction icon: Interface/Actions/shop.png event: !type:ChangelingEvolutionMenuActionEvent + priority: -70 - type: entity id: ActionChangelingAbsorb @@ -25,6 +26,7 @@ event: !type:LingAbsorbActionEvent useDelay: 5 canTargetSelf: false + priority: -60 - type: entity id: ActionChangelingCycleDNA @@ -39,6 +41,7 @@ itemIconStyle: BigAction event: !type:ChangelingCycleDNAActionEvent useDelay: 1 + priority: -69 - type: entity id: ActionChangelingTransform @@ -53,6 +56,7 @@ itemIconStyle: BigAction event: !type:ChangelingTransformActionEvent useDelay: 5 + priority: -68 - type: entity id: ActionLingRegenerate @@ -68,6 +72,7 @@ itemIconStyle: BigAction event: !type:LingRegenerateActionEvent useDelay: 115 + priority: -66 - type: entity id: ActionLingStingExtract @@ -86,6 +91,7 @@ event: !type:LingStingExtractActionEvent useDelay: 30 canTargetSelf: false + priority: -65 - type: entity id: ActionArmBlade @@ -100,6 +106,7 @@ itemIconStyle: BigAction event: !type:ArmBladeActionEvent useDelay: 1 + priority: -50 - type: entity id: ActionLingArmor @@ -114,6 +121,7 @@ itemIconStyle: BigAction event: !type:LingArmorActionEvent useDelay: 15 + priority: -49 - type: entity id: ActionLingInvisible @@ -128,6 +136,7 @@ itemIconStyle: BigAction event: !type:LingInvisibleActionEvent useDelay: 1 + priority: -48 - type: entity id: ActionLingEMP @@ -142,7 +151,7 @@ itemIconStyle: BigAction useDelay: 15 event: !type:LingEMPActionEvent - + priority: -47 # Stasis Death - type: entity id: ActionStasisDeath @@ -158,6 +167,7 @@ itemIconStyle: BigAction event: !type:StasisDeathActionEvent useDelay: 90 + priority: -46 # Blind sting - type: entity @@ -177,6 +187,7 @@ event: !type:BlindStingEvent useDelay: 2 canTargetSelf: false + priority: -64 # Adrenaline - type: entity @@ -192,6 +203,7 @@ itemIconStyle: BigAction event: !type:AdrenalineActionEvent useDelay: 90 + priority: -45 # Refresh - type: entity @@ -207,6 +219,7 @@ itemIconStyle: BigAction event: !type:ChangelingRefreshActionEvent useDelay: 5 + priority: -66 # Fleshmend - type: entity @@ -222,6 +235,7 @@ itemIconStyle: BigAction event: !type:OmniHealActionEvent useDelay: 90 + priority: -44 # Mute sting - type: entity @@ -241,6 +255,7 @@ event: !type:MuteStingEvent useDelay: 5 canTargetSelf: false + priority: -63 # Drug sting - type: entity @@ -260,6 +275,7 @@ event: !type:DrugStingEvent useDelay: 5 canTargetSelf: false + priority: -62 # Muscles - type: entity @@ -275,6 +291,7 @@ itemIconStyle: BigAction event: !type:ChangelingMusclesActionEvent useDelay: 1 + priority: -43 # Lesser form - type: entity @@ -291,6 +308,7 @@ checkCanInteract: false event: !type:ChangelingLesserFormActionEvent useDelay: 10 + priority: -67 # Arm shield - type: entity @@ -306,6 +324,7 @@ itemIconStyle: BigAction event: !type:ArmShieldActionEvent useDelay: 1 + priority: -51 # Last Resort - type: entity @@ -322,6 +341,7 @@ checkCanInteract: false event: !type:LastResortActionEvent useDelay: 1 + priority: -61 # Lay eggs - type: entity @@ -357,3 +377,21 @@ checkCanInteract: false event: !type:LingHatchActionEvent useDelay: 180 + priority: -99 + + # Fast Hatch +- type: entity + id: ActionLingHatchFast + name: action-hatch + description: action-hatch-desc + noSpawn: true + components: + - type: InstantAction + icon: + sprite: Interface/Actions/actions_ling.rsi + state: last_resort + itemIconStyle: BigAction + checkCanInteract: false + event: !type:LingHatchActionEvent + useDelay: 60 + priority: -99 diff --git a/Resources/Prototypes/ADT/changeling/mobs.yml b/Resources/Prototypes/ADT/changeling/mobs.yml index 107fa6dba6d..dc27877d674 100644 --- a/Resources/Prototypes/ADT/changeling/mobs.yml +++ b/Resources/Prototypes/ADT/changeling/mobs.yml @@ -126,6 +126,116 @@ Piercing: 10 - type: LingSlug +- type: entity + name: changeling slug + parent: SimpleMobBase + id: ChangelingHeadslugSpread + suffix: Spreader + description: e + components: + - type: Body + prototype: Mouse + - type: Speech + speechSounds: Squeak + speechVerb: SmallMob + - type: Sprite + drawdepth: SmallMobs + sprite: ADT/Mobs/Aliens/headslug.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: headslug + - type: Item + size: Tiny + - type: NpcFactionMember + factions: + - Mouse + - type: HTN + rootTask: + task: MouseCompound + - type: Physics + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 0.2 + density: 100 + mask: + - SmallMobMask + layer: + - SmallMobLayer + - type: MobState + - type: Deathgasp + - type: MobStateActions + actions: + Critical: + - ActionCritSuccumb + - ActionCritFakeDeath + - ActionCritLastWords + - type: MobThresholds + thresholds: + 0: Alive + 69: Critical + 70: Dead + - type: MovementSpeedModifier + baseWalkSpeed : 5 + baseSprintSpeed : 5 + - type: DamageStateVisuals + states: + Alive: + Base: headslug + Critical: + Base: headslug_dead + Dead: + Base: headslug_dead + - type: Food + - type: Tag + tags: + - ShoesRequiredStepTriggerImmune + - type: Respirator + damage: + types: + Asphyxiation: 0.25 + damageRecovery: + types: + Asphyxiation: -0.25 + - type: Barotrauma + damage: + types: + Blunt: 0.1 + - type: Vocal + sounds: + Male: Mouse + Female: Mouse + Unsexed: Mouse + wilhelmProbability: 0.001 + # TODO: Remove CombatMode when Prototype Composition is added + - type: CombatMode + - type: Bloodstream + bloodMaxVolume: 50 + - type: CanEscapeInventory + - type: MobPrice + price: 5000 + - type: BadFood + - type: NonSpreaderZombie + - type: PreventSpiller + - type: LanguageSpeaker # Frontier + speaks: + - Mouse + understands: + - Mouse + - type: MeleeWeapon + soundHit: + path: /Audio/Weapons/pierce.ogg + angle: 30 + animation: WeaponArcPunch + damage: + types: + Piercing: 10 + - type: LingSlug + spread: true + eggsAction: ActionLingHatchFast + - type: reagent id: LingToxin name: reagent-name-toxin diff --git a/Resources/Prototypes/Actions/types.yml b/Resources/Prototypes/Actions/types.yml index ee97d0c9a95..d4206983c14 100644 --- a/Resources/Prototypes/Actions/types.yml +++ b/Resources/Prototypes/Actions/types.yml @@ -9,6 +9,7 @@ event: !type:OpenEmotesActionEvent #event: !type:ScreamActionEvent checkCanInteract: false + priority: -98 - type: entity id: ActionScream @@ -21,6 +22,7 @@ icon: Interface/Actions/scream.png event: !type:ScreamActionEvent checkCanInteract: false + priority: -99 - type: entity id: OwOVoice From a472dda62a6bfbc348eee475116eeed184b6264a Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Wed, 13 Mar 2024 18:38:59 +0400 Subject: [PATCH 03/13] =?UTF-8?q?=D0=9F=D1=80=D0=B8=20=D1=83=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B8=20LingEggsHolder=20=D1=83=D0=B1?= =?UTF-8?q?=D0=B8=D1=80=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82=20=D0=B8=20=D0=B4=D0=B5?= =?UTF-8?q?=D0=B9=D1=81=D1=82=D0=B2=D0=B8=D1=8F=20=D0=B3=D0=B5=D0=BD=D0=BE?= =?UTF-8?q?=D0=BA=D1=80=D0=B0=D0=B4=D0=B0,=20=D0=BB=D0=B8=D1=87=D0=B8?= =?UTF-8?q?=D0=BD=D0=BA=D0=B0=20=D0=B3=D0=B5=D0=BD=D0=BE=D0=BA=D1=80=D0=B0?= =?UTF-8?q?=D0=B4=D0=B0=20=D0=BA=D0=B0=D0=BA=20=D1=80=D0=B5=D1=86=D0=B5?= =?UTF-8?q?=D0=BF=D1=82.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EntitySystems/ChangelingEggSystem.cs | 3 +- .../ChangelingSystem.Abilities.cs | 6 ++ .../EntitySystems/ChangelingSystem.cs | 17 +++-- .../Chemistry/ReagentEffects/LingEggs.cs | 19 +++++ .../Locale/ru-RU/reagents/meta/toxins.ftl | 3 + .../objects/consumable/food/meals.ftl | 3 + Resources/Prototypes/ADT/changeling/mobs.yml | 69 ++++++++++++++++++ .../gen\320\276_larva_white.rsi/icon.png" | Bin 0 -> 575 bytes .../inhand-left.png" | Bin 0 -> 262 bytes .../inhand-right.png" | Bin 0 -> 266 bytes .../gen\320\276_larva_white.rsi/meta.json" | 21 ++++++ 11 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 Content.Server/Chemistry/ReagentEffects/LingEggs.cs create mode 100644 "Resources/Textures/ADT/Objects/Specific/gen\320\276_larva_white.rsi/icon.png" create mode 100644 "Resources/Textures/ADT/Objects/Specific/gen\320\276_larva_white.rsi/inhand-left.png" create mode 100644 "Resources/Textures/ADT/Objects/Specific/gen\320\276_larva_white.rsi/inhand-right.png" create mode 100644 "Resources/Textures/ADT/Objects/Specific/gen\320\276_larva_white.rsi/meta.json" diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingEggSystem.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingEggSystem.cs index 43a57e738d7..b4fcd7a761b 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingEggSystem.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingEggSystem.cs @@ -29,7 +29,7 @@ private void OnInit(EntityUid uid, LingEggsHolderComponent component, MapInitEve { var damage_burn = new DamageSpecifier(_proto.Index(BruteDamageGroup), component.DamageAmount); _damageableSystem.TryChangeDamage(uid, damage_burn); /// To be sure that target is dead - var newLing = EnsureComp(uid); + var newLing = EnsureComp(uid); newLing.EggedBody = true; /// To make egged person into a ling var selfMessage = Loc.GetString("changeling-eggs-inform"); _popup.PopupEntity(selfMessage, uid, uid, PopupType.LargeCaution); /// Popup @@ -37,6 +37,7 @@ private void OnInit(EntityUid uid, LingEggsHolderComponent component, MapInitEve } private void OnShutdown(EntityUid uid, LingEggsHolderComponent component, ComponentShutdown args) { + RemComp(uid); _action.RemoveAction(uid, component.ChangelingHatchActionEntity); } } diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs index 333d2f9750b..95b8b67065b 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.Abilities.cs @@ -1003,8 +1003,14 @@ private void OnHatch(EntityUid uid, ChangelingComponent component, LingHatchActi else { + RemComp(uid); + if (SpawnLingMonkey(uid, component)) { + + var damage_brute = new DamageSpecifier(_proto.Index(BruteDamageGroup), component.GibDamage); + _damageableSystem.TryChangeDamage(uid, damage_brute); + args.Handled = true; } } diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs index 4751ab804ad..1a7b3864859 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs @@ -65,6 +65,7 @@ public override void Initialize() SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnShop); SubscribeLocalEvent(OnCycleDNA); @@ -149,6 +150,17 @@ private void OnMapInit(EntityUid uid, ChangelingComponent component, MapInitEven _action.AddAction(uid, ref component.ChangelingTransformActionEntity, component.ChangelingTransformAction); _action.AddAction(uid, ref component.ChangelingRefreshActionEntity, component.ChangelingRefreshAction); } + + private void OnShutdown(EntityUid uid, ChangelingComponent component, ComponentShutdown args) + { + _action.RemoveAction(uid, component.ChangelingEvolutionMenuActionEntity); + _action.RemoveAction(uid, component.ChangelingRegenActionEntity); + _action.RemoveAction(uid, component.ChangelingAbsorbActionEntity); + _action.RemoveAction(uid, component.ChangelingDNAStingActionEntity); + _action.RemoveAction(uid, component.ChangelingDNACycleActionEntity); + _action.RemoveAction(uid, component.ChangelingTransformActionEntity); + _action.RemoveAction(uid, component.ChangelingRefreshActionEntity); + } private void OnShop(EntityUid uid, ChangelingComponent component, ChangelingEvolutionMenuActionEvent args) { _store.OnInternalShop(uid); @@ -723,8 +735,6 @@ public bool SpawnLingMonkey(EntityUid uid, ChangelingComponent component) { var slug = Spawn(LingMonkeyId, Transform(uid).Coordinates); - RemComp(uid); - var newLingComponent = EnsureComp(slug); newLingComponent.Chemicals = component.Chemicals; newLingComponent.ChemicalsPerSecond = component.ChemicalsPerSecond; @@ -755,9 +765,6 @@ public bool SpawnLingMonkey(EntityUid uid, ChangelingComponent component) if (_mindSystem.TryGetMind(uid, out var mindId, out var mind)) _mindSystem.TransferTo(mindId, slug, mind: mind); - var damage_brute = new DamageSpecifier(_proto.Index(BruteDamageGroup), component.GibDamage); - _damageableSystem.TryChangeDamage(uid, damage_brute); - return true; } } diff --git a/Content.Server/Chemistry/ReagentEffects/LingEggs.cs b/Content.Server/Chemistry/ReagentEffects/LingEggs.cs new file mode 100644 index 00000000000..66cabf71c7e --- /dev/null +++ b/Content.Server/Chemistry/ReagentEffects/LingEggs.cs @@ -0,0 +1,19 @@ +using Content.Shared.Chemistry.Reagent; +using Robust.Shared.Prototypes; +using Content.Shared.Atmos.Miasma; +using Content.Shared.Changeling.Components; + +namespace Content.Server.Chemistry.ReagentEffects; + +public sealed partial class LingEggs : ReagentEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-missing", ("chance", Probability)); + + // Gives the entity a component that turns it into a f#cking changeling + public override void Effect(ReagentEffectArgs args) + { + var entityManager = args.EntityManager; + entityManager.EnsureComponent(args.SolutionEntity); + } +} diff --git a/Resources/Locale/ru-RU/reagents/meta/toxins.ftl b/Resources/Locale/ru-RU/reagents/meta/toxins.ftl index e5c61a1d593..0ec582d4352 100644 --- a/Resources/Locale/ru-RU/reagents/meta/toxins.ftl +++ b/Resources/Locale/ru-RU/reagents/meta/toxins.ftl @@ -72,3 +72,6 @@ reagent-desc-vestine = Имеет побочную реакцию с дрожь reagent-name-tazinide = тазинид reagent-desc-tazinide = Опасная металлическая смесь, которая может помешать любому движению посредством электрического тока. + +reagent-name-ling = личинки генокрада +reagent-desc-ling = Не самое приятное зрелище. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/meals.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/meals.ftl index 47a4b3b2b71..c7e7994345c 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/meals.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/food/meals.ftl @@ -52,3 +52,6 @@ ent-FoodSaladWatermelonFruitBowl = фруктовый арбузный боул .desc = Единственный салат, в котором можно съесть миску. ent-FoodMealTaco = тако .desc = Попробуйте кусочек! + +ent-ADTLingLarva = личинка генокрада + .desc = Не надо... diff --git a/Resources/Prototypes/ADT/changeling/mobs.yml b/Resources/Prototypes/ADT/changeling/mobs.yml index dc27877d674..a6ef10f8156 100644 --- a/Resources/Prototypes/ADT/changeling/mobs.yml +++ b/Resources/Prototypes/ADT/changeling/mobs.yml @@ -256,3 +256,72 @@ damage: types: Poison: 2 + + +- type: reagent + id: ADTLingEggs # Немножко костылей, но кому не пофиг? + name: reagent-name-ling + group: Toxins + desc: reagent-desc-ling + flavor: bitter + physicalDesc: reagent-physical-desc-skunky + color: "#ffd478" + worksOnTheDead: true + metabolisms: + Medicine: + effects: + - !type:LingEggs + conditions: + - !type:ReagentThreshold + min: 1 + - !type:HealthChange + damage: + types: + Poison: 15 + +- type: entity + name: synthetic changeling larva + parent: FoodBreadSliceBase + id: ADTLingLarva + description: No... Don't do it... + components: + - type: Food + - type: Item + sprite: ADT/Objects/Specific/genо_larva_white.rsi + layers: + - state: icon + inhandVisuals: + left: + - state: inhand-left + right: + - state: inhand-right + - type: Sprite + sprite: ADT/Objects/Specific/genо_larva_white.rsi + layers: + - state: icon + - type: SolutionContainerManager + solutions: + food: + maxVol: 4 + reagents: + - ReagentId: ADTLingEggs + Quantity: 4 # Just using the same values as the bun values, since the recipe for taco shells is roughly the same as buns. + - type: Tag + tags: [] + - type: FlavorProfile + flavors: + - terrible + +- type: reaction + id: ADTLingLarva #без понятия, как там у тебя личинка называется + quantized: true + reactants: + ADTMPolymorphine: + amount: 15 + Nutriment: #ну, раз мы создаём что-то биологическое, то пусть будут ещё и биологические приколы. + amount: 3 + Stimulants: + amount: 5 + effects: + - !type:CreateEntityReactionEffect + entity: ADTLingLarva #сам подставишь id сущности. diff --git "a/Resources/Textures/ADT/Objects/Specific/gen\320\276_larva_white.rsi/icon.png" "b/Resources/Textures/ADT/Objects/Specific/gen\320\276_larva_white.rsi/icon.png" new file mode 100644 index 0000000000000000000000000000000000000000..a6b9b0428db2a0c58b88d461bba63ddbd1457cb6 GIT binary patch literal 575 zcmV-F0>J%=P)*3AHYoG*?B*L5Lg(<>2D5<+|mpkfR*e!NJvGZ??3_!9gv# zlE|O@tKs)}nw8~yvlnGv?Yx<9_ItnI`@Q$QAqp%|;J+(SjXsv6Ng{UMH<`D5r z##b!M4*`HTR#i~;=9VUA2k7Pc4q;qBB-E@0{Oa+UE}x#6|H9T1`{k)s(vm3Vor()& z&)(eUfR{%j9HFZ|LW%ZvR}qfX1W@zI`7y>o=AjOUtZ*xP4Y2%I-2)#IyW=B$B$-Pv z_@VwzIOBd$D}d;*(z+UYI6LS2-N9MH&t99MNN9Ik49ByFdpLVEpVwmX!S~1QeeZJKdt(BKAWes}FIGqcB8CwG zWRJ}A)mAzm@AppMkERg(&8vC<=Nuqj*}dRRb~EE?z6VAMAnN%}num-??j?cuXuQph z6mC^!OyK0;>~qQi0cv0pf|ylZ`3bJc9&wBbKwil2Bpsf1IBwp0Yk>g{GaAKm1m*l= zqbOiHa5&%p-#SHAD;e>GD0|ow+0WMkdGtRcKCNeWPc`cL zuVF?t1>IaDmVd9rww1ZcZRKg{v7IIFliRVTo;~Zw*~aS;0*%*StX7BXZ;WXapK{Lm V!QL)CA)v4ZLn;{G-rC4}$UuNKpj$U! zS|Z=H1kS2$3sPCr7CN4pp!8zaiLN_OH}rf7x~aME|K2HnnsQ7m90Cds4GfG3#%|WQ z?WZ?cFX5VD-+yI~)-IV>zQ?TE?C1Hbax1pg-=F_&k zf)&XCOe0x1{&XJLV1CTD>!{>f?H|{6zq`NLz0*SZpY#pB>&*4l&kTNxoiKPRq6l+| cgwF$RVR`2Vt6gK~0zJpz>FVdQ&MBb@0QDtXG5`Po literal 0 HcmV?d00001 diff --git "a/Resources/Textures/ADT/Objects/Specific/gen\320\276_larva_white.rsi/meta.json" "b/Resources/Textures/ADT/Objects/Specific/gen\320\276_larva_white.rsi/meta.json" new file mode 100644 index 00000000000..6ea76d899a7 --- /dev/null +++ "b/Resources/Textures/ADT/Objects/Specific/gen\320\276_larva_white.rsi/meta.json" @@ -0,0 +1,21 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Made by .bolbyyy for ADT Server", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left" + }, + { + "name": "inhand-right" + } + + ] +} From 5742026228e051d11b77d9698996499f646fb8f5 Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Wed, 13 Mar 2024 18:47:57 +0400 Subject: [PATCH 04/13] yml --- Resources/Prototypes/ADT/changeling/mobs.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Resources/Prototypes/ADT/changeling/mobs.yml b/Resources/Prototypes/ADT/changeling/mobs.yml index a6ef10f8156..6cb91460a02 100644 --- a/Resources/Prototypes/ADT/changeling/mobs.yml +++ b/Resources/Prototypes/ADT/changeling/mobs.yml @@ -288,8 +288,6 @@ - type: Food - type: Item sprite: ADT/Objects/Specific/genо_larva_white.rsi - layers: - - state: icon inhandVisuals: left: - state: inhand-left From b8ff2ec6964c5b1cd00cf7dda8ac29c2050ef49f Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Wed, 13 Mar 2024 18:57:37 +0400 Subject: [PATCH 05/13] =?UTF-8?q?=D0=B1=D1=83=D1=82=D1=81=D1=8B=20=D0=B2?= =?UTF-8?q?=20=D1=8F=D1=89=D0=B8=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Resources/Prototypes/Catalog/Fills/Crates/salvage.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Resources/Prototypes/Catalog/Fills/Crates/salvage.yml b/Resources/Prototypes/Catalog/Fills/Crates/salvage.yml index da82c5c8d8a..08688ffc77e 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/salvage.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/salvage.yml @@ -21,6 +21,8 @@ - id: ClothingBeltUtility - id: OreBag - id: ClothingBeltSalvageWebbing + - id: ADTClothingJumpBoots + prob: 0.1 - type: entity id: CrateSalvageAssortedGoodies From 9621a88a5b589cb7c6d4b6ebfd60d9019fb7954e Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Wed, 13 Mar 2024 20:51:27 +0400 Subject: [PATCH 06/13] =?UTF-8?q?=D0=9C=D0=B8=D0=B4=D1=80=D0=B0=D1=83?= =?UTF-8?q?=D0=BD=D0=B4=20=D0=B3=D0=B5=D0=BD=D0=BE=D0=BA=D1=80=D0=B0=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ghost/roles/ghost-role-component.ftl | 4 ++ .../prototypes/entities/mobs/npcs/animals.ftl | 4 ++ Resources/Prototypes/ADT/changeling/mobs.yml | 58 +++++++++++++++++-- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl b/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl index 8109e6f94b5..aa08694c41b 100644 --- a/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/ru-RU/ghost/roles/ghost-role-component.ftl @@ -136,3 +136,7 @@ ghost-role-information-flesh-description = Утолить голод... ghost-role-information-argocyte-name = Аргоцит ghost-role-information-argocyte-description = Защитите своё будущее гнездо от вторжения. + +ghost-role-information-ling-name = Генокрад +ghost-role-information-ling-description = Ты - генокрад в форме червя. Найди себе оболочку и выживи. +ghost-role-information-ling-rules = Вы не крупный антагонист! В ваши цели входит только выживание, и оно ДОЛЖНО быть превыше всего. Тем не менее, помощь остальным генокрадам не запрещается. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/animals.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/animals.ftl index f328deb7cc6..0228f4eef7c 100644 --- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/animals.ftl +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/mobs/npcs/animals.ftl @@ -113,6 +113,10 @@ ent-ChangelingHeadslug = червь генокрада ent-ChangelingHeadslugSpread = червь генокрада .desc = Отвратительное нечто, оставшееся от генокрада. Почему вы просто стоите и смотрите?! Убейте это, пока не поздно! .suffix = Распространитель +ent-ChangelingHeadslugMidround = червь генокрада + .desc = Отвратительное нечто, оставшееся от генокрада. Почему вы просто стоите и смотрите?! Убейте это, пока не поздно! + .suffix = Гостроль +ling-round-end-agent-name = червь генокрада ent-MobKobold = кобольд .desc = Двоюродные братья унатхов, сливающиеся со своей средой обитания и являющиеся такими же противными, как макаки. Они готовы вырвать ваши волосы и заколоть вас до смерти. ent-MobMonkeySyndicateAgentNukeops = обезьяна diff --git a/Resources/Prototypes/ADT/changeling/mobs.yml b/Resources/Prototypes/ADT/changeling/mobs.yml index 6cb91460a02..66eeb306946 100644 --- a/Resources/Prototypes/ADT/changeling/mobs.yml +++ b/Resources/Prototypes/ADT/changeling/mobs.yml @@ -113,9 +113,9 @@ - type: PreventSpiller - type: LanguageSpeaker # Frontier speaks: - - Mouse + - Xeno understands: - - Mouse + - Xeno - type: MeleeWeapon soundHit: path: /Audio/Weapons/pierce.ogg @@ -221,9 +221,9 @@ - type: PreventSpiller - type: LanguageSpeaker # Frontier speaks: - - Mouse + - Xeno understands: - - Mouse + - Xeno - type: MeleeWeapon soundHit: path: /Audio/Weapons/pierce.ogg @@ -323,3 +323,53 @@ effects: - !type:CreateEntityReactionEffect entity: ADTLingLarva #сам подставишь id сущности. + +- type: entity + parent: ChangelingHeadslug + id: ChangelingHeadslugMidround + suffix: Ghost role + components: + - type: GenericAntag + rule: LingMidround + +- type: entity + parent: BaseGameRule + id: MidroundChangelingSpawn + noSpawn: true + components: + - type: StationEvent + weight: 10 + duration: 1 + earliestStart: 30 + minimumPlayers: 40 + - type: RandomSpawnRule + prototype: SpawnPointGhostLing + +- type: entity + noSpawn: true + parent: BaseGameRule + id: LingMidround + components: + - type: GenericAntagRule + agentName: ling-round-end-agent-name + objectives: + - EscapeLingShuttleObjective + +- type: entity + parent: MarkerBase + id: SpawnPointGhostLing + name: changeling spawn point + components: + - type: GhostRole + name: ghost-role-information-ling-name + description: ghost-role-information-ling-description + rules: ghost-role-information-ling-rules + - type: GhostRoleMobSpawner + prototype: ChangelingHeadslugMidround + - type: Sprite + layers: + - state: green + sprite: ADT/Mobs/Aliens/headslug.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: headslug From c5ac1a5d8cb6da59fd2211609ea0109fa6d659e8 Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Wed, 13 Mar 2024 20:56:22 +0400 Subject: [PATCH 07/13] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Resources/Prototypes/ADT/changeling/mobs.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Resources/Prototypes/ADT/changeling/mobs.yml b/Resources/Prototypes/ADT/changeling/mobs.yml index 66eeb306946..00a0a14e0e9 100644 --- a/Resources/Prototypes/ADT/changeling/mobs.yml +++ b/Resources/Prototypes/ADT/changeling/mobs.yml @@ -367,9 +367,7 @@ - type: GhostRoleMobSpawner prototype: ChangelingHeadslugMidround - type: Sprite + sprite: ADT/Mobs/Aliens/headslug.rsi layers: - - state: green - sprite: ADT/Mobs/Aliens/headslug.rsi - layers: - - map: ["enum.DamageStateVisualLayers.Base"] - state: headslug + - map: ["enum.DamageStateVisualLayers.Base"] + state: headslug From eaf04986bb5c19a6e18e090ddb4465cf84bb0c7c Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Thu, 14 Mar 2024 04:59:42 +0400 Subject: [PATCH 08/13] =?UTF-8?q?=D0=9D=D0=B5=D0=B4=D0=BE=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=D0=BD=D0=B0=D1=8F=20(=D0=B8=D0=B7-=D0=B7?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B0=D1=81=D1=80=D0=B0=D0=BD=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B8=20=D0=BE=D1=82=20=D0=BE=D1=84=D0=B8=D1=86=D0=B8?= =?UTF-8?q?=D0=B0=D0=BB=D0=BE=D0=B2)=20=D1=81=D0=B8=D1=81=D1=82=D0=B5?= =?UTF-8?q?=D0=BC=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D1=81=D0=BB=D0=B0=D0=B9?= =?UTF-8?q?=D0=BC=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SlimeHair/SlimeHairBoundUserInterface.cs | 81 +++++ .../ADT/SlimeHair/SlimeHairWindow.xaml | 9 + .../ADT/SlimeHair/SlimeHairWindow.xaml.cs | 49 +++ .../EntitySystems/ChangelingSystem.cs | 5 + .../ADT/SlimeHair/SlimeHairComponent.cs | 58 +++ .../SlimeHair/SlimeHairSystem.Abilities.cs | 41 +++ .../ADT/SlimeHair/SlimeHairSystem.cs | 330 ++++++++++++++++++ .../ADT/SlimeHair/SharedSlimeHairSystem.cs | 148 ++++++++ Resources/Prototypes/ADT/Actions/slime.yml | 14 + .../Entities/Mobs/Species/slime.yml | 7 + 10 files changed, 742 insertions(+) create mode 100644 Content.Client/ADT/SlimeHair/SlimeHairBoundUserInterface.cs create mode 100644 Content.Client/ADT/SlimeHair/SlimeHairWindow.xaml create mode 100644 Content.Client/ADT/SlimeHair/SlimeHairWindow.xaml.cs create mode 100644 Content.Server/ADT/SlimeHair/SlimeHairComponent.cs create mode 100644 Content.Server/ADT/SlimeHair/SlimeHairSystem.Abilities.cs create mode 100644 Content.Server/ADT/SlimeHair/SlimeHairSystem.cs create mode 100644 Content.Shared/ADT/SlimeHair/SharedSlimeHairSystem.cs create mode 100644 Resources/Prototypes/ADT/Actions/slime.yml diff --git a/Content.Client/ADT/SlimeHair/SlimeHairBoundUserInterface.cs b/Content.Client/ADT/SlimeHair/SlimeHairBoundUserInterface.cs new file mode 100644 index 00000000000..72f4d47a27e --- /dev/null +++ b/Content.Client/ADT/SlimeHair/SlimeHairBoundUserInterface.cs @@ -0,0 +1,81 @@ +using Content.Shared.Humanoid.Markings; +using Content.Shared.SlimeHair; +using Robust.Client.GameObjects; + +namespace Content.Client.ADT.SlimeHair; + +public sealed class SlimeHairBoundUserInterface : BoundUserInterface +{ + [ViewVariables] + private SlimeHairWindow? _window; + + public SlimeHairBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _window = new(); + + _window.OnHairSelected += tuple => SelectHair(SlimeHairCategory.Hair, tuple.id, tuple.slot); + _window.OnHairColorChanged += args => ChangeColor(SlimeHairCategory.Hair, args.marking, args.slot); + _window.OnHairSlotAdded += delegate () { AddSlot(SlimeHairCategory.Hair); }; + _window.OnHairSlotRemoved += args => RemoveSlot(SlimeHairCategory.Hair, args); + + _window.OnFacialHairSelected += tuple => SelectHair(SlimeHairCategory.FacialHair, tuple.id, tuple.slot); + _window.OnFacialHairColorChanged += + args => ChangeColor(SlimeHairCategory.FacialHair, args.marking, args.slot); + _window.OnFacialHairSlotAdded += delegate () { AddSlot(SlimeHairCategory.FacialHair); }; + _window.OnFacialHairSlotRemoved += args => RemoveSlot(SlimeHairCategory.FacialHair, args); + + _window.OnClose += Close; + _window.OpenCentered(); + } + + private void SelectHair(SlimeHairCategory category, string marking, int slot) + { + SendMessage(new SlimeHairSelectMessage(category, marking, slot)); + } + + private void ChangeColor(SlimeHairCategory category, Marking marking, int slot) + { + SendMessage(new SlimeHairChangeColorMessage(category, new(marking.MarkingColors), slot)); + } + + private void RemoveSlot(SlimeHairCategory category, int slot) + { + SendMessage(new SlimeHairRemoveSlotMessage(category, slot)); + } + + private void AddSlot(SlimeHairCategory category) + { + SendMessage(new SlimeHairAddSlotMessage(category)); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + + if (state is not SlimeHairUiState data || _window == null) + { + return; + } + + _window.UpdateState(data); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + if (_window != null) + _window.OnClose -= Close; + + _window?.Dispose(); + } +} + diff --git a/Content.Client/ADT/SlimeHair/SlimeHairWindow.xaml b/Content.Client/ADT/SlimeHair/SlimeHairWindow.xaml new file mode 100644 index 00000000000..580d4509365 --- /dev/null +++ b/Content.Client/ADT/SlimeHair/SlimeHairWindow.xaml @@ -0,0 +1,9 @@ + + + + + + diff --git a/Content.Client/ADT/SlimeHair/SlimeHairWindow.xaml.cs b/Content.Client/ADT/SlimeHair/SlimeHairWindow.xaml.cs new file mode 100644 index 00000000000..0df4321f7a5 --- /dev/null +++ b/Content.Client/ADT/SlimeHair/SlimeHairWindow.xaml.cs @@ -0,0 +1,49 @@ +using Content.Shared.Humanoid.Markings; +using Content.Shared.SlimeHair; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.ADT.SlimeHair; + +[GenerateTypedNameReferences] +public sealed partial class SlimeHairWindow : DefaultWindow +{ + // MMMMMMM + public Action<(int slot, string id)>? OnHairSelected; + public Action<(int slot, Marking marking)>? OnHairColorChanged; + public Action? OnHairSlotRemoved; + public Action? OnHairSlotAdded; + + public Action<(int slot, string id)>? OnFacialHairSelected; + public Action<(int slot, Marking marking)>? OnFacialHairColorChanged; + public Action? OnFacialHairSlotRemoved; + public Action? OnFacialHairSlotAdded; + + public SlimeHairWindow() + { + RobustXamlLoader.Load(this); + + HairPicker.OnMarkingSelect += args => OnHairSelected!(args); + HairPicker.OnColorChanged += args => OnHairColorChanged!(args); + HairPicker.OnSlotRemove += args => OnHairSlotRemoved!(args); + HairPicker.OnSlotAdd += delegate { OnHairSlotAdded!(); }; + + FacialHairPicker.OnMarkingSelect += args => OnFacialHairSelected!(args); + FacialHairPicker.OnColorChanged += args => OnFacialHairColorChanged!(args); + FacialHairPicker.OnSlotRemove += args => OnFacialHairSlotRemoved!(args); + FacialHairPicker.OnSlotAdd += delegate { OnFacialHairSlotAdded!(); }; + } + + public void UpdateState(SlimeHairUiState state) + { + HairPicker.UpdateData(state.Hair, state.Species, state.HairSlotTotal); + FacialHairPicker.UpdateData(state.FacialHair, state.Species, state.FacialHairSlotTotal); + + if (!HairPicker.Visible && !FacialHairPicker.Visible) + { + AddChild(new Label { Text = Loc.GetString("magic-mirror-component-activate-user-has-no-hair") }); + } + } +} diff --git a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs index 1a7b3864859..35fecb58ac2 100644 --- a/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs +++ b/Content.Server/ADT/Changeling/EntitySystems/ChangelingSystem.cs @@ -34,6 +34,8 @@ using Content.Shared.Mind; using Content.Shared.Sirena.NightVision.Components; using Content.Shared.CombatMode; +using Content.Server.UserInterface; +using Content.Server.SlimeHair; namespace Content.Server.Changeling.EntitySystems; @@ -76,6 +78,9 @@ public override void Initialize() private void OnStartup(EntityUid uid, ChangelingComponent component, ComponentStartup args) { + //RemComp(uid); // TODO: Исправить проблему с волосами слаймов + //RemComp(uid); + //RemComp(uid); _uplink.AddUplink(uid, FixedPoint2.New(10), ChangelingShopPresetPrototype, uid, EvolutionPointsCurrencyPrototype); // not really an 'uplink', but it's there to add the evolution menu StealDNA(uid, component); diff --git a/Content.Server/ADT/SlimeHair/SlimeHairComponent.cs b/Content.Server/ADT/SlimeHair/SlimeHairComponent.cs new file mode 100644 index 00000000000..be22dd50022 --- /dev/null +++ b/Content.Server/ADT/SlimeHair/SlimeHairComponent.cs @@ -0,0 +1,58 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Prototypes; +using Robust.Shared.Audio; + +namespace Content.Server.SlimeHair; + +/// +/// Allows humanoids to change their appearance mid-round. +/// +[RegisterComponent] +public sealed partial class SlimeHairComponent : Component +{ + [DataField] + public DoAfterId? DoAfter; + + /// + /// Magic mirror target, used for validating UI messages. + /// + [DataField] + public EntityUid? Target; + + /// + /// doafter time required to add a new slot + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan AddSlotTime = TimeSpan.FromSeconds(5); + + /// + /// doafter time required to remove a existing slot + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan RemoveSlotTime = TimeSpan.FromSeconds(2); + + /// + /// doafter time required to change slot + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan SelectSlotTime = TimeSpan.FromSeconds(3); + + /// + /// doafter time required to recolor slot + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan ChangeSlotTime = TimeSpan.FromSeconds(1); + + /// + /// Sound emitted when slots are changed + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public SoundSpecifier ChangeHairSound = new SoundPathSpecifier("/Audio/Items/scissors.ogg"); + + [DataField("hairAction")] + public EntProtoId Action = "ActionSlimeHair"; + + [DataField, AutoNetworkedField] + public EntityUid? ActionEntity; + +} diff --git a/Content.Server/ADT/SlimeHair/SlimeHairSystem.Abilities.cs b/Content.Server/ADT/SlimeHair/SlimeHairSystem.Abilities.cs new file mode 100644 index 00000000000..4125c1a1c25 --- /dev/null +++ b/Content.Server/ADT/SlimeHair/SlimeHairSystem.Abilities.cs @@ -0,0 +1,41 @@ +using System.Linq; +using Content.Server.DoAfter; +using Content.Server.Humanoid; +using Content.Shared.UserInterface; +using Content.Shared.DoAfter; +using Content.Shared.Humanoid; +using Content.Shared.Humanoid.Markings; +using Content.Shared.Interaction; +using Content.Shared.SlimeHair; +using Robust.Server.GameObjects; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Player; +using Content.Server.Actions; + +namespace Content.Server.SlimeHair; + +/// +/// Allows humanoids to change their appearance mid-round. +/// +public sealed partial class SlimeHairSystem +{ + private void InitializeSlimeAbilities() + { + SubscribeLocalEvent(SlimeHairAction); + } + + private void SlimeHairAction(EntityUid uid, SlimeHairComponent comp, SlimeHairActionEvent args) + { + if (args.Handled) + return; + + if (!TryComp(uid, out var actor)) + return; + + _uiSystem.TryOpen(uid, SlimeHairUiKey.Key, actor.PlayerSession); + + UpdateInterface(uid, comp); + + args.Handled = true; + } +} diff --git a/Content.Server/ADT/SlimeHair/SlimeHairSystem.cs b/Content.Server/ADT/SlimeHair/SlimeHairSystem.cs new file mode 100644 index 00000000000..c5a9d4dc615 --- /dev/null +++ b/Content.Server/ADT/SlimeHair/SlimeHairSystem.cs @@ -0,0 +1,330 @@ +using System.Linq; +using Content.Server.DoAfter; +using Content.Server.Humanoid; +using Content.Shared.UserInterface; +using Content.Shared.DoAfter; +using Content.Shared.Humanoid; +using Content.Shared.Humanoid.Markings; +using Content.Shared.Interaction; +using Content.Shared.SlimeHair; +using Robust.Server.GameObjects; +using Robust.Shared.Audio.Systems; +using Content.Server.UserInterface; +using Content.Server.SlimeHair; +using Content.Server.Actions; + +namespace Content.Server.SlimeHair; + +/// +/// Allows humanoids to change their appearance mid-round. +/// + +// TODO: Исправить проблему с генокрадом +public sealed partial class SlimeHairSystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly DoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly MarkingManager _markings = default!; + [Dependency] private readonly HumanoidAppearanceSystem _humanoid = default!; + [Dependency] private readonly SharedInteractionSystem _interaction = default!; + [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; + [Dependency] private readonly ActionsSystem _action = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnOpenUIAttempt); + + Subs.BuiEvents(SlimeHairUiKey.Key, subs => + { + subs.Event(OnUIClosed); + subs.Event(OnSlimeHairSelect); + subs.Event(OnTrySlimeHairChangeColor); + subs.Event(OnTrySlimeHairAddSlot); + subs.Event(OnTrySlimeHairRemoveSlot); + }); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnShutdown); + + SubscribeLocalEvent(OnSelectSlotDoAfter); + SubscribeLocalEvent(OnChangeColorDoAfter); + SubscribeLocalEvent(OnRemoveSlotDoAfter); + SubscribeLocalEvent(OnAddSlotDoAfter); + + InitializeSlimeAbilities(); + + } + + private void OnOpenUIAttempt(EntityUid uid, SlimeHairComponent mirror, ActivatableUIOpenAttemptEvent args) + { + if (!HasComp(uid)) + args.Cancel(); + } + + private void OnSlimeHairSelect(EntityUid uid, SlimeHairComponent component, SlimeHairSelectMessage message) + { + if (component.Target is not { } target || message.Session.AttachedEntity is not { } user) + return; + + _doAfterSystem.Cancel(component.DoAfter); + component.DoAfter = null; + + var doAfter = new SlimeHairSelectDoAfterEvent() + { + Category = message.Category, + Slot = message.Slot, + Marking = message.Marking, + }; + + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, user, component.SelectSlotTime, doAfter, uid, target: target, used: uid) + { + DistanceThreshold = SharedInteractionSystem.InteractionRange, + BreakOnTargetMove = false, + BreakOnDamage = true, + BreakOnHandChange = false, + BreakOnUserMove = false, + BreakOnWeightlessMove = false, + NeedHand = false + }, out var doAfterId); + + component.DoAfter = doAfterId; + _audio.PlayPvs(component.ChangeHairSound, uid); + } + + private void OnSelectSlotDoAfter(EntityUid uid, SlimeHairComponent component, SlimeHairSelectDoAfterEvent args) + { + if (args.Handled || args.Target == null || args.Cancelled) + return; + + if (component.Target != args.Target) + return; + + MarkingCategories category; + + switch (args.Category) + { + case SlimeHairCategory.Hair: + category = MarkingCategories.Hair; + break; + case SlimeHairCategory.FacialHair: + category = MarkingCategories.FacialHair; + break; + default: + return; + } + + _humanoid.SetMarkingId(uid, category, args.Slot, args.Marking); + + UpdateInterface(uid, component); + } + + private void OnTrySlimeHairChangeColor(EntityUid uid, SlimeHairComponent component, SlimeHairChangeColorMessage message) + { + if (component.Target is not { } target || message.Session.AttachedEntity is not { } user) + return; + + _doAfterSystem.Cancel(component.DoAfter); + component.DoAfter = null; + + var doAfter = new SlimeHairChangeColorDoAfterEvent() + { + Category = message.Category, + Slot = message.Slot, + Colors = message.Colors, + }; + + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, user, component.ChangeSlotTime, doAfter, uid, target: target, used: uid) + { + BreakOnTargetMove = false, + BreakOnDamage = true, + BreakOnHandChange = false, + BreakOnUserMove = false, + BreakOnWeightlessMove = false, + NeedHand = false + }, out var doAfterId); + + component.DoAfter = doAfterId; + } + private void OnChangeColorDoAfter(EntityUid uid, SlimeHairComponent component, SlimeHairChangeColorDoAfterEvent args) + { + if (args.Handled || args.Target == null || args.Cancelled) + return; + + if (component.Target != args.Target) + return; + + MarkingCategories category; + switch (args.Category) + { + case SlimeHairCategory.Hair: + category = MarkingCategories.Hair; + break; + case SlimeHairCategory.FacialHair: + category = MarkingCategories.FacialHair; + break; + default: + return; + } + + _humanoid.SetMarkingColor(uid, category, args.Slot, args.Colors); + + // using this makes the UI feel like total ass + // que + // UpdateInterface(uid, component.Target, message.Session); + } + + private void OnTrySlimeHairRemoveSlot(EntityUid uid, SlimeHairComponent component, SlimeHairRemoveSlotMessage message) + { + if (component.Target is not { } target || message.Session.AttachedEntity is not { } user) + return; + + _doAfterSystem.Cancel(component.DoAfter); + component.DoAfter = null; + + var doAfter = new SlimeHairRemoveSlotDoAfterEvent() + { + Category = message.Category, + Slot = message.Slot, + }; + + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, user, component.RemoveSlotTime, doAfter, uid, target: target, used: uid) + { + DistanceThreshold = SharedInteractionSystem.InteractionRange, + BreakOnTargetMove = false, + BreakOnDamage = true, + BreakOnHandChange = false, + BreakOnUserMove = false, + BreakOnWeightlessMove = false, + NeedHand = false + }, out var doAfterId); + + component.DoAfter = doAfterId; + _audio.PlayPvs(component.ChangeHairSound, uid); + } + + private void OnRemoveSlotDoAfter(EntityUid uid, SlimeHairComponent component, SlimeHairRemoveSlotDoAfterEvent args) + { + if (args.Handled || args.Target == null || args.Cancelled) + return; + + if (component.Target != args.Target) + return; + + MarkingCategories category; + + switch (args.Category) + { + case SlimeHairCategory.Hair: + category = MarkingCategories.Hair; + break; + case SlimeHairCategory.FacialHair: + category = MarkingCategories.FacialHair; + break; + default: + return; + } + + _humanoid.RemoveMarking(component.Target.Value, category, args.Slot); + + UpdateInterface(uid, component); + } + + private void OnTrySlimeHairAddSlot(EntityUid uid, SlimeHairComponent component, SlimeHairAddSlotMessage message) + { + if (component.Target == null) + return; + + if (message.Session.AttachedEntity == null) + return; + + _doAfterSystem.Cancel(component.DoAfter); + component.DoAfter = null; + + var doAfter = new SlimeHairAddSlotDoAfterEvent() + { + Category = message.Category, + }; + + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, message.Session.AttachedEntity.Value, component.AddSlotTime, doAfter, uid, target: component.Target.Value, used: uid) + { + BreakOnTargetMove = false, + BreakOnDamage = true, + BreakOnHandChange = false, + BreakOnUserMove = false, + BreakOnWeightlessMove = false, + NeedHand = false + }, out var doAfterId); + + component.DoAfter = doAfterId; + _audio.PlayPvs(component.ChangeHairSound, uid); + } + private void OnAddSlotDoAfter(EntityUid uid, SlimeHairComponent component, SlimeHairAddSlotDoAfterEvent args) + { + if (args.Handled || args.Target == null || args.Cancelled || !TryComp(component.Target, out HumanoidAppearanceComponent? humanoid)) + return; + + MarkingCategories category; + + switch (args.Category) + { + case SlimeHairCategory.Hair: + category = MarkingCategories.Hair; + break; + case SlimeHairCategory.FacialHair: + category = MarkingCategories.FacialHair; + break; + default: + return; + } + + var marking = _markings.MarkingsByCategoryAndSpecies(category, humanoid.Species).Keys.FirstOrDefault(); + + if (string.IsNullOrEmpty(marking)) + return; + + _humanoid.AddMarking(uid, marking, Color.Black); + + UpdateInterface(uid, component); + + } + + private void UpdateInterface(EntityUid uid, SlimeHairComponent component) + { + if (!TryComp(uid, out var humanoid)) + return; + + var hair = humanoid.MarkingSet.TryGetCategory(MarkingCategories.Hair, out var hairMarkings) + ? new List(hairMarkings) + : new(); + + var facialHair = humanoid.MarkingSet.TryGetCategory(MarkingCategories.FacialHair, out var facialHairMarkings) + ? new List(facialHairMarkings) + : new(); + + var state = new SlimeHairUiState( + humanoid.Species, + hair, + humanoid.MarkingSet.PointsLeft(MarkingCategories.Hair) + hair.Count, + facialHair, + humanoid.MarkingSet.PointsLeft(MarkingCategories.FacialHair) + facialHair.Count); + + component.Target = uid; + _uiSystem.TrySetUiState(uid, SlimeHairUiKey.Key, state); + } + + private void OnUIClosed(Entity ent, ref BoundUIClosedEvent args) + { + ent.Comp.Target = null; + } + + private void OnMapInit(EntityUid uid, SlimeHairComponent component, MapInitEvent args) + { + _action.AddAction(uid, ref component.ActionEntity, component.Action); + } + private void OnShutdown(EntityUid uid, SlimeHairComponent component, ComponentShutdown args) + { + _action.RemoveAction(uid, component.ActionEntity); + } + +} diff --git a/Content.Shared/ADT/SlimeHair/SharedSlimeHairSystem.cs b/Content.Shared/ADT/SlimeHair/SharedSlimeHairSystem.cs new file mode 100644 index 00000000000..88a41820a88 --- /dev/null +++ b/Content.Shared/ADT/SlimeHair/SharedSlimeHairSystem.cs @@ -0,0 +1,148 @@ +using Content.Shared.DoAfter; +using Content.Shared.Humanoid.Markings; +using Robust.Shared.Player; +using Robust.Shared.Serialization; +using Content.Shared.Actions; + +namespace Content.Shared.SlimeHair; + +[Serializable, NetSerializable] +public enum SlimeHairUiKey : byte +{ + Key +} + +[Serializable, NetSerializable] +public enum SlimeHairCategory : byte +{ + Hair, + FacialHair +} + +[Serializable, NetSerializable] +public sealed class SlimeHairSelectMessage : BoundUserInterfaceMessage +{ + public SlimeHairSelectMessage(SlimeHairCategory category, string marking, int slot) + { + Category = category; + Marking = marking; + Slot = slot; + } + + public SlimeHairCategory Category { get; } + public string Marking { get; } + public int Slot { get; } +} + +[Serializable, NetSerializable] +public sealed class SlimeHairChangeColorMessage : BoundUserInterfaceMessage +{ + public SlimeHairChangeColorMessage(SlimeHairCategory category, List colors, int slot) + { + Category = category; + Colors = colors; + Slot = slot; + } + + public SlimeHairCategory Category { get; } + public List Colors { get; } + public int Slot { get; } +} + +[Serializable, NetSerializable] +public sealed class SlimeHairRemoveSlotMessage : BoundUserInterfaceMessage +{ + public SlimeHairRemoveSlotMessage(SlimeHairCategory category, int slot) + { + Category = category; + Slot = slot; + } + + public SlimeHairCategory Category { get; } + public int Slot { get; } +} + +[Serializable, NetSerializable] +public sealed class SlimeHairSelectSlotMessage : BoundUserInterfaceMessage +{ + public SlimeHairSelectSlotMessage(SlimeHairCategory category, int slot) + { + Category = category; + Slot = slot; + } + + public SlimeHairCategory Category { get; } + public int Slot { get; } +} + +[Serializable, NetSerializable] +public sealed class SlimeHairAddSlotMessage : BoundUserInterfaceMessage +{ + public SlimeHairAddSlotMessage(SlimeHairCategory category) + { + Category = category; + } + + public SlimeHairCategory Category { get; } +} + +[Serializable, NetSerializable] +public sealed class SlimeHairUiState : BoundUserInterfaceState +{ + public SlimeHairUiState(string species, List hair, int hairSlotTotal, List facialHair, int facialHairSlotTotal) + { + Species = species; + Hair = hair; + HairSlotTotal = hairSlotTotal; + FacialHair = facialHair; + FacialHairSlotTotal = facialHairSlotTotal; + } + + public NetEntity Target; + + public string Species; + + public List Hair; + public int HairSlotTotal; + + public List FacialHair; + public int FacialHairSlotTotal; +} + +[Serializable, NetSerializable] +public sealed partial class SlimeHairRemoveSlotDoAfterEvent : DoAfterEvent +{ + public override DoAfterEvent Clone() => this; + public SlimeHairCategory Category; + public int Slot; +} + +[Serializable, NetSerializable] +public sealed partial class SlimeHairAddSlotDoAfterEvent : DoAfterEvent +{ + public override DoAfterEvent Clone() => this; + public SlimeHairCategory Category; +} + +[Serializable, NetSerializable] +public sealed partial class SlimeHairSelectDoAfterEvent : DoAfterEvent +{ + public SlimeHairCategory Category; + public int Slot; + public string Marking = string.Empty; + + public override DoAfterEvent Clone() => this; +} + +[Serializable, NetSerializable] +public sealed partial class SlimeHairChangeColorDoAfterEvent : DoAfterEvent +{ + public override DoAfterEvent Clone() => this; + public SlimeHairCategory Category; + public int Slot; + public List Colors = new List(); +} + +public sealed partial class SlimeHairActionEvent : InstantActionEvent +{ +} diff --git a/Resources/Prototypes/ADT/Actions/slime.yml b/Resources/Prototypes/ADT/Actions/slime.yml new file mode 100644 index 00000000000..01883b92c30 --- /dev/null +++ b/Resources/Prototypes/ADT/Actions/slime.yml @@ -0,0 +1,14 @@ +- type: entity + id: ActionSlimeHair + name: action-slime-hair + description: action-slime-hair-desc + noSpawn: true + components: + - type: InstantAction + icon: + sprite: Mobs/Aliens/slimes.rsi + state: rainbow_baby_slime + itemIconStyle: BigAction + checkCanInteract: false + event: !type:SlimeHairActionEvent + useDelay: 1 diff --git a/Resources/Prototypes/Entities/Mobs/Species/slime.yml b/Resources/Prototypes/Entities/Mobs/Species/slime.yml index 0c1b69d3b00..d9e551f6491 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/slime.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/slime.yml @@ -94,6 +94,13 @@ tallscale: 1 short: true shortscale: 0.85 + #- type: SlimeHair # TODO: Исправить проблему с генокрадом + #- type: ActivatableUI + # key: enum.SlimeHairUiKey.Key + #- type: UserInterface + # interfaces: + # - key: enum.SlimeHairUiKey.Key + # type: SlimeHairBoundUserInterface - type: entity From 127ceb052ed9794aba71e05cccac6a23144feb45 Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Thu, 14 Mar 2024 23:31:50 +0400 Subject: [PATCH 09/13] =?UTF-8?q?=D0=9E=D0=B1=D0=BE=D1=88=D1=91=D0=BB=20?= =?UTF-8?q?=D1=81=D1=80=D0=B0=D0=BD=D1=8C=20=D0=BE=D1=84=D0=B8=D1=86=D0=B8?= =?UTF-8?q?=D0=B0=D0=BB=D0=BE=D0=B2,=20=D0=B2=D1=81=D1=91=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ADT/SlimeHair/SlimeHairComponent.cs | 13 ++++++++----- Content.Server/ADT/SlimeHair/SlimeHairSystem.cs | 9 +++------ Resources/Audio/ADT/slime-hair.ogg | Bin 0 -> 18353 bytes Resources/Locale/ru-RU/ADT/slime-hair.ftl | 4 ++++ Resources/Prototypes/ADT/Actions/slime.yml | 5 ++--- .../Prototypes/Entities/Mobs/Species/slime.yml | 15 ++++++++------- .../ADT/Actions/slime-hair.rsi/hair.png | Bin 0 -> 712 bytes .../ADT/Actions/slime-hair.rsi/meta.json | 14 ++++++++++++++ 8 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 Resources/Audio/ADT/slime-hair.ogg create mode 100644 Resources/Locale/ru-RU/ADT/slime-hair.ftl create mode 100644 Resources/Textures/ADT/Actions/slime-hair.rsi/hair.png create mode 100644 Resources/Textures/ADT/Actions/slime-hair.rsi/meta.json diff --git a/Content.Server/ADT/SlimeHair/SlimeHairComponent.cs b/Content.Server/ADT/SlimeHair/SlimeHairComponent.cs index be22dd50022..0a66cc51e2b 100644 --- a/Content.Server/ADT/SlimeHair/SlimeHairComponent.cs +++ b/Content.Server/ADT/SlimeHair/SlimeHairComponent.cs @@ -23,7 +23,7 @@ public sealed partial class SlimeHairComponent : Component /// doafter time required to add a new slot /// [DataField, ViewVariables(VVAccess.ReadWrite)] - public TimeSpan AddSlotTime = TimeSpan.FromSeconds(5); + public TimeSpan AddSlotTime = TimeSpan.FromSeconds(2); /// /// doafter time required to remove a existing slot @@ -35,7 +35,7 @@ public sealed partial class SlimeHairComponent : Component /// doafter time required to change slot /// [DataField, ViewVariables(VVAccess.ReadWrite)] - public TimeSpan SelectSlotTime = TimeSpan.FromSeconds(3); + public TimeSpan SelectSlotTime = TimeSpan.FromSeconds(2); /// /// doafter time required to recolor slot @@ -46,10 +46,13 @@ public sealed partial class SlimeHairComponent : Component /// /// Sound emitted when slots are changed /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public SoundSpecifier ChangeHairSound = new SoundPathSpecifier("/Audio/Items/scissors.ogg"); + [DataField] + public SoundSpecifier ChangeHairSound = new SoundPathSpecifier("/Audio/ADT/slime-hair.ogg") // ;) + { + Params = AudioParams.Default.WithVolume(-1f), + }; - [DataField("hairAction")] +[DataField("hairAction")] public EntProtoId Action = "ActionSlimeHair"; [DataField, AutoNetworkedField] diff --git a/Content.Server/ADT/SlimeHair/SlimeHairSystem.cs b/Content.Server/ADT/SlimeHair/SlimeHairSystem.cs index c5a9d4dc615..b4e54b8f426 100644 --- a/Content.Server/ADT/SlimeHair/SlimeHairSystem.cs +++ b/Content.Server/ADT/SlimeHair/SlimeHairSystem.cs @@ -89,7 +89,6 @@ private void OnSlimeHairSelect(EntityUid uid, SlimeHairComponent component, Slim }, out var doAfterId); component.DoAfter = doAfterId; - _audio.PlayPvs(component.ChangeHairSound, uid); } private void OnSelectSlotDoAfter(EntityUid uid, SlimeHairComponent component, SlimeHairSelectDoAfterEvent args) @@ -115,7 +114,7 @@ private void OnSelectSlotDoAfter(EntityUid uid, SlimeHairComponent component, Sl } _humanoid.SetMarkingId(uid, category, args.Slot, args.Marking); - + _audio.PlayPvs(component.ChangeHairSound, uid); UpdateInterface(uid, component); } @@ -200,7 +199,6 @@ private void OnTrySlimeHairRemoveSlot(EntityUid uid, SlimeHairComponent componen }, out var doAfterId); component.DoAfter = doAfterId; - _audio.PlayPvs(component.ChangeHairSound, uid); } private void OnRemoveSlotDoAfter(EntityUid uid, SlimeHairComponent component, SlimeHairRemoveSlotDoAfterEvent args) @@ -226,7 +224,7 @@ private void OnRemoveSlotDoAfter(EntityUid uid, SlimeHairComponent component, Sl } _humanoid.RemoveMarking(component.Target.Value, category, args.Slot); - + _audio.PlayPvs(component.ChangeHairSound, uid); UpdateInterface(uid, component); } @@ -257,7 +255,6 @@ private void OnTrySlimeHairAddSlot(EntityUid uid, SlimeHairComponent component, }, out var doAfterId); component.DoAfter = doAfterId; - _audio.PlayPvs(component.ChangeHairSound, uid); } private void OnAddSlotDoAfter(EntityUid uid, SlimeHairComponent component, SlimeHairAddSlotDoAfterEvent args) { @@ -284,7 +281,7 @@ private void OnAddSlotDoAfter(EntityUid uid, SlimeHairComponent component, Slime return; _humanoid.AddMarking(uid, marking, Color.Black); - + _audio.PlayPvs(component.ChangeHairSound, uid); UpdateInterface(uid, component); } diff --git a/Resources/Audio/ADT/slime-hair.ogg b/Resources/Audio/ADT/slime-hair.ogg new file mode 100644 index 0000000000000000000000000000000000000000..b41cbf52bc39606e76b61ebebcc23232fc08c102 GIT binary patch literal 18353 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 Date: Thu, 14 Mar 2024 23:37:16 +0400 Subject: [PATCH 10/13] =?UTF-8?q?=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Resources/Prototypes/Entities/Mobs/Species/slime.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Mobs/Species/slime.yml b/Resources/Prototypes/Entities/Mobs/Species/slime.yml index 645f5686435..131c9227d9e 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/slime.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/slime.yml @@ -96,7 +96,6 @@ shortscale: 0.85 - type: SlimeHair # TODO: Исправить проблему с генокрадом. ## Done. Мейби стоит чуть подредактировать позже, но это потом, когда у меня сил побольше будет. - type: UserInterface - range: 0 interfaces: - key: enum.SlimeHairUiKey.Key type: SlimeHairBoundUserInterface From 1256b155f89f7b426cc9fb61f8d13f375b06dd20 Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Fri, 15 Mar 2024 00:19:44 +0400 Subject: [PATCH 11/13] =?UTF-8?q?=D0=A7=D0=B5=D0=BD=D0=B4=D0=B6=D0=BB?= =?UTF-8?q?=D0=BE=D0=9E=D0=9E=D0=9E=D0=BE=D0=BE=D0=9E=D0=9E=D0=9E=D0=9E?= =?UTF-8?q?=D0=9E=D0=93!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Resources/Changelog/ChangelogADT.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/ChangelogADT.yml b/Resources/Changelog/ChangelogADT.yml index c3f68df9167..b3c4c2e6075 100644 --- a/Resources/Changelog/ChangelogADT.yml +++ b/Resources/Changelog/ChangelogADT.yml @@ -1457,3 +1457,9 @@ Entries: - {message: "Респрайт руки-клинка на версию из tg station.", type: Tweak} id: 55706 #костыль отображения в Обновлениях time: '2024-03-12T12:00:00.0000000+00:00' + +- author: Котя + changes: + - {message: "Добавлена возможность слаймолюдам произвольно менять свою причёску.", type: Add} + id: 55706 #костыль отображения в Обновлениях + time: '2024-03-15T12:00:00.0000000+00:00' From a1f946afcc7adb13a83648973f263a8a50d7ddc3 Mon Sep 17 00:00:00 2001 From: FaDeOkno Date: Fri, 15 Mar 2024 01:52:39 +0400 Subject: [PATCH 12/13] =?UTF-8?q?=D0=A7=D0=B5=D1=80=D1=82=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B5=D0=B7=D0=BD=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=BE=D0=B1=D1=89?= =?UTF-8?q?=D0=B5=D0=B3=D0=B0=D0=BB=D0=B0=D0=BA=D1=82=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D0=BA=D0=BE=D0=B3=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Content.Server/ADT/Language/LanguageSystem.cs | 18 +++++++++++++++++- .../Language/Components/CommonLangUnknown.cs | 14 ++++++++++++++ Resources/Locale/ru-RU/traits/traits.ftl | 2 ++ Resources/Prototypes/Traits/disabilities.yml | 8 ++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 Content.Shared/ADT/Language/Components/CommonLangUnknown.cs diff --git a/Content.Server/ADT/Language/LanguageSystem.cs b/Content.Server/ADT/Language/LanguageSystem.cs index 1654f2ddfbf..e76ce23cd36 100644 --- a/Content.Server/ADT/Language/LanguageSystem.cs +++ b/Content.Server/ADT/Language/LanguageSystem.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Text; using Content.Shared.GameTicking; using Content.Shared.Language; @@ -23,6 +23,7 @@ public override void Initialize() SubscribeLocalEvent(OnInitLanguageSpeaker); SubscribeAllEvent(it => RandomRoundSeed = _random.Next()); + SubscribeLocalEvent(OnUnknow); InitializeWindows(); } @@ -35,6 +36,21 @@ private void OnInitLanguageSpeaker(EntityUid uid, LanguageSpeakerComponent compo } } + private void OnUnknow(EntityUid uid, UnknowLanguageComponent unknow, MapInitEvent args) + { + TryComp(uid, out var component); + + if (component != null) + { + component.SpokenLanguages.Remove(unknow.LanguageToForgot); + component.UnderstoodLanguages.Remove(unknow.LanguageToForgot); + component.CurrentLanguage = component.SpokenLanguages.FirstOrDefault(UniversalPrototype); + } + else + return; + + } + /// /// Obfuscate speech of the given entity, or using the given language. /// diff --git a/Content.Shared/ADT/Language/Components/CommonLangUnknown.cs b/Content.Shared/ADT/Language/Components/CommonLangUnknown.cs new file mode 100644 index 00000000000..bac1230704f --- /dev/null +++ b/Content.Shared/ADT/Language/Components/CommonLangUnknown.cs @@ -0,0 +1,14 @@ +using Content.Shared.Actions; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Shared.Language; + +[RegisterComponent] +public sealed partial class UnknowLanguageComponent : Component +{ + [DataField("language")] + public string LanguageToForgot = "GalacticCommon"; +} diff --git a/Resources/Locale/ru-RU/traits/traits.ftl b/Resources/Locale/ru-RU/traits/traits.ftl index 69f14b6b499..3e7cceedbde 100644 --- a/Resources/Locale/ru-RU/traits/traits.ftl +++ b/Resources/Locale/ru-RU/traits/traits.ftl @@ -24,3 +24,5 @@ trait-frontal-lisp-name = Фронтальная шепелявость trait-frontal-lisp-desc = Вы говорите с шепелявостью trait-socialanxiety-name = Заикание trait-socialanxiety-desc = Вы беспокоитесь, когда говорите и заикаетесь +trait-common-lang-unknown-name = Унесённый ветрами +trait-common-lang-unknown-desc = По тем или иным причинам, вы не знаете общегалактического языка. diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml index 53d481c37e8..9e2f7052ab0 100644 --- a/Resources/Prototypes/Traits/disabilities.yml +++ b/Resources/Prototypes/Traits/disabilities.yml @@ -60,3 +60,11 @@ description: trait-frontal-lisp-desc components: - type: FrontalLisp + +- type: trait + id: GalacticCommonUnknow + name: trait-common-lang-unknown-name + description: trait-common-lang-unknown-desc + components: + - type: UnknowLanguage + language: GalacticCommon From e7fa29faeabbcba4e4a89eec5c9711de2019c5c8 Mon Sep 17 00:00:00 2001 From: FaDeOkno <143940725+FaDeOkno@users.noreply.github.com> Date: Fri, 15 Mar 2024 01:55:35 +0400 Subject: [PATCH 13/13] =?UTF-8?q?=D0=A7=D0=B5=D0=BD=D0=B4=D0=B6=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=20=D0=B0=D0=BF=D0=B4=D0=B5=D0=B9=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Resources/Changelog/ChangelogADT.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Resources/Changelog/ChangelogADT.yml b/Resources/Changelog/ChangelogADT.yml index 47e1977acf6..fa162c6a729 100644 --- a/Resources/Changelog/ChangelogADT.yml +++ b/Resources/Changelog/ChangelogADT.yml @@ -1484,5 +1484,6 @@ Entries: - author: Котя changes: - {message: "Добавлена возможность слаймолюдам произвольно менять свою причёску.", type: Add} + - {message: "Добавлена черта незнания общегалактического. Не берите её на главах, прошу.", type: Add} id: 55708 #костыль отображения в Обновлениях - time: '2024-03-15T12:00:00.0000000+00:00' \ No newline at end of file + time: '2024-03-15T12:00:00.0000000+00:00'