2D-Platformer/Assets/Scripts/Systems/Weapon/WeaponFiringSystem.cs
2022-02-12 12:53:50 +02:00

130 lines
No EOL
4.4 KiB
C#

using Cinemachine;
using Events;
using System;
using Unity.Entities;
using UnityEngine;
using Zenject;
using Hash128 = Unity.Entities.Hash128;
using Object = UnityEngine.Object;
using Random = System.Random;
namespace DefaultNamespace
{
[UpdateInGroup(typeof(PresentationSystemGroup)), UpdateAfter(typeof(PlayerWeaponSystem))]
public class WeaponFiringSystem : InjectableComponentSystem
{
[Serializable]
public class Settings
{
public ParticleSystem SmokeParticles;
public CinemachineImpulseSource WeaponImpulseSource;
}
[Inject] private readonly SoundManager soundManager;
[Inject] private ParticleSystemFactory particleSystemFactory;
private readonly Random random = new Random();
[Inject] private Settings settings;
protected override void OnSystemUpdate()
{
Entities.WithAll<WeaponPartsData>()
.ForEach(
(
Entity entity,
WeaponPropertiesData weaponProp,
ref FireWeaponEvent e,
ref AnimatorStateData animatorState,
ref WeaponData weaponData,
ref WeaponAccuracyData accuracy) =>
{
var weapon = weaponProp.Weapon;
var ammoType = weapon.AmmoType.Data;
var weaponParts = EntityManager.GetSharedComponentData<WeaponPartsData>(entity);
var rateOfFireDelta = 1f / weapon.Data.RateOfFire;
if (weaponData.ClipAmmo > 0)
{
if (EntityManager.HasComponent<ReloadEvent>(entity))
{
PostUpdateCommands.SetComponent(entity, new ReloadEvent { Cancel = true });
}
if (animatorState.State.IsTag("Interactive") || animatorState.State.IsTag("Firing"))
{
weaponData.ClipAmmo--;
weaponData.FireTimer += rateOfFireDelta;
for (var j = 0; j < weapon.Data.ProjectileCount; j++)
{
var projectileObj = Object.Instantiate(weapon.AmmoType.Template);
var rigidbody = projectileObj.GetComponent<Rigidbody2D>();
rigidbody.MovePosition(weaponParts.Barrel.position);
projectileObj.transform.position = weaponParts.Barrel.position;
var sharedData = new ProjectileSharedData
{
Damage = ammoType.Damage * weapon.Data.DamageMultiply,
MaxLife = ammoType.MaxLife,
RicochetChance = ammoType.RicochetChance
};
var dir = ((Vector2)weaponParts.Barrel.right).Rotate(
((float)random.NextGaussian() - 0.5f) *
11.25f *
(1 - weapon.Data.Accuracy * Mathf.Clamp01(accuracy.Accuracy)));
var projectileData = new ProjectileData
{
Life = ammoType.MaxLife, Velocity = dir * ammoType.Speed, HitMask = e.LayerMask
};
PostUpdateActions.Enqueue(
() =>
{
var projectileEntity = GameObjectEntity.AddToEntityManager(EntityManager, projectileObj);
EntityManager.AddSharedComponentData(projectileEntity, sharedData);
EntityManager.AddComponentData(projectileEntity, projectileData);
//EntityManager.AddComponentData(projectileEntity, default(TransformMatrix));
//todo find Matrix Component data
});
}
if (weaponParts.ShellsExit != null)
{
particleSystemFactory.Create(new Hash128(weapon.AmmoType.ShellsParticles.AssetGUID)).Completed += operation =>
{
operation.Result.GetComponent<ParticleSystem>()
.Emit(
new ParticleSystem.EmitParams
{
position = weaponParts.ShellsExit.position, applyShapeToPosition = true
},
1);
};
}
particleSystemFactory.Create(new Hash128(weapon.MuzzleFlash.AssetGUID)).Completed += operation =>
{
operation.Result.GetComponent<ParticleSystem>()
.Emit(
new ParticleSystem.EmitParams
{
position = weaponParts.Barrel.position,
rotation = Vector2.SignedAngle(weaponParts.Barrel.right, Vector2.up)
},
1);
};
settings.SmokeParticles.Emit(new ParticleSystem.EmitParams { position = weaponParts.Barrel.position }, 1);
weapon.FireSound.PlayRandomOneShot(weaponParts.Audio);
settings.WeaponImpulseSource.GenerateImpulseAt(weaponParts.Barrel.position, Vector3.one * e.ScreenShake);
}
}
else if (weaponData.Ammo <= 0 && weaponData.ClipAmmo <= 0)
{
weaponData.FireTimer += rateOfFireDelta;
}
PostUpdateCommands.RemoveComponent<FireWeaponEvent>(entity);
});
}
}
}