private void AddModOrGrass(Vector2 location)
        {
            // We have 4 kinds of things that a mod can add:
            // largeterrainfeatures, terrainfeatures, resourceclumps and objects.
            // To create a truly random order, we shuffle the kind of things (using lambdas in a list),
            // and then we shuffle the callbacks provided by mods.
            foreach (var action in DeepWoodsAPI.ToShuffledList(new List <Func <bool> >()
            {
                () => {
                    foreach (var modLargeTerrainFeature in DeepWoodsAPI.ToShuffledList(ModEntry.GetAPI().LargeTerrainFeatures))
                    {
                        if (modLargeTerrainFeature.Item1(deepWoods, location))
                        {
                            deepWoods.largeTerrainFeatures.Add(modLargeTerrainFeature.Item2());
                            return(true);
                        }
                    }
                    return(false);
                },
                () => {
                    foreach (var modResourceClump in DeepWoodsAPI.ToShuffledList(ModEntry.GetAPI().ResourceClumps))
                    {
                        if (modResourceClump.Item1(deepWoods, location))
                        {
                            deepWoods.resourceClumps.Add(modResourceClump.Item2());
                            return(true);
                        }
                    }
                    return(false);
                },
                () => {
                    foreach (var modTerrainFeature in DeepWoodsAPI.ToShuffledList(ModEntry.GetAPI().TerrainFeatures))
                    {
                        if (modTerrainFeature.Item1(deepWoods, location))
                        {
                            deepWoods.terrainFeatures[location] = modTerrainFeature.Item2();
                            return(true);
                        }
                    }
                    return(false);
                },
                () => {
                    foreach (var modObject in DeepWoodsAPI.ToShuffledList(ModEntry.GetAPI().Objects))
                    {
                        if (modObject.Item1(deepWoods, location))
                        {
                            deepWoods.objects[location] = modObject.Item2();
                            return(true);
                        }
                    }
                    return(false);
                }
            }))
            {
                if (action())
                {
                    // A mod added something, return
                    return;
                }
            }

            // Mods didn't add anything, add grass
            deepWoods.terrainFeatures[location] = new LootFreeGrass(GetSeasonGrassType(), this.random.GetRandomValue(1, 3));
        }
예제 #2
0
        // Called whenever a player warps, both from and to may be null
        public static void PlayerWarped(Farmer who, GameLocation rawFrom, GameLocation rawTo)
        {
            DeepWoods from = rawFrom as DeepWoods;
            DeepWoods to   = rawTo as DeepWoods;

            if (from != null && to != null && from.Name == to.Name)
            {
                return;
            }

            from?.RemovePlayer(who);
            to?.AddPlayer(who);

            // everything that follows should only be done if this is the local player
            if (who != Game1.player)
            {
                ModEntry.Log("Player (" + who.UniqueMultiplayerID + ") warped from: " + rawFrom?.Name + ", to: " + rawTo?.Name, LogLevel.Trace);
                return;
            }

            ModEntry.Log("Local Player (" + who.UniqueMultiplayerID + ") warped from: " + rawFrom?.Name + ", to: " + rawTo?.Name, LogLevel.Trace);

            if (rawTo is Woods woods)
            {
                OpenPassageInSecretWoods(woods);
            }

            if (from != null && to == null)
            {
                // We left the deepwoods, fix lighting
                DeepWoodsManager.FixLighting();

                // Stop music
                Game1.changeMusicTrack("none");
                Game1.updateMusic();

                // Workaround for bug where players are warped to [0,0] for some reason
                if (rawTo is Woods)
                {
                    who.Position = new Vector2(WOODS_WARP_LOCATION.X * 64, WOODS_WARP_LOCATION.Y * 64);
                }
            }

            if (from != null &&
                to != null &&
                from.Parent == null &&
                to.Parent == from &&
                !lostMessageDisplayedToday &&
                !to.spawnedFromObelisk.Value &&
                ExitDirToEnterDir(CastEnterDirToExitDir(from.EnterDir)) == to.EnterDir)
            {
                Game1.addHUDMessage(new HUDMessage(I18N.LostMessage)
                {
                    noIcon = true
                });
                lostMessageDisplayedToday = true;
            }

            if (to != null &&
                to.level.Value >= Settings.Level.MinLevelForWoodsObelisk &&
                !Game1.player.hasOrWillReceiveMail(WOODS_OBELISK_WIZARD_MAIL_ID) &&
                (Game1.player.mailReceived.Contains("hasPickedUpMagicInk") || Game1.player.hasMagicInk))
            {
                Game1.addMailForTomorrow(WOODS_OBELISK_WIZARD_MAIL_ID);
            }
        }
예제 #3
0
        private static void OpenPassageInSecretWoods(Woods woods)
        {
            // Game isn't running
            if (!ModEntry.IsDeepWoodsGameRunning)
            {
                ModEntry.Log("OpenPassageInSecretWoods: Cancelled, mod not initialized.", LogLevel.Trace);
                return;
            }

            // If warps exist, the map might be patched already, but we can't be 100% sure
            // So we just use this as an indicator not to print any warnings about stuff already being patched we might encounter further down.
            var  existingWarpLocations  = woods.warps.Where(warp => "DeepWoods".Equals(warp.TargetName)).Select(warp => new SimpleCoord(warp.X, warp.Y));
            bool possiblyPatchedAlready = existingWarpLocations.Any();

            Layer buildingsLayer = woods.map.GetLayer("Buildings");

            // Just to be sure
            if (buildingsLayer == null)
            {
                ModEntry.Log("OpenPassageInSecretWoods: Cancelled, invalid map (buildingsLayer is null).", LogLevel.Trace);
                return;
            }

            ModEntry.Log("OpenPassageInSecretWoods:", LogLevel.Trace);

            TileSheet borderTileSheet = woods.map.TileSheets.First();
            int       borderTileIndex = 0;

            int removed    = 0;
            int added      = 0;
            int warpsAdded = 0;

            foreach (var location in Settings.WoodsPassage.DeleteBuildingTiles)
            {
                if (buildingsLayer.Tiles[location.X, location.Y] == null)
                {
                    if (!possiblyPatchedAlready)
                    {
                        ModEntry.Log($"    Can't remove tile from building layer at {location.X}, {location.Y}, there is no tile here! (Custom Woods map? Please modify WoodsPassage settings in the DeepWoods config file for custom Woods maps.)", LogLevel.Trace);
                    }
                }
                else
                {
                    ModEntry.Log($"    Removing tile from building layer at {location.X}, {location.Y}.", LogLevel.Trace);
                    buildingsLayer.Tiles[location.X, location.Y] = null;
                    removed++;
                }
            }

            foreach (var location in Settings.WoodsPassage.AddBuildingTiles)
            {
                if (buildingsLayer.Tiles[location.X, location.Y] == null)
                {
                    ModEntry.Log($"    Adding tile to building layer at {location.X}, {location.Y}.", LogLevel.Trace);
                    buildingsLayer.Tiles[location.X, location.Y] = new StaticTile(buildingsLayer, borderTileSheet, BlendMode.Alpha, borderTileIndex);
                    added++;
                }
                else
                {
                    if (!possiblyPatchedAlready)
                    {
                        ModEntry.Log($"    Can't add tile to building layer at {location.X}, {location.Y}, already have a tile there! (Custom Woods map? Please modify WoodsPassage settings in the DeepWoods config file for custom Woods maps.)", LogLevel.Trace);
                    }
                }
            }

            foreach (var location in Settings.WoodsPassage.WarpLocations)
            {
                if (!existingWarpLocations.Contains(location))
                {
                    ModEntry.Log($"    Adding warp to DeepWoods at {location.X}, {location.Y}.", LogLevel.Trace);
                    woods.warps.Add(new Warp(location.X, location.Y, "DeepWoods", Settings.Map.RootLevelEnterLocation.X, Settings.Map.RootLevelEnterLocation.Y + 1, false));
                    warpsAdded++;
                }
            }

            if (possiblyPatchedAlready && added == 0 && removed == 0 && warpsAdded == 0)
            {
                ModEntry.Log($"OpenPassageInSecretWoods skipped. Map was already patched.", LogLevel.Trace);
            }
            else
            {
                ModEntry.Log($"OpenPassageInSecretWoods done. (Added {added}/{Settings.WoodsPassage.AddBuildingTiles.Length} tiles, removed {removed}/{Settings.WoodsPassage.DeleteBuildingTiles.Length} tiles, added {warpsAdded}/{Settings.WoodsPassage.WarpLocations.Length} warps.)", LogLevel.Trace);
            }
        }
예제 #4
0
        private void DoDeath(GameLocation location, Vector2 tileLocation)
        {
            DelayedAction.playSoundAfterDelay("leafrustle", 100, (GameLocation)null);
            Color  color         = Color.Green;
            string currentSeason = Game1.currentSeason;

            if (!(currentSeason == "spring"))
            {
                if (!(currentSeason == "summer"))
                {
                    if (!(currentSeason == "fall"))
                    {
                        if (currentSeason == "winter")
                        {
                            color = Color.Cyan;
                        }
                    }
                    else
                    {
                        color = Color.IndianRed;
                    }
                }
                else
                {
                    color = Color.ForestGreen;
                }
            }
            else
            {
                color = Color.Green;
            }
            for (int index1 = 0; index1 <= this.size.Value; ++index1)
            {
                for (int index2 = 0; index2 < 12; ++index2)
                {
                    ModEntry.GetMultiplayer().broadcastSprites(location, new TemporaryAnimatedSprite[1]
                    {
                        new TemporaryAnimatedSprite("LooseSprites\\Cursors", new Rectangle(355, 1200 + (Game1.IsFall ? 16 : (Game1.IsWinter ? -16 : 0)), 16, 16), Utility.getRandomPositionInThisRectangle(this.getBoundingBox(), Game1.random) - new Vector2(0.0f, (float)Game1.random.Next(64)), false, 0.01f, Game1.IsWinter ? Color.Cyan : Color.White)
                        {
                            motion             = new Vector2((float)Game1.random.Next(-10, 11) / 10f, (float)-Game1.random.Next(5, 7)),
                            acceleration       = new Vector2(0.0f, (float)Game1.random.Next(13, 17) / 100f),
                            accelerationChange = new Vector2(0.0f, -1f / 1000f),
                            scale                     = 4f,
                            layerDepth                = (float)((double)tileLocation.Y * 64.0 / 10000.0),
                            animationLength           = 11,
                            totalNumberOfLoops        = 99,
                            interval                  = (float)Game1.random.Next(20, 90),
                            delayBeforeAnimationStart = (index1 + 1) * index2 * 20
                        }
                    });
                    if (index2 % 6 == 0)
                    {
                        ModEntry.GetMultiplayer().broadcastSprites(location, new TemporaryAnimatedSprite[1]
                        {
                            new TemporaryAnimatedSprite(50, Utility.getRandomPositionInThisRectangle(this.getBoundingBox(), Game1.random) - new Vector2(32f, (float)Game1.random.Next(32, 64)), color, 8, false, 100f, 0, -1, -1f, -1, 0)
                        });
                        ModEntry.GetMultiplayer().broadcastSprites(location, new TemporaryAnimatedSprite[1]
                        {
                            new TemporaryAnimatedSprite(12, Utility.getRandomPositionInThisRectangle(this.getBoundingBox(), Game1.random) - new Vector2(32f, (float)Game1.random.Next(32, 64)), Color.White, 8, false, 100f, 0, -1, -1f, -1, 0)
                        });
                    }
                }
            }
        }
            // This method is also called by the patch in DeepWoodsMTNCompatibilityMod.
            // We return false when we handled this message, so Harmony will cancel the original MTN handler.
            private static bool InternalProcessIncomingMessage(IncomingMessage msg)
            {
                if (msg.MessageType == Settings.Network.DeepWoodsMessageId)
                {
                    int deepwoodsMessageType = msg.Reader.ReadInt32();
                    int randId = Game1.random.Next();

                    ModEntry.Log("InterceptProcessIncomingMessage[" + randId + "], master id: " + Game1.MasterPlayer.UniqueMultiplayerID + ", local id: " + Game1.player.UniqueMultiplayerID + ", msg.FarmerID: " + msg.FarmerID + ", deepwoodsMessageType: " + deepwoodsMessageType, StardewModdingAPI.LogLevel.Debug);

                    Farmer who = Game1.getFarmer(msg.FarmerID);
                    if (who == null || who == Game1.player)
                    {
                        ModEntry.Log(" who is null or local!", StardewModdingAPI.LogLevel.Warn);
                        return(true); // execute original
                    }

                    if (deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_INIT)
                    {
                        ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_INIT", StardewModdingAPI.LogLevel.Debug);
                        if (Game1.IsMasterGame)
                        {
                            // Client requests settings and state, send it:
                            List <string> deepWoodsLevelNames = new List <string>();
                            foreach (var location in Game1.locations)
                            {
                                if (location is DeepWoods deepWoods)
                                {
                                    deepWoodsLevelNames.Add(deepWoods.Name);
                                }
                            }

                            object[] data = new object[deepWoodsLevelNames.Count + 4];
                            data[0] = NETWORK_MESSAGE_DEEPWOODS_INIT;
                            data[1] = JsonConvert.SerializeObject(Settings);
                            data[2] = JsonConvert.SerializeObject(DeepWoodsState);
                            data[3] = (int)deepWoodsLevelNames.Count;
                            for (int i = 0; i < deepWoodsLevelNames.Count; i++)
                            {
                                data[i + 4] = deepWoodsLevelNames[i];
                            }

                            ModEntry.Log(" [" + randId + "] Client requests settings and state, deepWoodsLevelNames.Count: " + deepWoodsLevelNames.Count + ", deepWoodsLevelNames: " + String.Join(", ", deepWoodsLevelNames.ToArray()), StardewModdingAPI.LogLevel.Debug);
                            who.queueMessage(Settings.Network.DeepWoodsMessageId, Game1.MasterPlayer, data);
                        }
                        else
                        {
                            // Server sent us settings and state!
                            Settings       = JsonConvert.DeserializeObject <DeepWoodsSettings>(msg.Reader.ReadString());
                            DeepWoodsState = JsonConvert.DeserializeObject <DeepWoodsStateData>(msg.Reader.ReadString());
                            int           numDeepWoodsLevelNames = msg.Reader.ReadInt32();
                            List <string> deepWoodsLevelNames    = new List <string>();
                            for (int i = 0; i < numDeepWoodsLevelNames; i++)
                            {
                                deepWoodsLevelNames.Add(msg.Reader.ReadString());
                            }
                            ModEntry.Log(" [" + randId + "] Server sent us settings and state, deepWoodsLevelNames.Count: " + deepWoodsLevelNames.Count + ", deepWoodsLevelNames: " + String.Join(", ", deepWoodsLevelNames.ToArray()), StardewModdingAPI.LogLevel.Debug);
                            ModEntry.DeepWoodsInitServerAnswerReceived(deepWoodsLevelNames);
                        }
                    }
                    else
                    {
                        if (!Game1.IsMasterGame && !ModEntry.IsDeepWoodsGameRunning)
                        {
                            if (ModEntry.HasRequestedInitMessageFromServer)
                            {
                                ModEntry.Log("Got message from server before init message!", StardewModdingAPI.LogLevel.Warn);
                            }
                            else
                            {
                                ModEntry.Log("Got message from server before init message, never sent init message request!", StardewModdingAPI.LogLevel.Warn);
                            }
                        }
                        if (deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_WARP)
                        {
                            ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_WARP", StardewModdingAPI.LogLevel.Debug);
                            DeepWoodsWarpMessageData data = ReadDeepWoodsWarpMessage(msg.Reader);
                            if (Game1.IsMasterGame)
                            {
                                // Client requests that we load and activate a specific DeepWoods level they want to warp into.
                                DeepWoods deepWoods = DeepWoodsManager.AddDeepWoodsFromObelisk(data.Level);
                                // Send message to client telling them we have the level ready.
                                ModEntry.Log(" [" + randId + "] Client requests that we load and activate a specific DeepWoods level they want to warp into: data.Level:" + data.Level, StardewModdingAPI.LogLevel.Debug);
                                who.queueMessage(Settings.Network.DeepWoodsMessageId, Game1.MasterPlayer, new object[] { NETWORK_MESSAGE_DEEPWOODS_WARP, deepWoods.level.Value, deepWoods.Name, new Vector2(deepWoods.enterLocation.Value.X, deepWoods.enterLocation.Value.Y) });
                            }
                            else
                            {
                                // Server informs us that we can warp now!
                                ModEntry.Log(" [" + randId + "] Server informs us that we can warp now: data.Level:" + data.Level + ", data.Name:" + data.Name, StardewModdingAPI.LogLevel.Debug);
                                DeepWoodsManager.AddBlankDeepWoodsToGameLocations(data.Name);
                                DeepWoodsManager.WarpFarmerIntoDeepWoodsFromServerObelisk(data.Name, data.EnterLocation);
                            }
                        }
                        else if (deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_LEVEL)
                        {
                            ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_LEVEL", StardewModdingAPI.LogLevel.Debug);
                            if (!Game1.IsMasterGame && who == Game1.MasterPlayer)
                            {
                                DeepWoodsState.LowestLevelReached = msg.Reader.ReadInt32();
                                ModEntry.Log(" [" + randId + "] DeepWoodsState.LowestLevelReached: " + DeepWoodsState.LowestLevelReached, StardewModdingAPI.LogLevel.Debug);
                            }
                        }
                        else if (deepwoodsMessageType == NETWORK_MESSAGE_RCVD_STARDROP_FROM_UNICORN)
                        {
                            ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_RCVD_STARDROP_FROM_UNICORN", StardewModdingAPI.LogLevel.Debug);
                            if (Game1.IsMasterGame)
                            {
                                DeepWoodsState.PlayersWhoGotStardropFromUnicorn.Add(who.UniqueMultiplayerID);
                            }
                        }
                        else if (deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_ADDREMOVE)
                        {
                            ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_ADDREMOVE", StardewModdingAPI.LogLevel.Debug);
                            if (!Game1.IsMasterGame)
                            {
                                bool   added = msg.Reader.ReadByte() != 0;
                                string name  = msg.Reader.ReadString();
                                ModEntry.Log(" [" + randId + "] added: " + added + ", name: " + name, StardewModdingAPI.LogLevel.Debug);
                                if (added)
                                {
                                    DeepWoodsManager.AddBlankDeepWoodsToGameLocations(name);
                                }
                                else
                                {
                                    DeepWoodsManager.RemoveDeepWoodsFromGameLocations(name);
                                }
                            }
                        }
                        else
                        {
                            ModEntry.Log(" [" + randId + "] unknown deepwoodsMessageType: " + deepwoodsMessageType + "!", StardewModdingAPI.LogLevel.Warn);
                            return(true); // execute original
                        }
                    }

                    return(false); // don't execute original
                }

                return(true); // execute original
            }
예제 #6
0
 public override object GetApi()
 {
     return(ModEntry.GetAPI());
 }
예제 #7
0
        Monster CreateRandomMonster(Vector2 location)
        {
            Monster monster = null;

            if (Game1.isDarkOut() && CanHazMonster(Settings.Monsters.Bat))
            {
                monster = new Bat(new Vector2());
            }
            else if (Game1.isDarkOut() && CanHazMonster(Settings.Monsters.Ghost))
            {
                monster = new Ghost(new Vector2());
            }
            else if (CanHazMonster(Settings.Monsters.BigSlime))
            {
                monster = new BigSlime(new Vector2(), GetSlimeLevel());
            }
            else if (CanHazMonster(Settings.Monsters.Grub))
            {
                monster = new Grub(new Vector2(), true);
            }
            else if (CanHazMonster(Settings.Monsters.Fly))
            {
                monster = new Fly(new Vector2(), true);
            }
            else if (CanHazMonster(Settings.Monsters.Brute))
            {
                monster = new ShadowBrute(new Vector2());
            }
            else if (CanHazMonster(Settings.Monsters.Golem))
            {
                monster = new RockGolem(new Vector2(), deepWoods.GetCombatLevel());
            }
            else if (CanHazMonster(Settings.Monsters.RockCrab))
            {
                monster = new RockCrab(new Vector2(), GetRockCrabType());
            }
            else if (CanHazMonster(Settings.Monsters.Bug))
            {
                monster = new Bug(new Vector2(), 121);
                monster.isHardModeMonster.Value = true;
            }
            else if (CanHazMonster(Settings.Monsters.ArmoredBug))
            {
                monster = new Bug(new Vector2(), 121);
                monster.isHardModeMonster.Value = true;
            }
            else if (Game1.isDarkOut() && CanHazMonster(Settings.Monsters.PutridGhost))
            {
                monster = new Ghost(new Vector2(), "Putrid Ghost");
            }
            else if (Game1.isDarkOut() && CanHazMonster(Settings.Monsters.DustSprite))
            {
                monster = new DustSpirit(new Vector2()); new Leaper();
            }
            else if (Game1.isDarkOut() && CanHazMonster(Settings.Monsters.Spider))
            {
                monster = new Leaper(new Vector2());
            }
            else
            {
                foreach (var modMonster in DeepWoodsAPI.ToShuffledList(ModEntry.GetAPI().Monsters))
                {
                    // Item1 is a mod provided function that returns true if the mod wants to spawn a custom monster at this location.
                    // Item2 is a mod provided function that returns the custom monster.
                    if (modMonster.Item1(deepWoods, location))
                    {
                        monster = modMonster.Item2();
                        break;
                    }
                }
            }

            // No other monster was selected and no mod provided a monster, default to green slime
            if (monster == null)
            {
                monster = new GreenSlime(new Vector2(), GetSlimeLevel());
            }

            if (!Settings.Monsters.DisableBuffedMonsters &&
                deepWoods.level.Value >= Settings.Level.MinLevelForBuffedMonsters &&
                !this.random.CheckChance(Settings.Monsters.ChanceForUnbuffedMonster))
            {
                BuffMonster(monster);
            }

            if (!Settings.Monsters.DisableDangerousMonsters &&
                deepWoods.level.Value >= Settings.Level.MinLevelForDangerousMonsters &&
                !this.random.CheckChance(Settings.Monsters.ChanceForNonDangerousMonster))
            {
                monster.isHardModeMonster.Value = true;
            }

            monster.faceDirection(this.random.GetRandomValue(0, 4));

            return(monster);
        }
예제 #8
0
 public static void SendMessage(string messageType, long playerID)
 {
     ModEntry.SendMessage(true, messageType, playerID);
 }
예제 #9
0
 public override void Entry(IModHelper helper)
 {
     ModEntry.mod = this;
     I18N.Init(helper.Translation);
     RegisterEvents(helper.Events);
 }
예제 #10
0
        private void Warp(ExitDirection exitDir)
        {
            if (Game1.locationRequest == null)
            {
                bool warped = false;

                string   targetDeepWoodsName   = null;
                Location?targetLocationWrapper = null;

                if (level.Value == 1 && exitDir == ExitDirection.TOP)
                {
                    targetDeepWoodsName   = "Woods";
                    targetLocationWrapper = WOODS_WARP_LOCATION;
                }
                else if (GetExit(exitDir) is DeepWoodsExit exit)
                {
                    targetDeepWoodsName = exit.TargetLocationName;
                    if (exit.TargetLocation.X == 0 && exit.TargetLocation.Y == 0)
                    {
                        if (Game1.getLocationFromName(targetDeepWoodsName) is DeepWoods exitDeepWoods)
                        {
                            exit.TargetLocation = new Location(exitDeepWoods.enterLocation.X, exitDeepWoods.enterLocation.Y);
                        }
                    }
                    targetLocationWrapper = exit.TargetLocation;
                }
                else if (CastEnterDirToExitDir(EnterDir) == exitDir)
                {
                    targetDeepWoodsName = parentName.Value;
                    if (ParentExitLocation.X == 0 && ParentExitLocation.Y == 0)
                    {
                        if (Game1.getLocationFromName(targetDeepWoodsName) is DeepWoods parentDeepWoods)
                        {
                            ParentExitLocation = parentDeepWoods.GetExit(EnterDirToExitDir(EnterDir)).Location;
                        }
                    }
                    targetLocationWrapper = ParentExitLocation;
                }

                ModEntry.Log($"Trying to warp from {this.Name}: (ExitDir: {exitDir}, Position: {Game1.player.Position.X}, {Game1.player.Position.Y}, targetDeepWoodsName: {targetDeepWoodsName}, targetLocation: {(targetLocationWrapper?.X ?? -1)}, {(targetLocationWrapper?.Y ?? -1)})", LogLevel.Trace);

                if (targetLocationWrapper.HasValue && targetDeepWoodsName != null)
                {
                    Location targetLocation = targetLocationWrapper.Value;

                    if (!(targetLocation.X == 0 && targetLocation.Y == 0))
                    {
                        if (exitDir == ExitDirection.LEFT)
                        {
                            targetLocation.X += 1;
                        }
                        else if (exitDir == ExitDirection.BOTTOM)
                        {
                            targetLocation.Y += 1;
                        }

                        if (targetDeepWoodsName != "Woods")
                        {
                            DeepWoodsManager.currentWarpRequestName     = targetDeepWoodsName;
                            DeepWoodsManager.currentWarpRequestLocation = new Vector2(targetLocation.X * 64, targetLocation.Y * 64);
                            if (!Game1.IsMasterGame)
                            {
                                DeepWoodsManager.AddBlankDeepWoodsToGameLocations(targetDeepWoodsName);
                            }
                        }

                        Game1.warpFarmer(targetDeepWoodsName, targetLocation.X, targetLocation.Y, false);
                        warped = true;
                    }
                }

                if (!warped)
                {
                    ModEntry.Log("Warp from " + this.Name + " failed. (ExitDir: " + exitDir + ")", LogLevel.Warn);
                }
            }
        }
예제 #11
0
 public override void Entry(IModHelper helper)
 {
     ModEntry.mod = this;
     RegisterEvents(helper.Events);
 }
예제 #12
0
        private void OnModMessageReceived(object sender, ModMessageReceivedEventArgs e)
        {
            if (e.FromModID != this.ModManifest.UniqueID)
            {
                return;
            }

            ModEntry.Log($"[{(Context.IsMainPlayer ? "host" : "farmhand")}] Received {e.Type} from {e.FromPlayerID}.", LogLevel.Trace);

            switch (e.Type)
            {
            // farmhand requested metadata
            case MessageId.RequestMetadata:
                if (Context.IsMainPlayer)
                {
                    // client requests settings and state, send it:
                    InitResponseMessage response = new InitResponseMessage
                    {
                        Settings   = DeepWoodsSettings.Settings,
                        State      = DeepWoodsSettings.DeepWoodsState,
                        LevelNames = Game1.locations.OfType <DeepWoods>().Select(p => p.Name).ToArray()
                    };
                    ModEntry.SendMessage(response, MessageId.Metadata, e.FromPlayerID);
                }
                break;

            // host sent metadata
            case MessageId.Metadata:
                if (!Context.IsMainPlayer)
                {
                    InitResponseMessage response = e.ReadAs <InitResponseMessage>();
                    DeepWoodsSettings.Settings       = response.Settings;
                    DeepWoodsSettings.DeepWoodsState = response.State;
                    ModEntry.DeepWoodsInitServerAnswerReceived(response.LevelNames);
                }
                break;

            // farmhand requested that we load and activate a DeepWoods level
            case MessageId.RequestWarp:
                if (Context.IsMainPlayer)
                {
                    // load level
                    int       level     = e.ReadAs <int>();
                    DeepWoods deepWoods = DeepWoodsManager.AddDeepWoodsFromObelisk(level);

                    // send response
                    WarpMessage response = new WarpMessage
                    {
                        Level         = deepWoods.Level,
                        Name          = deepWoods.Name,
                        EnterLocation = new Vector2(deepWoods.enterLocation.Value.X, deepWoods.enterLocation.Value.Y)
                    };
                    ModEntry.SendMessage(response, MessageId.Warp, e.FromPlayerID);
                }
                break;

            // host loaded area for warp
            case MessageId.Warp:
                if (!Context.IsMainPlayer)
                {
                    WarpMessage data = e.ReadAs <WarpMessage>();

                    DeepWoodsManager.AddBlankDeepWoodsToGameLocations(data.Name);
                    DeepWoodsManager.WarpFarmerIntoDeepWoodsFromServerObelisk(data.Name, data.EnterLocation);
                }
                break;

            // host sent 'lowest level reached' update
            case MessageId.SetLowestLevelReached:
                if (!Context.IsMainPlayer)
                {
                    DeepWoodsState.LowestLevelReached = e.ReadAs <int>();
                }
                break;

            // host sent 'received stardrop from unicorn' update
            case MessageId.SetUnicornStardropReceived:
                if (Context.IsMainPlayer)
                {
                    DeepWoodsState.PlayersWhoGotStardropFromUnicorn.Add(e.FromPlayerID);
                }
                break;

            // host added/removed location
            case MessageId.AddLocation:
                if (!Context.IsMainPlayer)
                {
                    string name = e.ReadAs <string>();
                    DeepWoodsManager.AddBlankDeepWoodsToGameLocations(name);
                }
                break;

            case MessageId.RemoveLocation:
                if (!Context.IsMainPlayer)
                {
                    string name = e.ReadAs <string>();
                    DeepWoodsManager.RemoveDeepWoodsFromGameLocations(name);
                }
                break;

            default:
                ModEntry.Log("   ignored unknown type.", LogLevel.Trace);
                break;
            }
        }
예제 #13
0
        private void OpenPassageInSecretWoods(Woods woods)
        {
            // TODO: Configurable (and moddable!) locations to modify Woods

            // Game isn't running
            if (!isDeepWoodsGameRunning)
            {
                ModEntry.Log("OpenPassageInSecretWoods: Cancelled, mod not initialized.", LogLevel.Trace);
                return;
            }

            // Already patched
            if (woods.warps.Where(warp => "DeepWoods".Equals(warp.TargetName)).Any())
            {
                ModEntry.Log("OpenPassageInSecretWoods: Cancelled, map already patched.", LogLevel.Trace);
                return;
            }

            Layer buildingsLayer = woods.map.GetLayer("Buildings");

            // Just to be sure
            if (buildingsLayer == null)
            {
                ModEntry.Log("OpenPassageInSecretWoods: Cancelled, invalid map (buildingsLayer is null).", LogLevel.Trace);
                return;
            }

            ModEntry.Log("OpenPassageInSecretWoods:", LogLevel.Trace);

            TileSheet borderTileSheet = woods.map.TileSheets.First();
            int       borderTileIndex = 0;

            int removed = 0;
            int added   = 0;

            foreach (var location in Settings.WoodsPassage.DeleteBuildingTiles)
            {
                if (buildingsLayer.Tiles[location.X, location.Y] == null)
                {
                    ModEntry.Log($"    Can't remove tile from building layer at {location.X}, {location.Y}, there is no tile here! (Custom Woods map? Please modify WoodsPassage settings in the DeepWoods config file for custom Woods maps.)", LogLevel.Trace);
                }
                else
                {
                    ModEntry.Log($"    Removing tile from building layer at {location.X}, {location.Y}.", LogLevel.Trace);
                    buildingsLayer.Tiles[location.X, location.Y] = null;
                    removed++;
                }
            }

            foreach (var location in Settings.WoodsPassage.AddBuildingTiles)
            {
                if (buildingsLayer.Tiles[location.X, location.Y] == null)
                {
                    ModEntry.Log($"    Adding tile to building layer at {location.X}, {location.Y}.", LogLevel.Trace);
                    buildingsLayer.Tiles[location.X, location.Y] = new StaticTile(buildingsLayer, borderTileSheet, BlendMode.Alpha, borderTileIndex);
                    added++;
                }
                else
                {
                    ModEntry.Log($"    Can't add tile to building layer at {location.X}, {location.Y}, already have a tile there! (Custom Woods map? Please modify WoodsPassage settings in the DeepWoods config file for custom Woods maps.)", LogLevel.Trace);
                }
            }

            foreach (var location in Settings.WoodsPassage.WarpLocations)
            {
                ModEntry.Log($"    Adding warp to DeepWoods at {location.X}, {location.Y}.", LogLevel.Trace);
                woods.warps.Add(new Warp(location.X, location.Y, "DeepWoods", Settings.Map.RootLevelEnterLocation.X, Settings.Map.RootLevelEnterLocation.Y + 1, false));
            }

            ModEntry.Log($"OpenPassageInSecretWoods done. (Added {added}/{Settings.WoodsPassage.AddBuildingTiles.Length} tiles, removed {removed}/{Settings.WoodsPassage.DeleteBuildingTiles.Length} tiles, added {Settings.WoodsPassage.WarpLocations.Length} warps.)", LogLevel.Trace);
        }
예제 #14
0
        private void OnReturnedToTitle(object sender, ReturnedToTitleEventArgs args)
        {
            ModEntry.Log("GameEvents_AfterReturnToTitle", StardewModdingAPI.LogLevel.Trace);

            isDeepWoodsGameRunning = false;
        }