diff --git a/Content.Server/Power/Components/ApcPowerReceiverBatteryComponent.cs b/Content.Server/Power/Components/ApcPowerReceiverBatteryComponent.cs new file mode 100644 index 0000000000..e2af146f26 --- /dev/null +++ b/Content.Server/Power/Components/ApcPowerReceiverBatteryComponent.cs @@ -0,0 +1,49 @@ +using Content.Server.Power.EntitySystems; +using Content.Shared.Power.EntitySystems; + +namespace Content.Server.Power.Components; + +/// +/// Attached to APC powered entities that possess a rechargeable internal battery. +/// If external power is interrupted, the entity will draw power from this battery instead. +/// Requires and to function. +/// +[RegisterComponent] +[Access([typeof(PowerNetSystem), typeof(SharedPowerReceiverSystem)])] +public sealed partial class ApcPowerReceiverBatteryComponent : Component +{ + /// + /// Indicates whether power is currently being drawn from the battery. + /// + [DataField] + public bool Enabled = false; + + /// + /// The passive load the entity places on the APC power network. + /// If not connected to an active APC power network, this amount + /// of power is drained from the battery every second. + /// + [DataField] + public float IdleLoad { get; set; } = 5f; + + /// + /// Determines how much battery charge the entity's battery gains + /// per second when connected to an active APC power network. + /// + [DataField] + public float BatteryRechargeRate { get; set; } = 50f; + + /// + /// While the battery is being recharged, the load this entity places on the APC + /// power network is increased by the multiplied + /// by this factor. + /// + [DataField] + public float BatteryRechargeEfficiency { get; set; } = 1f; +} + +/// +/// Raised whenever an ApcPowerReceiverBattery starts / stops discharging +/// +[ByRefEvent] +public readonly record struct ApcPowerReceiverBatteryChangedEvent(bool Enabled); diff --git a/Content.Server/Power/EntitySystems/PowerNetSystem.cs b/Content.Server/Power/EntitySystems/PowerNetSystem.cs index a7098649ce..dbc17f2b9d 100644 --- a/Content.Server/Power/EntitySystems/PowerNetSystem.cs +++ b/Content.Server/Power/EntitySystems/PowerNetSystem.cs @@ -22,6 +22,7 @@ namespace Content.Server.Power.EntitySystems [Dependency] private readonly PowerNetConnectorSystem _powerNetConnector = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly IParallelManager _parMan = default!; + [Dependency] private readonly BatterySystem _battery = default!; private readonly PowerState _powerState = new(); private readonly HashSet _powerNetReconnectQueue = new(); @@ -278,7 +279,7 @@ namespace Content.Server.Power.EntitySystems // Send events where necessary. // TODO: Instead of querying ALL power components every tick, and then checking if an event needs to be // raised, should probably assemble a list of entity Uids during the actual solver steps. - UpdateApcPowerReceiver(); + UpdateApcPowerReceiver(frameTime); UpdatePowerConsumer(); UpdateNetworkBattery(); } @@ -306,10 +307,12 @@ namespace Content.Server.Power.EntitySystems _powerNetReconnectQueue.Clear(); } - private void UpdateApcPowerReceiver() + private void UpdateApcPowerReceiver(float frameTime) { var appearanceQuery = GetEntityQuery(); var metaQuery = GetEntityQuery(); + var apcBatteryQuery = GetEntityQuery(); + var enumerator = AllEntityQuery(); while (enumerator.MoveNext(out var uid, out var apcReceiver)) { @@ -318,6 +321,42 @@ namespace Content.Server.Power.EntitySystems || MathHelper.CloseToPercent(apcReceiver.NetworkLoad.ReceivingPower, apcReceiver.Load)); + // Check if the entity has an internal battery + if (apcBatteryQuery.TryComp(uid, out var apcBattery) && TryComp(uid, out var battery)) + { + apcReceiver.Load = apcBattery.IdleLoad; + + // Try to draw power from the battery if there isn't sufficient external power + var requireBattery = !powered && !apcReceiver.PowerDisabled; + + if (requireBattery) + { + _battery.SetCharge(uid, battery.CurrentCharge - apcBattery.IdleLoad * frameTime, battery); + } + + // Otherwise try to charge the battery + else if (powered && !_battery.IsFull(uid, battery)) + { + apcReceiver.Load += apcBattery.BatteryRechargeRate * apcBattery.BatteryRechargeEfficiency; + _battery.SetCharge(uid, battery.CurrentCharge + apcBattery.BatteryRechargeRate * frameTime, battery); + } + + // Enable / disable the battery if the state changed + var enableBattery = requireBattery && battery.CurrentCharge > 0; + + if (apcBattery.Enabled != enableBattery) + { + apcBattery.Enabled = enableBattery; + + var apcBatteryEv = new ApcPowerReceiverBatteryChangedEvent(enableBattery); + RaiseLocalEvent(uid, ref apcBatteryEv); + + _appearance.SetData(uid, PowerDeviceVisuals.BatteryPowered, enableBattery); + } + + powered |= enableBattery; + } + // If new value is the same as the old, then exit if (!apcReceiver.Recalculate && apcReceiver.Powered == powered) continue; diff --git a/Content.Shared/Power/SharedPowerDevice.cs b/Content.Shared/Power/SharedPowerDevice.cs index 4274dde60f..043a4dac48 100644 --- a/Content.Shared/Power/SharedPowerDevice.cs +++ b/Content.Shared/Power/SharedPowerDevice.cs @@ -6,6 +6,7 @@ namespace Content.Shared.Power public enum PowerDeviceVisuals : byte { VisualState, - Powered + Powered, + BatteryPowered } } diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml index 9f34a1c5d1..d71e40aa14 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml @@ -16,6 +16,34 @@ tags: - HideContextMenu - type: AnimationPlayer + +- type: entity + parent: MuzzleFlashEffect + id: MuzzleFlashEffectOmnilaser + categories: [ HideSpawnMenu ] + components: + - type: Sprite + drawdepth: BelowMobs + offset: 0.15, 0 + layers: + - shader: unshaded + map: ["enum.EffectLayers.Unshaded"] + sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi + state: omnilaser_flash + +- type: entity + parent: MuzzleFlashEffect + id: MuzzleFlashEffectHeavyLaser + categories: [ HideSpawnMenu ] + components: + - type: Sprite + drawdepth: BelowMobs + offset: 0.15, 0 + layers: + - shader: unshaded + map: ["enum.EffectLayers.Unshaded"] + sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi + state: heavylaser_flash # One bullet to bring them all into the darkness and bind them - type: entity @@ -949,6 +977,81 @@ collection: WeakHit forceSound: true +- type: entity + name : energy bolt + id: BulletEnergyTurretBase + parent: BaseBullet + categories: [ HideSpawnMenu ] + components: + - type: Reflective + reflective: + - Energy + - type: FlyBySound + sound: + collection: EnergyMiss + params: + volume: 5 + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi + layers: + - state: heavylaser + shader: unshaded + - type: Physics + - type: Fixtures + fixtures: + projectile: + shape: + !type:PhysShapeAabb + bounds: "-0.15,-0.3,0.15,0.3" + hard: false + mask: + - Opaque + fly-by: *flybyfixture + - type: Ammo + +- type: entity + name : laser bolt + id: BulletEnergyTurretLaser + parent: BulletEnergyTurretBase + categories: [ HideSpawnMenu ] + components: + - type: Ammo + muzzleFlash: MuzzleFlashEffectHeavyLaser + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi + layers: + - state: heavylaser + shader: unshaded + - type: Projectile + impactEffect: BulletImpactEffectOrangeDisabler + damage: + types: + Heat: 28 + +- type: entity + name : disabler bolt + id: BulletEnergyTurretDisabler + parent: BulletEnergyTurretBase + categories: [ HideSpawnMenu ] + components: + - type: Ammo + muzzleFlash: MuzzleFlashEffectOmnilaser + - type: Sprite + sprite: Objects/Weapons/Guns/Projectiles/projectiles_tg.rsi + layers: + - state: omnilaser + shader: unshaded + - type: StaminaDamageOnCollide + damage: 30 + - type: Projectile + impactEffect: BulletImpactEffectDisabler + damage: + types: + Heat: 0 + soundHit: + collection: WeakHit + forceSound: true + - type: entity name: tesla gun lightning id: TeslaGunBullet @@ -1051,4 +1154,4 @@ - type: ProjectileSpread proto: BulletDisablerSmg count: 3 #bit stronger than a disabler if you hit your shots you goober, still not a 2 hit stun though - spread: 9 + spread: 9 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Turrets/turrets_ballistic.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Turrets/turrets_ballistic.yml new file mode 100644 index 0000000000..c5dbb1b216 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Turrets/turrets_ballistic.yml @@ -0,0 +1,138 @@ +- type: entity + parent: [BaseWeaponBallisticTurret, BaseSyndicateContraband] + id: WeaponTurretSyndicate + suffix: Syndicate + components: + - type: NpcFactionMember + factions: + - Syndicate + +- type: entity + parent: BaseWeaponBallisticTurret + id: WeaponTurretSyndicateDisposable + name: disposable ballistic turret + suffix: Syndicate, Disposable + components: + - type: NpcFactionMember + factions: + - Syndicate + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 600 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:TriggerBehavior + - type: Gun + fireRate: 2 + selectedMode: FullAuto + availableModes: + - FullAuto + soundGunshot: /Audio/Weapons/Guns/Gunshots/gun_sentry.ogg + - type: BallisticAmmoProvider + proto: CartridgePistol + capacity: 50 + - type: Construction + deconstructionTarget: null + graph: WeaponTurretSyndicateDisposable + node: disposableTurret + - type: Repairable + qualityNeeded: "Anchoring" + doAfterDelay: 3 + - type: TriggerWhenEmpty + - type: ExplodeOnTrigger + - type: Explosive + explosionType: Default + maxIntensity: 10 + intensitySlope: 1.5 + totalIntensity: 30 + canCreateVacuum: false + +- type: entity + parent: BaseWeaponBallisticTurret + id: WeaponTurretNanoTrasen + suffix: NanoTrasen + components: + - type: NpcFactionMember + factions: + - NanoTrasen + +- type: entity + parent: BaseWeaponBallisticTurret + id: WeaponTurretHostile + suffix: Hostile + components: + - type: NpcFactionMember + factions: + - SimpleHostile + +- type: entity + parent: BaseWeaponBallisticTurret + id: WeaponTurretAllHostile + suffix: All hostile + components: + - type: NpcFactionMember + factions: + - AllHostile + +- type: entity + parent: BaseWeaponBallisticTurret + id: WeaponTurretXeno + name: xeno turret + suffix: Xeno + description: Shoots 9mm acid projectiles. + components: + - type: NpcFactionMember + factions: + - Xeno + - type: Sprite + sprite: Objects/Weapons/Guns/Turrets/xenoturret.rsi + noRot: true + layers: + - state: acid_turret + - type: BallisticAmmoProvider + proto: BulletAcid + capacity: 500 + - type: Gun + fireRate: 1 + selectedMode: FullAuto + soundGunshot: /Audio/Weapons/Xeno/alien_spitacid.ogg + - type: HTN + rootTask: + task: TurretCompound + blackboard: + SoundTargetInLOS: !type:SoundPathSpecifier + path: /Audio/Animals/snake_hiss.ogg + - type: Damageable + damageContainer: Biological + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/gib1.ogg + - !type:SpawnEntitiesBehavior + spawn: + FoodMeatXeno: + min: 3 + max: 5 + - type: InteractionPopup + interactDelay: 1.0 + successChance: 0.8 + interactSuccessString: petting-success-generic + interactFailureString: petting-failure-generic + interactSuccessSound: + path: /Audio/Animals/snake_hiss.ogg \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Turrets/turrets_base.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Turrets/turrets_base.yml new file mode 100644 index 0000000000..aaa45a2136 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Turrets/turrets_base.yml @@ -0,0 +1,135 @@ +- type: entity + parent: BaseStructure + id: BaseWeaponTurret + name: turret + abstract: true + components: + - type: Clickable + - type: InteractionOutline + - type: Actions + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.45,-0.45,0.45,0.45" + density: 60 + mask: + - MachineMask + layer: + - MachineLayer + - type: Sprite + sprite: Objects/Weapons/Guns/Turrets/turrets.rsi + drawdepth: Mobs + layers: + - state: syndie_lethal + - type: InteractionPopup + interactDelay: 0.2 + successChance: 0.8 + interactSuccessString: petting-success-generic + interactFailureString: petting-failure-generic + interactSuccessSound: + path: /Audio/Effects/double_beep.ogg + - type: CombatMode + toggleMouseRotator: false + - type: Damageable + damageContainer: Inorganic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 600 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:PlaySoundBehavior + sound: + collection: MetalGlassBreak + - trigger: + !type:DamageTrigger + damage: 300 + # TODO: Construction graph + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:PlaySoundBehavior + sound: + collection: MetalGlassBreak + - !type:SpawnEntitiesBehavior + spawn: + SheetSteel1: + min: 3 + max: 5 + - type: HTN + rootTask: + task: TurretCompound + blackboard: + RotateSpeed: !type:Single + 3.141 + SoundTargetInLOS: !type:SoundPathSpecifier + path: /Audio/Effects/double_beep.ogg + - type: MouseRotator + angleTolerance: 5 + rotationSpeed: 180 + simple4DirMode: false + - type: NoRotateOnInteract + - type: NoRotateOnMove + - type: Input + context: "human" + +- type: entity + parent: BaseWeaponTurret + id: BaseWeaponBallisticTurret + description: A ballistic machine gun auto-turret. + name: ballistic turret + abstract: true + components: + - type: ContainerContainer + containers: + ballistic-ammo: !type:Container + - type: Gun + fireRate: 6 + selectedMode: FullAuto + availableModes: + - FullAuto + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/gun_sentry.ogg + - type: BallisticAmmoProvider + proto: CartridgeCaselessRifle + capacity: 500 + +- type: entity + parent: BaseWeaponTurret + id: BaseWeaponEnergyTurret + name: laser turret + description: An auto-turret armed with a heavy laser. Its weapon will recharge while connected to an active power grid. + abstract: true + components: + - type: Sprite + sprite: Objects/Weapons/Guns/Turrets/sentry_turret.rsi + drawdepth: FloorObjects + granularLayersRendering: true + layers: + - state: support + renderingStrategy: NoRotation + - state: base + - state: lethal + shader: unshaded + - type: Gun + projectileSpeed: 15 + fireRate: 1.5 + soundGunshot: + path: /Audio/Weapons/Guns/Gunshots/taser2.ogg + - type: ProjectileBatteryAmmoProvider + proto: BulletEnergyTurretLaser + fireCost: 100 + - type: Battery + maxCharge: 2000 + startingCharge: 0 + - type: ApcPowerReceiverBattery + idlePowerUse: 5 + batteryRechargeRate: 200 + batteryRechargeEfficiency: 1.225 + - type: ApcPowerReceiver + powerLoad: 5 + - type: ExtensionCableReceiver \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Turrets/turrets_broken.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Turrets/turrets_broken.yml new file mode 100644 index 0000000000..96218cd87d --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Turrets/turrets_broken.yml @@ -0,0 +1,31 @@ +- type: entity + parent: BaseStructure + id: WeaponTurretSyndicateBroken + name: ballistic turret (broken) + description: A ballistic machine gun auto-turret. + components: + - type: Clickable + - type: InteractionOutline + - type: Sprite + sprite: Objects/Weapons/Guns/Turrets/turrets.rsi + drawdepth: Mobs + layers: + - state: syndie_broken + - type: Damageable + damageContainer: Inorganic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 450 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:PlaySoundBehavior + sound: + collection: MetalGlassBreak + - !type:SpawnEntitiesBehavior + spawn: + SheetSteel1: + min: 2 + max: 4 \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/turrets.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/turrets.yml deleted file mode 100644 index 8da72b49ae..0000000000 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/turrets.yml +++ /dev/null @@ -1,259 +0,0 @@ -- type: entity - parent: BaseStructure - id: WeaponTurretSyndicateBroken - name: ballistic turret (broken) - description: A ballistic machine gun auto-turret. - components: - - type: Clickable - - type: InteractionOutline - - type: Sprite - sprite: Objects/Weapons/Guns/Turrets/turrets.rsi - drawdepth: Mobs - layers: - - state: syndie_broken - - type: Damageable - damageContainer: Inorganic - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 450 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - !type:PlaySoundBehavior - sound: - collection: MetalGlassBreak - - !type:SpawnEntitiesBehavior - spawn: - SheetSteel1: - min: 2 - max: 4 - -- type: entity - parent: BaseStructure - id: BaseWeaponTurret - name: ballistic turret - abstract: true - components: - - type: Clickable - - type: InteractionOutline - - type: Actions - - type: Fixtures - fixtures: - fix1: - shape: - !type:PhysShapeAabb - bounds: "-0.45,-0.45,0.45,0.45" - density: 60 - mask: - - MachineMask - layer: - - MachineLayer - - type: ContainerContainer - containers: - ballistic-ammo: !type:Container - - type: Sprite - sprite: Objects/Weapons/Guns/Turrets/turrets.rsi - drawdepth: Mobs - layers: - - state: syndie_lethal - - type: InteractionPopup - interactDelay: 0.2 - successChance: 0.8 - interactSuccessString: petting-success-generic - interactFailureString: petting-failure-generic - interactSuccessSound: - path: /Audio/Effects/double_beep.ogg - - type: CombatMode - toggleMouseRotator: false - - type: Damageable - damageContainer: Inorganic - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 600 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - trigger: - !type:DamageTrigger - damage: 300 - # TODO: Construction graph - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - !type:PlaySoundBehavior - sound: - collection: MetalGlassBreak - - !type:SpawnEntitiesBehavior - spawn: - SheetSteel1: - min: 3 - max: 5 - - type: Gun - fireRate: 6 - selectedMode: FullAuto - availableModes: - - FullAuto - soundGunshot: /Audio/Weapons/Guns/Gunshots/gun_sentry.ogg - # TODO: Power ammo provider? - - type: BallisticAmmoProvider - proto: CartridgeCaselessRifle - capacity: 500 - - type: HTN - rootTask: - task: TurretCompound - blackboard: - RotateSpeed: !type:Single - 3.141 - SoundTargetInLOS: !type:SoundPathSpecifier - path: /Audio/Effects/double_beep.ogg - - type: MouseRotator - angleTolerance: 5 - rotationSpeed: 180 - simple4DirMode: false - - type: NoRotateOnInteract - - type: NoRotateOnMove - - type: Input - context: "human" - -- type: entity - parent: [BaseWeaponTurret, BaseSyndicateContraband] - id: WeaponTurretSyndicate - suffix: Syndicate - components: - - type: NpcFactionMember - factions: - - Syndicate - -- type: entity - parent: BaseWeaponTurret - name: disposable ballistic turret - id: WeaponTurretSyndicateDisposable - suffix: Syndicate, Disposable - components: - - type: NpcFactionMember - factions: - - Syndicate - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 600 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - trigger: - !type:DamageTrigger - damage: 100 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - !type:TriggerBehavior - - type: Gun - fireRate: 2 - selectedMode: FullAuto - availableModes: - - FullAuto - soundGunshot: /Audio/Weapons/Guns/Gunshots/gun_sentry.ogg - - type: BallisticAmmoProvider - proto: CartridgePistol - capacity: 50 - - type: Construction - deconstructionTarget: null - graph: WeaponTurretSyndicateDisposable - node: disposableTurret - - type: Repairable - qualityNeeded: "Anchoring" - doAfterDelay: 3 - - type: TriggerWhenEmpty - - type: ExplodeOnTrigger - - type: Explosive - explosionType: Default - maxIntensity: 10 - intensitySlope: 1.5 - totalIntensity: 30 - canCreateVacuum: false - -- type: entity - parent: BaseWeaponTurret - id: WeaponTurretNanoTrasen - suffix: NanoTrasen - components: - - type: NpcFactionMember - factions: - - NanoTrasen - -- type: entity - parent: BaseWeaponTurret - id: WeaponTurretHostile - suffix: Hostile - components: - - type: NpcFactionMember - factions: - - SimpleHostile - -- type: entity - parent: BaseWeaponTurret - id: WeaponTurretAllHostile - suffix: All hostile - components: - - type: NpcFactionMember - factions: - - AllHostile - -- type: entity - name: xeno turret - description: Shoots 9mm acid projectiles. - parent: BaseWeaponTurret - id: WeaponTurretXeno - suffix: Xeno - components: - - type: NpcFactionMember - factions: - - Xeno - - type: Sprite - sprite: Objects/Weapons/Guns/Turrets/xenoturret.rsi - noRot: true - layers: - - state: acid_turret - - type: BallisticAmmoProvider - proto: BulletAcid - capacity: 500 - - type: Gun - fireRate: 1 - selectedMode: FullAuto - soundGunshot: /Audio/Weapons/Xeno/alien_spitacid.ogg - - type: HTN - rootTask: - task: TurretCompound - blackboard: - SoundTargetInLOS: !type:SoundPathSpecifier - path: /Audio/Animals/snake_hiss.ogg - - type: Damageable - damageContainer: Biological - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 100 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - !type:PlaySoundBehavior - sound: - path: /Audio/Effects/gib1.ogg - - !type:SpawnEntitiesBehavior - spawn: - FoodMeatXeno: - min: 3 - max: 5 - - type: InteractionPopup - interactDelay: 1.0 - successChance: 0.8 - interactSuccessString: petting-success-generic - interactFailureString: petting-failure-generic - interactSuccessSound: - path: /Audio/Animals/snake_hiss.ogg