azsteal-SmartSpawnController/src/Behaviors/BotUnspawnController.cs

164 lines
5.3 KiB
C#
Raw Normal View History

2021-11-05 02:46:37 +01:00
using astealz.SmartSpawnController.Utils;
using EFT;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace astealz.SmartSpawnController.Behaviors
{
class BotUnspawnController : MonoBehaviour
{
private const int playersPool = 40;
private const int maxAttempts = 2;
private const float updateRate = 5f;
private float timer = 0;
private Player localPlayer = null;
private float maxDist = float.MaxValue;
private float sqrMaxDist = float.MaxValue;
private readonly List<Player> players = new List<Player>(playersPool);
private readonly Dictionary<string, int> playerCounters = new Dictionary<string, int>(playersPool);
2021-12-06 15:27:03 +00:00
private readonly List<WildSpawnType> rolesToLeave =
new List<WildSpawnType>(Enum.GetValues(typeof(WildSpawnType)).Length) {
WildSpawnType.assault,
WildSpawnType.assaultGroup,
WildSpawnType.cursedAssault,
WildSpawnType.pmcBot
2021-11-05 02:46:37 +01:00
};
public bool DEBUG_ENABLED => Globals.Config.Debug;
public bool VERBOSE_ENABLED => Globals.Config.Verbose;
public BotUnspawnController()
{
enabled = false;
}
public void SetRoles(WildSpawnType[] roles)
{
if (roles == null || roles.Length == 0)
return;
rolesToLeave.Clear();
foreach (var role in roles)
{
rolesToLeave.Add(role);
}
}
public void SetMaxDist(float maxDist)
{
if (maxDist < 100f || maxDist > 1000f)
{
maxDist = 500f;
Utils.Logger.Info("Maximal distance must be in range [100, 1000]");
}
this.maxDist = maxDist;
this.sqrMaxDist = maxDist * maxDist;
}
void OnEnable()
{
Utils.Logger.Info($"BotUnspawnController activated!");
Utils.Logger.Info($"Max distance to unspawn: {maxDist.ToString("F1")} / roles to unspawn: {string.Join(", ", rolesToLeave)}");
}
void OnDisable()
{
Utils.Logger.Info($"BotUnspawnController deactivated!");
}
void Update()
{
timer += Time.deltaTime;
if (timer < updateRate)
return;
timer = 0;
if (localPlayer == null)
localPlayer = Globals.LocalPlayer;
if (localPlayer == null)
return;
players.Clear();
foreach (var player in Globals.GameWorld.RegisteredPlayers)
{
if (!player.isActiveAndEnabled || !player.IsAI)
continue;
players.Add(player);
}
foreach (var player in players)
{
BotOwner botOwner = player.GetBotOwner();
// we need an active bot
if (botOwner.BotState != EBotState.Active)
continue;
string profileId = player.ProfileId;
if (string.IsNullOrWhiteSpace(profileId))
{
Utils.Logger.Error("Bot ProfileId is empty!");
continue;
}
// don't bother those who already wanna leave (game logic, especially when cultists are spawned)
if (botOwner.IsWannaLeave())
continue;
//var role = botOwner.Profile.Info.Settings.Role;
WildSpawnType role = botOwner.Profile.GetRole();
// filter by bot role
if (false == rolesToLeave.Contains(role))
continue;
// calc distance
var sqrDist = (botOwner.Transform.position - localPlayer.Transform.position).sqrMagnitude;
// bot has 'maxAttempts' attempts to get closer to local player
int playerCounter = maxAttempts;
if (!playerCounters.TryGetValue(profileId, out playerCounter))
playerCounters.Add(profileId, playerCounter);
if (sqrDist > sqrMaxDist)
// and minus one
playerCounter -= 1;
else if (playerCounter < maxAttempts)
// oh, he's trying...
playerCounter += 1;
if (playerCounter > 0)
{
playerCounters[profileId] = playerCounter;
// next
continue;
}
// he didn't make it...
BotZone botZone = botOwner.GetBotZone();
string zone = botZone != null ? botZone.NameZone : null;
if (string.IsNullOrWhiteSpace(zone))
zone = "unknown";
if (VERBOSE_ENABLED)
Utils.Logger.Verbose($"[{role}] '{botOwner.Profile.GetNickname().TransliterateThis()}' is leaving zone '{zone}'");
// remove bot from dictionary
playerCounters.Remove(profileId);
// despawning
player.KillMe(EBodyPart.Head, 999f);
player.PlayerBody.PlayerBones.transform.position += Vector3.down * 100f;
}
}
}
}