131 lines
4.7 KiB
C#
131 lines
4.7 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using BITFALL;
|
|
using BITFALL.Bullet;
|
|
using BITKit;
|
|
using BITKit.Entities;
|
|
using Net.BITKit.Quadtree;
|
|
using Net.Project.B.Faction;
|
|
using Net.Project.B.Health;
|
|
using Project.B.CharacterController;
|
|
using Unity.Mathematics;
|
|
using UnityEngine;
|
|
using UnityEngine.AI;
|
|
using Random = UnityEngine.Random;
|
|
|
|
namespace Net.Project.B.AI
|
|
{
|
|
public class AIShooterService : IDisposable
|
|
{
|
|
private readonly IBulletService _bulletService;
|
|
private readonly IEntitiesService _entitiesService;
|
|
private readonly ITicker _ticker;
|
|
private readonly ConcurrentDictionary<int, LimitTimes> _fireLimits = new();
|
|
private readonly ConcurrentDictionary<int, IntervalUpdate> _fireIntervals = new();
|
|
private readonly ConcurrentDictionary<int, IntervalUpdate> _fireRateIntervals = new();
|
|
|
|
private readonly LayerMask _layerMask=LayerMask.GetMask("Default");
|
|
|
|
private static LimitTimes CreateLimitTimes(int id)
|
|
{
|
|
return new LimitTimes(3);
|
|
}
|
|
|
|
private static IntervalUpdate CreateFireRateIntervals(int id)
|
|
{
|
|
return new IntervalUpdate(0.1f);
|
|
}
|
|
|
|
private readonly BulletData _bulletData = new()
|
|
{
|
|
InitialDamage = 30,
|
|
MaxDamage = 30,
|
|
StartSpeed = 256,
|
|
};
|
|
|
|
public AIShooterService(ITicker ticker, IBulletService bulletService, IEntitiesService entitiesService)
|
|
{
|
|
_ticker = ticker;
|
|
_bulletService = bulletService;
|
|
_entitiesService = entitiesService;
|
|
|
|
_bulletService.OnHit += OnHit;
|
|
|
|
_ticker.Add(OnTick);
|
|
}
|
|
|
|
private bool OnHit(int arg1, int arg2)
|
|
{
|
|
return (_fireIntervals.ContainsKey(arg1) && _fireIntervals.ContainsKey(arg2)) is false;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_bulletService.OnHit -= OnHit;
|
|
_ticker.Remove(OnTick);
|
|
}
|
|
|
|
private void OnTick(float obj)
|
|
{
|
|
|
|
|
|
foreach (var (entity,blackBoard, characterController, shooter,healthComponent,navMeshAgent) in _entitiesService
|
|
.QueryComponents<IEntity,AIBlackBoard, ICharacterController, AIShooter,IHealthComponent,NavMeshAgent>())
|
|
{
|
|
if(healthComponent.HealthPoint<0)continue;
|
|
if(blackBoard.AlertValue is not 1)continue;
|
|
if(blackBoard is not {Target:not null,AlertValue:1})continue;
|
|
|
|
#if UNITY_EDITOR
|
|
{
|
|
blackBoard.Target.ServiceProvider.QueryComponents(out ICharacterController zombieCharacterController);
|
|
|
|
var targetPos = zombieCharacterController.ViewPosition + zombieCharacterController.Velocity * obj;
|
|
|
|
Debug.DrawLine(characterController.ViewPosition,targetPos,Color.green,obj);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
if (_fireRateIntervals.GetOrAdd(entity.Id, CreateFireRateIntervals).AllowUpdate is false) continue;
|
|
|
|
var fireLimits = _fireLimits.GetOrAdd(entity.Id, CreateLimitTimes);
|
|
|
|
if (_fireIntervals.GetOrCreate(entity.Id).AllowUpdate)
|
|
{
|
|
fireLimits.Reset();
|
|
}
|
|
|
|
if (fireLimits.Allow is false) continue;
|
|
{
|
|
blackBoard.Target.ServiceProvider.QueryComponents(out ICharacterController zombieCharacterController);
|
|
|
|
var targetPos = zombieCharacterController.ViewPosition + zombieCharacterController.Velocity * obj;
|
|
|
|
if (Physics.Linecast(characterController.ViewPosition, targetPos, out var hit,layerMask:_layerMask))
|
|
{
|
|
//Debug.DrawLine(characterController.ViewPosition,hit.point,Color.red,obj);
|
|
//navMeshAgent.SetDestination(targetPos);
|
|
continue;
|
|
}
|
|
|
|
|
|
|
|
_bulletData.Initiator = entity.Id;
|
|
_bulletData.Position = characterController.ViewPosition;
|
|
_bulletData.Rotation =
|
|
Quaternion.LookRotation( targetPos- characterController.ViewPosition) *
|
|
Quaternion.Euler(Random.insideUnitSphere)
|
|
;
|
|
_bulletData.Forward = (Quaternion)_bulletData.Rotation * Vector3.forward;
|
|
_bulletService.Spawn(_bulletData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|