/// <summary> /// Fires a round of ammo out of the weapon. /// </summary> /// <param name="shooter">Entity that is operating the weapon, usually the player.</param> /// <param name="targetPos">Target position on the map to shoot at.</param> private void Fire(EntityUid shooter, Vector2 targetPos) { if (ShotsLeft == 0) { SoundSystem.Play(Filter.Broadcast(), SoundEmpty.GetSound(), Owner); return; } var ammo = PeekAmmo(); if (TakeProjectile(Entities.GetComponent <TransformComponent>(shooter).Coordinates) is not { Valid: true } projectile) { SoundSystem.Play(Filter.Broadcast(), SoundEmpty.GetSound(), Owner); return; } // At this point firing is confirmed var direction = (targetPos - Entities.GetComponent <TransformComponent>(shooter).WorldPosition).ToAngle(); var angle = GetRecoilAngle(direction); // This should really be client-side but for now we'll just leave it here if (Entities.HasComponent <CameraRecoilComponent>(shooter)) { var kick = -angle.ToVec() * 0.15f; EntitySystem.Get <CameraRecoilSystem>().KickCamera(shooter, kick); } // This section probably needs tweaking so there can be caseless hitscan etc. if (Entities.TryGetComponent(projectile, out HitscanComponent? hitscan)) { FireHitscan(shooter, hitscan, angle); } else if (Entities.HasComponent <ProjectileComponent>(projectile) && Entities.TryGetComponent(ammo, out AmmoComponent? ammoComponent)) { FireProjectiles(shooter, projectile, ammoComponent.ProjectilesFired, ammoComponent.EvenSpreadAngle, angle, ammoComponent.Velocity, ammo.Value); if (CanMuzzleFlash) { EntitySystem.Get <GunSystem>().MuzzleFlash(Owner, ammoComponent, angle); } if (ammoComponent.Caseless) { Entities.DeleteEntity(ammo.Value); } } else { // Invalid types throw new InvalidOperationException(); } SoundSystem.Play(Filter.Broadcast(), SoundGunshot.GetSound(), Owner); _lastFire = _gameTiming.CurTime; }
/// <summary> /// Fires a round of ammo out of the weapon. /// </summary> /// <param name="shooter">Entity that is operating the weapon, usually the player.</param> /// <param name="targetPos">Target position on the map to shoot at.</param> private void Fire(IEntity shooter, Vector2 targetPos) { if (ShotsLeft == 0) { SoundSystem.Play(Filter.Broadcast(), SoundEmpty.GetSound(), Owner); return; } var ammo = PeekAmmo(); var projectile = TakeProjectile(shooter.Transform.Coordinates); if (projectile == null) { SoundSystem.Play(Filter.Broadcast(), SoundEmpty.GetSound(), Owner); return; } // At this point firing is confirmed var direction = (targetPos - shooter.Transform.WorldPosition).ToAngle(); var angle = GetRecoilAngle(direction); // This should really be client-side but for now we'll just leave it here if (shooter.TryGetComponent(out CameraRecoilComponent? recoilComponent)) { recoilComponent.Kick(-angle.ToVec() * 0.15f); } // This section probably needs tweaking so there can be caseless hitscan etc. if (projectile.TryGetComponent(out HitscanComponent? hitscan)) { FireHitscan(shooter, hitscan, angle); } else if (projectile.HasComponent <ProjectileComponent>() && ammo != null && ammo.TryGetComponent(out AmmoComponent? ammoComponent)) { FireProjectiles(shooter, projectile, ammoComponent.ProjectilesFired, ammoComponent.EvenSpreadAngle, angle, ammoComponent.Velocity, ammo); if (CanMuzzleFlash) { ammoComponent.MuzzleFlash(Owner, angle); } if (ammoComponent.Caseless) { ammo.Delete(); } } else { // Invalid types throw new InvalidOperationException(); } SoundSystem.Play(Filter.Broadcast(), SoundGunshot.GetSound(), Owner); _lastFire = _gameTiming.CurTime; }
public override ComponentState GetComponentState() { var slotsSpent = new bool?[Capacity]; for (var i = 0; i < Capacity; i++) { slotsSpent[i] = null; var ammoEntity = _ammoSlots[i]; if (ammoEntity != default && Entities.TryGetComponent(ammoEntity, out AmmoComponent? ammo)) { slotsSpent[i] = ammo.Spent; } } //TODO: make yaml var to not sent currentSlot/UI? (for russian roulette) return(new RevolverBarrelComponentState( _currentSlot, FireRateSelector, slotsSpent, SoundGunshot.GetSound())); }