internal void CheckForFirstHorse(object sender, NpcListChangedEventArgs e) { // FirstHorseReceived status already known if (Creator.FirstHorseReceived) { Helper.Events.World.NpcListChanged -= CheckForFirstHorse; } // Check for the arrival of the vanilla horse else if (e != null && e.Added != null) { foreach (NPC npc in e.Added) { if (npc is Horse horse) { if (ModApi.IsNotATractorOrCart(horse)) { // The first horse is given to the host player AddCreature(horse, 0, Game1.MasterPlayer); Creator.FirstHorseReceived = true; this.Helper.Events.World.NpcListChanged -= this.CheckForFirstHorse; return; } } } } }
/**************************** ** Additional Functionality *****************************/ /// <summary>Calls a horse that the player owns to the player's location</summary> /// <returns>Returns true if a horse was successfully called.</returns> internal static bool CallHorse(long id = 0) { // Make sure that the player is calling the horse while outside if (!Game1.player.currentLocation.IsOutdoors) { ModEntry.SMonitor.Log("You cannot call for a horse while indoors.", LogLevel.Warn); Game1.chatBox.addInfoMessage("You hear your Grandfather's voice echo in your head.. \"Now is not the time to use that.\""); return(false); } // Teleport the horse with the given ID or the last horse ridden List <Horse> taxis = ModApi.GetHorses().ToList(); taxis.Reverse(); foreach (Horse taxi in taxis) { if (ModApi.IsWildHorse(taxi)) { continue; } else if (id != 0 && GetShortID(taxi) == id) { Game1.warpCharacter(taxi, Game1.player.currentLocation, Game1.player.getTileLocation()); return(true); } else if (id == 0) { Game1.warpCharacter(taxi, Game1.player.currentLocation, Game1.player.getTileLocation()); return(true); } } return(false); }
private static Character GetCreature(long longID) { // Check that LongID belongs to a creature in the database, or is otherwise a Stray or WildHorse. if (IDToCategory.ContainsKey(longID)) { switch (IDToCategory[longID]) { case CreatureCategory.Pet: foreach (Pet pet in ModApi.GetPets()) { if (GetLongID(pet) == longID) { return(pet); } } return(null); case CreatureCategory.Horse: foreach (Horse horse in ModApi.GetHorses()) { if (GetLongID(horse) == longID) { return(horse); } } return(null); case CreatureCategory.Animal: foreach (FarmAnimal animal in ModApi.GetAnimals()) { if (GetLongID(animal) == longID) { return(animal); } } return(null); default: return(null); } } else { if (ModApi.IsStray(longID)) { if (Creator.StrayInfo != null) { return(Creator.StrayInfo.PetInstance); } } else if (ModApi.IsWildHorse(longID)) { if (Creator.HorseInfo != null) { return(Creator.HorseInfo.HorseInstance); } } return(null); } }
/// <summary>Removes the Pet, Horse, or FarmAnimal with the given LongID from the A&S database</summary> internal void RemoveCreature(long longID) { if (!ModApi.IsInDatabase(longID)) { return; } // Ensure creature is not on map Character creature = GetCreature(longID); if (creature != null && (creature is Pet || creature is Horse)) { Game1.removeThisCharacterFromAllLocations(creature as NPC); } // Remove FarmAnimal-specific ID markers from lists else if (AnimalLongToShortIDs.ContainsKey(longID)) { int shortID = AnimalLongToShortIDs[longID]; AnimalLongToShortIDs.Remove(longID); AnimalShortToLongIDs.Remove(shortID); } // Scrub internal IDs and skin mapping from system IDToCategory.Remove(longID); SkinMap.Remove(longID); }
/// <summary>Returns an unused Short ID for a new creature to use.</summary> private int GetUnusedShortID() { int newShortID = 1; // Gather all current ShortIDs List <int> usedIDs = new List <int>(); foreach (Horse horse in ModApi.GetHorses()) { usedIDs.Add(GetShortID(horse)); } foreach (Pet pet in ModApi.GetPets()) { usedIDs.Add(GetShortID(pet)); } foreach (FarmAnimal animal in ModApi.GetAnimals()) { usedIDs.Add(GetShortID(animal)); } // Find an unused ShortID and return it while (usedIDs.Contains(newShortID)) { newShortID++; } return(newShortID); }
public static void ClearUnownedPets() { foreach (NPC npc in Utility.getAllCharacters()) { if (npc is Horse horse && ModApi.IsWildHorse(horse)) { Game1.removeThisCharacterFromAllLocations(horse); }
/// <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); } } }
/// <summary>Update BeingRidden, such that horses can be manually re-added on dismount, preventing the disappearence of dismounted multihorses.</summary> internal static void HorseMountedCheck(object sender, NpcListChangedEventArgs e) { foreach (NPC npc in e.Removed) { if (npc is Horse horse && horse.rider != null && !ModApi.IsWildHorse(horse)) { BeingRidden.Add(horse); } } }
internal static int GetRandomSkin(string type) { type = Sanitize(type); if (!ModApi.HasSkins(type)) { return(0); } int randomLookup = Randomizer.Next(0, Assets[type].Keys.Count); return(Assets[type].ElementAt(randomLookup).Key); }
/************************ ** Skin Handling *************************/ /// <param name="creature">The creature (Pet, Horse, or FarmAnimal) to set the skin for</param> /// <param name="skinID">The file ID of the skin to set.</param> internal static int SetSkin(Character creature, int skinID) { if (!ModApi.IsInDatabase(creature) || !ModApi.HasSkins(ModApi.GetInternalType(creature))) { return(0); } SkinMap[GetLongID(creature)] = skinID; UpdateSkin(creature); return(skinID); }
internal static AnimalSkin GetSkin(Character creature) { if (!ModApi.HasSkins(ModApi.GetInternalType(creature)) || !ModApi.IsInDatabase(creature)) { return(null); } int skinID; string type = ModApi.GetInternalType(creature); // Take care of Strays and WildHorses if (Creator.StrayInfo != null && ModApi.IsStray(creature)) { skinID = Creator.StrayInfo.SkinID; } else if (Creator.HorseInfo != null && ModApi.IsWildHorse(creature)) { skinID = Creator.HorseInfo.SkinID; } // Take care of FarmAnimal subtypes else if (creature is FarmAnimal animal) { skinID = SkinMap[GetLongID(creature)]; if (ModApi.HasBabySprite(type) && animal.age.Value < animal.ageWhenMature.Value) { type = "baby" + type; } else if (ModApi.HasShearedSprite(type) && animal.showDifferentTextureWhenReadyForHarvest.Value && animal.currentProduce.Value <= 0) { type = "sheared" + type; } } // Take care of owned Pets and Horses else { skinID = SkinMap[GetLongID(creature)]; } if (!Assets[ModApi.GetInternalType(creature)].ContainsKey(skinID)) { ModEntry.SMonitor.Log($"{creature.Name}'s skin ID no longer exists in `/assets/skins`. Skin will be randomized.", LogLevel.Alert); skinID = RandomizeSkin(creature); } else if (skinID == 0) { return(null); } return(GetSkin(type, skinID)); }
internal static int GetRandomSkin(string type) { type = Sanitize(type); if (!ModApi.HasSkins(type)) { return(0); } // ** TODO: Find out why erroring with stray spawn, issue in GetSkin likely. // Issue related to lack of cat skins? Fix this // Android: A Button works, but not right click int randomLookup = Randomizer.Next(0, Assets[type].Keys.Count); return(Assets[type].ElementAt(randomLookup).Key); }
/**************************** ** Additional Functionality *****************************/ /// <summary>Calls a horse that the player owns to the player's location</summary> /// <returns>Returns true if a horse was successfully called.</returns> internal static bool CallHorse(int id = 0) { // Make sure that the player is calling the horse while outside if (!Game1.player.currentLocation.IsOutdoors) { Game1.chatBox.addInfoMessage("You hear your Grandfather's voice echo in your head.. \"Now is not the time to use that.\""); return(false); } // Teleport the first horse you find that the player actually owns List <Horse> taxis = ModApi.GetHorses().ToList(); taxis.Reverse(); foreach (Horse taxi in taxis) { long longID = GetLongID(taxi); // If the player called for a specific horse if (id != 0 && GetShortID(taxi) == id) { // Ensure that the player owns this horse if (HorseOwnershipMap[longID] != Game1.player) { SMonitor.Log($"Horse {id} ({taxi.Name}) does not belong to this player. (Belongs to ({HorseOwnershipMap[longID].Name}))", LogLevel.Error); return(false); } Game1.warpCharacter(taxi, Game1.player.currentLocation, Game1.player.getTileLocation()); return(true); } // Otherwise else if (id == 0) { // Ensure that the player owns this horse if (HorseOwnershipMap[longID] != Game1.player) { continue; } else { Game1.warpCharacter(taxi, Game1.player.currentLocation, Game1.player.getTileLocation()); return(true); } } } SMonitor.Log("This player does not own any horses to call.", LogLevel.Debug); return(false); }
/// <summary>Refreshes the texture of the creature's sprite if the texture it has is different from the one in the skin mapping</summary> internal static void UpdateSkin(Character creature) { if (!ModApi.IsInDatabase(creature) && !ModApi.IsStray(creature) && !ModApi.IsWildHorse(creature)) { return; } AnimalSkin skin = GetSkin(creature); if (skin != null && creature.Sprite.textureName.Value != skin.AssetKey) { int[] spriteInfo = ModApi.GetSpriteInfo(creature); creature.Sprite = new AnimatedSprite(skin.AssetKey, spriteInfo[0], spriteInfo[1], spriteInfo[2]); } }
/// <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.IsNotATractorOrCart(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); } }
/// <summary>Removes the Pet, Horse, or FarmAnimal with the given LongID from the A&S database</summary> internal void RemoveCreature(long longID) { if (!ModApi.IsInDatabase(longID)) { return; } // Ensure creature is not on map Character creature = GetCreature(longID); if (creature != null && (creature is Pet || creature is Horse)) { Game1.removeThisCharacterFromAllLocations(creature as NPC); } // Scrub internal IDs and skin mapping from system IDToCategory.Remove(longID); SkinMap.Remove(longID); }
internal static int GetShortID(Character creature) { if (!ModApi.IsInDatabase(creature)) { return(0); } if (creature is Pet pet) { return(pet.Manners); } else if (creature is Horse horse) { return(horse.Manners); } else if (creature is FarmAnimal animal && AnimalLongToShortIDs.ContainsKey(GetLongID(animal))) { return(AnimalLongToShortIDs[GetLongID(animal)]); } return(0); }
/// <summary>Determines whether an animal has been removed or added in the game, and either removes or adds it to the A&S database.</summary> internal void AnimalListChangeCheck() { if (Game1.getFarm() != null && AnimalCount != Game1.getFarm().getAllFarmAnimals().Count) { List <long> existingAnimalIDs = new List <long>(); List <FarmAnimal> newAnimals = new List <FarmAnimal>(); // Check for new animals and populate lists containing existing and new animals foreach (FarmAnimal animal in ModApi.GetAnimals().ToList()) { if (!ModApi.IsInDatabase(animal)) { newAnimals.Add(animal); } else { existingAnimalIDs.Add(animal.myID.Value); } } // Remove animals that no longer exist List <long> animalIDs = new List <long>(SkinMap.Keys); foreach (long id in animalIDs) { if (IDToCategory[id] == CreatureCategory.Animal && !existingAnimalIDs.Contains(id)) { RemoveCreature(id); } } // Add new animals foreach (FarmAnimal animal in newAnimals) { AddCreature(animal); } // Update last known animal count AnimalCount = Game1.getFarm().getAllFarmAnimals().Count; } }
/// <summary>Adds the given Pet, Horse, or FarmAnimal into the A&S database</summary> internal void AddCreature(Character creature, int skinID = 0, Farmer owner = null) { string type = ModApi.GetInternalType(creature); if (ModApi.IsInDatabase(creature) || !ModApi.IsRegisteredType(type)) { return; } // Set internal IDs SetShortID(creature, GetUnusedShortID()); IDToCategory[GetLongID(creature)] = ModApi.GetCreatureCategory(type); // Set ownership if (creature is Horse) { if (owner != null) { HorseOwnershipMap.Add(GetLongID(creature), owner); // DEBUG Monitor.Log($"Horse ID: {GetShortID(creature)}\nOwner: {owner.Name}", LogLevel.Debug); } else { Monitor.Log($"No adopter able to be detected. Horse {GetShortID(creature)} will be owned by the host player.", LogLevel.Debug); HorseOwnershipMap.Add(GetLongID(creature), Game1.MasterPlayer); } } // Give a skin if (skinID != 0) { SetSkin(creature, skinID); } else { RandomizeSkin(creature); } }
/**************************** ** Additional Functionality *****************************/ /// <summary>Calls a horse that the player owns to the player's location</summary> /// <returns>Returns true if a horse was successfully called.</returns> internal static bool CallHorse(long id = 0) { // Make sure that the player is calling the horse while outside if (!Game1.player.currentLocation.IsOutdoors) { ModEntry.SMonitor.Log("You cannot call for a horse while indoors.", LogLevel.Alert); Game1.chatBox.addInfoMessage("You hear your Grandfather's voice echo in your head.. \"Now is not the time to use that.\""); return(false); } // Teleport the first horse you find that the player actually owns foreach (Horse taxi in ModApi.GetHorses()) { if (ModApi.IsInDatabase(taxi) && (id == 0 || id == GetLongID(taxi))) { Game1.warpCharacter(taxi, Game1.player.currentLocation, Game1.player.getTileLocation()); return(true); } } return(false); }
/// <summary>Adds the given Pet, Horse, or FarmAnimal into the A&S database</summary> internal void AddCreature(Character creature, int skinID = 0) { string type = ModApi.GetInternalType(creature); if (ModApi.IsInDatabase(creature) || !ModApi.IsRegisteredType(type)) { return; } // Set internal IDs SetShortID(creature, GetUnusedShortID()); IDToCategory[GetLongID(creature)] = ModApi.GetCreatureCategory(type); // Give a skin if (skinID != 0) { SetSkin(creature, skinID); } else { RandomizeSkin(creature); } }
/// <summary>Calls all horses owned by the player to return to the player's stable</summary> internal static void CorralHorses() { // Find the farm's stable Stable horsehut = null; foreach (Building building in Game1.getFarm().buildings) { if (building is Stable) { horsehut = building as Stable; } } if (horsehut != null) { // WARP THEM. WARP THEM ALL. int stableX = int.Parse(horsehut.tileX.ToString()) + 1; int stableY = int.Parse(horsehut.tileY.ToString()) + 1; Vector2 stableWarp = new Vector2(stableX, stableY); foreach (Horse horse in ModApi.GetHorses()) { if (!ModApi.IsWildHorse(horse)) { Game1.warpCharacter(horse, "farm", stableWarp); } } ModEntry.SMonitor.Log("All horses have been warped to the stable.", LogLevel.Info); return; } // Player does not own a stable ModEntry.SMonitor.Log("NOTICE: You don't have a stable to warp to!", LogLevel.Error); Game1.chatBox.addInfoMessage("Your Grandfather's voice echoes in your head.. \"You aren't yet ready for this gift.\""); }
/// <summary>Calls all horses owned by the player to return to the player's stable</summary> internal static void CorralHorses() { // Gather the taxis List <Horse> horses = new List <Horse>(); foreach (Horse horse in ModApi.GetHorses()) { horses.Add(horse); } // Ensure you own at least one taxi if (horses.Count == 0) { ModEntry.SMonitor.Log("NOTICE: You do not own any horses", LogLevel.Error); Game1.chatBox.addInfoMessage("Your Grandfather's voice echoes in your head.. \"You aren't yet ready for this gift.\""); return; } // Find the farm's stable(s) List <Stable> horsehuts = new List <Stable>(); foreach (Building building in Game1.getFarm().buildings) { if (building is Stable stable) { foreach (Horse horse in horses) { if (stable.HorseId == horse.HorseId) { horsehuts.Add(building as Stable); break; } } } } // Player does not own a stable if (horsehuts.Count == 0) { ModEntry.SMonitor.Log("NOTICE: You don't have a stable to warp to!", LogLevel.Error); Game1.chatBox.addInfoMessage("Your Grandfather's voice echoes in your head.. \"You aren't yet ready for this gift.\""); return; } // WARP THEM. WARP THEM ALL. foreach (Horse horse in horses) { foreach (Stable stable in horsehuts) { if (horse.HorseId == stable.HorseId) { int stableX = int.Parse(stable.tileX.ToString()) + 1; int stableY = int.Parse(stable.tileY.ToString()) + 1; Vector2 stableWarp = new Vector2(stableX, stableY); Game1.warpCharacter(horse, "farm", stableWarp); break; } } } ModEntry.SMonitor.Log("All horses have been warped to the stable.", LogLevel.Info); }
/// <summary>Initiate A&S data on farm</summary> public void UpdateCreatureCount() { // TODO: Put this where it belongs. Use to load game, then check in UpdateTicked to make sure all farmhands and host have animals and skins known if (Game1.getFarm() != null) { Game1.getFarm().modData[$"{this.ModManifest.UniqueID}/count-farmanimals"] = Game1.getFarm().getAllFarmAnimals().Count.ToString(); Game1.getFarm().modData[$"{this.ModManifest.UniqueID}/count-pets"] = ModApi.GetPets().Count().ToString(); Game1.getFarm().modData[$"{this.ModManifest.UniqueID}/count-horses"] = ModApi.GetHorses().Count().ToString(); } }
internal static int RandomizeSkin(Character creature) { return(SetSkin(creature, GetRandomSkin(ModApi.GetInternalType(creature)))); }
/// <summary> /// Given the ID for an animal, pet, or horse, and that creature's type, return the AnimalSkin mapped to that creature. /// Return null if the creature type isn't handled. /// </summary> internal AnimalSkin GetSkin(Character creature) { switch (creature) { case Horse horse: // No horse skins are loaded if (HorseAssets[Sanitize(horse.GetType().Name)].Count == 0) { return(null); } // A wild horse is being checked if (horse.Manners == WildHorse.WildID) { return(GetSkinFromID(horse.GetType().Name, Creator.HorseInfo.SkinID)); } // Horse is not in system else if (horse.Manners == 0 || !HorseSkinMap.ContainsKey(horse.Manners)) { this.Monitor.Log($"Horse not in system: {horse.Name}", LogLevel.Error); return(null); } // Ensure skin ID given is a valid number for the given horse type int horseSkinID = HorseSkinMap[horse.Manners]; if (horseSkinID < 1 || horseSkinID > HorseAssets[Sanitize(horse.GetType().Name)].Count) { this.Monitor.Log($"{horse.Name}'s skin ID no longer exists in `/assets/skins`. Skin will be randomized.", LogLevel.Alert); horseSkinID = SetRandomSkin(horse); } // Horse has a skin. Return it. return(GetSkinFromID(horse.GetType().Name, horseSkinID)); case Pet pet: string petType = Sanitize(pet.GetType().Name); // Break out of unhandled types if (!ModApi.GetHandledPetTypes().Contains(petType)) { break; } else if (PetAssets[Sanitize(pet.GetType().Name)].Count == 0) { return(null); } // A stray pet is being checked if (pet.Manners == Stray.StrayID) { return(GetSkinFromID(pet.GetType().Name, Creator.StrayInfo.SkinID)); } // Pet is not in system else if (pet.Manners == 0 || !PetSkinMap.ContainsKey(pet.Manners)) { this.Monitor.Log($"Pet not in system: {pet.Name}", LogLevel.Error); return(null); } // Ensure skin ID given is a current valid number for the given pet type int petSkinID = PetSkinMap[pet.Manners]; if (petSkinID < 1 || petSkinID > PetAssets[petType].Count) { this.Monitor.Log($"{pet.Name}'s skin ID no longer exists in `/assets/skins`. Skin will be randomized.", LogLevel.Alert); petSkinID = SetRandomSkin(pet); } return(GetSkinFromID(petType, petSkinID)); case FarmAnimal animal: string animalType = Sanitize(animal.type.Value); // Break out of unhandled types if (!ModApi.GetHandledAnimalTypes().Contains(animalType)) { break; } else if (AnimalAssets[Sanitize(animal.type.Value)].Count == 0) { return(null); } // Set sub-type if applicable if (ModApi.HasBabySprite(animalType) && animal.age.Value < animal.ageWhenMature.Value) { animalType = "baby" + animalType; } else if (ModApi.HasShearedSprite(animalType) && animal.currentProduce.Value <= 0) { animalType = "sheared" + animalType; } // Animal is not in system if (!AnimalSkinMap.ContainsKey(animal.myID.Value)) { return(null); } // Ensure skin ID given is a current valid number for the given animal type int animalSkinID = AnimalSkinMap[animal.myID.Value]; if (animalSkinID < 1 || animalSkinID > AnimalAssets[animalType].Count) { this.Monitor.Log($"{animal.Name}'s skin ID is no longer exists in `/assets/skins`. Skin will be randomized.", LogLevel.Alert); animalSkinID = SetRandomSkin(animal); } return(GetSkinFromID(animalType, animalSkinID)); default: break; } return(null); }