Even More Modifiers  1.0.0.0
A mod for rolling various bonus stats on items
RollingStrategy.cs
Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Linq;
3 using Loot.Api.Core;
4 using Loot.Api.Delegators;
5 using Loot.Api.Graphics;
7 using Terraria;
8 using Terraria.ID;
9 using Terraria.Utilities;
10 
11 namespace Loot.Api.Strategy
12 {
13  public abstract class RollingStrategy
14  {
15  // Forces the next roll to succeed
16  protected bool _forceNextRoll;
17 
20 
21  private void InitFields(Item item, RollingStrategyProperties properties)
22  {
23  this.properties = properties;
24  modifierItem = LootModItem.GetInfo(item);
25  }
26 
27  private WeightedRandom<Modifier> GetRandomList(ModifierContext context, ModifierPool pool)
28  {
29  WeightedRandom<Modifier> wr = new WeightedRandom<Modifier>();
30  foreach (var e in pool.GetRollableModifiers(context))
31  {
32  wr.Add(e, e.Properties.RollChance);
33  }
34  return wr;
35  }
36 
37  internal List<Modifier> _Roll(ModifierPool pool, ModifierContext modifierContext, RollingStrategyProperties properties)
38  {
39  InitFields(modifierContext.Item, properties);
40  var list = PreRoll(pool, modifierContext, properties);
41  list = Roll(list, pool, modifierContext, properties);
42  PostRoll(ref list, pool, modifierContext, properties);
43  GraphicsGlobalItem.UpdateGraphicsEntities(list, modifierContext.Item);
44  return list;
45  }
46 
47  public virtual void PlaySoundEffect(Item item)
48  {
49  Main.PlaySound(SoundID.Item37, -1, -1);
50  }
51 
52  public virtual List<Modifier> Roll(List<Modifier> currentModifiers, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
53  {
54  if (currentModifiers.Count >= properties.MaxRollableLines)
55  {
56  return currentModifiers;
57  }
58 
59  WeightedRandom<Modifier> wr = new WeightedRandom<Modifier>();
60  if (modifierContext.Pool != null)
61  {
62  foreach (var modifier in modifierContext.Pool.GetRollableModifiers(modifierContext))
63  {
64  wr.Add(modifier, modifier.Properties.RollChance);
65  }
66  }
67  else if (modifierContext.PoolSet != null && modifierContext.PoolSet.Any())
68  {
69  var randomPool = modifierContext.PoolSet[Main.rand.Next(modifierContext.PoolSet.Count - 1)];
70  foreach (var modifier in randomPool.GetRollableModifiers(modifierContext))
71  {
72  wr.Add(modifier, modifier.Properties.RollChance);
73  }
74  }
75  else
76  {
77  wr = GetRandomList(modifierContext, drawPool);
78  }
79 
80  var list = currentModifiers;
81 
82  if (properties.MinRollableLines > properties.MaxRollableLines)
83  properties.MaxRollableLines = properties.MinRollableLines;
84 
85  // Up to n times, try rolling a mod
86  for (int i = 0; i < properties.MaxRollableLines; ++i)
87  {
88  int z = currentModifiers.Count;
89  Modifier line = null;
90  int tries = 0;
91 
92  while (tries < 4 && currentModifiers.Count < properties.MaxRollableLines)
93  {
94  line = PreRollLine(ref currentModifiers, drawPool, modifierContext, properties) ?? RollLine(currentModifiers, drawPool, modifierContext, properties, wr);
95  if (line == null) continue;
96  currentModifiers.Add(line);
97  PostRollLine(ref currentModifiers, line, drawPool, modifierContext, properties);
98  if (currentModifiers.Count > z) break;
99  }
100 
101  // If it is a unique modifier, remove it from the list to be rolled
102  if (line != null && line.Properties.IsUnique)
103  {
104  wr.elements.RemoveAll(x => x.Item1.Type == line.Type);
105  wr.needsRefresh = true;
106  }
107  }
108 
109  return list;
110  }
111 
112  public virtual List<Modifier> PreRoll(ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
113  {
114  var preset = properties?.PresetLines?.Invoke() ?? new List<Modifier>();
115  preset.ForEach(x => RollProperties(x, preset, modifierContext, properties));
116  preset.ForEach(x => x.Roll(modifierContext, preset));
117  return preset;
118  }
119 
120  public virtual void PostRoll(ref List<Modifier> modifiers, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
121  {
122 
123  }
124 
125  public virtual Modifier PreRollLine(ref List<Modifier> currentModifiers, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
126  {
127  return null;
128  }
129 
130  public virtual Modifier RollLine(List<Modifier> currentModifiers, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties, WeightedRandom<Modifier> weightedRandom)
131  {
132  // If there are no mods left, or we fail the roll, break.
133  if (weightedRandom.elements.Count <= 0
134  || !_forceNextRoll
135  && currentModifiers.Count >= properties.MinRollableLines
136  && Main.rand.NextFloat() > properties.RollNextChance)
137  {
138  return null;
139  }
140 
141  _forceNextRoll = false;
142 
143  // Get a next weighted random mod
144  // Clone the mod (new instance) and roll its properties, then roll it
145  Modifier rolledModifier = (Modifier)weightedRandom.Get().Clone();
146  RollProperties(rolledModifier, currentModifiers, modifierContext, properties);
147 
148  rolledModifier.Roll(modifierContext, currentModifiers);
149 
150  // If the mod deemed to be unable to be added,
151  // Force that the next roll is successful
152  // (no RNG on top of RNG)
153  if (!rolledModifier.PostRoll(modifierContext, currentModifiers))
154  {
155  _forceNextRoll = true;
156  return null;
157  }
158 
159  return rolledModifier;
160  }
161 
162  public virtual void PostRollLine(ref List<Modifier> modifiers, Modifier line, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
163  {
164  }
165 
166  private void RollProperties(Modifier modifier, List<Modifier> modifiers, ModifierContext modifierContext, RollingStrategyProperties properties)
167  {
168  float luck = properties.ExtraLuck;
169  float magnitudePower = properties.MagnitudePower;
170 
171  if (modifierContext.Player != null)
172  {
173  luck += ModifierDelegatorPlayer.GetPlayer(modifierContext.Player).GetEffect<LuckEffect>().Luck;
174  }
175  if (modifierContext.Rarity != null)
176  {
177  luck += modifierContext.Rarity.ExtraLuck;
178  magnitudePower += modifierContext.Rarity.ExtraMagnitudePower;
179  }
180 
181  modifier.Properties =
182  modifier.GetModifierProperties(modifierContext.Item)
183  .Build()
184  .RollMagnitudeAndPower(magnitudePower, luck);
185  }
186  }
187 
188 }
static void UpdateGraphicsEntities(List< Modifier > modifiers, Item item)
Defines a modifier, which is an unloaded GlobalItem Making it a GlobalItem gives easy access to all h...
Definition: Modifier.cs:21
void InitFields(Item item, RollingStrategyProperties properties)
virtual void PostRoll(ref List< Modifier > modifiers, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
int MaxRollableLines
The maximum amount of modifiers that can roll
This class is responsible for handling ShaderEntity and GlowmaskEntity that come from the Modifiers o...
float ExtraLuck
Gives extra luck when rolling modifiers
RollingStrategyProperties properties
ModifierProperties RollMagnitudeAndPower(float magnitudePower=1f, float lukStat=0f)
Defines a context in which a Modifier might be rolled Which fields are available (not null) depends o...
float RollNextChance
Chance to roll a consecutive modifier
List< ModifierPool > PoolSet
ModifierProperties Properties
Definition: Modifier.cs:44
virtual List< Modifier > Roll(List< Modifier > currentModifiers, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
void RollProperties(Modifier modifier, List< Modifier > modifiers, ModifierContext modifierContext, RollingStrategyProperties properties)
Defines properties that will be used when an item is being rolled in a IRollingStrategy<T> These can ...
virtual void PostRollLine(ref List< Modifier > modifiers, Modifier line, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
virtual Modifier RollLine(List< Modifier > currentModifiers, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties, WeightedRandom< Modifier > weightedRandom)
virtual void Clone(ref Modifier clone)
Allows modders to do custom cloning here Happens after default cloning, which clones various info (mo...
Definition: Modifier.cs:100
Defines an item that may be modified by modifiers from mods
Definition: LootModItem.cs:21
static ModifierDelegatorPlayer GetPlayer(Player player)
virtual Modifier PreRollLine(ref List< Modifier > currentModifiers, ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
Defines a modifier pool. A modifier pool holds a certain amount of effects in an array It allows to r...
Definition: ModifierPool.cs:37
static LootModItem GetInfo(Item item)
virtual void PlaySoundEffect(Item item)
virtual void Roll(ModifierContext ctx, IEnumerable< Modifier > rolledModifiers)
Allows modders to do something when the modifier is rolled in the given context The passed rolledModi...
Definition: Modifier.cs:74
virtual List< Modifier > PreRoll(ModifierPool drawPool, ModifierContext modifierContext, RollingStrategyProperties properties)
float MagnitudePower
The minimum strength of lines to roll
virtual bool PostRoll(ModifierContext ctx, IEnumerable< Modifier > rolledModifiers)
Returns if the modifier will actually be added after it is rolled. This is called after Roll is calle...
virtual ModifierProperties.ModifierPropertiesBuilder GetModifierProperties(Item item)
WeightedRandom< Modifier > GetRandomList(ModifierContext context, ModifierPool pool)
Func< List< Modifier > > PresetLines
Returns a list of lines that will be rolled initially
Holds player-entity data and handles it
int MinRollableLines
The minimum amount of modifiers to roll