Coding Help Exceptions while trying to add a Buff to the game. [SOLVED]

SomeoneEls

Sodbuster
The idea is that a buff will be added to the game periodically to the bpm of a song. Here is the code for the method itself, but I highlighted with //problem here to show where the problem area is. This is supposed to be run by a thread.

public void OSTBPM(object o)
{
string track = "";
bool running = false;
Action<object> wait = (j) =>
{
string t = track;
Game1.showRedMessage("Great!",false);
for(int tim = 0; tim< 50; tim++)
{
if(t != track)
{
break;
}
Thread.Sleep(1);
}
running = false;
};


buffDataMusic = new BuffAttributesData();
buffDataMusic.AttackMultiplier = 3;
buffDataMusic.LuckLevel = 3;

buffEffectsMusic = new BuffEffects(buffDataMusic);

int val = 0;
while (true)
{
try
{
track = Game1.getMusicTrackName();

while (Game1.getMusicTrackName() != null && BPM.TryGetValue(Game1.getMusicTrackName(), out val) && Game1.player != null && track == Game1.getMusicTrackName())
{
val /= 2;
for(int tim = 0; tim< val-75; tim++)
{
Thread.Sleep(1);
if(Game1.getMusicTrackName() != track)
{
break;
}

}
if(Game1.getMusicTrackName() == track)
{


for(int tim = 0; tim< 150; tim++)
{

// Problem here.
musicAttack = new Buff("1337", "none", "none", 150, null, 20, buffEffectsMusic, false, "MusicBuff", "Only active now")

Game1.player.applyBuff(musicAttack);


if (Game1.getMusicTrackName() != track)
{
break;
}
if(Helper.Input.IsDown(SButton.MouseLeft) && running == false)
{

running = true;
new Thread(new ParameterizedThreadStart(wait)).Start();
}

Thread.Sleep(1);
}


}


}
}
catch (Exception e)
{
while(!(Game1.getMusicTrackName() != null && BPM.TryGetValue(Game1.getMusicTrackName(), out val) && Game1.player != null))
{
Thread.Sleep(1);
//Console.WriteLine("fail");
}
}
}
}

The problem itself is an exception which is here. It happens almost randomly.
Edit: this was not the core problem, as there were more exceptions due to the new buffs.
[game] An error occurred in the base update loop: ArgumentNullException: Value cannot be null. (Parameter 'key')
at System.Collections.Generic.Dictionary`2.FindValue(TKey key)
at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value)
at StardewValley.Buffs.BuffManager.Update(GameTime time) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Buffs\BuffManager.cs:line 266
at StardewValley.Farmer.Update(GameTime time, GameLocation location) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Farmer.cs:line 7301
at StardewValley.Game1.UpdateCharacters(GameTime time) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Game1.cs:line 10676
at StardewValley.Game1._update(GameTime gameTime) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Game1.cs:line 4324
at StardewValley.Game1.Update(GameTime gameTime) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Game1.cs:line 3454
at StardewModdingAPI.Framework.SCore.OnPlayerInstanceUpdating(SGame instance, GameTime gameTime, Action runUpdate) in /home/pathoschild/git/SMAPI/src/SMAPI/Framework/SCore.cs:line 1094

For some reason, musicAttack has to be defined in the for loop it in or the game thinks that the milliseconds duration is null. I'm adding a new key that isn't in the buffs file, so this might be an issue?
Ill see if I can add it, but for now, any help would be great :D
 
Last edited:

SomeoneEls

Sodbuster
Learned that this causes a crash when trying to play the lewis community center cutscene at the start of the game.


UPDATE: I fixed this by adding IL code via Transpliers. This was hell. However, some more exceptions still exist

[game] An error occurred in the base update loop: InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator.MoveNext()
at StardewValley.Buffs.BuffManager.GetValues() in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Buffs\BuffManager.cs:line 125
at StardewValley.Buffs.BuffManager.Update_PatchedBy<SomeoneEls.chaosaddon>(BuffManager this, GameTime time)
at StardewValley.Farmer.Update(GameTime time, GameLocation location)
at StardewValley.Game1.UpdateCharacters(GameTime time)
at StardewValley.Game1._update(GameTime gameTime)
at StardewValley.Game1.Update(GameTime gameTime)
at StardewModdingAPI.Framework.SCore.OnPlayerInstanceUpdating(SGame instance, GameTime gameTime, Action runUpdate)

[game] An error occurred in the base update loop: ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
at StardewValley.Buffs.BuffManager.Update(GameTime time) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Buffs\BuffManager.cs:line 264
at StardewValley.Farmer.Update(GameTime time, GameLocation location) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Farmer.cs:line 7301
at StardewValley.Game1.UpdateCharacters(GameTime time) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Game1.cs:line 10676
at StardewValley.Game1._update(GameTime gameTime) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Game1.cs:line 4324
at StardewValley.Game1.Update(GameTime gameTime) in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\Game1.cs:line 3454

Plus there was an issue where the thread method just fails. I dunno why.

Here is the IL code if intrested. Im confident that its fine, as these 'new' issues had existed before I changed the code in this way. I marked the injected code with [new code here]

### Patch: System.Void StardewValley.Buffs.BuffManager::Update(Microsoft.Xna.Framework.GameTime time)
### Replacement: static System.Void StardewValley.Buffs.BuffManager::StardewValley.Buffs.BuffManager.Update_PatchedBy<SomeoneEls.chaosaddon>(StardewValley.Buffs.BuffManager this, Microsoft.Xna.Framework.GameTime time)
AccessTools.Property: Could not find property for type StardewValley.Buffs.BuffManager and name AppliedBuffIds
IL_0000: Local var 0: System.Int32
IL_0000: Local var 1: System.String
IL_0000: Local var 2: StardewValley.Buff
IL_0000: // start original
IL_0000: ldarg.0
IL_0001: callvirt virtual System.Boolean StardewValley.Buffs.BuffManager::IsLocallyControlled()
IL_0006: brtrue => Label0
IL_000B: br => Label7
IL_0010: Label0
IL_0010: ldarg.0
IL_0011: ldfld Netcode.NetStringList StardewValley.Buffs.BuffManager::AppliedBuffIds
IL_0016: callvirt virtual System.Int32 Netcode.NetList`2<System.String, Netcode.NetString>::get_Count()
IL_001B: ldc.i4.1
IL_001C: sub
IL_001D: stloc.0
IL_001E: br => Label1
IL_0023: Label4
IL_0023: ldarg.0
IL_0024: ldfld Netcode.NetStringList StardewValley.Buffs.BuffManager::AppliedBuffIds
IL_0029: ldloc.0
IL_002A: callvirt virtual System.String Netcode.NetList`2<System.String, Netcode.NetString>::get_Item(System.Int32 index)
IL_002F: stloc.1
[new code here]
IL_0030: ldloc.1
IL_0031: ldnull
IL_0032: ceq
IL_0034: brtrue => Label6
[new code here]
IL_0039: ldarg.0
IL_003A: ldfld System.Collections.Generic.IDictionary`2<System.String, StardewValley.Buff> StardewValley.Buffs.BuffManager::AppliedBuffs
IL_003F: ldloc.1
IL_0040: ldloca.s 2 (StardewValley.Buff)
IL_0042: callvirt abstract virtual System.Boolean System.Collections.Generic.IDictionary`2<System.String, StardewValley.Buff>::TryGetValue(System.String key, StardewValley.Buff& value)
IL_0047: brfalse => Label2
IL_004C: ldloc.2
IL_004D: ldarg.1
IL_004E: callvirt virtual System.Boolean StardewValley.Buff::update(Microsoft.Xna.Framework.GameTime time)
IL_0053: brfalse => Label3
IL_0058: Label2
IL_0058: ldarg.0
IL_0059: ldloc.1
IL_005A: call System.Void StardewValley.Buffs.BuffManager::Remove(System.String id)
IL_005F: Label3
IL_005F: ldloc.0
IL_0060: ldc.i4.1
IL_0061: sub
IL_0062: stloc.0
IL_0063: Label1
IL_0063: ldloc.0
IL_0064: ldc.i4.0
IL_0065: bge => Label4
IL_006A: ldarg.0
IL_006B: ldfld System.Boolean StardewValley.Buffs.BuffManager::Dirty
IL_0070: brfalse => Label5
IL_0075: ldarg.0
IL_0076: callvirt virtual StardewValley.Buffs.BuffEffects StardewValley.Buffs.BuffManager::GetValues()
IL_007B: pop
IL_007C: Label5
IL_007C: br => Label8
IL_0081: Label6
IL_0081: nop
IL_0082: // end original
IL_0082: Label7
IL_0082: Label8
IL_0082: ret
DONE






EDIT2: I think I figured out what to do to fix the "Collection was modified; enumeration operation may not execute." exception. Its based on this thread on stack overflow. https://stackoverflow.com/questions...odified-enumeration-operation-may-not-execute
Basically, because AppliedBuffs is changing so fast, the AppliedBuffs.Keys is changed while it is being added to. Adding .toList() hopefully will fix this.
 
Last edited:

SomeoneEls

Sodbuster
Yeah, im stupid. Seems like the solution to all of this was uh.. just not updating the game 150 times to add a buff.

for(int tim = 0; tim< 150; tim++)
{

// Problem here.
musicAttack = new Buff("1337", "none", "none", 150, null, 20, buffEffectsMusic, false, "MusicBuff", "Only active now")

Game1.player.applyBuff(musicAttack);
.
.
.
this wasnt supposed to be inside the for loop. I am facepalming so hard rn.
 
Top