Modding Help [SMAPI]Diference in behavor on 'AfterDayStarted' between loading and on a day afterwards

Discussion in 'Mods' started by Digus, Dec 1, 2017.

  1. Digus

    Digus Spaceman Spiff

    I'm opening a series of dialog in a method that are called by the TimeEvents.AfterDayStarted .

    When loading the game from the title, the game runs for a couple of frames before pausing and showing the dialogs. The screen is in the middle of a fade-in. If there are more than one dialog, you can close one by one without any change on the back screen of the game, it remains in the middle of the fade-in. You can click anywhere on the screen to closes the dialog. When all dialogs are closed, the fade-in resumes and the game go as normal.

    Then, when going to sleep and waiting for the next day to start, the game show the saves message, and just after, the dialogs start to show, no fade-in seems to be happening. After closing the first dialog, a new one show and again, everything seems right. But now, if you click on the back screen instead of the dialog, the screen of the game fades-in. The game does not start, it just fades-in. You have to click again to close the dialog. If there is more, they all happen normally, but now with the back screen already faded-in.

    I looked into the SMAPI code and saw nothing that could be causing this difference. I saw that there is a count down after load that does not happen when starting the next day without loading. But that is not what is causing the issue. I manually implemented another count down in my code and it happen the same way, the only difference is that on the second scenario, the screen will be a little faded-in when the first dialog happen. But the sequence is the same, the problem only happen in the second dialog. You have to do a extra click to close it, since the first one will resume the fade-in.

    The problem is probably some difference in the game code between open a save game and coming from a day before. It's like it places a overlay on the screen that when clicked release the fade-in effect.

    I don't know if anyone can help me since it requires some specific knowledge of the game code.
    I don't have access to my code to show it right now, but later I can upload it an place a link here.
    But it's nothing complicated.
    On the TimeEvents.AfterDayStarted I construct a list. Then I set the messagePause(might be another name) flag and place a GameEvents.UpdateTick . On this updateTick method I go thought the list one by one starting the dialogs. When a dialog is up I just return the updateTick method, so the game handles it normally.
    When the last dialog is closed I remove the GameEvents.UpdateTick event.

    The thing bothering me the most is the extra click to close the second dialog. It gives the player a feel that something when wrong.
     
      Last edited: Dec 1, 2017
    • Digus

      Digus Spaceman Spiff

      One other thing. This second dialog has a "afterDialogBehavior". It opens a choose name menu. The problem happen before closing the dialog, so I thought It has nothing to do with it, but who knows, it's the only difference between these dialogs.
       
        Last edited: Dec 1, 2017
      • Digus

        Digus Spaceman Spiff

        Code:
        public static void NotifyBirthTomorrow()
        {
           List<string> animals = new List<string>();
           foreach (PregnancyItem pregancyItem in AnimalsReadyForBirthTomorrow().ToList())
           {
             FarmAnimal farmAnimal = GetAnimal(pregancyItem.Id);
             if (farmAnimal != null)
             {
               animals.Add(farmAnimal.displayName);
             }   
           }   
           if (animals.Count() > 1)
           {
             string animalsString =  string.Join(", ", animals.Take(animals.Count() - 1)) + " and " + animals.Last();
             Game1.drawObjectDialogue(DataLoader.i18n.Get("Tool.InseminationSyringe.BirthsTomorrow", new { animalNames = animalsString }));
           } else if (animals.Count() == 1)
           {
             Game1.drawObjectDialogue(DataLoader.i18n.Get("Tool.InseminationSyringe.BirthTomorrow", new { animalName = animals.FirstOrDefault() }));
           }   
        }
        
        private static void tickUpdate(object sender, EventArgs e)
        {
           if (Game1.dialogueUp)
             return;
           if (parentAnimal == null)
           {
             if (parentAnimals.Count > 0)
             {
               parentAnimal = parentAnimals.Dequeue();
               if ((parentAnimal.home.indoors as AnimalHouse).isFull())
               {
                 if (!DataLoader.ModConfig.DisableFullBuildingForBirthNotification)
                 {
                   Game1.drawObjectDialogue(DataLoader.i18n.Get("Tool.InseminationSyringe.FullBuilding", new { animalName = parentAnimal.displayName, buildingType = parentAnimal.displayHouse }));
                 }
                 parentAnimal = null;
               }
               else
               {
                 Game1.drawObjectDialogue(Game1.content.LoadString("Strings\\Events:AnimalBirth", (object)parentAnimal.displayName, (object)parentAnimal.shortDisplayType()));
               }
             }
             else
             {
               Game1.messagePause = false;
               GameEvents.UpdateTick -= tickUpdate;
             }
           }
           else if (Game1.activeClickableMenu == null)
           {
             NamingMenu.doneNamingBehavior b = new NamingMenu.doneNamingBehavior(addNewHatchedAnimal);
             string title = Game1.content.LoadString("Strings\\Events:AnimalNamingTitle", (object)parentAnimal.displayType);
             Game1.activeClickableMenu = (IClickableMenu)new NamingMenu(b, title, (string)null);
           }
        }
        
        private static void addNewHatchedAnimal(string name)
        {
           Building building = parentAnimal.home;
           FarmAnimal farmAnimal = new FarmAnimal(parentAnimal.type, MultiplayerUtility.getNewID(), Game1.player.uniqueMultiplayerID)
           {
             name = name,
             displayName = name,
             parentId = parentAnimal.myID,
             home = building,
             homeLocation = new Vector2((float)building.tileX, (float)building.tileY)
           };
           farmAnimal.setRandomPosition(farmAnimal.home.indoors);
           (building.indoors as AnimalHouse).animals.Add(farmAnimal.myID, farmAnimal);
           (building.indoors as AnimalHouse).animalsThatLiveHere.Add(farmAnimal.myID);
        
           PregnancyItem pregnacyItem = PregnancyController.GetPregnancyItem(parentAnimal.myID);
           parentAnimal.allowReproduction = pregnacyItem.AllowReproductionBeforeInsemination;
           PregnancyController.RemovePregnancyItem(pregnacyItem.Id);
           parentAnimal = null;
        
           Game1.exitActiveMenu();
        }
        Here is the code.
        There is no 'afterDialogBehavior', it is just afterwards with the NamingMenu . The problem happen before that is ever called.
         
        • Digus

          Digus Spaceman Spiff

          I completely removed the creation of the NamingMenu and replaced with just
          Code:
          parentAnimal = null;
          The problem persisted, so it has nothing to do with that.
           
          • Pathoschild

            Pathoschild Tiy's Beard

            That difference is by design. SMAPI adds a small delay between the game load and the AfterDayStarted event because the game isn't fully loaded when the fade-in starts. That isn't an issue on a day transition, so there's no delay then.

            Can you post a zip of your full mod code so I see what it's doing?
             
            • Digus

              Digus Spaceman Spiff

              That I learned after one weekend trying to find a way to do the birth before the screen fades in and giving up.

              Just uploaded the version I'm testing in to my git:
              https://github.com/Digus/StardewValleyMods/tree/version_1.3.0/ButcherMod

              If you want to test what is happening, here is my save file:
              https://www.dropbox.com/s/3lumzc5dl0lumaa/Modder_166466185.rar?dl=0
              And the mod data, it needs to be unpacked inside the ButcherMod folder, it has the data to make the birth happen.
              https://www.dropbox.com/s/9zg6jvrp45evtwx/data.rar?dl=0

              You need to start the day, them sleep again. On the day transition, it will notify about one birth next day. On the next dialog, it will say some animal gave birth last night. Now, if you click outside of the dialog box, instead of closing it, it will fade in the screen and the dialog is still open. You have to click again to close the dialog. Then it goes as expected.

              If you then close the game and load again on the same day, that does not happen. The game will only resume fadein after all dialogs are closed, and no extra click in need to close any dialog.

              I already know it's not a problem with SMAPI, just the away the game handle the flux of events. I'm just trying to find a way to do what I want consistently. I will probably just check if the game is completely fade in before showing any dialog.
               
              • Digus

                Digus Spaceman Spiff

                Well, I found an acceptable solution for my problem.
                I changed the code to handle all dialog shows in the tickUpdate.
                Now the tickUpdate only do stuff if the 'fadeToBlackAlpha' is 0 or less.
                I'm also only pausing the game after that, otherwise it does not work when loading. (the screen ill be permanently dark, when loading, the game does not update fadeToBlackAlpha if the messagePause flag is set)

                This way my messages will start just after the fade in happen in both cases. And no extra click is needed to close any dialog. I could not find where in the game code this extra click was implemented to resume the fade in, so this is a acceptable work around.
                 
                  Pathoschild likes this.

                Share This Page