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

Refactor LighthouseProgressionClass + adjust lightkeeper standing to -0.01 when player becomes hostile with Zryachiy/followers

This commit is contained in:
Dev 2023-07-30 10:04:35 +01:00
parent 8b4847714c
commit aa9a1af8c4
2 changed files with 116 additions and 67 deletions

View File

@ -10,142 +10,189 @@ namespace Aki.SinglePlayer.Models.Progression
{ {
private bool _isScav; private bool _isScav;
private GameWorld _gameWorld; private GameWorld _gameWorld;
private Player _player;
private float _timer; private float _timer;
private bool _addedToEnemy; private bool _playerFlaggedAsEnemyToBosses;
private List<MineDirectionalColliders> _mines; private List<MineDirectionalColliders> _bridgeMines;
private RecodableItemClass _transmitter; private RecodableItemClass _transmitter;
private List<IAIDetails> _bosses; private List<IAIDetails> _zryachiyAndFollowers = new List<IAIDetails>();
private bool _aggressor; private bool _aggressor;
private bool _disabledDoor; private bool _isDoorDisabled;
private readonly string _transmitterId = "62e910aaf957f2915e0a5e36"; private readonly string _transmitterId = "62e910aaf957f2915e0a5e36";
private readonly string _lightKeeperTid = "638f541a29ffd1183d187f57";
public void Start() public void Start()
{ {
_gameWorld = Singleton<GameWorld>.Instance; _gameWorld = Singleton<GameWorld>.Instance;
_bosses = new List<IAIDetails>(); _player = _gameWorld?.MainPlayer;
_mines = GameObject.FindObjectsOfType<MineDirectionalColliders>().ToList();
if (_gameWorld == null || !string.Equals(_gameWorld.MainPlayer.Location, "lighthouse", System.StringComparison.OrdinalIgnoreCase)) // Exit if not on lighthouse
if (_gameWorld == null || !string.Equals(_player.Location, "lighthouse", System.StringComparison.OrdinalIgnoreCase))
{ {
return; return;
} }
// if player is a scav, there is no need to continue this method. // Expensive, run after gameworld / lighthouse checks above
if (_gameWorld.MainPlayer.Side == EPlayerSide.Savage) _bridgeMines = FindObjectsOfType<MineDirectionalColliders>().ToList();
// Player is a scav, exit
if (_player.Side == EPlayerSide.Savage)
{ {
_isScav = true; _isScav = true;
return; return;
} }
// Get the players Transmitter. _transmitter = GetTransmitterFromInventory();
_transmitter = (RecodableItemClass) _gameWorld.MainPlayer.Profile.Inventory.AllRealPlayerItems.FirstOrDefault(x => x.TemplateId == _transmitterId); if (PlayerHasTransmitterInInventory())
if (_transmitter != null)
{ {
GameObject.Find("Attack").SetActive(false); GameObject.Find("Attack").SetActive(false);
// this zone was added in a newer version and the gameObject actually has a \ // Zone was added in a newer version and the gameObject actually has a \
GameObject.Find("CloseZone\\").SetActive(false); GameObject.Find("CloseZone\\").SetActive(false);
// Give access to the Lightkeepers door. // Give access to Lightkeepers door
_gameWorld.BufferZoneController.SetPlayerAccessStatus(_gameWorld.MainPlayer.ProfileId, true); _gameWorld.BufferZoneController.SetPlayerAccessStatus(_player.ProfileId, true);
} }
} }
public void Update() public void Update()
{ {
if (_gameWorld == null || _addedToEnemy || _disabledDoor || _transmitter == null) return; IncrementLastUpdateTimer();
_timer += Time.deltaTime;
// Exit early if last update() run time was < 10 secs ago
if (_timer < 10f) if (_timer < 10f)
{ {
return; return;
} }
if (_bosses.Count == 0) // Skip if:
// GameWorld missing
// Player not an enemy to Zryachiy
// Lk door not accessible
// Player has no transmitter on thier person
if (_gameWorld == null || _playerFlaggedAsEnemyToBosses || _isDoorDisabled || _transmitter == null)
{ {
SetupBosses(); return;
}
// Find Zryachiy and prep him
if (_zryachiyAndFollowers.Count == 0)
{
SetupZryachiyAndFollowerHostility();
} }
if (_isScav) if (_isScav)
{ {
PlayerIsScav(); MakeZryachiyAndFollowersHostileToPlayer();
return; return;
} }
if (_gameWorld?.MainPlayer?.HandsController?.Item?.TemplateId == _transmitterId) // (active/green)
if (PlayerHasActiveTransmitterInHands())
{ {
if (_transmitter?.RecodableComponent?.Status == RadioTransmitterStatus.Green) SetBridgeMinesStatus(false);
{
foreach (var mine in _mines)
{
if (mine.gameObject.activeSelf)
{
mine.gameObject.SetActive(false);
}
}
}
} }
else else
{ {
foreach (var mine in _mines) SetBridgeMinesStatus(true);
{
if (!mine.gameObject.activeSelf)
{
mine.gameObject.SetActive(true);
}
}
} }
if (_aggressor) if (_aggressor)
{ {
PlayerIsAggressor(); DisableAccessToLightKeeper();
} }
} }
private void SetupBosses() private RecodableItemClass GetTransmitterFromInventory()
{ {
foreach (var aiBot in _gameWorld.AllAlivePlayersList) return (RecodableItemClass)_player.Profile.Inventory.AllRealPlayerItems.FirstOrDefault(x => x.TemplateId == _transmitterId);
{ }
if (!aiBot.IsYourPlayer)
{
// Edge case of bossZryachiy not being hostile to player
if (aiBot.AIData.BotOwner.IsRole(WildSpawnType.bossZryachiy) || aiBot.AIData.BotOwner.IsRole(WildSpawnType.followerZryachiy))
{
// Subscribe to Bosses OnDeath event
aiBot.OnPlayerDeadOrUnspawn += player1 =>
{
if (player1?.KillerId == _gameWorld.MainPlayer.ProfileId)
{
_aggressor = true;
}
};
_bosses.Add(aiBot); private bool PlayerHasTransmitterInInventory()
} {
return _transmitter != null;
}
/// <summary>
/// Update _time to diff from last run of update()
/// </summary>
private void IncrementLastUpdateTimer()
{
_timer += Time.deltaTime;
}
private bool PlayerHasActiveTransmitterInHands()
{
return _gameWorld?.MainPlayer?.HandsController?.Item?.TemplateId == _transmitterId
&& _transmitter?.RecodableComponent?.Status == RadioTransmitterStatus.Green;
}
/// <summary>
/// Set all brdige mines to desire state
/// </summary>
/// <param name="active">What state mines should be</param>
private void SetBridgeMinesStatus(bool active)
{
// Find mines with opposite state of what we want
foreach (var mine in _bridgeMines.Where(mine => mine.gameObject.activeSelf == !active))
{
mine.gameObject.SetActive(active);
}
}
private void SetupZryachiyAndFollowerHostility()
{
// only process non-players (ai)
foreach (var aiBot in _gameWorld.AllAlivePlayersList.Where(x => !x.IsYourPlayer))
{
// Edge case of bossZryachiy not being hostile to player
if (aiBot.AIData.BotOwner.IsRole(WildSpawnType.bossZryachiy) || aiBot.AIData.BotOwner.IsRole(WildSpawnType.followerZryachiy))
{
// Subscribe to bots OnDeath event
aiBot.OnPlayerDeadOrUnspawn += player1 =>
{
// If player kills zryachiy or follower, force aggressor state
// Also set players Lk standing to negative (allows access to quest chain (Making Amends))
if (player1?.KillerId == _player.ProfileId)
{
_aggressor = true;
_player.Profile.TradersInfo[_lightKeeperTid].SetStanding(-0.01);
}
};
// Save bot to list for later access
_zryachiyAndFollowers.Add(aiBot);
} }
} }
} }
private void PlayerIsScav() /// <summary>
/// Iterate over bots gathered from SetupZryachiyHostility()
/// </summary>
private void MakeZryachiyAndFollowersHostileToPlayer()
{ {
// If player is a scav, they must be added to the bosses enemy list otherwise they wont kill them // If player is a scav, they must be added to the bosses enemy list otherwise they wont kill them
foreach (var boss in _bosses) foreach (var bot in _zryachiyAndFollowers)
{ {
boss.AIData.BotOwner.BotsGroup.AddEnemy(_gameWorld.MainPlayer); bot.AIData.BotOwner.BotsGroup.AddEnemy(_player);
} }
_addedToEnemy = true; // Flag player was added to enemy list
_playerFlaggedAsEnemyToBosses = true;
} }
private void PlayerIsAggressor() /// <summary>
/// Disable door + set transmitter to 'red'
/// </summary>
private void DisableAccessToLightKeeper()
{ {
// Disable access to Lightkeepers door for the player // Disable access to Lightkeepers door for the player
_gameWorld.BufferZoneController.SetPlayerAccessStatus(_gameWorld.MainPlayer.ProfileId, false); _gameWorld.BufferZoneController.SetPlayerAccessStatus(_gameWorld.MainPlayer.ProfileId, false);
_transmitter?.RecodableComponent?.SetStatus(RadioTransmitterStatus.Yellow); _transmitter?.RecodableComponent?.SetStatus(RadioTransmitterStatus.Yellow);
_transmitter?.RecodableComponent?.SetEncoded(false); _transmitter?.RecodableComponent?.SetEncoded(false);
_disabledDoor = true; _isDoorDisabled = true;
} }
} }
} }

View File

@ -17,8 +17,10 @@ namespace Aki.SinglePlayer.Patches.Progression
private static void PatchPostfix() private static void PatchPostfix()
{ {
var gameWorld = Singleton<GameWorld>.Instance; var gameWorld = Singleton<GameWorld>.Instance;
if (gameWorld == null || gameWorld.MainPlayer.Location.ToLower() != "lighthouse")
if (gameWorld == null || gameWorld.MainPlayer.Location.ToLower() != "lighthouse") return; {
return;
}
gameWorld.GetOrAddComponent<LighthouseProgressionClass>(); gameWorld.GetOrAddComponent<LighthouseProgressionClass>();
} }