Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/AI/AIShooterService.cs
2025-06-24 23:49:13 +08:00

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);
}
}
}
}
}