164 lines
5.3 KiB
C#
164 lines
5.3 KiB
C#
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);
|
|
|
|
private readonly List<WildSpawnType> rolesToLeave =
|
|
new List<WildSpawnType>(Enum.GetValues(typeof(WildSpawnType)).Length) {
|
|
WildSpawnType.assault,
|
|
WildSpawnType.assaultGroup,
|
|
WildSpawnType.cursedAssault,
|
|
WildSpawnType.pmcBot
|
|
};
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|