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

137 lines
No EOL
5.1 KiB
C#

using Events;
using Markers;
using System;
using Unity.Entities;
using UnityEngine;
using Zenject;
namespace DefaultNamespace
{
[UpdateInGroup(typeof(PresentationSystemGroup)), UpdateAfter(typeof(PlayerActionMapSystem))]
public class PlayerWeaponSystem : InjectableComponentSystem
{
[Serializable]
public class Settings
{
public LayerMask BulletLayerMask;
public LayerMask ProjectileCheckLayerMask;
public float ShotScreenShakeAmount;
}
[Inject] private readonly PlayerFacade playerFacade;
[Inject] private readonly Settings settings;
protected override void OnSystemUpdate()
{
var enabledWindowsCount = Entities.WithAllReadOnly<WindowComponentData, EnabledComponentData>().ToEntityQuery().CalculateEntityCount();
Entities.WithAll<Slot>()
.WithAllReadOnly<ActorWeaponReferenceData, ActorWeaponPropertiesData, ActorGrenadeComponent, AnimatorStateData, PlayerInput>()
.ForEach(
(
Entity entity,
ActorMeleeSharedData meleeShared,
ref PlayerData playerData,
ref ActorAnimationData animation,
ref ActorMeleeData melee,
ref ActorGrenadeData grenadeData) =>
{
var inventory = EntityManager.GetBuffer<Slot>(entity);
var weaponReference = EntityManager.GetComponentData<ActorWeaponReferenceData>(entity);
var weapon = EntityManager.GetSharedComponentData<ActorWeaponPropertiesData>(entity);
var animationState = EntityManager.GetComponentData<AnimatorStateData>(entity);
var input = EntityManager.GetComponentData<PlayerInput>(entity);
var weaponEntity = weaponReference.Weapon;
var grenade = EntityManager.GetComponentObject<ActorGrenadeComponent>(entity);
var weaponAnimationState = EntityManager.GetComponentData<AnimatorStateData>(weaponEntity);
var isInteractiveWeaponAnimation = weaponAnimationState.State.IsTag("Interactive");
var inInteractiveAnimation = animationState.State.IsTag("Interactive");
animation.AttackSpeed = weapon.Weapon.Data.RateOfFire;
if (input.Melee && melee.MeleeTimer <= 0 && inInteractiveAnimation && isInteractiveWeaponAnimation)
{
animation.Triggers |= AnimationTriggerType.Melee;
melee.MeleeTimer = meleeShared.Cooldown;
}
if (inventory.Begin().Any(id => id.Type == SlotType.Grenade) &&
input.Grenade &&
grenadeData.GrenadeTimer <= 0 &&
inInteractiveAnimation &&
isInteractiveWeaponAnimation &&
!EntityManager.HasComponent<ItemUseEventData>(entity))
{
PostUpdateCommands.AddComponent(
entity,
new ItemUseEventData { Inventory = entity, Slot = inventory.Begin().IndexOf(e => e.Type == SlotType.Grenade) });
grenadeData.GrenadeTimer = grenade.Cooldown;
}
if (EntityManager.Exists(weaponEntity))
{
if (EntityManager.TryGetComponentData<WeaponData>(weaponEntity, out var weaponData))
{
if ((input.Reload || weaponData.ClipAmmo <= 0) &&
weaponData.ReloadTimer <= 0 &&
!EntityManager.HasComponent<ReloadEvent>(weaponEntity) &&
inInteractiveAnimation &&
isInteractiveWeaponAnimation &&
weaponData.Ammo > 0 &&
weaponData.ClipAmmo < weapon.Weapon.Data.ClipCapacity)
{
PostUpdateCommands.AddComponent(weaponEntity, new ReloadEvent());
}
if (EntityManager.HasComponent<WeaponPartsData>(weaponEntity))
{
var weaponParts = EntityManager.GetSharedComponentData<WeaponPartsData>(weaponEntity);
var animator = EntityManager.GetComponentObject<Animator>(weaponEntity);
if (CanFire(weaponParts.Barrel.position) &&
inInteractiveAnimation &&
enabledWindowsCount <= 0 &&
!input.OverUi &&
(weapon.Weapon.Data.Automatic ? input.Attacking : input.AttackPressed) &&
weaponData.FireTimer <= 0 &&
weaponData.ClipAmmo > 0 &&
weaponData.ReloadTimer <= 0)
{
PostUpdateCommands.PostEntityEvent(
EntityManager,
weaponEntity,
new FireWeaponEvent
{
LayerMask = settings.BulletLayerMask, ScreenShake = weapon.Weapon.Data.ScreenShake
});
animation.Triggers |= AnimationTriggerType.Attack;
if (animator)
{
animator.SetBool("Firing", true);
}
if (EntityManager.TryGetComponentData<ActorWeaponAccuracyData>(entity, out var accuracy))
{
accuracy.Accuracy += weapon.Weapon.Data.AccuracyDegrade;
accuracy.AccuracyAttackTime += weapon.Weapon.Data.AccuracyAttackTime;
accuracy.AccuracyRegainSpeed = weapon.Weapon.Data.AccuracyRegainSpeed;
EntityManager.SetComponentData(entity, accuracy);
}
}
else if (weaponData.FireTimer <= 0 && animator != null && animator.isActiveAndEnabled)
{
animator.SetBool("Firing", false);
}
}
}
}
});
}
public bool CanFire(Vector2 pos)
{
return !Physics2D.OverlapCircle(pos, 0.05f, settings.ProjectileCheckLayerMask);
}
}
}