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:
parent
8b4847714c
commit
aa9a1af8c4
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user