List <SprinklerInfo> findAllSprinklers(GameLocation location) { List <SprinklerInfo> sprinklers = new List <SprinklerInfo>(); // search through the map looking for sprinklers for (int tileX = 0; tileX < location.map.Layers[0].LayerWidth; ++tileX) { for (int tileY = 0; tileY < location.map.Layers[0].LayerHeight; ++tileY) { Vector2 key = new Vector2(tileX, tileY); if (location.Objects.ContainsKey(key)) { StardewValley.Object obj = location.Objects[key]; // if the object is a sprinkler, classify it and, if eligible, add it to the list if (obj.Name.Contains("Sprinkler")) { SprinklerInfo candidate = new SprinklerInfo(); candidate.position = new Point(tileX, tileY); // classify candidate if (obj.Name.Contains("Quality")) { candidate.type = PlantingMinionTask.SprinklerTypes.Quality; } else if (obj.Name.Contains("Iridium")) { candidate.type = PlantingMinionTask.SprinklerTypes.Iridium; } else { candidate.type = PlantingMinionTask.SprinklerTypes.Standard; } // determine if eligible (that is, the sprinkler isn't completely surrounded by crops already) bool[,] map = PlantingMinionTask.getSprinklerMapFromType(candidate.type); for (int x = candidate.position.X - 2; x <= candidate.position.X + 2; ++x) { for (int y = candidate.position.Y - 2; y <= candidate.position.Y + 2; ++y) { if (map[x - candidate.position.X + 2, y - candidate.position.Y + 2]) { if (location.doesTileHaveProperty(x, y, "Diggable", "Back") != null) { Vector2 pos = new Vector2(x, y); //if (location.isTileLocationTotallyClearAndPlaceable(x,y)) if ((!location.terrainFeatures.ContainsKey(pos) || (location.isTileHoeDirt(pos) && !location.isCropAtTile(x, y))) && !location.Objects.ContainsKey(pos) && location.map.GetLayer("Paths")?.PickTile(new xTile.Dimensions.Location(x, y), Game1.viewport.Size) == null && location.isTilePassable(new xTile.Dimensions.Location(x, y), Game1.viewport)) { candidate.seedsRequired++; } } } } } if (candidate.seedsRequired > 0) { sprinklers.Add(candidate); } } } } } return(sprinklers); }
private void spawnMinionsForPlanting(GameLocation location, StardewValley.Farmer who, int seedIndex, ref int numSeeds, int fertilizerIndex, ref int numFertilizer) { const int sprinklersPerMinion = 15; Stopwatch sw = new Stopwatch(); sw.Start(); // clear previous tasks SkeletalMinionsMod.taskPool.clearTasks(location, new List <string> { nameof(PlantingMinionTask) }); // find all eligible sprinklers List <SprinklerInfo> sprinklers = findAllSprinklers(location); int numSkeletons = sprinklers.Count / sprinklersPerMinion; if (numSkeletons == 0) { numSkeletons = 1; } int totalSeedCount = numSeeds; int totalFertilizerCount = numFertilizer; // create tasks from sprinklers foreach (SprinklerInfo sprinkler in sprinklers) { PlantingMinionTask task = new PlantingMinionTask(location, sprinkler.position, sprinkler.type, sprinkler.seedsRequired, seedIndex, fertilizerIndex); SkeletalMinionsMod.taskPool.addTask(task); } List <Point> spawnPoints = findNearestSpawnLocations(who.getTileLocationPoint(), location, (uint)numSkeletons); // spawn skeletons for (int i = 0; i < spawnPoints.Count; ++i) { SkeletalMinion minion = new SkeletalMinion(new Vector2(spawnPoints[i].X, spawnPoints[i].Y) * Game1.tileSize, location, who, SkeletalMinionsMod.taskPool, new List <string> { nameof(PlantingMinionTask) }); int seedsToAdd = Math.Min(totalSeedCount / numSkeletons, numSeeds); int fertilizerToAdd = Math.Min(totalFertilizerCount / numSkeletons, numFertilizer); numSeeds -= seedsToAdd; numFertilizer -= fertilizerToAdd; if (seedsToAdd > 0) { minion.addItemToInventory(new StardewValley.Object(seedIndex, seedsToAdd)); } if (fertilizerToAdd > 0) { minion.addItemToInventory(new StardewValley.Object(fertilizerIndex, fertilizerToAdd)); } location.characters.Add(minion); Utility.drawLightningBolt(new Vector2(spawnPoints[i].X * Game1.tileSize, spawnPoints[i].Y * Game1.tileSize), location); } sw.Stop(); SkeletalMinionsMod.mod.Monitor.Log($"Spawning (planting) minions took {sw.ElapsedMilliseconds} ms."); }