private void Setup() { this.Monitor.Log("Performing setup...", LogLevel.Trace); // Handle patches specific to other mods var registry = this.Helper.Data.ReadJsonFile <Dictionary <string, string> >("assets/TownPatches/registry.json"); string patchVersion = "Vanilla"; foreach (var pair in registry) { if (!this.Helper.ModRegistry.IsLoaded(pair.Key)) { continue; } patchVersion = pair.Value; break; } // Setup for patching var town = Game1.getLocationFromName("Town"); var patch = this.Helper.Content.Load <Map>("assets/TownPatches/" + patchVersion + ".tbin"); var layers = town.map.Layers.Where(a => patch.GetLayer(a.Id) != null).Select(a => a.Id); // Perform patching foreach (string layer in layers) { Layer toLayer = town.map.GetLayer(layer), fromLayer = patch.GetLayer(layer); // First patch area: The road for (int x = 96; x < 120; x++) { for (int y = 53; y < 61; y++) { var tile = fromLayer.Tiles[x, y]; if (tile == null) { toLayer.Tiles[x, y] = null; } else { toLayer.Tiles[x, y] = new StaticTile(toLayer, town.map.GetTileSheet(tile.TileSheet.Id), BlendMode.Additive, tile.TileIndex); } var vect = new Vector2(x, y); town.largeTerrainFeatures.Filter(a => a.tilePosition.Value != vect); } } // Second patch area: replacing the pink tree for (int x = 110; x < 116; x++) { for (int y = 46; y < 53; y++) { var tile = fromLayer.Tiles[x, y]; if (tile == null) { toLayer.Tiles[x, y] = null; } else { toLayer.Tiles[x, y] = new StaticTile(toLayer, town.map.GetTileSheet(tile.TileSheet.Id), BlendMode.Additive, tile.TileIndex); } } } } // Add new locations foreach (string map in this.Maps) { try { this.Monitor.Log("Adding sundrop location: " + Path.GetFileNameWithoutExtension(map), LogLevel.Trace); var loc = new GameLocation(this.Helper.Content.GetActualAssetKey(Path.Combine("assets", "Maps", map)), Path.GetFileNameWithoutExtension(map)); this.SetupLocation(loc); Game1.locations.Add(loc); } catch (Exception err) { this.Monitor.Log("Unable to add [" + map + "] location, error follows\n" + err.ToString(), LogLevel.Error); } } var promenade = Game1.getLocationFromName("SundropPromenade"); if (promenade == null) { this.Monitor.Log("Promenade failed to load, cancelling further setup as a result.", LogLevel.Error); return; } // Setup warps to sundrop [TEMP: Will become warps to SundropBusStop map in the future] town.warps.Add(new Warp(120, 55, "SundropPromenade", 1, 29, false)); town.warps.Add(new Warp(120, 56, "SundropPromenade", 1, 30, false)); town.warps.Add(new Warp(120, 57, "SundropPromenade", 1, 31, false)); town.warps.Add(new Warp(120, 58, "SundropPromenade", 1, 32, false)); // Add warp back to Pelican [TEMP: Will be removed once proper travel is implemented] promenade.setTileProperty(3, 37, "Buildings", "Action", "Warp 119 56 Town"); // Temp NPC spawns NPC npc = new NPC(new AnimatedSprite(this.Helper.Content.GetActualAssetKey("assets/Characters/Sprites/Joe.png"), 18, 16, 32), new Vector2(24, 20) * 64f, 2, "Joe") { Portrait = this.Helper.Content.Load <Texture2D>("assets/Characters/Portraits/Joe.png"), Breather = false, HideShadow = true }; npc.DefaultMap = "SundropPromenade"; npc.DefaultPosition = new Vector2(23, 20) * 64f; npc.Schedule = this.Helper.Reflection.GetMethod(npc, "parseMasterSchedule").Invoke <Dictionary <int, SchedulePathDescription> >("610 80 20 2/630 23 20 2/710 80 20 2/730 23 20 2/810 80 20 2/830 23 20 2/910 80 20 2/930 23 20 2"); npc.setNewDialogue("Mr. Bones wanted me to take care of Mr. Cake for him while he deals with a corruption claim by this guy called Stubbs...$bNo idea why the cat even bothers, everyone knows Mr. Cake is best doggo!"); promenade.addCharacter(npc); NPC cake = new MrCake(new Vector2(22, 20), npc); cake.setNewDialogue("Mr. Cake looks at you with approval."); promenade.addCharacter(cake); this.AddCameoChar("ChefRude", "SundropPromenade", new Vector2(24, 50), "So much work to do... $b#$sI just cant keep up..."); }
private void LateSetup() { this.Monitor.Log("Performing late setup...", LogLevel.Debug); var promenade = Game1.getLocationFromName("SundropPromenade"); var start = DateTime.Now; if (promenade == null) { return; } List <Task> tasks = new List <Task> { Task.Run(() => { this.Monitor.Log("Repairing locations...", LogLevel.Trace); Parallel.ForEach(Game1.locations, loc => { if (loc.map.Properties.ContainsKey("IsSundropLocation")) { this.SetupLocation(loc); } }); }), Task.Run(() => { this.Monitor.Log("Spawning characters...", LogLevel.Trace); Parallel.ForEach(this.Helper.Data.ReadJsonFile <CharacterInfo[]>("assets/Data/CharacterSpawns.json"), info => { if (Game1.getLocationFromName(info.Map) == null) { this.Monitor.Log("Unable to add villager by name of `" + info.Name + "` because their default map failed to load, this character will not appear in your game as a result.", LogLevel.Error); } else { try { this.Monitor.Log("Adding sundrop villager: " + info.Name, LogLevel.Trace); var pos = new Vector2(info.Position[0], info.Position[1]); var villagerNpc = new NPC(new AnimatedSprite(this.Helper.Content.GetActualAssetKey("assets/Characters/Sprites/" + info.Texture + ".png"), 18, 16, 32), pos * 64f, 2, info.Name) { Portrait = this.Helper.Content.Load <Texture2D>("assets/Characters/Portraits/" + info.Texture + ".png"), DefaultMap = info.Map, DefaultPosition = pos * 64f }; villagerNpc.setNewDialogue(info.Message); lock (Game1.getLocationFromName(info.Map)) Game1.getLocationFromName(info.Map).addCharacter(villagerNpc); } catch (Exception err) { this.Monitor.Log("Unable to add villager by name of `" + info.Name + "` due to a unexpected issue, this character will not appear in your game as a result.\n" + err, LogLevel.Error); } } }); }), Task.Run(() => { this.Monitor.Log("Spawning cameos...", LogLevel.Trace); Parallel.ForEach(this.Helper.Data.ReadJsonFile <CharacterInfo[]>("assets/Data/CameoSpawns.json"), info => { if (Game1.getLocationFromName(info.Map) == null) { this.Monitor.Log("Unable to add cameo character for `" + info.Name + "` because their default map failed to load, this character will not appear in your game as a result.", LogLevel.Warn); } else { try { this.Monitor.Log("Adding sundrop cameo: " + info.Name, LogLevel.Trace); var pos = new Vector2(info.Position[0], info.Position[1]); var cameoNpc = new NPC(new AnimatedSprite(this.Helper.Content.GetActualAssetKey("assets/Characters/Cameos/" + info.Name + "Sprite.png"), 18, 16, 32), pos * 64f, 2, info.Name) { Portrait = this.Helper.Content.Load <Texture2D>("assets/Characters/Cameos/" + info.Name + "Portrait.png"), DefaultMap = info.Map, DefaultPosition = pos * 64f }; cameoNpc.setNewDialogue(info.Message); lock (Game1.getLocationFromName(info.Map)) Game1.getLocationFromName(info.Map).addCharacter(cameoNpc); } catch (Exception err) { this.Monitor.Log("Unable to add cameo character for `" + info.Name + "` due to a unexpected issue, this character will not appear in your game as a result.\n" + err, LogLevel.Warn); } } }); }) }; Task.WaitAll(tasks.ToArray()); var npc = Game1.getCharacterFromName("Joe"); if (npc != null) { npc.Schedule = this.Helper.Reflection.GetMethod(npc, "parseMasterSchedule").Invoke <Dictionary <int, SchedulePathDescription> >("610 80 20 2/630 23 20 2/710 80 20 2/730 23 20 2/810 80 20 2/830 23 20 2/910 80 20 2/930 23 20 2"); NPC cake = new MrCake(new Vector2(22, 20), npc); cake.setNewDialogue("Mr. Cake looks at you with approval."); promenade?.addCharacter(cake); } SundropCityMod.FixBushes(); var end = DateTime.Now; var time = end.Subtract(start); this.Monitor.Log("Late setup took " + time.TotalMilliseconds + " milliseconds, sundrop is now ready for you - enjoy!", LogLevel.Debug); }