public override TagCompound Save() { IList <TagCompound> villagerData = new List <TagCompound>(); for (int i = 0; i < Main.maxNPCs; i++) { NPC npcAtIndex = Main.npc[i]; if (!LWMUtils.IsTypeOfVillager(npcAtIndex)) { continue; } else { TagCompound villagerDataTag = new TagCompound { { "type", (int)((Villager)npcAtIndex.modNPC).villagerType }, { "spriteVar", ((Villager)npcAtIndex.modNPC).spriteVariation }, { "x", npcAtIndex.Center.X }, { "y", npcAtIndex.Center.Y }, { "name", npcAtIndex.GivenName }, { "homePos", ((Villager)npcAtIndex.modNPC).homePosition } }; villagerData.Add(villagerDataTag); } } return(new TagCompound { { "VillageReputation", villageReputation }, { "VillagerData", villagerData }, { "VillageGiftCooldown", villageGiftCooldown } }); }
private void NPC_VanillaFindFrame(On.Terraria.NPC.orig_VanillaFindFrame orig, NPC self, int frameHeight) { if (LWMUtils.IsTypeOfVillager(self)) { self.townNPC = true; } orig(self, frameHeight); if (LWMUtils.IsTypeOfVillager(self)) { self.townNPC = false; } }
private void NPC_AI_007_TownEntities(On.Terraria.NPC.orig_AI_007_TownEntities orig, NPC self) { if (LWMUtils.IsTypeOfVillager(self)) { self.townNPC = true; self.homeTileX = (int)((Villager)self.modNPC).homePosition.X; self.homeTileY = (int)((Villager)self.modNPC).homePosition.Y; } orig(self); if (LWMUtils.IsTypeOfVillager(self)) { self.townNPC = false; } }
public static void TileRightClicked(int i, int j, VillagerType villageShrineType) { shrineType = villageShrineType; Instance.Toggle(); itemSlotPos = LWMUtils.FindMultiTileTopLeft(i, j, TileType <HarpyShrineTile>()) + new Vector2(-5, -11); }
private void SkyVillageGenTask(GenerationProgress progress) { progress.Message = "Generating Structures...Sky Village"; progress.Start(0f); #region Mapping Floating Islands List <FloatingIsland> islands = new List <FloatingIsland>(); int islandsZone = (int)(Main.maxTilesY * 0.18f); bool[] visitedCoords = new bool[Main.maxTilesX * islandsZone]; bool validCoordinate(Point16 pos) { //Making sure the coordinate is within the visitedCoords array if (pos.Y >= islandsZone) { return(false); } Tile tile = Framing.GetTileSafely(pos); if (tile.type != TileID.Cloud && tile.type != TileID.RainCloud) { return(false); } return(true); } //left top most visible screen coord is (41, 41)? for (int i = 41; i < Main.maxTilesX; i++) { for (int j = 41; j < islandsZone; j++) { Point16 currentPos = new Point16(i, j); if (!validCoordinate(currentPos)) { continue; } List <Point16> currentIsland = new List <Point16>(); //Simple BFS Algorithm implementation Queue <TileNode> queue = new Queue <TileNode>(); TileNode startingNode = new TileNode(currentPos); queue.Enqueue(startingNode); while (queue.Count != 0) { TileNode activeNode = queue.Dequeue(); if (!validCoordinate(activeNode.position)) { continue; } //1D array that holds values of 2D coordinates needs a special formula for the index int index = activeNode.position.Y * Main.maxTilesX + activeNode.position.X; //index = row * maxColumns + column if (visitedCoords[index]) { continue; } else { visitedCoords[index] = true; } //If current coord wasn't visited yet, add it to the current island list currentIsland.Add(activeNode.position); List <TileNode> childNodes = activeNode.GetChildren(); childNodes.ForEach(child => queue.Enqueue(child)); } //300 tiles? I should probably make some tests and define an average/2 if (currentIsland.Count > 300) { islands.Add(new FloatingIsland(currentIsland)); } progress.Set((i * j / visitedCoords.Length) * 0.80f); } } #endregion #region Finding Suitable Spot and Generating it int structureWidth = 160; int structureHeight = 92; //TODO: MAKE IT CHOOSE SPOTS THAT ARE NOT IN BETWEEN ISLANDS IF THEY'RE CLOSER TO THE CENTER (can happen in small worlds) //X int worldCenter = Main.maxTilesX / 2; int biggestDistanceBetweenIslands = 0; int smallestDistanceToWorldCenter = Main.maxTilesX; int xCoord = 0; for (int i = 0; i < islands.Count; i++) { //Can't do islands[i + 1] on last element if (i != islands.Count - 1) { //Finding the biggest distance between two islands where the middle spot between the two is the closest to the world center int distanceBetweenIslands = Math.Abs(islands[i + 1].xMin - islands[i].xMax); //Math.Abs not needed since they're ordered? int theoricalXCoord = islands[i].xMax + distanceBetweenIslands / 2 - structureWidth / 2; if (distanceBetweenIslands > biggestDistanceBetweenIslands && Math.Abs(theoricalXCoord - worldCenter) < smallestDistanceToWorldCenter) { biggestDistanceBetweenIslands = distanceBetweenIslands; smallestDistanceToWorldCenter = Math.Abs(theoricalXCoord - worldCenter); xCoord = theoricalXCoord; } } } progress.Set(0.85f); //Y int yAverage = 0; foreach (FloatingIsland island in islands) { yAverage += island.GetYAverage(); } yAverage /= islands.Count; //Make sure structure y value doesn't go below 41 (world border) yAverage = yAverage - structureHeight > 41 ? yAverage - structureHeight : 42; progress.Set(0.90f); StructureHelper.StructureHelper.GenerateStructure("Structures/SkyVillageStructure", new Point16(xCoord, yAverage), mod); #endregion //Finding shrine top left position for (int i = xCoord; i < xCoord + structureWidth; i++) { for (int j = yAverage; j < yAverage + structureHeight; j++) { if (Framing.GetTileSafely(i, j).type == TileType <HarpyShrineTile>()) { shrineCoords[(int)VillagerType.Harpy] = LWMUtils.FindMultiTileTopLeft(i, j, TileType <HarpyShrineTile>()); } } } //This Gen task is in the Sky Village Gen task since the islands are mapped in this method, and we need those SkyBudGenTask(progress, islands); progress.End(); }