using System.Collections.Generic; using Content.Server.GameObjects.Components.Mobs; using Content.Shared.GameObjects; using Robust.Server.GameObjects; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Projectiles { [RegisterComponent] public class ProjectileComponent : Component, ICollideSpecial, ICollideBehavior { public override string Name => "Projectile"; public bool IgnoreShooter = true; private EntityUid _shooter = EntityUid.Invalid; private Dictionary _damages; [ViewVariables] public Dictionary Damages { get => _damages; set => _damages = value; } public bool DeleteOnCollide => _deleteOnCollide; private bool _deleteOnCollide; // Get that juicy FPS hit sound private string _soundHit; private string _soundHitSpecies; public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); serializer.DataField(ref _deleteOnCollide, "delete_on_collide", true); // If not specified 0 damage serializer.DataField(ref _damages, "damages", new Dictionary()); serializer.DataField(ref _soundHit, "soundHit", null); serializer.DataField(ref _soundHitSpecies, "soundHitSpecies", null); } public float TimeLeft { get; set; } = 10; /// /// Function that makes the collision of this object ignore a specific entity so we don't collide with ourselves /// /// public void IgnoreEntity(IEntity shooter) { _shooter = shooter.Uid; } /// /// Special collision override, can be used to give custom behaviors deciding when to collide /// /// /// bool ICollideSpecial.PreventCollide(IPhysBody collidedwith) { if (IgnoreShooter && collidedwith.Owner.Uid == _shooter) return true; return false; } /// /// Applies the damage when our projectile collides with its victim /// /// void ICollideBehavior.CollideWith(IEntity entity) { if (_soundHitSpecies != null && entity.HasComponent()) { EntitySystem.Get().PlayAtCoords(_soundHitSpecies, entity.Transform.GridPosition); } else if (_soundHit != null) { EntitySystem.Get().PlayAtCoords(_soundHit, entity.Transform.GridPosition); } if (entity.TryGetComponent(out DamageableComponent damage)) { Owner.EntityManager.TryGetEntity(_shooter, out var shooter); foreach (var (damageType, amount) in _damages) { damage.TakeDamage(damageType, amount, Owner, shooter); } } if (!entity.Deleted && entity.TryGetComponent(out CameraRecoilComponent recoilComponent) && Owner.TryGetComponent(out PhysicsComponent physicsComponent)) { var direction = physicsComponent.LinearVelocity.Normalized; recoilComponent.Kick(direction); } } void ICollideBehavior.PostCollide(int collideCount) { if (collideCount > 0 && DeleteOnCollide) Owner.Delete(); } } }