0
0
mirror of https://github.com/sp-tarkov/modules.git synced 2025-02-13 00:30:44 -05:00

IsEnemyPatch Improvements (!156)

Revised `IsEnemyPatch` with the following changes:
* Added a check to see if the player is in the group's `Allies` collection (needed for mod support)
* Added a check to see if the player is in the group (possibly needed for future mod support)
* Fixed Zryachiy check (and added his followers) by allowing the EFT method to run for them
* Refactoring for clarity and to reorder the checks based on priority:
    1) Null check(s)
    2) Check if the player is in the group or in its `Allies` or `Enemies` collections
    3) Allow the EFT method to run for certain bot roles
    4) Finally, add the player to the group's `Enemies` collection if needed

**This is a big change, so please double-check my work!** I tested this in multiple raids, in several maps, with and without SAIN, and I didn't find any issues.

Reviewed-on: SPT/Modules#156
Co-authored-by: DanW <danw@noreply.dev.sp-tarkov.com>
Co-committed-by: DanW <danw@noreply.dev.sp-tarkov.com>
This commit is contained in:
DanW 2024-08-15 08:45:47 +00:00 committed by chomp
parent 471c191bbb
commit af96c37815
2 changed files with 80 additions and 55 deletions

View File

@ -1,4 +1,5 @@
using EFT;
using System.Collections.Generic;
namespace SPT.Custom.CustomAI
{
@ -42,5 +43,20 @@ namespace SPT.Custom.CustomAI
return false;
}
public static List<BotOwner> GetAllMembers(this BotsGroup group)
{
List<BotOwner> members = new List<BotOwner>();
if (group != null)
{
for (int m = 0; m < group.MembersCount; m++)
{
members.Add(group.Member(m));
}
}
return members;
}
}
}

View File

@ -1,8 +1,10 @@
using SPT.Reflection.Patching;
using EFT;
using EFT;
using HarmonyLib;
using SPT.Custom.CustomAI;
using SPT.Reflection.Patching;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using HarmonyLib;
namespace SPT.Custom.Patches
{
@ -25,7 +27,28 @@ namespace SPT.Custom.Patches
if (requester == null)
{
__result = false;
return false; // Skip original
}
// Check existing enemies list
// Could also check x.Value.Player?.Id - BSG do it this way
if (!__instance.Enemies.IsNullOrEmpty() && __instance.Enemies.Any(x => x.Key?.Id == requester.Id))
{
__result = true;
return false; // Skip original
}
// Do not force bots to be enemies if they are allies
if (!__instance.Allies.IsNullOrEmpty() && __instance.Allies.Any(x => x?.Id == requester.Id))
{
__result = false;
return false; // Skip original
}
// Bots should not become hostile with their group members here. This is needed in case mods add mixed groups (i.e. BEAR's and USEC's).
if (__instance.GetAllMembers().Any(i => i?.Id == requester.Id))
{
__result = false;
return false; // Skip original
}
@ -35,73 +58,59 @@ namespace SPT.Custom.Patches
|| __instance.InitialBotType == WildSpawnType.sectantWarrior
|| __instance.InitialBotType == WildSpawnType.sectantPriest
|| __instance.InitialBotType == WildSpawnType.sectactPriestEvent
|| __instance.InitialBotType == WildSpawnType.ravangeZryachiyEvent)
|| __instance.InitialBotType == WildSpawnType.ravangeZryachiyEvent
|| __instance.InitialBotType == WildSpawnType.bossZryachiy
|| __instance.InitialBotType == WildSpawnType.followerZryachiy)
{
return true; // Do original code
}
var isEnemy = false; // default not an enemy
// Check existing enemies list
// Could also check x.Value.Player?.Id - BSG do it this way
if (!__instance.Enemies.IsNullOrEmpty() && __instance.Enemies.Any(x => x.Key.Id == requester.Id))
// Let EFT manage Rogue behavior toward PMC's
if (__instance.InitialBotType == WildSpawnType.exUsec
&& __instance.Side == EPlayerSide.Savage
&& requester.Side != EPlayerSide.Savage)
{
__result = true;
return false; // Skip original
}
else
{
// Weird edge case - without this you get spammed with key already in enemy list error when you move around on lighthouse
// Make zryachiy use existing isEnemy() code
if (__instance.InitialBotType == WildSpawnType.bossZryachiy)
{
return false; // Skip original
}
if (__instance.Side == EPlayerSide.Usec)
{
if (requester.Side == EPlayerSide.Bear || requester.Side == EPlayerSide.Savage ||
ShouldAttackUsec(requester))
{
isEnemy = true;
__instance.AddEnemy(requester, EBotEnemyCause.checkAddTODO);
}
}
else if (__instance.Side == EPlayerSide.Bear)
{
if (requester.Side == EPlayerSide.Usec || requester.Side == EPlayerSide.Savage ||
ShouldAttackBear(requester))
{
isEnemy = true;
__instance.AddEnemy(requester, EBotEnemyCause.checkAddTODO);
}
}
else if (__instance.Side == EPlayerSide.Savage)
{
if (requester.Side != EPlayerSide.Savage)
{
//Lets exUsec warn Usecs and fire at will at Bears
if (__instance.InitialBotType == WildSpawnType.exUsec)
{
return true; // Let BSG handle things
}
// everyone else is an enemy to savage (scavs)
isEnemy = true;
__instance.AddEnemy(requester, EBotEnemyCause.checkAddTODO);
}
}
return true; // Do original code
}
__result = isEnemy;
// In all other cases, requester needs to be added to the enemies collection of the bot group if it should be treated as hostile
// NOTE: Manually adding enemies is needed as a result of EFT's implementation of PMC's because they are not hostile toward
// Scavs (any probably other bot types too)
__result = CheckIfPlayerShouldBeEnemy(__instance, requester);
if (__result)
{
__instance.AddEnemy(requester, EBotEnemyCause.checkAddTODO);
}
return false; // Skip original
}
/// <summary>
/// Returns true if requester should be an enemy of the bot group
/// </summary>
/// <param name="__instance"></param>
/// <param name="requester"></param>
/// <returns></returns>
private static bool CheckIfPlayerShouldBeEnemy(BotsGroup __instance, IPlayer requester)
{
switch (__instance.Side)
{
case EPlayerSide.Usec:
return requester.Side != EPlayerSide.Usec || ShouldAttackUsec(requester);
case EPlayerSide.Bear:
return requester.Side != EPlayerSide.Bear || ShouldAttackBear(requester);
case EPlayerSide.Savage:
return requester.Side != EPlayerSide.Savage;
}
return false;
}
/// <summary>
/// Return True when usec default behavior is attack + bot is usec
/// </summary>
/// <param name="requester"></param>
/// <returns>bool</returns>
/// <returns></returns>
private static bool ShouldAttackUsec(IPlayer requester)
{
var requesterMind = requester?.AIData?.BotOwner?.Settings?.FileSettings?.Mind;