Skip to content

Commit

Permalink
Fix effects being unbound while still required
Browse files Browse the repository at this point in the history
  • Loading branch information
Jofairden committed Jul 12, 2018
1 parent 67834fa commit f021a2f
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 48 deletions.
156 changes: 109 additions & 47 deletions Modifiers/ModifierCachePlayer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using CheatSheet;
Expand All @@ -15,7 +16,7 @@ namespace Loot.Modifiers
* \\WHEN NEEDED\\. This means only 'active' items are being updated, that means any held item
* and items that are equipped (armor/accessory)
*/

/// <summary>
/// The following code caches the item held and items equipped by players
/// When equips and held items change, their respective modifiers' effects are automatically
Expand All @@ -25,22 +26,24 @@ namespace Loot.Modifiers
public sealed class ModifierCachePlayer : ModPlayer
{
private bool IsMouseUsable(Item item) => item.damage > 0;

private Item _oldHeldItem;
private Item[] _oldEquips;
private bool _forceEquipUpdate;
private Item[] _oldCheatSheetEquips;
internal bool Ready;
private List<Type> _modifierEffects;

public override void Initialize()
{
_oldHeldItem = null;
_oldEquips = new Item[8];
_forceEquipUpdate = false;
_oldCheatSheetEquips = new Item[6]; // MaxExtraAccessories = 6
_modifierEffects = new List<Type>();
Ready = false;
}

// Automatically binds the delegations for a player and given modifier
// Will look for the UsesEffect attribute on the Modifier, which links
// that modifier to any effects. If there are effects in present,
Expand Down Expand Up @@ -80,21 +83,25 @@ private void AutoDetach(Item item, Player player, Modifier modifier)
{
AutoBindDelegations(player, modifier, (modplr, methods, effect) =>
{
if (effect.IsBeingDelegated)
// type checks make sure we dont unbind any effects that are used by
// other items being equipped right now
if (effect.IsBeingDelegated && !_modifierEffects.Contains(effect.GetType()))
{
modplr.OnResetEffects -= effect.ResetEffects;
foreach (MethodInfo method in methods)
{
var attr = method.GetCustomAttribute<AutoDelegation>();
attr.Detach(modplr, method, effect);
}

effect._DetachDelegations(item, modplr);
effect.IsBeingDelegated = false;
}

ActivatedModifierItem.Item(item).IsActivated = false;
});
}

private void AutoAttach(Item item, Player player, Modifier modifier)
{
AutoBindDelegations(player, modifier, (modplr, methods, effect) =>
Expand All @@ -107,22 +114,71 @@ private void AutoAttach(Item item, Player player, Modifier modifier)
var attr = method.GetCustomAttribute<AutoDelegation>();
attr.Attach(modplr, method, effect);
}

effect.AttachDelegations(item, modplr);
effect.IsBeingDelegated = true;
}

ActivatedModifierItem.Item(item).IsActivated = true;
});
}

private void CacheModifierEffects(Player player)
{
bool anyDifferentEquip = player.armor.Take(8 + player.extraAccessorySlots)
.Select((x, i) => new {Value = x, Index = i})
.Any(x => _oldEquips[x.Index] != null && x.Value.IsNotTheSameAs(_oldEquips[x.Index]));

// Only recache if needed, so check if there are changes
if ((_oldHeldItem != null && _oldHeldItem.IsNotTheSameAs(player.HeldItem))
|| anyDifferentEquip)
{
_modifierEffects.Clear();

for (int i = 0; i < 8 + player.extraAccessorySlots; i++)
{
var equip = player.armor[i];
if (equip != null && !equip.IsAir)
CacheItemModifierEffects(equip);
}

if (player.HeldItem != null && !player.HeldItem.IsAir)
CacheItemModifierEffects(player.HeldItem);
}
}

private void CacheItemModifierEffects(Item item)
{
var mods = EMMItem.GetActivePool(item);
foreach (var modifier in mods)
{
var effectsAttribute = modifier
.GetType()
.GetCustomAttribute<UsesEffect>();

if (effectsAttribute != null)
{
ModifierPlayer modPlayer = ModifierPlayer.Player(player);
foreach (Type effect in effectsAttribute.Effects)
{
var modEffect = modPlayer.GetEffect(effect);
if (modEffect != null) _modifierEffects.Add(modEffect.GetType());
}
}
}
}

public override void PreUpdate()
{
CacheModifierEffects(player);

// If held item needs an update
if (_oldHeldItem == null || _oldHeldItem.IsNotTheSameAs(player.HeldItem))
{
Ready = false;

// detach old held item
if (_oldHeldItem != null && !_oldHeldItem.IsAir && IsMouseUsable(_oldHeldItem))
if (_oldHeldItem != null && !_oldHeldItem.IsAir && IsMouseUsable(_oldHeldItem))
{
foreach (Modifier m in EMMItem.GetActivePool(_oldHeldItem))
{
Expand Down Expand Up @@ -172,7 +228,6 @@ public override void PreUpdate()
// attach new
if (newEquip != null && !newEquip.IsAir)
{

foreach (Modifier m in EMMItem.GetActivePool(newEquip))
{
AutoAttach(newEquip, player, m);
Expand All @@ -185,61 +240,68 @@ public override void PreUpdate()

if (Loot.CheatSheetLoaded)
{
// get cheat sheet slots
var curEquips = CheatSheetInterface.GetEnabledExtraAccessories(player).Take(_oldCheatSheetEquips.Length).ToArray();
UpdateCheatSheetCache();
}

_forceEquipUpdate = false;
Ready = true;
}

// This needs to be separate because of CheatSheetInterface static reference
// to not freak out JIT
private void UpdateCheatSheetCache()
{
// get cheat sheet slots
var curEquips = CheatSheetInterface.GetEnabledExtraAccessories(player).Take(_oldCheatSheetEquips.Length).ToArray();

// go over enabled slots
for (int i = 0; i < curEquips.Length; i++)
{
var oldEquip = _oldCheatSheetEquips[i];
var newEquip = curEquips[i];

// go over enabled slots
for (int i = 0; i < curEquips.Length; i++)
// update delegations
if (oldEquip == null || newEquip.IsNotTheSameAs(oldEquip))
{
var oldEquip = _oldCheatSheetEquips[i];
var newEquip = curEquips[i];
Ready = false;

// update delegations
if (oldEquip == null || newEquip.IsNotTheSameAs(oldEquip))
// detach old first
if (oldEquip != null && !oldEquip.IsAir)
{
Ready = false;

// detach old first
if (oldEquip != null && !oldEquip.IsAir)
foreach (Modifier m in EMMItem.GetActivePool(oldEquip))
{
foreach (Modifier m in EMMItem.GetActivePool(oldEquip))
{
AutoDetach(oldEquip, player, m);
}
AutoDetach(oldEquip, player, m);
}

// attach new
if (newEquip != null && !newEquip.IsAir)
}

// attach new
if (newEquip != null && !newEquip.IsAir)
{
foreach (Modifier m in EMMItem.GetActivePool(newEquip))
{
foreach (Modifier m in EMMItem.GetActivePool(newEquip))
{
AutoAttach(newEquip, player, m);
}
AutoAttach(newEquip, player, m);
}

_oldCheatSheetEquips[i] = newEquip;
}

_oldCheatSheetEquips[i] = newEquip;
}
}

// current enabled is smaller than total
if (curEquips.Length < _oldCheatSheetEquips.Length)
// current enabled is smaller than total
if (curEquips.Length < _oldCheatSheetEquips.Length)
{
var outOfDateEquips = _oldCheatSheetEquips.Skip(curEquips.Length);
if (outOfDateEquips.Any()) Ready = false;

// for all disabled slots but still had a registered item, detach it
foreach (var item in outOfDateEquips.Where(x => x != null && !x.IsAir))
{
var outOfDateEquips = _oldCheatSheetEquips.Skip(curEquips.Length);
if (outOfDateEquips.Any()) Ready = false;

// for all disabled slots but still had a registered item, detach it
foreach (var item in outOfDateEquips.Where(x => x!= null && !x.IsAir))
foreach (Modifier m in EMMItem.GetActivePool(item))
{
foreach (Modifier m in EMMItem.GetActivePool(item))
{
AutoDetach(item, player, m);
}
AutoDetach(item, player, m);
}
}
}

_forceEquipUpdate = false;
Ready = true;
}
}
}
2 changes: 1 addition & 1 deletion build.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
author = Jofairden
version = 0.1.0.6
version = 0.1.0.7
displayName = Even More Modifiers
homepage = https://forums.terraria.org/index.php?threads/even-more-modifiers-relaunch-beta.68438/
hideCode = false
Expand Down

0 comments on commit f021a2f

Please sign in to comment.