/// <summary>Refreshes creature information based on how much information the save file contains</summary>
        internal static void LoadCreatureSkins()
        {
            foreach (FarmAnimal animal in ModApi.GetAnimals())
            {
                ModEntry.UpdateSkin(animal);
            }

            foreach (Pet pet in ModApi.GetPets())
            {
                // Remove extra Strays left on the map
                if (ModApi.IsStray(pet))
                {
                    Game1.removeThisCharacterFromAllLocations(pet);
                }
                else
                {
                    ModEntry.UpdateSkin(pet);
                }
            }

            foreach (Horse horse in ModApi.GetHorses())
            {
                // Remove extra WildHorses left on the map
                if (ModApi.IsWildHorse(horse))
                {
                    Game1.removeThisCharacterFromAllLocations(horse);
                }
                else if (ModApi.IsNotATractor(horse))
                {
                    ModEntry.UpdateSkin(horse);
                }
            }
        }
        /// <summary>Load skin assets from the /assets/skins directory into the A&S database</summary>
        internal static void LoadAssets()
        {
            // Gather handled types
            string validTypes = string.Join(", ", ModApi.GetHandledAllTypes());

            foreach (string path in Directory.EnumerateFiles(Path.Combine(SHelper.DirectoryPath, "assets", "skins"), "*", SearchOption.AllDirectories))
            {
                string   extension = Path.GetExtension(path);
                string   fileName  = Path.GetFileNameWithoutExtension(path);
                string[] nameParts = fileName.Split(new[] { '_' }, 2);
                string   type      = ModEntry.Sanitize(nameParts[0]);
                int      skinID    = 0;

                if (!ValidExtensions.Contains(extension))
                {
                    ModEntry.SMonitor.Log($"Ignored skin `{fileName}` with invalid extension (extension must be one of type {string.Join(", ", ValidExtensions)})", LogLevel.Warn);
                }
                else if (!ModEntry.Assets.ContainsKey(type))
                {
                    ModEntry.SMonitor.Log($"Ignored skin `{fileName}` with invalid naming convention (can't parse {nameParts[0]} as an animal, pet, or horse. Expected one of type: {validTypes})", LogLevel.Warn);
                }
                else if (nameParts.Length != 2)
                {
                    ModEntry.SMonitor.Log($"Ignored skin `{fileName} with invalid naming convention (no skin ID found)", LogLevel.Warn);
                }
                else if (nameParts.Length == 2 && !int.TryParse(nameParts[1], out skinID))
                {
                    ModEntry.SMonitor.Log($"Ignored skin `{fileName}` with invalid skin ID (can't parse {nameParts[1]} as a number)", LogLevel.Warn);
                }
                else if (skinID <= 0)
                {
                    ModEntry.SMonitor.Log($"Ignored skin `{fileName}` with skin ID of less than or equal to 0. Skins must have an ID of at least 1.", LogLevel.Warn);
                }
                else
                {
                    // File naming is valid, add asset into system
                    string assetKey = SHelper.Content.GetActualAssetKey(Path.Combine(Path.GetDirectoryName(path), extension.Equals("xnb") ? Path.GetFileNameWithoutExtension(path) : Path.GetFileName(path)));
                    ModEntry.Assets[type].Add(skinID, new AnimalSkin(type, skinID, assetKey));
                }
            }

            // Print loaded assets to console
            StringBuilder summary = new StringBuilder();

            summary.AppendLine(
                "Statistics:\n"
                + "\n  Registered types: " + validTypes
                + "\n  Skins:"
                );
            foreach (KeyValuePair <string, Dictionary <int, AnimalSkin> > skinEntry in ModEntry.Assets)
            {
                if (skinEntry.Value.Count > 0)
                {
                    summary.AppendLine($"    {skinEntry.Key}: {skinEntry.Value.Count} skins ({string.Join(", ", skinEntry.Value.Select(p => Path.GetFileName(p.Value.AssetKey)).OrderBy(p => p))})");
                }
            }

            ModEntry.SMonitor.Log(summary.ToString(), LogLevel.Trace);
            ModEntry.AssetsLoaded = true;
        }
Exemple #3
0
        /// <summary>Creates a new WildHorse instance</summary>
        internal WildHorse()
        {
            // Create WildHorse traits
            SkinID = ModEntry.GetRandomSkin(ModEntry.Sanitize(typeof(Horse).Name));
            Map    = Game1.getLocationFromName(SpawningMaps[Randomizer.Next(0, SpawningMaps.Count)]);
            Tile   = GetRandomSpawnLocation(Map);

            // Create Horse instance
            HorseInstance = new Horse(new Guid(), (int)Tile.X, (int)Tile.Y)
            {
                Manners     = WildID,
                Name        = "Wild horse",
                displayName = "Wild horse"
            };

            int[] info = ModApi.GetSpriteInfo(HorseInstance);
            if (SkinID != 0)
            {
                HorseInstance.Sprite = new AnimatedSprite(ModEntry.GetSkin(ModEntry.Sanitize(typeof(Horse).Name), SkinID).AssetKey, info[0], info[1], info[2]);
            }

            // Put that thing where it belongs
            Game1.warpCharacter(HorseInstance, Map, Tile);

            if (ModEntry.Config.NotifyHorseSpawn)
            {
                string message = $"A wild horse has been spotted at: {Map.Name} -- {Tile.X}, {Tile.Y}";
                ModEntry.SMonitor.Log(message, LogLevel.Debug);
                Game1.chatBox.addInfoMessage(message);
            }
        }
Exemple #4
0
        /// <summary>Creates a new Stray</summary>
        internal Stray()
        {
            // Create Stray traits
            PetType = ModEntry.PetTypeMap.Keys.ToList()[Randomizer.Next(0, ModEntry.PetTypeMap.Count)];
            SkinID  = ModEntry.GetRandomSkin(PetType);

            // Create Pet instance
            PetInstance                     = (Pet)Activator.CreateInstance(ModEntry.PetTypeMap[PetType], (int)CreationLocation.X, (int)CreationLocation.Y);
            PetInstance.Manners             = StrayID;
            PetInstance.Name                = "Stray";
            PetInstance.displayName         = "Stray";
            PetInstance.farmerPassesThrough = true;

            int[] info = ModApi.GetSpriteInfo(PetInstance);
            PetInstance.Sprite = new AnimatedSprite(ModEntry.GetSkin(PetType, SkinID).AssetKey, info[0], info[1], info[2]);

            // Put that thing where it belongs
            Game1.warpCharacter(PetInstance, Marnies, CreationLocation);

            if (ModEntry.Config.NotifyStraySpawn)
            {
                string message = $"A stray pet is available to adopt at Marnie's!";
                ModEntry.SMonitor.Log(message, LogLevel.Debug);
                Game1.chatBox.addInfoMessage(message);
            }
        }
 /// <summary>Spawns all owned pets into the FarmHouse</summary>
 internal void IndoorWeatherPetSpawn()
 {
     foreach (Pet pet in ModApi.GetPets())
     {
         pet.warpToFarmHouse(Game1.player);
     }
 }
        internal static void SaveData(object s, EventArgs e)
        {
            // Only allow the host player to save Adopt & Skin data
            if (!Context.IsMainPlayer)
            {
                return;
            }

            // Ensure strays and wild horses don't persist
            ModApi.ClearUnownedPets();

            // Save skin and category maps
            SHelper.Data.WriteSaveData("skin-map", ModEntry.SkinMap);
            SHelper.Data.WriteSaveData("id-to-category", ModEntry.IDToCategory);

            // Save Short ID maps
            SHelper.Data.WriteSaveData("animal-long-to-short-ids", ModEntry.AnimalLongToShortIDs);
            SHelper.Data.WriteSaveData("animal-short-to-long-ids", ModEntry.AnimalShortToLongIDs);

            // Save Stray and WildHorse spawn potential
            SHelper.Data.WriteSaveData("first-pet-received", ModEntry.Creator.FirstPetReceived.ToString());
            SHelper.Data.WriteSaveData("first-horse-received", ModEntry.Creator.FirstHorseReceived.ToString());

            // Save data version. May be used for reverse-compatibility for files.
            SHelper.Data.WriteSaveData("data-version", "4");

            // Remove Adopt & Skin from update loop
            StopUpdateChecks(null, null);
        }
Exemple #7
0
        /// <summary>Checks whether the user's cursor is currently over a Pet or Horse and updates the text to display in the tooltip</summary>
        internal void HoverCheck()
        {
            bool    isHovering = false;
            Vector2 mousePos   = new Vector2(Game1.getOldMouseX() + Game1.viewport.X, Game1.getOldMouseY() + Game1.viewport.Y) / Game1.tileSize;

            // Show pet tooltip
            foreach (Pet pet in ModApi.GetPets())
            {
                if (IsWithinSpriteBox(mousePos, pet))
                {
                    isHovering = true;
                    HoverText  = pet.displayName;
                }
            }
            // Show horse tooltip
            foreach (Horse horse in ModApi.GetHorses())
            {
                if (IsWithinSpriteBox(mousePos, horse))
                {
                    isHovering = true;
                    HoverText  = horse.displayName;
                }
            }

            // Clear hover text when not hovering over a pet or horse
            if (!isHovering)
            {
                HoverText = null;
            }
        }
Exemple #8
0
        public void RegisterBFAVAnimals()
        {
            Dictionary <string, string[]> bfavAnimals = BFAVApi.GetFarmAnimalsByCategory("2");

            foreach (KeyValuePair <string, string[]> pair in bfavAnimals)
            {
                foreach (string type in pair.Value)
                {
                    // Only register types that are not already registered
                    if (!ModApi.IsRegisteredType(type))
                    {
                        string newType = ModEntry.Sanitize(pair.Key);
                        if (newType.Contains("dinosaur"))
                        {
                            ModApi.RegisterAnimalType(type, false, false);
                        }
                        else if (newType.Contains("sheep"))
                        {
                            ModApi.RegisterAnimalType(type, true, true);
                        }
                        else
                        {
                            ModApi.RegisterAnimalType(type);
                        }
                    }
                }
            }
        }
Exemple #9
0
 public static void ClearUnownedPets()
 {
     foreach (NPC npc in Utility.getAllCharacters())
     {
         if (npc is Horse horse && ModApi.IsWildHorse(horse))
         {
             Game1.removeThisCharacterFromAllLocations(horse);
         }
Exemple #10
0
 /// <summary>Returns an enumerable list of all owned Pet instances. This excludes strays.</summary>
 public static IEnumerable <Pet> GetPets()
 {
     foreach (NPC npc in Utility.getAllCharacters())
     {
         if (npc is Pet pet && !ModApi.IsStray(pet))
         {
             yield return(pet);
         }
     }
 }
        /**************************
        ** Setup + Load/Save Logic
        ***************************/

        /// <summary>Sets up initial values needed for A&S.</summary>
        internal static void Setup(object sender, SaveLoadedEventArgs e)
        {
            ModApi.RegisterDefaultTypes();
            IntegrateMods();

            LoadAssets();

            // Remove the Setup from the loop, so that it isn't done twice when the player returns to the title screen and loads again
            SHelper.Events.GameLoop.SaveLoaded -= Setup;
        }
Exemple #12
0
        /// <summary>Checks that the given argument is of a recognized creature group or recognized creature type.</summary>
        /// <param name="arg">The argument to be checked</param>
        /// <returns>Returns true if the given argument is stored in CreatureGroups or is a known FarmAnimal, Pet, or Horse type. Otherwise gives a console error report and returns false.</returns>
        internal static bool EnforceArgTypeGroup(string arg)
        {
            string        type         = ModEntry.Sanitize(arg);
            List <string> handledTypes = ModApi.GetHandledAllTypes();

            if (!CreatureGroups.Contains(type) && !handledTypes.Contains(type))
            {
                ModEntry.SMonitor.Log($"Argument given isn't one of {string.Join(", ", CreatureGroups)}, or a handled creature type. Handled types:\n{string.Join(", ", handledTypes)}", LogLevel.Error);
                return(false);
            }

            return(true);
        }
Exemple #13
0
        /// <summary>Return the information on a pet or horse that the list_animals console command uses.
        internal static string GetPrintString(Character creature)
        {
            List <string> handledTypes = new List <string>();
            string        name         = "";
            string        type         = "";
            int           shortID      = 0;
            int           skinID       = 0;

            switch (creature)
            {
            case Horse horse:
                handledTypes = ModApi.GetHandledHorseTypes();
                name         = horse.Name;
                type         = ModEntry.Sanitize(horse.GetType().Name);
                shortID      = horse.Manners;
                skinID       = ModEntry.HorseSkinMap[horse.Manners];
                break;

            case Pet pet:
                handledTypes = ModApi.GetHandledPetTypes();
                name         = pet.Name;
                type         = ModEntry.Sanitize(pet.GetType().Name);
                shortID      = pet.Manners;
                skinID       = ModEntry.PetSkinMap[pet.Manners];
                break;

            case FarmAnimal animal:
                handledTypes = ModApi.GetHandledAnimalTypes();
                name         = animal.Name;
                type         = ModEntry.Sanitize(animal.type.Value);
                shortID      = ModEntry.AnimalLongToShortIDs[animal.myID.Value];
                skinID       = ModEntry.AnimalSkinMap[animal.myID.Value];
                break;

            default:
                return("");
            }

            if (handledTypes.Contains(type))
            {
                return($"\n # {name}:  Type - {type}\n" +
                       $"Short ID:   {shortID}\n" +
                       $"Skin ID:    {skinID}");
            }
            else
            {
                return($"\n # {name}:  Type - {type}\n" +
                       "Skin type not handled\n");
            }
        }
        /*********************************
        ** H O R S E   A D O P T I O N **
        *********************************/

        /// <summary>Adopts and names the wild horse being interacted with. Called in the CheckHorse event handler.</summary>
        internal void HorseNamer(string horseName)
        {
            // Name Horse and add to Adopt & Skin database
            HorseInfo.HorseInstance.Name        = horseName;
            HorseInfo.HorseInstance.displayName = horseName;
            HorseInfo.HorseInstance.HorseId     = ModApi.GetRandomStableID();
            Earth.AddCreature(HorseInfo.HorseInstance, HorseInfo.SkinID);

            // Horse is no longer a WildHorse to keep track of
            HorseInfo = null;

            // Exit the naming menu
            Game1.drawObjectDialogue($"Adopted {horseName}.");
        }
        /// <summary>Refreshes creature information based on how much information the save file contains</summary>
        internal static void LoadCreatureSkins()
        {
            foreach (FarmAnimal animal in ModApi.GetAnimals())
            {
                if (!ModEntry.AnimalLongToShortIDs.ContainsKey(ModEntry.GetLongID(animal)))
                {
                    Entry.AddCreature(animal);
                }
                else
                {
                    ModEntry.UpdateSkin(animal);
                }
            }


            foreach (Pet pet in ModApi.GetPets())
            {
                // Remove extra Strays left on the map
                if (ModApi.IsStray(pet))
                {
                    Game1.removeThisCharacterFromAllLocations(pet);
                }
                else if (ModEntry.GetLongID(pet) == 0)
                {
                    Entry.AddCreature(pet);
                }
                else
                {
                    ModEntry.UpdateSkin(pet);
                }
            }

            foreach (Horse horse in ModApi.GetHorses())
            {
                // Remove extra WildHorses left on the map
                if (ModApi.IsWildHorse(horse))
                {
                    Game1.removeThisCharacterFromAllLocations(horse);
                }
                else if (ModApi.IsNotATractor(horse) && ModEntry.GetLongID(horse) == 0)
                {
                    Entry.AddCreature(horse);
                }
                else if (ModApi.IsNotATractor(horse))
                {
                    ModEntry.UpdateSkin(horse);
                }
            }
        }
        /// <summary>Returns the first Stable instance found on the farm.</summary>
        internal static Guid GetStableID()
        {
            Guid stableID = ZeroHorseID;

            foreach (Horse horse in ModApi.GetHorses())
            {
                if (horse.HorseId != ZeroHorseID)
                {
                    stableID = horse.HorseId;
                    break;
                }
            }

            return(stableID);
        }
Exemple #17
0
 /// <summary>Returns an enumerable list of all existing Horse instances. This includes WildHorses and excludes tractors.</summary>
 public static IEnumerable <Horse> GetAllHorses()
 {
     foreach (NPC npc in Utility.getAllCharacters())
     {
         if (npc is Horse horse && ModApi.IsNotATractor(horse))
         {
             yield return(horse);
         }
     }
     // Horses being ridden don't technically exist, and must be added separately
     foreach (Horse horse in ModEntry.BeingRidden)
     {
         yield return(horse);
     }
 }
Exemple #18
0
        /**************************
        ** Setup + Load/Save Logic
        ***************************/

        /// <summary>Sets up initial values needed for A&S.</summary>
        internal static void Setup(object sender, SaveLoadedEventArgs e)
        {
            // Register FarmAnimal Types
            Dictionary <string, string> farmAnimalData = ModEntry.SHelper.Content.Load <Dictionary <string, string> >("Data/FarmAnimals", ContentSource.GameContent);

            foreach (KeyValuePair <string, string> pair in farmAnimalData)
            {
                // Ignore unused FarmAnimal type in SDV code
                if (pair.Key.ToLower() == "hog" || pair.Key.ToLower() == "babyhog")
                {
                    continue;
                }

                string[] animalInfo  = pair.Value.Split(new[] { '/' });
                string   harvestTool = animalInfo[22];
                int      maturedDay  = int.Parse(animalInfo[1]);

                ModApi.RegisterType(pair.Key, typeof(FarmAnimal), maturedDay > 0, ModEntry.Sanitize(harvestTool) == "shears");
            }

            // Register default supported pet types
            ModApi.RegisterType("cat", typeof(Cat));
            ModApi.RegisterType("dog", typeof(Dog));

            // Register horse type
            ModApi.RegisterType("horse", typeof(Horse));

            LoadAssets();

            // Alert player that there are creatures with no skins loaded for them
            List <string> skinless = new List <string>();

            foreach (string type in ModEntry.Assets.Keys)
            {
                if (ModEntry.Assets[type].Count == 0)
                {
                    skinless.Add(type);
                }
            }
            if (skinless.Count > 0)
            {
                ModEntry.SMonitor.Log($"NOTICE: The following creature types have no skins located in `/assets/skins`:\n" +
                                      $"{string.Join(", ", skinless)}", LogLevel.Debug);
            }

            // Remove the Setup from the loop, so that it isn't done twice when the player returns to the title screen and loads again
            SHelper.Events.GameLoop.SaveLoaded -= Setup;
        }
Exemple #19
0
        internal static void SaveData(object s, EventArgs e)
        {
            // Only allow the host player to save Adopt & Skin data
            if (!Context.IsMainPlayer)
            {
                return;
            }

            // Ensure strays and wild horses don't persist
            ModApi.ClearUnownedPets();

            // Save skin and category maps
            SHelper.Data.WriteSaveData("skin-map", ModEntry.SkinMap);
            SHelper.Data.WriteSaveData("id-to-category", ModEntry.IDToCategory);

            // Save Short ID maps
            SHelper.Data.WriteSaveData("animal-long-to-short-ids", ModEntry.AnimalLongToShortIDs);
            SHelper.Data.WriteSaveData("animal-short-to-long-ids", ModEntry.AnimalShortToLongIDs);

            // Save Pet to owner map

            /*Dictionary<long, long> petOwnership = new Dictionary<long, long>();
             * foreach (KeyValuePair<long, Farmer> pair in ModEntry.OwnerMap)
             * {
             *  petOwnership[pair.Key] = ModApi.FarmerToID(pair.Value);
             * }
             * SHelper.Data.WriteSaveData("pet-ownership-map", petOwnership); */
            // Save Horse to owner map
            Dictionary <long, long> horseOwnership = new Dictionary <long, long>();

            foreach (KeyValuePair <long, Farmer> pair in ModEntry.HorseOwnershipMap)
            {
                horseOwnership[pair.Key] = ModApi.FarmerToID(pair.Value);
            }
            SHelper.Data.WriteSaveData("horse-ownership-map", horseOwnership);

            // Save Stray and WildHorse spawn potential
            SHelper.Data.WriteSaveData("first-pet-received", ModEntry.Creator.FirstPetReceived.ToString());
            SHelper.Data.WriteSaveData("first-horse-received", ModEntry.Creator.FirstHorseReceived.ToString());

            // Save data version. May be used for reverse-compatibility for files.
            SHelper.Data.WriteSaveData("data-version", "5");

            // Remove Adopt & Skin from update loop
            StopUpdateChecks(null, null);
        }
Exemple #20
0
        /// <summary>Return the information on a pet or horse that the list_animals console command uses.
        internal static string GetPrintString(Character creature)
        {
            string name    = creature.Name;
            string type    = ModApi.GetInternalType(creature);
            int    shortID = ModEntry.GetShortID(creature);
            long   longID  = ModEntry.GetLongID(creature);
            int    skinID  = 0;

            if (ModEntry.SkinMap.ContainsKey(longID))
            {
                skinID = ModEntry.SkinMap[longID];
            }

            return($"\n # {name}:  Type - {type}\n" +
                   $"Short ID:   {shortID}\n" +
                   $"Skin ID:    {skinID}");
        }
        /// <summary>Refreshes creature information based on how much information the save file contains</summary>
        internal static void LoadCreatureSkins()
        {
            foreach (FarmAnimal animal in ModApi.GetAnimals())
            {
                if (!ModEntry.AnimalLongToShortIDs.ContainsKey(ModEntry.GetLongID(animal)))
                {
                    Entry.AddCreature(animal);
                }
                else
                {
                    ModEntry.UpdateSkin(animal);
                }
            }


            foreach (Pet pet in ModApi.GetPets())
            {
                if (ModEntry.GetLongID(pet) == 0)
                {
                    Entry.AddCreature(pet);
                }
                else
                {
                    ModEntry.UpdateSkin(pet);
                }
            }

            foreach (Horse horse in ModApi.GetHorses())
            {
                if (ModEntry.GetLongID(horse) == 0)
                {
                    Entry.AddCreature(horse);
                }
                else
                {
                    ModEntry.UpdateSkin(horse);
                }
            }
        }
Exemple #22
0
        /// <summary>Creates a new Stray</summary>
        internal Stray()
        {
            // Create Stray traits
            PetType = ModEntry.PetTypeMap.Keys.ToList()[Randomizer.Next(0, ModEntry.PetTypeMap.Count)];
            SkinID  = ModEntry.GetRandomSkin(PetType);

            // Create Pet instance
            PetInstance                     = PetConstructors[ModEntry.PetTypeMap[PetType]]();
            PetInstance.Manners             = StrayID;
            PetInstance.Name                = "Stray";
            PetInstance.displayName         = "Stray";
            PetInstance.farmerPassesThrough = true;

            int[] info = ModApi.GetSpriteInfo(PetInstance);
            if (SkinID != 0)
            {
                PetInstance.Sprite = new AnimatedSprite(ModEntry.GetSkin(PetType, SkinID).AssetKey, info[0], info[1], info[2]);
            }

            // Put that thing where it belongs
            PetInstance.currentLocation = Marnies;
            Game1.warpCharacter(PetInstance, Marnies, CreationLocation);
        }
        /// <summary>Creates a new WildHorse instance</summary>
        internal WildHorse()
        {
            // Create WildHorse traits
            SkinID = ModEntry.GetRandomSkin(ModEntry.Sanitize(typeof(Horse).Name));
            Map    = Game1.getLocationFromName(PlayerSpecifiedSpawnMaps[Randomizer.Next(0, PlayerSpecifiedSpawnMaps.Count)]);
            Tile   = GetRandomSpawnLocation(Map);

            // Create Horse instance
            HorseInstance = new Horse(new Guid(), (int)Tile.X, (int)Tile.Y)
            {
                Manners     = WildID,
                Name        = "Wild horse",
                displayName = "Wild horse"
            };

            int[] info = ModApi.GetSpriteInfo(HorseInstance);
            if (SkinID != 0)
            {
                HorseInstance.Sprite = new AnimatedSprite(ModEntry.GetSkin(ModEntry.Sanitize(typeof(Horse).Name), SkinID).AssetKey, info[0], info[1], info[2]);
            }

            // Put that thing where it belongs
            Game1.warpCharacter(HorseInstance, Map, Tile);
        }
        internal void SpreadPets(object sender, WarpedEventArgs e)
        {
            List <Pet> pets = ModApi.GetPets().ToList();

            // No pets are in the game
            if (pets.Count == 0)
            {
                return;
            }

            // Only do teleport if the player is entering the Farm, FarmHouse, or Marnie's
            if (!typeof(Farm).IsAssignableFrom(e.NewLocation.GetType()) &&
                !typeof(FarmHouse).IsAssignableFrom(e.NewLocation.GetType()) &&
                (Stray.Marnies != e.NewLocation))
            {
                return;
            }

            // Ensure Stray isn't moved around by vanilla
            ModEntry.Creator.MoveStrayToSpawn();


            if (IsIndoorWeather())
            {
                IndoorWeatherPetSpawn();
                return;
            }
            else
            {
                // Find area to warp pets to
                Farm           farm          = Game1.getFarm();
                int            initX         = (int)pets[0].getTileLocation().X;
                int            initY         = (int)pets[0].getTileLocation().Y;
                List <Vector2> warpableTiles = new List <Vector2>();
                int            cer           = ModEntry.Config.CuddleExplosionRadius;

                // Collect a set of potential tiles to warp a pet to
                for (int i = -cer; i < cer; i++)
                {
                    for (int j = -cer; j < cer; j++)
                    {
                        int warpX = initX + i;
                        int warpY = initY + j;
                        if (warpX < 0)
                        {
                            warpX = 0;
                        }
                        if (warpY < 0)
                        {
                            warpY = 0;
                        }

                        Vector2 tile = new Vector2(warpX, warpY);
                        if (IsTileAccessible(farm, tile))
                        {
                            warpableTiles.Add(tile);
                        }
                    }
                }

                // No placeable tiles found within the range given in the Config
                if (warpableTiles.Count == 0)
                {
                    ModEntry.SMonitor.Log($"Pets cannot be spread within the given radius: {cer}", LogLevel.Debug);
                    return;
                }

                // Spread pets
                foreach (Pet pet in ModApi.GetPets())
                {
                    Vector2 ranTile = warpableTiles[Randomizer.Next(0, warpableTiles.Count)];
                    Game1.warpCharacter(pet, farm, ranTile);
                }
            }
        }
Exemple #25
0
        /// <summary>Load skin assets from the /assets/skins directory into the A&S database</summary>
        internal static void LoadAssets()
        {
            // Gather handled types
            string validTypes = string.Join(", ", ModApi.GetHandledAllTypes());



            // Add custom sprites
            foreach (string path in Directory.EnumerateFiles(Path.Combine(SHelper.DirectoryPath, "assets", "skins"), "*", SearchOption.AllDirectories))
            {
                PullSprite(Path.GetRelativePath(SHelper.DirectoryPath, path)); // must be a relative path
            }
            // Grab the directory for the /Mods folder from the /Mods/AdoptSkin

            //string modFolderPath = SHelper.DirectoryPath
            foreach (string path in Directory.EnumerateFiles(Path.Combine(SHelper.DirectoryPath)))
            {
                // Warn for invalid files
                if (InvalidExt.Count > 0)
                {
                    ModEntry.SMonitor.Log($"Ignored skins with invalid extension:\n`{string.Join("`, `", InvalidExt)}`\nExtension must be one of type {string.Join(", ", ValidExtensions)}", LogLevel.Warn);
                }
            }
            if (InvalidType.Count > 0)
            {
                ModEntry.SMonitor.Log($"Ignored skins with invalid naming convention:\n`{string.Join("`, `", InvalidType)}`\nCan't parse as an animal, pet, or horse. Expected one of type: {validTypes}", LogLevel.Warn);
            }
            if (InvalidID.Count > 0)
            {
                ModEntry.SMonitor.Log($"Ignored skins with invalid naming convention (no skin ID found):\n`{string.Join("`, `", InvalidID)}`", LogLevel.Warn);
            }
            if (InvalidNum.Count > 0)
            {
                ModEntry.SMonitor.Log($"Ignored skins with invalid ID (can't parse ID number):\n`{string.Join("`, `", InvalidNum)}`", LogLevel.Warn);
            }
            if (InvalidRange.Count > 0)
            {
                ModEntry.SMonitor.Log($"Ignored skins with ID of less than or equal to 0 (Skins must have an ID of at least 1):\n`{string.Join("`, `", InvalidRange)}`", LogLevel.Warn);
            }

            EnforceSpriteSets();

            // Print loaded assets to console
            StringBuilder summary = new StringBuilder();

            summary.AppendLine(
                "Statistics:\n"
                + "\n  Registered types: " + validTypes
                + "\n  Skins:"
                );
            foreach (KeyValuePair <string, Dictionary <int, AnimalSkin> > skinEntry in ModEntry.Assets)
            {
                if (skinEntry.Value.Count > 0)
                {
                    summary.AppendLine($"    {skinEntry.Key}: {skinEntry.Value.Count} skins ({string.Join(", ", skinEntry.Value.Select(p => Path.GetFileName(p.Value.AssetKey)).OrderBy(p => p))})");
                }
            }

            ModEntry.SMonitor.Log(summary.ToString(), LogLevel.Trace);
            ModEntry.AssetsLoaded = true;
        }
Exemple #26
0
        /// <summary>Adds creatures into the system based on the data from older versions' save files or for files new to A&S.</summary>
        internal static void LoadSkinsOldVersion()
        {
            Dictionary <Character, int> creaturesToAdd = new Dictionary <Character, int>();

            // Load pet information stored from older version formats
            Dictionary <long, int> petSkinMap = SHelper.Data.ReadSaveData <Dictionary <long, int> >("pet-skin-map") ?? new Dictionary <long, int>();

            foreach (Pet pet in ModApi.GetPets())
            {
                long longID = ModEntry.GetLongID(pet);
                // Pet unregistered
                if (longID == 0)
                {
                    creaturesToAdd.Add(pet, 0);
                }
                // Pet registered in previous system
                else if (petSkinMap.ContainsKey(longID))
                {
                    creaturesToAdd.Add(pet, petSkinMap[longID]);
                }
                // Reset any previous known ShortID
                pet.Manners = 0;
            }

            // Load horse information stored from older version formats
            Dictionary <long, int> horseSkinMap = SHelper.Data.ReadSaveData <Dictionary <long, int> >("horse-skin-map") ?? new Dictionary <long, int>();

            foreach (Horse horse in ModApi.GetHorses())
            {
                long longID = ModEntry.GetLongID(horse);
                // Horse unregistered
                if (longID == 0)
                {
                    creaturesToAdd.Add(horse, 0);
                }
                // Horse registered in previous system
                else if (horseSkinMap.ContainsKey(longID))
                {
                    creaturesToAdd.Add(horse, horseSkinMap[longID]);
                }
                // Reset any previous known ShortID
                horse.Manners = 0;
            }

            // Load animal information stored from older version formats
            Dictionary <long, int> animalSkinMap = SHelper.Data.ReadSaveData <Dictionary <long, int> >("animal-skin-map") ?? new Dictionary <long, int>();

            ModEntry.AnimalLongToShortIDs = new Dictionary <long, int>();
            ModEntry.AnimalShortToLongIDs = new Dictionary <int, long>();
            foreach (FarmAnimal animal in ModApi.GetAnimals())
            {
                long longID = ModEntry.GetLongID(animal);
                // Animal registered in previous system
                if (animalSkinMap.ContainsKey(longID))
                {
                    creaturesToAdd.Add(animal, animalSkinMap[longID]);
                }
                // Animal unregistered
                else
                {
                    creaturesToAdd.Add(animal, 0);
                }
            }

            // Add in all creatures from older systems
            foreach (KeyValuePair <Character, int> creatureInfo in creaturesToAdd)
            {
                Entry.AddCreature(creatureInfo.Key, creatureInfo.Value);
            }
        }
Exemple #27
0
        internal static void LoadData(object s, EventArgs e)
        {
            // Only allow the host player to load Adopt & Skin data
            if (Context.IsMainPlayer)
            {
                //SMonitor.Log("Multiplayer Farmhand detected. Adopt & Skin has been disabled.", LogLevel.Debug);
                SMonitor.Log("Host detected! Let's WRECK IT", LogLevel.Debug);

                // Load skin and category maps
                ModEntry.SkinMap      = SHelper.Data.ReadSaveData <Dictionary <long, int> >("skin-map") ?? new Dictionary <long, int>();
                ModEntry.IDToCategory = SHelper.Data.ReadSaveData <Dictionary <long, ModEntry.CreatureCategory> >("id-to-category") ?? new Dictionary <long, ModEntry.CreatureCategory>();

                // Load Short ID maps
                ModEntry.AnimalLongToShortIDs = SHelper.Data.ReadSaveData <Dictionary <long, int> >("animal-long-to-short-ids") ?? new Dictionary <long, int>();
                ModEntry.AnimalShortToLongIDs = SHelper.Data.ReadSaveData <Dictionary <int, long> >("animal-short-to-long-ids") ?? new Dictionary <int, long>();

                // Set up maps if save data is from an older data format of A&S
                if (ModEntry.SkinMap.Count == 0)
                {
                    LoadSkinsOldVersion();
                }

                // Load Pet ownership map
                // TODO: Similar to horse ownership loading

                // Load Horse ownership map
                Dictionary <long, long> horseOwnerMap = SHelper.Data.ReadSaveData <Dictionary <long, long> >("horse-ownership-map") ?? new Dictionary <long, long>();
                ModEntry.HorseOwnershipMap = new Dictionary <long, Farmer>();

                foreach (KeyValuePair <long, long> pair in horseOwnerMap)
                {
                    foreach (Farmer farmer in Game1.getAllFarmers())
                    {
                        if (pair.Key == ModApi.FarmerToID(farmer))
                        {
                            ModEntry.HorseOwnershipMap[pair.Key] = farmer;
                        }
                    }
                }

                // If no horses are mapped to owners, or there are some unmapped horses, assign them all to the host player
                if (ModEntry.HorseOwnershipMap.Count != ModApi.GetHorses().Count())
                {
                    foreach (Horse horse in ModApi.GetHorses())
                    {
                        long horseID = ModEntry.GetLongID(horse);
                        if (horseID != 0 && !ModEntry.HorseOwnershipMap.ContainsKey(horseID))
                        {
                            ModEntry.HorseOwnershipMap.Add(horseID, Game1.MasterPlayer);
                        }
                    }
                }
                // If there are extra horses on the mapping, remove them. This deal with a bug in older versions of A&S
                if (ModEntry.HorseOwnershipMap.Count > ModApi.GetHorses().Count())
                {
                    List <Horse> horses         = ModApi.GetHorses().ToList();
                    List <long>  existingHorses = new List <long>();
                    // Find the IDs of all existing, owned Horses
                    foreach (Horse horse in horses)
                    {
                        existingHorses.Add(ModEntry.GetLongID(horse));
                    }

                    // Find the stowaways.
                    List <long> idsToRemove = new List <long>();
                    foreach (long horseID in ModEntry.HorseOwnershipMap.Keys)
                    {
                        if (!existingHorses.Contains(horseID))
                        {
                            idsToRemove.Add(horseID);
                        }
                    }

                    // Yeet them from the mapping.
                    foreach (long id in idsToRemove)
                    {
                        ModEntry.HorseOwnershipMap.Remove(id);
                    }
                }

                // Load received first pet/horse status
                ModEntry.Creator.FirstHorseReceived = bool.Parse(SHelper.Data.ReadSaveData <string>("first-horse-received") ?? "false");
                ModEntry.Creator.FirstPetReceived   = bool.Parse(SHelper.Data.ReadSaveData <string>("first-pet-received") ?? "false");
                Entry.CheckForFirstPet(null, null);
                Entry.CheckForFirstHorse(null, null);
                //return;
            }


            // Refresh skins via skinmap
            LoadCreatureSkins();

            // Make sure Marnie's cows put some clothes on
            foreach (GameLocation loc in Game1.locations)
            {
                if (loc is Forest forest)
                {
                    foreach (FarmAnimal animal in forest.marniesLivestock)
                    {
                        string type = ModApi.GetInternalType(animal);
                        if (ModApi.HasSkins(type))
                        {
                            int[]      spriteInfo = ModApi.GetSpriteInfo(animal);
                            AnimalSkin skin       = ModEntry.GetSkin(type, ModEntry.GetRandomSkin(type));
                            animal.Sprite = new AnimatedSprite(skin.AssetKey, spriteInfo[0], spriteInfo[1], spriteInfo[2]);
                        }
                    }
                }
            }

            // Set configuration for walk-through pets
            foreach (Pet pet in ModApi.GetPets())
            {
                if (ModEntry.Config.WalkThroughPets)
                {
                    pet.farmerPassesThrough = true;
                }
                else
                {
                    pet.farmerPassesThrough = false;
                }
            }

            // Set last known animal count
            ModEntry.AnimalCount = Game1.getFarm().getAllFarmAnimals().Count;

            // Add Adopt & Skin to the update loop
            StartUpdateChecks();
        }
        internal void SpreadPets(object sender, WarpedEventArgs e)
        {
            // ** TODO: Only one pet on farmer's bed
            // TODO: If no pets, handle error
            List <Pet> pets = ModApi.GetPets().ToList();

            // No pets are in the game
            if (pets.Count == 0)
            {
                return;
            }

            // Ensure Stray isn't moved around by vanilla
            if (typeof(Farm).IsAssignableFrom(e.NewLocation.GetType()) ||
                typeof(FarmHouse).IsAssignableFrom(e.NewLocation.GetType()) ||
                Stray.Marnies != e.NewLocation)
            {
                ModEntry.Creator.MoveStrayToSpawn();
            }

            // Only move pets once at beginning of day and once at night
            if ((!Game1.isDarkOut() && PetsPlacedForDay) ||
                (Game1.isDarkOut() && PetsPlacedForNight))
            {
                return;
            }


            if (IsIndoorWeather())
            {
                IndoorWeatherPetSpawn();
                PetsPlacedForDay   = true;
                PetsPlacedForNight = true;
                return;
            }
            else
            {
                // Place everyone at the correct starting point, at the water dish
                foreach (Pet pet in ModApi.GetPets())
                {
                    pet.setAtFarmPosition();
                }

                // Find area to warp pets to
                Farm           farm          = Game1.getFarm();
                int            initX         = (int)pets[0].getTileLocation().X;
                int            initY         = (int)pets[0].getTileLocation().Y;
                List <Vector2> warpableTiles = new List <Vector2>();
                int            cer           = ModEntry.Config.CuddleExplosionRadius;

                // Collect a set of potential tiles to warp a pet to
                for (int i = -cer; i < cer; i++)
                {
                    for (int j = -cer; j < cer; j++)
                    {
                        int warpX = initX + i;
                        int warpY = initY + j;
                        if (warpX < 0)
                        {
                            warpX = 0;
                        }
                        if (warpY < 0)
                        {
                            warpY = 0;
                        }

                        Vector2 tile = new Vector2(warpX, warpY);
                        if (IsTileAccessible(farm, tile))
                        {
                            warpableTiles.Add(tile);
                        }
                    }
                }

                // No placeable tiles found within the range given in the Config
                if (warpableTiles.Count == 0)
                {
                    ModEntry.SMonitor.Log($"Pets cannot be spread within the given radius: {cer}", LogLevel.Debug);
                    return;
                }

                // Spread pets
                foreach (Pet pet in ModApi.GetPets())
                {
                    Vector2 ranTile = warpableTiles[Randomizer.Next(0, warpableTiles.Count)];
                    Game1.warpCharacter(pet, farm, ranTile);
                }

                PetsPlacedForDay = true;
            }
        }
Exemple #29
0
        /*************************
        ** Miscellaneous Helpers
        *************************/

        /// <summary>Returns a List of Characters of all creatures of the specified creature type or custom grouping</summary>
        internal List <Character> GetCreaturesFromGroup(string group)
        {
            group = ModEntry.Sanitize(group);
            List <Character> calledGroup = new List <Character>();

            if (!CreatureGroups.Contains(group) && !ModApi.GetHandledAllTypes().Contains(group))
            {
                ModEntry.SMonitor.Log($"Specified grouping is not handled by Adopt & Skin: {group}", LogLevel.Error);
                return(calledGroup);
            }

            // Add FarmAnimal types to the return list
            if (group == "all" || group == "animal")
            {
                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    calledGroup.Add(animal);
                }
            }
            else if (group == "coop")
            {
                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (animal.isCoopDweller())
                    {
                        calledGroup.Add(animal);
                    }
                }
            }
            else if (group == "barn")
            {
                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (!animal.isCoopDweller())
                    {
                        calledGroup.Add(animal);
                    }
                }
            }
            else if (group == "chicken")
            {
                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (ModApi.IsChicken(animal))
                    {
                        calledGroup.Add(animal);
                    }
                }
            }
            else if (group == "cow")
            {
                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (ModApi.IsCow(animal))
                    {
                        calledGroup.Add(animal);
                    }
                }
            }
            else if (ModApi.GetHandledAnimalTypes().Contains(group))
            {
                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (ModApi.GetInternalType(animal) == group)
                    {
                        calledGroup.Add(animal);
                    }
                }
            }


            // Add Pet types to the return list
            if (group == "all" || group == "pet")
            {
                foreach (Pet pet in ModApi.GetPets())
                {
                    calledGroup.Add(pet);
                }
            }
            else if (ModApi.GetHandledPetTypes().Contains(group))
            {
                foreach (Pet pet in ModApi.GetPets())
                {
                    if (ModApi.GetInternalType(pet) == group)
                    {
                        calledGroup.Add(pet);
                    }
                }
            }


            // Add Horse types to the return list
            if (group == "all" || ModApi.GetHandledHorseTypes().Contains(group))
            {
                foreach (Horse horse in ModApi.GetHorses())
                {
                    calledGroup.Add(horse);
                }
            }


            return(calledGroup);
        }
Exemple #30
0
        /******************
        ** Print Strings
        ******************/

        /// <summary>Prints the the requested creature information from the list_animals console command.</summary>
        internal static void PrintRequestedCreatures(string arg)
        {
            string type = ModEntry.Sanitize(arg);

            // -- Handle FarmAnimal type arguments --
            if (type == "all" || type == "animal")
            {
                List <string> animalInfo = new List <string>();

                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    animalInfo.Add(GetPrintString(animal));
                }

                ModEntry.SMonitor.Log("Animals:", LogLevel.Debug);
                ModEntry.SMonitor.Log($"{string.Join(", ", animalInfo)}\n", LogLevel.Info);
            }
            // Handle coop animal types only
            else if (type == "coop")
            {
                List <string> coopInfo = new List <string>();

                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (animal.isCoopDweller())
                    {
                        coopInfo.Add(GetPrintString(animal));
                    }
                }

                ModEntry.SMonitor.Log("Coop Animals:", LogLevel.Debug);
                ModEntry.SMonitor.Log($"{string.Join(", ", coopInfo)}\n", LogLevel.Info);
            }
            // Handle barn animal types only
            else if (type == "barn")
            {
                List <string> barnInfo = new List <string>();

                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (!animal.isCoopDweller())
                    {
                        barnInfo.Add(GetPrintString(animal));
                    }
                }

                ModEntry.SMonitor.Log("Barn Animals:", LogLevel.Debug);
                ModEntry.SMonitor.Log($"{string.Join(", ", barnInfo)}\n", LogLevel.Info);
            }
            // Handle chicken type arguments
            else if (type == "chicken")
            {
                List <string> chickenInfo = new List <string>();

                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (ModApi.IsChicken(ModApi.GetInternalType(animal)))
                    {
                        chickenInfo.Add(GetPrintString(animal));
                    }
                }

                ModEntry.SMonitor.Log("Chickens:", LogLevel.Debug);
                ModEntry.SMonitor.Log($"{string.Join(", ", chickenInfo)}\n", LogLevel.Info);
            }
            // Handle cow type arguments
            else if (type == "cow")
            {
                List <string> cowInfo = new List <string>();

                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (ModApi.IsCow(ModApi.GetInternalType(animal)))
                    {
                        cowInfo.Add(GetPrintString(animal));
                    }
                }

                ModEntry.SMonitor.Log("Cows:", LogLevel.Debug);
                ModEntry.SMonitor.Log($"{string.Join(", ", cowInfo)}\n", LogLevel.Info);
            }
            // Handle other animal type arguments
            else if (ModApi.GetHandledAnimalTypes().Contains(type))
            {
                List <string> animalInfo = new List <string>();

                foreach (FarmAnimal animal in ModApi.GetAnimals())
                {
                    if (type == ModEntry.Sanitize(animal.type.Value))
                    {
                        animalInfo.Add(GetPrintString(animal));
                    }
                }

                ModEntry.SMonitor.Log($"{arg}s:", LogLevel.Debug);
                ModEntry.SMonitor.Log($"{string.Join(", ", animalInfo)}\n", LogLevel.Info);
            }


            // -- Handle Pet type arguments --
            if (type == "all" || type == "pet")
            {
                List <string> petInfo = new List <string>();

                foreach (Pet pet in ModApi.GetPets())
                {
                    petInfo.Add(GetPrintString(pet));
                }

                ModEntry.SMonitor.Log("Pets:", LogLevel.Debug);
                ModEntry.SMonitor.Log($"{string.Join(", ", petInfo)}\n", LogLevel.Info);
            }
            else if (ModApi.GetHandledPetTypes().Contains(type))
            {
                List <string> petInfo = new List <string>();

                foreach (Pet pet in ModApi.GetPets())
                {
                    if (type == ModEntry.Sanitize(pet.GetType().Name))
                    {
                        petInfo.Add(GetPrintString(pet));
                    }
                }

                ModEntry.SMonitor.Log($"{arg}s:", LogLevel.Debug);
                ModEntry.SMonitor.Log($"{string.Join(", ", petInfo)}\n", LogLevel.Info);
            }


            // -- Handle Horse type arguments --
            if (type == "all" || ModApi.GetHandledHorseTypes().Contains(type))
            {
                List <string> horseInfo = new List <string>();

                foreach (Horse horse in ModApi.GetHorses())
                {
                    horseInfo.Add(GetPrintString(horse));
                }

                ModEntry.SMonitor.Log("Horses:", LogLevel.Debug);
                ModEntry.SMonitor.Log($"{string.Join(", ", horseInfo)}\n", LogLevel.Info);
            }
        }