Modding Help NullReferenceException help?

Discussion in 'Mods' started by AlisterAzimuth, Oct 15, 2016.

  1. AlisterAzimuth

    AlisterAzimuth Scruffy Nerf-Herder

    So I'm making a good bit of headway into my mod, I've got it to where it loads easily enough without inhibiting the startup of StardewModdingAPI, and it's recognized and accounted for. HOWEVER, when I go to trigger the event to test it, It displays this message:

    [02:41: 35.166 PM] An exception occured in XNA UpdateTick: System.NullReferenceException: Object reference not set to an instance of an object.
    at FriendlierNPCs.FriendlierNPCs.GameEvents_UpdateTick(Object sender, EventArgs e)
    at System.EventHandler.Invoke(Object sender, EventArgs e)
    at StardewModdingAPI.Events.GameEvents.InvokeUpdateTick()


    From what I looked up and what Visual Studio's telling me, I'm getting a null error because of a field never being used, and a field is never assigned to, and therefore defaulting the value to null.

    Here's the code in its latest iteration before building the DLL

    using StardewModdingAPI;
    using StardewValley;
    using System;

    namespace FriendlierNPCs
    {
    public class FriendlierNPCs : Mod
    {
    private Event currentEvent;
    private readonly object name;
    private readonly object Mine;

    public override void Entry(params object[] objects)
    {
    StardewModdingAPI.Events.GameEvents.UpdateTick += GameEvents_UpdateTick;
    }

    private void GameEvents_UpdateTick(object sender, EventArgs e)
    {
    if (Game1.killScreen && !Game1.eventUp)
    {
    if (this.name.Equals("Mine"))
    {
    string text;
    string text2;
    switch (Game1.random.Next(7))
    {
    case 0:
    text = "Robin";
    text2 = "Data\\ExtraDialogue:Mines_PlayerKilled_Robin";
    goto IL_B8;
    case 1:
    text = "Clint";
    text2 = "Data\\ExtraDialogue:Mines_PlayerKilled_Clint";
    goto IL_B8;
    case 2:
    text = "Abigail";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Abigail")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Abigail_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Abigail_NotSpouse");
    goto IL_B8;
    case 3:
    text = "Alex";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Alex")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Alex_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Alex_NotSpouse");
    goto IL_B8;
    case 4:
    text = "Elliot";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Elliot")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Elliott_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Elliott_NotSpouse");
    goto IL_B8;
    case 5:
    text = "Emily";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Emily")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Emily_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Emily_NotSpouse");
    goto IL_B8;
    case 6:
    text = "Haley";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Haley")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Haley_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Haley_NotSpouse");
    goto IL_B8;
    case 7:
    text = "Harvey";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Harvey")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Harvey_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Harvey_NotSpouse");
    goto IL_B8;
    case 8:
    text = "Leah";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Leah")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Leah_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Leah_NotSpouse");
    goto IL_B8;
    case 9:
    text = "Maru";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Maru")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Maru_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Maru_NotSpouse");
    goto IL_B8;
    case 10:
    text = "Penny";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Penny")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Penny_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Penny_NotSpouse");
    goto IL_B8;
    case 11:
    text = "Sam";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Sam")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Sam_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Sam_NotSpouse");
    goto IL_B8;
    case 12:
    text = "Sebastian";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Sebastian")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Sebastian_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Sebastian_NotSpouse");
    goto IL_B8;
    case 13:
    text = "Shane";
    text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Shane")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Shane_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Shane_NotSpouse");
    goto IL_B8;
    }
    text = "Linus";
    text2 = "Data\\ExtraDialogue:Mines_PlayerKilled_Linus";
    IL_B8:
    if (Game1.random.NextDouble() < 0.1 && Game1.player.spouse != null && !Game1.player.spouse.Contains("engaged") && Game1.player.spouse.Length > 1)
    {
    text = Game1.player.spouse;
    text2 = (Game1.player.isMale ? "Data\\ExtraDialogue:Mines_PlayerKilled_Spouse_PlayerMale" : "Data\\ExtraDialogue:Mines_PlayerKilled_Spouse_PlayerFemale");
    }
    this.currentEvent = new Event(Game1.content.LoadString("Data\\Events\\Mine: PlayerKilled", new object[]
    {
    text,
    text2,
    Game1.player.name
    }), -1);
    }
    else if (this.name.Equals("Hospital"))
    {
    this.currentEvent = new Event(Game1.content.LoadString("Data\\Events\\Hospital: PlayerKilled", new object[]
    {
    Game1.player.name
    }), -1);
    }
    }
    }

    }
    }​

    I'm not very sure how to rectify this, and I'd gladly appreciate any pointers. Sometimes the solution's right in my face and I can't see it until it's pointed to me.

    Cheers!
     
    • VIspReaderUS

      VIspReaderUS Void-Bound Voyager

      try deleting

      private readonly object Mine; // you're not using this?

      and change

      private readonly object name; >> private string name = "mine";

      you dont even initialized 'name'.
       
      • AlisterAzimuth

        AlisterAzimuth Scruffy Nerf-Herder

        Well I applied what you said, and it got the errors to stop, although it's not creating the desired results of what I want, plus it produced a bug that's mainly aesthetic in nature

        None of the listed NPCs are going to retrieve the player aside from the default four, and when the death animation is triggered, the sprite freezes in the last frame to the action before death.
         
        • VIspReaderUS

          VIspReaderUS Void-Bound Voyager

          i have no idea what you're trying to do
           
          • AlisterAzimuth

            AlisterAzimuth Scruffy Nerf-Herder

            Essentially, I'm trying to get the rest of the bachelors/bachelorettes to go to the caves to retrieve the player when they die, like Maru does. This mod is supposed to give those permissions to the rest of the NPCs to go in the caves and retrieve the player.

            So say for instance Maru can go in there despite not being a spouse, and get the player. I'm trying to give that ability to Elliott,Sam,Sebastian,Alex,Shane and Harvey along with Emily, Abigail, Leah, Penny, and Haley.

            What's not working is the game isn't choosing from the listed NPC list I provided, despite having the extraDialogue.xnb edited and prepared to give them dialogue in this setting.
             
            • VIspReaderUS

              VIspReaderUS Void-Bound Voyager

              yeah, im stumped... i havent got a chance to testing events stuff yet, so im not much of a help here
               
              • AlisterAzimuth

                AlisterAzimuth Scruffy Nerf-Herder

                Ah, it's fine. It's better than it was before at least. Maybe it has something to do with when the mod itself is loaded into SMAPI
                 
                • VIspReaderUS

                  VIspReaderUS Void-Bound Voyager

                  check each line from top to bottom and see if its doing what it supposed to do, if{} everything...xD... log.aSync("passed")... log all strings... one step at a time
                   
                  • maddy99

                    maddy99 Big Damn Hero

                    I'd change these -
                    string text;
                    string text2;

                    to

                    string text = string.empty;
                    string text2 = string.empty;

                    and maybe your events -
                    this.currentEvent = new Event(Game1.content.LoadString("Data\\Events\\XXXXXX: PlayerKilled", new object[]
                    {
                    Game1.player.name
                    }), -1);

                    to

                    var killedString = Game1.content.LoadString("Data\\Events\\XXXXXX: PlayerKilled", new object[]
                    {
                    Game1.player.name
                    });

                    if (killedString != null)
                    {
                    this.currentEvent = new Event(Game1.content.LoadString("Data\\Events\\XXXXXX: PlayerKilled", new object[]
                    {
                    Game1.player.name
                    }), -1);
                    }

                    Also, maybe throw some debug messages to dump current values for those variables. Any that are null should still throw an error instead of printing.
                     
                    • AlisterAzimuth

                      AlisterAzimuth Scruffy Nerf-Herder

                      I just now tried that, and it gave me a whole new slew of ; expected errors and one ) expected error.

                      I'm not very sure if I'm rewriting these right :(
                       
                      • maddy99

                        maddy99 Big Damn Hero

                        Intellisense and all that should be catching most of those and telling you where the errors are("if (killedString != null) ;" should be "if (killedString != null)" for starters), what tool are you using to write your code?

                        Edit: The below code should compile -

                        using StardewModdingAPI;
                        using StardewValley;
                        using System;

                        namespace FriendlierNPCs
                        {
                        public class FriendlierNPCs : Mod
                        {
                        private Event currentEvent;
                        private string name = "Mine";
                        public override void Entry(params object[] objects)
                        {
                        StardewModdingAPI.Events.GameEvents.UpdateTick += GameEvents_UpdateTick;
                        }

                        private void GameEvents_UpdateTick(object sender, EventArgs e)
                        {
                        if (Game1.killScreen && !Game1.eventUp)
                        {
                        if (this.name.Equals("Mine"))
                        {
                        string text = string.Empty;
                        string text2 = string.Empty;
                        switch (Game1.random.Next(14))
                        {
                        case 0:
                        text = "Robin";
                        text2 = "Data\\ExtraDialogue:Mines_PlayerKilled_Robin";
                        goto IL_B8;
                        case 1:
                        text = "Clint";
                        text2 = "Data\\ExtraDialogue:Mines_PlayerKilled_Clint";
                        goto IL_B8;
                        case 2:
                        text = "Abigail";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Abigail")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Abigail_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Abigail_NotSpouse");
                        goto IL_B8;
                        case 3:
                        text = "Alex";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Alex")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Alex_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Alex_NotSpouse");
                        goto IL_B8;
                        case 4:
                        text = "Elliot";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Elliot")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Elliott_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Elliott_NotSpouse");
                        goto IL_B8;
                        case 5:
                        text = "Emily";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Emily")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Emily_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Emily_NotSpouse");
                        goto IL_B8;
                        case 6:
                        text = "Haley";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Haley")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Haley_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Haley_NotSpouse");
                        goto IL_B8;
                        case 7:
                        text = "Harvey";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Harvey")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Harvey_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Harvey_NotSpouse");
                        goto IL_B8;
                        case 8:
                        text = "Leah";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Leah")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Leah_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Leah_NotSpouse");
                        goto IL_B8;
                        case 9:
                        text = "Maru";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Maru")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Maru_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Maru_NotSpouse");
                        goto IL_B8;
                        case 10:
                        text = "Penny";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Penny")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Penny_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Penny_NotSpouse");
                        goto IL_B8;
                        case 11:
                        text = "Sam";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Sam")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Sam_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Sam_NotSpouse");
                        goto IL_B8;
                        case 12:
                        text = "Sebastian";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Sebastian")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Sebastian_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Sebastian_NotSpouse");
                        goto IL_B8;
                        case 13:
                        text = "Shane";
                        text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals("Shane")) ? "Data\\ExtraDialogue:Mines_PlayerKilled_Shane_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_Shane_NotSpouse");
                        goto IL_B8;
                        }
                        text = "Linus";
                        text2 = "Data\\ExtraDialogue:Mines_PlayerKilled_Linus";
                        IL_B8:
                        if (Game1.random.NextDouble() < 0.1 && Game1.player.spouse != null && !Game1.player.spouse.Contains("engaged") && Game1.player.spouse.Length > 1)
                        {
                        text = Game1.player.spouse;
                        text2 = (Game1.player.isMale ? "Data\\ExtraDialogue:Mines_PlayerKilled_Spouse_PlayerMale" : "Data\\ExtraDialogue:Mines_PlayerKilled_Spouse_PlayerFemale");
                        }
                        var killedString = Game1.content.LoadString(Game1.content.LoadString("Data\\Events\\Mine:playerKilled", new object[]
                        {
                        text,
                        text2,
                        Game1.player.name
                        }));
                        if (killedString != null)
                        {
                        this.currentEvent = new
                        Event(killedString, -1);
                        }
                        }
                        else if (this.name.Equals("Hospital"))
                        {
                        this.currentEvent = new Event(Game1.content.LoadString("Data\\Events\\Hospital:playerKilled", new object[]
                        {
                        Game1.player.name
                        }), -1);
                        }
                        }
                        }

                        }
                        }
                         
                        • AlisterAzimuth

                          AlisterAzimuth Scruffy Nerf-Herder

                          I'm using Microsoft Visual Studio 2016, and as for the code you provided I ran through SMAPI I got this error:
                          [10:06:10.400 PM] An exception occured in XNA UpdateTick: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.​
                          at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
                          at StardewValley.LocalizedContentManager.LoadString(String path, Object[] substitutions)
                          at FriendlierNPCs.FriendlierNPCs.GameEvents_UpdateTick(Object sender, EventArgs e)
                          at System.EventHandler.Invoke(Object sender, EventArgs e)
                          at StardewModdingAPI.Events.GameEvents.InvokeUpdateTick()

                          Sorry if I seem to not understand a lot of stuff, first time modding that isn't simple xnb modding.
                           
                          • maddy99

                            maddy99 Big Damn Hero

                            No worries.

                            That error basically says that whatever string you passed to LoadString as a key wasn't found. If you wrap that block in a try/catch, you can spit out whatever string it was.
                             
                            • AlisterAzimuth

                              AlisterAzimuth Scruffy Nerf-Herder

                              How exactly would I put that into play? Because to tell you the truth this is my first time looking at C# and trying to write in it.
                               
                              • maddy99

                                maddy99 Big Damn Hero

                                I hope you don't mind, I've cleaned it up a bit to make it a bit easier to work with for you. I only partially implemented the NPC dictionary though, so you'll need to flesh that out, but this gives an example of a try/catch as well as hopefully an easier to manage list of NPCs. This should functionally be identical to your original code, I haven't tested it however.


                                using StardewModdingAPI;
                                using StardewValley;
                                using System;
                                using System.Collections.Generic;

                                namespace FriendlierNPCs
                                {
                                public class FriendlierNPCs : Mod
                                {
                                private Event currentEvent;
                                private string name = "Mine";

                                private Dictionary<int, string> npcDictionary;

                                public override void Entry(params object[] objects)
                                {
                                StardewModdingAPI.Events.GameEvents.UpdateTick += GameEvents_UpdateTick;
                                _InitializeDictionary();
                                }

                                private void _InitializeDictionary()
                                {
                                //Add new NPCs here
                                npcDictionary = new Dictionary<int, string>();
                                npcDictionary.Add(0, "Robin");
                                npcDictionary.Add(1, "Clint");
                                npcDictionary.Add(2, "Abigail");
                                npcDictionary.Add(3, "Alex");
                                }

                                private void GameEvents_UpdateTick(object sender, EventArgs e)
                                {
                                if (Game1.killScreen && !Game1.eventUp)
                                {
                                string location = string.Empty;
                                string text = string.Empty;
                                string text2 = string.Empty;


                                if (this.name.Equals("Mine"))
                                {
                                location = "Mine";

                                var index = Game1.random.Next(14);

                                if (npcDictionary.ContainsKey(index))
                                {
                                text = npcDictionary[index];
                                }
                                else
                                {
                                text = "Linus";
                                }

                                if (text == "Robin" || text == "Clint" || text == "Linus")
                                {
                                text2 = "Data\\ExtraDialogue:Mines_PlayerKilled_" + text;
                                }
                                else
                                {
                                text2 = ((Game1.player.spouse != null && Game1.player.spouse.Equals(text)) ? "Data\\ExtraDialogue:Mines_PlayerKilled_" + text + "_Spouse" : "Data\\ExtraDialogue:Mines_PlayerKilled_" + text + "_NotSpouse");
                                }

                                if (Game1.random.NextDouble() < 0.1 && Game1.player.spouse != null && !Game1.player.spouse.Contains("engaged") && Game1.player.spouse.Length > 1)
                                {
                                text = Game1.player.spouse;
                                text2 = (Game1.player.isMale ? "Data\\ExtraDialogue:Mines_PlayerKilled_Spouse_PlayerMale" : "Data\\ExtraDialogue:Mines_PlayerKilled_Spouse_PlayerFemale");
                                }

                                var killedString = Game1.content.LoadString(Game1.content.LoadString("Data\\Events\\Mine:playerKilled", new object[]
                                {
                                text,
                                text2,
                                Game1.player.name
                                }));
                                if (killedString != null)
                                {
                                this.currentEvent = new
                                Event(killedString, -1);
                                }
                                }
                                // Unless "name" is reset, this'll never fire.
                                else if (this.name.Equals("Hospital"))
                                {
                                location = "Hospital";
                                }

                                var killerString = string.Empty;

                                try
                                {
                                var obj = location == "Mine" ? new object[] { text, text2, Game1.player.name } : new object[] { Game1.player.name };
                                killerString = Game1.content.LoadString("Data\\Events\\" + location + ":playerKilled", obj);

                                this.currentEvent = new Event(killerString);
                                }
                                catch(Exception ex)
                                {
                                Log.Error("ERROR: Dumping Values");
                                Log.Error("Text = " + text);
                                Log.Error("Text2 = " + text2);
                                Log.Error("Location = " + location);
                                Log.Error("KillerString = " + killerString);
                                Log.Error("ERROR: " + ex.Message);
                                }
                                }
                                }
                                }
                                }
                                 
                                • Entoarox

                                  Entoarox Oxygen Tank

                                  At the top of your tick event, add the following:

                                  Code:
                                  if(!Game1.hasLoadedGame)
                                      return;
                                  From what I can tell, you are running code before a savegame is loaded, and a lot of properties are not yet set without a savegame.


                                  Also, `this.name.Equals` should be `Game1.currentLocation.name.Equals`
                                   
                                  • AlisterAzimuth

                                    AlisterAzimuth Scruffy Nerf-Herder

                                    So regarding the above code, it should look something like this?:
                                    Code:
                                    public class FriendlierNPCs : Mod
                                        {
                                            private Event currentEvent;
                                            private string name = "Mine";
                                            public override void Entry(params object[] objects)
                                            {
                                                if (!Game1.hasLoadedGame)
                                                    return;
                                                StardewModdingAPI.Events.GameEvents.UpdateTick += GameEvents_UpdateTick;
                                            }
                                    
                                            private void GameEvents_UpdateTick(object sender, EventArgs e)
                                    
                                    
                                    If so it seems to not throw a bunch of errors in my face, although it still loads before choosing a save file.
                                     
                                    • Entoarox

                                      Entoarox Oxygen Tank

                                      No, you need to add the if to the updateTick event, as it currently stands your event never even registers.
                                       
                                      • AlisterAzimuth

                                        AlisterAzimuth Scruffy Nerf-Herder

                                        I'm probably doing this all wrong then, because I've put it in various spots and have gotten the same result. Mod loading before a chosen save state and all.
                                         
                                        • VIspReaderUS

                                          VIspReaderUS Void-Bound Voyager

                                          xD....paste your whole code
                                           

                                          Share This Page