示例#1
0
        public static void SpawnJunimoAtPosition(Vector2 pos, JunimoHut hut, int junimoNumber)
        {
            if (hut == null)
            {
                return;
            }
            Farm farm = Game1.getFarm();

            /*
             * Added by Mizzion. This will set the color of the junimos based on what gem is inside the hut.
             */
            bool  isPrismatic = false;
            Color?gemColor    = getGemColor(ref isPrismatic, hut);//Reflection.GetMethod(hut, "getGemColor").Invoke<Color>(isPrismatic);

            /*
             * End added By Mizzion
             */

            JunimoHarvester junimoHarvester = new JunimoHarvester(pos, hut, junimoNumber, gemColor);

            junimoHarvester.isPrismatic.Value = isPrismatic; //Added by Mizzion, Fixes the Prismatic Junimos.
            farm.characters.Add((NPC)junimoHarvester);
            hut.myJunimos.Add(junimoHarvester);

            if (Game1.isRaining)
            {
                var alpha = Reflection.GetField <float>(junimoHarvester, "alpha");
                alpha.SetValue(Config.FunChanges.RainyJunimoSpiritFactor);
            }
            if (!Utility.isOnScreen(Utility.Vector2ToPoint(pos), 64, farm))
            {
                return;
            }
            farm.playSound("junimoMeep1");
        }
        public CachedMessageEmojis(IModHelper helper, int numberVanillaEmojis)
        {
            Reflection = helper.Reflection;

            messagesField             = Reflection.GetField <List <ChatMessage> >(Game1.chatBox, "messages");
            cheatHistoryPositionField = Reflection.GetField <int>(Game1.chatBox, "cheatHistoryPosition");
            choosingEmojiField        = Reflection.GetField <bool>(Game1.chatBox, "choosingEmoji");
            emojiMenuIconField        = Reflection.GetField <ClickableTextureComponent>(Game1.chatBox, "emojiMenuIcon");

            formatMessageMethod = Reflection.GetMethod(Game1.chatBox, "formatMessage");
            messageColorMethod  = Reflection.GetMethod(Game1.chatBox, "messageColor");

            PlayerMessageList = new List <PlayerMessage>();

            NumberVanillaEmoji = numberVanillaEmojis;

            chatCommandsIsLoaded = helper.ModRegistry.IsLoaded("cat.chatcommands");
            if (chatCommandsIsLoaded)
            {
                displayLineIndexField    = Reflection.GetField <int>(Game1.chatBox, "displayLineIndex");
                getEndDisplayIndexMethod = Reflection.GetMethod(Game1.chatBox, "GetEndDisplayIndex");
            }

            SubscribeEvents();
        }
示例#3
0
        public ServerMenuSlot(CoopMenu menu, IReflectionHelper reflection, string serverName, string ip) : base(menu)
        {
            this.ServerName = serverName;
            this.IP         = ip;
            this.reflection = reflection;
            this.menu       = menu;

            var menuSlotsField = reflection.GetField <List <MenuSlot> >(menu, "menuSlots");//menuSlots for Join, hostSlots for Host
            var list           = menuSlotsField.GetValue();

            deleteButton = new ClickableTextureComponent("",
                                                         new Rectangle(0, 0, 48, 48), "", "Delete", Game1.mouseCursors, new Rectangle(322, 498, 12, 12), 3f, false);

            CoopMenuPerformLeftClickPreListenerAndOverrider.PerformLeftClick += (x) =>
            {
                if (deleteButton.bounds.Contains(Game1.getMousePosition()) &&
                    reflection.GetField <CoopMenu.Tab>(menu, "currentTab").GetValue() == CoopMenu.Tab.JOIN_TAB &&
                    reflection.GetField <List <MenuSlot> >(menu, "menuSlots").GetValue() != null)
                {
                    DeleteBookmark?.Invoke(menu, this);

                    x.Override = true;
                }
            };
        }
示例#4
0
        /// <summary>Apply the mod textures to the given menu, if applicable.</summary>
        /// <param name="menu">The menu to change.</param>
        /// <param name="isFarmExpansion">Whether the menu is the Farm Expansion build menu.</param>
        /// <param name="isPelicanFiber">Whether the menu is the Pelican Fiber build menu.</param>
        /// <param name="isGarage">Whether a blueprint is for a tractor garage.</param>
        /// <param name="reflection">The SMAPI API for accessing internal code.</param>
        public void ApplyTextures(IClickableMenu menu, bool isFarmExpansion, bool isPelicanFiber, Func <BluePrint, bool> isGarage, IReflectionHelper reflection)
        {
            // vanilla menu
            if (menu is CarpenterMenu carpenterMenu)
            {
                if (isGarage(carpenterMenu.CurrentBlueprint))
                {
                    Building building = reflection.GetField <Building>(carpenterMenu, "currentBuilding").GetValue();
                    if (building.texture.Value != this.GarageTexture && this.GarageTexture != null)
                    {
                        building.texture = new Lazy <Texture2D>(() => this.GarageTexture);
                    }
                }
                return;
            }

            // Farm Expansion & Pelican Fiber menus

            if (isFarmExpansion || isPelicanFiber)
            {
                BluePrint currentBlueprint = reflection.GetProperty <BluePrint>(menu, isFarmExpansion ? "CurrentBlueprint" : "currentBlueprint").GetValue();
                if (isGarage(currentBlueprint))
                {
                    Building building = reflection.GetField <Building>(menu, "currentBuilding").GetValue();
                    if (building.texture.Value != this.GarageTexture && this.GarageTexture != null)
                    {
                        building.texture = new Lazy <Texture2D>(() => this.GarageTexture);
                    }
                }
            }
        }
示例#5
0
        public void Shake(IReflectionHelper helper, Vector2 tile)
        {
            // can't just call shake because it drops items. We don't want to drop items.
            // see Tree::shake for the logic this replicates

            // already shaking
            if (helper.GetField <float>(tree, "maxShake").GetValue() != 0)
            {
                return;
            }

            tree.shakeLeft.Value = this.left;
            helper.GetField <float>(tree, "maxShake").SetValue((float)(tree.growthStage.Value >= 5 ? Math.PI / 128f : Math.PI / 64f));

            if (tree.growthStage.Value >= 3 && !tree.stump.Value)
            {
                if (tree.growthStage.Value >= 5)
                {
                    if (Game1.random.NextDouble() < 0.66)
                    {
                        List <Leaf> leaves = helper.GetField <List <Leaf> >(this.tree, "leaves").GetValue();

                        int num = Game1.random.Next(1, 6);
                        for (int index = 0; index < num; ++index)
                        {
                            leaves.Add(new Leaf(new Vector2((float)Game1.random.Next((int)((double)tile.X * 64.0 - 64.0), (int)((double)tile.X * 64.0 + 128.0)), (float)Game1.random.Next((int)((double)tile.Y * 64.0 - 256.0), (int)((double)tile.Y * 64.0 - 192.0))), (float)Game1.random.Next(-10, 10) / 100f, Game1.random.Next(4), (float)Game1.random.Next(5) / 10f));
                        }
                    }

                    if (Game1.random.NextDouble() < 0.01 && (this.tree.currentLocation.GetSeasonForLocation().Equals("spring") || this.tree.currentLocation.GetSeasonForLocation().Equals("summer") || this.tree.currentLocation.GetLocationContext() == GameLocation.LocationContext.Island))
                    {
                        while (Game1.random.NextDouble() < 0.8)
                        {
                            location.addCritter((Critter) new Butterfly(new Vector2(tile.X + (float)Game1.random.Next(1, 3), tile.Y - 2f + (float)Game1.random.Next(-1, 2)), this.tree.currentLocation.GetLocationContext() == GameLocation.LocationContext.Island));
                        }
                    }
                }
                else
                {
                    if (Game1.random.NextDouble() < 0.66)
                    {
                        List <Leaf> leaves = helper.GetField <List <Leaf> >(this.tree, "leaves").GetValue();

                        int num = Game1.random.Next(1, 3);
                        for (int index = 0; index < num; ++index)
                        {
                            leaves.Add(new Leaf(new Vector2((float)Game1.random.Next((int)((double)tile.X * 64.0), (int)((double)tile.X * 64.0 + 48.0)), (float)((double)tile.Y * 64.0 - 32.0)), (float)Game1.random.Next(-10, 10) / 100f, Game1.random.Next(4), (float)Game1.random.Next(30) / 10f));
                        }
                    }
                }
            }
            else
            {
                if (tree.stump.Value)
                {
                    helper.GetField <float>(tree, "shakeTimer").SetValue(100);
                }
            }
        }
示例#6
0
        /// <summary>Render the UI.</summary>
        /// <param name="spriteBatch">The sprite batch being drawn.</param>
        public override void draw(SpriteBatch spriteBatch)
        {
            // disable when game is using immediate sprite sorting
            if (!ValidatedDrawMode)
            {
                IReflectedField <SpriteSortMode> sortModeField =
                    Reflection.GetField <SpriteSortMode>(Game1.spriteBatch, "spriteSortMode", required: false) // XNA
                    ?? Reflection.GetField <SpriteSortMode>(Game1.spriteBatch, "_sortMode");                   // MonoGame
                if (sortModeField.GetValue() == SpriteSortMode.Immediate)
                {
                    Monitor.Log("Aborted the weather draw because the game's current rendering mode isn't compatible with the mod's UI. This only happens in rare cases (e.g. the Stardew Valley Fair).", LogLevel.Warn);
                    exitThisMenu(playSound: false);
                    return;
                }
                ValidatedDrawMode = true;
            }

            // calculate dimensions
            int       x             = xPositionOnScreen;
            int       y             = yPositionOnScreen;
            const int gutter        = 15;
            float     leftOffset    = gutter;
            float     topOffset     = gutter;
            float     contentWidth  = width - gutter * 2;
            float     contentHeight = height - gutter * 2;

            // get font
            SpriteFont font       = Game1.smallFont;
            float      lineHeight = font.MeasureString("ABC").Y;

            //at this point I'm going to manually put this in as I don't need in many places,
            // and I kinda want to have this where I can understand what it's for
            float spaceWidth = DrawHelper.GetSpaceWidth(font);

            // draw background
            // (This uses a separate sprite batch because it needs to be drawn before the
            // foreground batch, and we can't use the foreground batch because the background is
            // outside the clipping area.)
            spriteBatch.DrawSprite(Sprites.Letter.Sheet, Sprites.Letter.Sprite, x, y, scale: width / (float)Sprites.Letter.Sprite.Width);

            // begin draw

            // draw weather icon
            spriteBatch.Draw(IconSheet.WeatherSource, new Vector2(x + leftOffset, y + topOffset), IconSheet.GetWeatherSprite(CurrentWeather.GetCurrentConditions()), Color.White);
            leftOffset += 72;

            // draw text as sent from outside the menu
            float wrapWidth = width - leftOffset - gutter;

            {
                Vector2 textSize = spriteBatch.DrawTextBlock(font, MenuText, new Vector2(x + leftOffset, y + topOffset), wrapWidth);
                topOffset += textSize.Y;
                topOffset += lineHeight;
            }

            drawMouse(Game1.spriteBatch);
        }
示例#7
0
        /// <summary>Raised after the player presses a button on the keyboard, controller, or mouse.</summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event data.</param>
        private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
        {
            if (Game1.activeClickableMenu is GameMenu gameMenu && gameMenu.currentTab == GameMenu.mapTab)
            {
                if (modHelper.Input.IsDown(SButton.LeftAlt) && modHelper.Input.IsDown(SButton.MouseLeft))
                {
                    MapPage mapPage  = (MapPage)Reflection.GetField <List <IClickableMenu> >(gameMenu, "pages").GetValue()[GameMenu.mapTab];
                    Vector2 mapCoord = new Vector2(Reflection.GetField <int>(mapPage, "mapX").GetValue(), Reflection.GetField <int>(mapPage, "mapY").GetValue());

                    //Vector2 mapPos = Utility.getTopLeftPositionForCenteringOnScreen(Sprites.Map.SourceRectangle.Width * Game1.pixelZoom, Sprites.Map.SourceRectangle.Height * Game1.pixelZoom);
                    Vector2 pingedCoord = new Vector2(e.Cursor.ScreenPixels.X - mapCoord.X, e.Cursor.ScreenPixels.Y - mapCoord.Y);

                    int mapWidth  = Sprites.Map.SourceRectangle.Width * Game1.pixelZoom;
                    int mapHeight = Sprites.Map.SourceRectangle.Height * Game1.pixelZoom;
                    if (IsPingWithinMapBounds(mapWidth, mapHeight, pingedCoord))
                    {
                        //TODO: Send ping to players

                        if (config.ShowPingsInChat)
                        {
                            string hoverText = Reflection.GetField <string>(mapPage, "hoverText").GetValue();

                            if (!String.IsNullOrWhiteSpace(hoverText))
                            {
                                hoverText = $"\"{GetHoverTextLocationName(hoverText)}\"";
                            }

                            if (!MapPings.ContainsKey(Game1.player))
                            {
                                MapPings.Add(Game1.player, new PlayerMapPing(Color.Red));
                            }

                            MapPings[Game1.player].AddPing(Game1.player, pingedCoord, hoverText);

                            string messageKey  = "UserNotificationMessageFormat";
                            string messageText = $"{Game1.player.Name} pinged {hoverText} [X:{pingedCoord.X}, Y:{pingedCoord.Y}]";

                            if (Game1.IsMultiplayer)
                            {
                                Multiplayer multiplayer = Reflection.GetField <Multiplayer>(typeof(Game1), "multiplayer").GetValue();
                                multiplayer.globalChatInfoMessage(messageKey, messageText);
                            }
                            else
                            {
                                Game1.chatBox.addInfoMessage(Game1.content.LoadString("Strings\\UI:Chat_" + messageKey, messageText));
                            }
                        }
#if DEBUG
                        ModEntry.ModLogger.Log($"MapCoords => (x: {pingedCoord.X}, y: {pingedCoord.Y})");
                        ModEntry.ModLogger.Log($"Map (X: {mapCoord.X}, Y: {mapCoord.Y})");
#endif
                    }

                    modHelper.Input.Suppress(SButton.MouseLeft);
                }
            }
        }
示例#8
0
 public CommandEmojiMenu(IReflectionHelper reflection, ChatBox chatBox, Texture2D emojiTexture,
                         Texture2D chatBoxTexture) : base(chatBox, emojiTexture, chatBoxTexture)
 {
     this.bUpArrow               = reflection.GetField <ClickableComponent>(this, "upArrow").GetValue();
     this.bDownArrow             = reflection.GetField <ClickableComponent>(this, "downArrow").GetValue();
     this.bSendArrow             = reflection.GetField <ClickableComponent>(this, "sendArrow").GetValue();
     this.bEmojiSelectionButtons =
         reflection.GetField <List <ClickableComponent> >(this, "emojiSelectionButtons").GetValue();
     this.bPageStartIndex   = reflection.GetField <int>(this, "pageStartIndex");
     this.bUpArrowPressed   = reflection.GetMethod(this, "upArrowPressed");
     this.bDownArrowPressed = reflection.GetMethod(this, "downArrowPressed");
 }
示例#9
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="recipe">The recipe to parse.</param>
 /// <param name="reflectionHelper">Simplifies access to private game code.</param>
 /// <param name="translations">Provides translations stored in the mod folder.</param>
 public RecipeModel(CraftingRecipe recipe, IReflectionHelper reflectionHelper, ITranslationHelper translations)
     : this(
         key : recipe.name,
         type : recipe.isCookingRecipe ? RecipeType.Cooking : RecipeType.Crafting,
         displayType : translations.Get(recipe.isCookingRecipe ? L10n.RecipeTypes.Cooking : L10n.RecipeTypes.Crafting),
         ingredients : reflectionHelper.GetField <Dictionary <int, int> >(recipe, "recipeList").GetValue(),
         item : item => recipe.createItem(),
         mustBeLearned : true,
         outputItemIndex : reflectionHelper.GetField <List <int> >(recipe, "itemToProduce").GetValue()[0]
         )
 {
 }
示例#10
0
        public void Shake(IReflectionHelper helper, Vector2 tile)
        {
            // can't just call shake because it drops items. We don't want to drop items.
            // unfortunately almost identical, but different from, TreeShaker
            // see FruitTree::shake for the logic this replicates

            // already shaking
            if (helper.GetField <float>(fruitTree, "maxShake").GetValue() != 0)
            {
                return;
            }

            fruitTree.shakeLeft.Value = this.left;
            helper.GetField <float>(fruitTree, "maxShake").SetValue((float)(fruitTree.growthStage.Value >= 5 ? Math.PI / 128f : Math.PI / 64f));

            if (fruitTree.growthStage.Value >= 3 && !fruitTree.stump.Value)
            {
                if (fruitTree.growthStage.Value >= 4)
                {
                    if (Game1.random.NextDouble() < 0.66)
                    {
                        List <Leaf> leaves = helper.GetField <List <Leaf> >(this.fruitTree, "leaves").GetValue();

                        int num = Game1.random.Next(1, 6);
                        for (int index = 0; index < num; ++index)
                        {
                            leaves.Add(new Leaf(new Vector2((float)Game1.random.Next((int)((double)tile.X * 64.0 - 64.0), (int)((double)tile.X * 64.0 + 128.0)), (float)Game1.random.Next((int)((double)tile.Y * 64.0 - 256.0), (int)((double)tile.Y * 64.0 - 192.0))), (float)Game1.random.Next(-10, 10) / 100f, Game1.random.Next(4), (float)Game1.random.Next(5) / 10f));
                        }
                    }
                }
                else
                {
                    if (Game1.random.NextDouble() < 0.66)
                    {
                        List <Leaf> leaves = helper.GetField <List <Leaf> >(this.fruitTree, "leaves").GetValue();

                        int num = Game1.random.Next(1, 3);
                        for (int index = 0; index < num; ++index)
                        {
                            leaves.Add(new Leaf(new Vector2((float)Game1.random.Next((int)((double)tile.X * 64.0), (int)((double)tile.X * 64.0 + 48.0)), (float)((double)tile.Y * 64.0 - 32.0)), (float)Game1.random.Next(-10, 10) / 100f, Game1.random.Next(4), (float)Game1.random.Next(30) / 10f));
                        }
                    }
                }
            }
            else
            {
                if (fruitTree.stump.Value)
                {
                    helper.GetField <float>(fruitTree, "shakeTimer").SetValue(100);
                }
            }
        }
示例#11
0
        private bool ShouldDrawIndicator(NPC npc)
        {
            IReflectionHelper reflection = QuestFrameworkMod.Instance.Helper.Reflection;

            return(npc.isVillager() &&
                   this.ActiveIndicators.Contains(npc.Name) &&
                   !npc.IsInvisible &&
                   !npc.IsEmoting &&
                   !npc.isSleeping.Value &&
                   !Game1.eventUp &&
                   reflection.GetField <int>(npc, "textAboveHeadTimer").GetValue() <= 0 &&
                   reflection.GetField <string>(npc, "textAboveHead").GetValue() == null);
        }
示例#12
0
        public void Shake(IReflectionHelper helper, Vector2 tile)
        {
            // can't just call shake because it drops items. We don't want to drop items.
            // see Bush::shake for the logic this replicates

            // already shaking
            if (helper.GetField <float>(this.bush, "maxShake").GetValue() != 0)
            {
                return;
            }

            helper.GetField <bool>(this.bush, "shakeLeft").SetValue(this.left);
            helper.GetField <float>(this.bush, "maxShake").SetValue((float)Math.PI / 128f);
        }
示例#13
0
 /// <summary>Construct an instance.</summary>
 /// <param name="recipe">The recipe to parse.</param>
 /// <param name="reflectionHelper">Simplifies access to private game code.</param>
 public RecipeModel(CraftingRecipe recipe, IReflectionHelper reflectionHelper)
     : this(
         key : recipe.name,
         type : recipe.isCookingRecipe ? RecipeType.Cooking : RecipeType.Crafting,
         displayType : recipe.isCookingRecipe ? L10n.RecipeTypes.Cooking() : L10n.RecipeTypes.Crafting(),
         ingredients : reflectionHelper.GetField <Dictionary <int, int> >(recipe, "recipeList").GetValue(),
         item : item => recipe.createItem(),
         mustBeLearned : true,
         outputItemIndex : reflectionHelper.GetField <List <int> >(recipe, "itemToProduce").GetValue()[0],
         minOutput : recipe.numberProducedPerCraft,
         isForMachine : obj => false
         )
 {
 }
示例#14
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="reflection">Simplifies access to private code.</param>
        /// <param name="options">The available dropdown options.</param>
        /// <param name="selected">The selected key, if any.</param>
        /// <param name="getKeyString">The logic to get the </param>
        public SimpleDropdown(IReflectionHelper reflection, IEnumerable <KeyValuePair <TKey, string> > options, TKey?selected = default, Func <TKey, string>?getKeyString = null)
        {
            getKeyString ??= raw => raw.ToString() ?? string.Empty;

            // parse options
            var optionKeys   = new List <string?>();
            var optionLabels = new List <string>();
            var lookup       = new List <Tuple <string, TKey, string> >();

            foreach ((TKey key, string value) in options)
            {
                string keyStr = getKeyString(key);

                optionKeys.Add(keyStr);
                optionLabels.Add(value);
                lookup.Add(Tuple.Create(keyStr, key, value));
            }

            // build dropdown
            this.Options  = lookup;
            this.Dropdown = new OptionsDropDown(null, -int.MaxValue)
            {
                dropDownOptions        = optionKeys,
                dropDownDisplayOptions = optionLabels
            };
            this.IsExpandedField = reflection.GetField <bool>(this.Dropdown, "clicked");

            // select element
            this.TrySelect(selected);
        }
示例#15
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="contentPack">The content pack from which the patch was loaded.</param>
        /// <param name="name">The raw patch name to display in error messages.</param>
        /// <param name="patch">The patch instance from Content Patcher.</param>
        /// <param name="reflection">Simplifies access to private code.</param>
        /// <param name="reflection">Simplifies access to game content.</param>
        public PatchData(IContentPack contentPack, string name, object patch, IReflectionHelper reflection)
        {
            this.ContentPack = contentPack;
            this.Name        = name;
            this.Reflection  = reflection;

            this.LastChangedTickProperty = reflection.GetProperty <int>(patch, "LastChangedTick");
            this.IsReadyProperty         = reflection.GetProperty <bool>(patch, "IsReady");
            this.IsAppliedProperty       = reflection.GetProperty <bool>(patch, "IsApplied");
            this.FromAssetProperty       = reflection.GetProperty <string>(patch, "FromAsset");
            this.TargetAssetProperty     = reflection.GetProperty <IAssetName>(patch, "TargetAsset");
            this.FromAreaProperty        = reflection.GetField <object>(patch, "FromArea");
            this.ToAreaProperty          = reflection.GetField <object>(patch, "ToArea");

            this.RefreshIfNeeded();
        }
示例#16
0
        public int GetClickedItemIndex(IReflectionHelper reflection, ShopMenu shopMenu, Point p)
        {
            int currentItemIndex = reflection.GetField <int>(shopMenu, "currentItemIndex").GetValue();
            int saleButtonIndex  = shopMenu.forSaleButtons.FindIndex(button => button.containsPoint(p.X, p.Y));

            return(saleButtonIndex > -1 ? currentItemIndex + saleButtonIndex : -1);
        }
示例#17
0
 private static void DoEmote_Postfix(Farmer __instance, int whichEmote)
 {
     if (Context.IsMultiplayer && __instance is Farmer && __instance.IsLocalPlayer && __instance.IsEmoting)
     {
         // Traverse.Create(typeof(Game1)).Field("multiplayer").GetValue<Multiplayer>().BroadcastEmote(whichEmote);
         Reflection.GetField <Multiplayer>(typeof(Game1), "multiplayer").GetValue().BroadcastEmote(whichEmote);
     }
 }
示例#18
0
        /// <summary>Helper method getting which item in the shop was clicked.</summary>
        /// <param name="reflection">Reflection helper.</param>
        /// <param name="shopMenu">Native shop menu.</param>
        /// <param name="p">Mouse location.</param>
        /// <returns>The clicked item or null if none was clicked.</returns>
        public static ISalable GetClickedShopItem(IReflectionHelper reflection, ShopMenu shopMenu, Point p)
        {
            var itemsForSale = reflection.GetField <List <ISalable> >(shopMenu, "forSale").GetValue();
            int index        = GetClickedItemIndex(reflection, shopMenu, p);

            Debug.Assert(index < itemsForSale.Count);
            return(index >= 0 ? itemsForSale[index] : null);
        }
示例#19
0
 /// <summary>Construct an instance.</summary>
 /// <param name="recipe">The recipe to parse.</param>
 /// <param name="reflectionHelper">Simplifies access to private game code.</param>
 public RecipeModel(CraftingRecipe recipe, IReflectionHelper reflectionHelper)
     : this(
         key : recipe.name,
         type : recipe.isCookingRecipe ? RecipeType.Cooking : RecipeType.Crafting,
         displayType : recipe.isCookingRecipe ? I18n.RecipeType_Cooking() : I18n.RecipeType_Crafting(),
         ingredients : reflectionHelper
         .GetField <Dictionary <int, int> >(recipe, "recipeList").GetValue()
         .Select(p => new RecipeIngredientModel(p.Key, p.Value)),
         item : item => recipe.createItem(),
         mustBeLearned : true,
         minOutput : recipe.numberProducedPerCraft,
         machineParentSheetIndex : null,
         isForMachine : obj => false
         )
 {
     this.OutputItemIndex = reflectionHelper.GetField <List <int> >(recipe, "itemToProduce").GetValue()[0];
     this.OutputItemType  = this.GetItemType(recipe, this.OutputItemIndex.Value);
 }
示例#20
0
        private void MenuEvents_MenuChanged(object sender, EventArgsClickableMenuChanged e)
        {
            if (Game1.activeClickableMenu is GameMenu gameMenu)
            {
                if (gameMenu.currentTab == GameMenu.mapTab)
                {
                    mapPage   = (MapPage)Reflection.GetField <List <IClickableMenu> >(gameMenu, "pages").GetValue()[GameMenu.mapTab];
                    mapXField = Reflection.GetField <int>(mapPage, "mapX");
                    mapYField = Reflection.GetField <int>(mapPage, "mapY");

                    IsMapOpen = true;
                }
                else
                {
                    IsMapOpen = false;
                }
            }
        }
        public void BroadcastEmote(int whichEmote)
        {
            TemporaryAnimatedSprite emoteStart = new TemporaryAnimatedSprite("TileSheets\\emotes", new Rectangle(0, 0, 16, 16), new Vector2(Game1.player.Position.X, Game1.player.Position.Y - 160), false, 0f, Color.White)
            {
                interval                = 80f,
                animationLength         = 4,
                scale                   = 4f,
                layerDepth              = 0.9f,
                local                   = false,
                timeBasedMotion         = true,
                attachedCharacter       = Game1.player,
                extraInfoForEndBehavior = 0,
                endFunction             = FinishedAnimation
            };

            TemporaryAnimatedSprite emote = new TemporaryAnimatedSprite("TileSheets\\emotes", new Rectangle(0, whichEmote * 16, 16, 16), new Vector2(Game1.player.Position.X, Game1.player.Position.Y - 160), false, 0f, Color.White)
            {
                delayBeforeAnimationStart = 100,
                interval                = 250f,
                animationLength         = 4,
                scale                   = 4f,
                layerDepth              = 1f,
                local                   = false,
                timeBasedMotion         = true,
                attachedCharacter       = Game1.player,
                extraInfoForEndBehavior = 1,
                endFunction             = FinishedAnimation
            };

            TemporaryAnimatedSprite emoteEnding = new TemporaryAnimatedSprite("TileSheets\\emotes", new Rectangle(0, 0, 16, 16), new Vector2(Game1.player.Position.X, Game1.player.Position.Y - 160), false, 0f, Color.White)
            {
                delayBeforeAnimationStart = 800,
                interval                = 80f,
                animationLength         = 4,
                scale                   = 4f,
                layerDepth              = 0.9f,
                local                   = false,
                timeBasedMotion         = true,
                pingPong                = true,                             // This makes the animation play, forwards, and when finished backwards
                sourceRect              = new Rectangle(48, 0, 16, 16),     // Set the current sprite position to the last animation image
                currentParentTileIndex  = 3,                                // To play the animation backwards, we tell it that its in the last frame
                attachedCharacter       = Game1.player,
                extraInfoForEndBehavior = 2,
                endFunction             = FinishedAnimation
            };

            temporaryAnimationList = new List <TemporaryAnimatedSprite>()
            {
                emoteStart,
                emote,
                emoteEnding
            };

            Multiplayer multiplayer = Reflection.GetField <Multiplayer>(typeof(Game1), "multiplayer").GetValue();

            multiplayer.broadcastSprites(Game1.player.currentLocation, temporaryAnimationList);
        }
示例#22
0
    public List <string>?GetCookingRecipes()
    {
        if (!IsLoaded || Entry == null)
        {
            return(null);
        }

        List <string>?removed = Helper.GetField <List <string> >(Entry, "_cookingRecipesToRemove", false)?.GetValue();

        if (removed == null)
        {
            return(null);
        }

        Log($"Removed {removed.Count} cooking recipes due to CCS.", LogLevel.Debug);

        return(Self.Recipes.GetRecipes(true).Select(v => v.Name).Where(v => !removed.Contains(v)).ToList());
    }
示例#23
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="town">The town to search.</param>
 /// <param name="tile">The machine's position in its location.</param>
 /// <param name="trashCanIndex">The trash can index.</param>
 /// <param name="reflection">Simplifies access to private game code.</param>
 public TrashCanMachine(Town town, Vector2 tile, int trashCanIndex, IReflectionHelper reflection)
 {
     this.Tile             = tile;
     this.TrashCansChecked = reflection.GetField <IList <bool> >(town, "garbageChecked").GetValue();
     if (trashCanIndex >= 0 && trashCanIndex < this.TrashCansChecked.Count)
     {
         this.TrashCanIndex = trashCanIndex;
     }
 }
示例#24
0
        private void Update(object sender, EventArgsInput e)
        {
            if (!(Game1.activeClickableMenu is GameMenu))
            {
                return;
            }
            var menuList = _reflection.GetField <List <IClickableMenu> >(Game1.activeClickableMenu, "pages").GetValue();

            foreach (var menu in menuList)
            {
                if (!(menu is InventoryPage))
                {
                    continue;
                }
                var item = _reflection.GetField <Item>(menu, "hoveredItem").GetValue();
                if (item == null)
                {
                    return;
                }

                var newSlot = -1;
                var oldSlot = Game1.player.Items.IndexOf(item);

                foreach (var ent in _keyBindings)
                {
                    foreach (var inputButton in ent.Value)
                    {
                        if (inputButton.key.ToString().Equals(e.Button.ToString()))
                        {
                            newSlot = ent.Key;
                        }
                    }
                }

                if (newSlot == -1)
                {
                    return;
                }

                var currentItem = Game1.player.Items[newSlot];
                Game1.player.items[newSlot] = item;
                Game1.player.items[oldSlot] = currentItem;
            }
        }
示例#25
0
 public BetterSlingshot(IReflectionHelper reflection, BetterSlingshotsConfig config, SObject currentProjectile, bool isActionButtonDown, int which) : base(which)
 {
     this.attachments[0]     = currentProjectile;
     this.reflection         = reflection;
     this.config             = config;
     this.isActionButtonDown = isActionButtonDown;
     this.autoFireRate       = this.GetFireRate();
     this.baseCanPlaySound   = reflection.GetField <bool>(this, "canPlaySound");
     this.isAutomatic        = config.AutomaticSlingshots.IndexOf(Enum.GetName(typeof(SlingshotType), SlingshotManager.GetTypeFromIndex(this.initialParentTileIndex)), StringComparison.InvariantCultureIgnoreCase) != -1;
 }
示例#26
0
        /// <summary>Update the indoor pot state on load for automation.</summary>
        /// <param name="indoorPot">The indoor pot to update.</param>
        /// <param name="reflection">Simplifies access to private code.</param>
        /// <remarks>Derived from <see cref="IndoorPot.updateWhenCurrentLocation"/>. When an indoor pot is loaded from the save file, the bush it contains isn't updated immediately. Instead it's marked dirty and will call <see cref="Bush.loadSprite"/> when the player first enters the location. For Automate, that means a bush that's already harvested may reset and produce a new harvest for the day.</remarks>
        private void UpdateIndoorPotOnLoad(IndoorPot indoorPot, IReflectionHelper reflection)
        {
            NetBool bushLoadDirty = reflection.GetField <NetBool>(indoorPot, "bushLoadDirty").GetValue();

            if (bushLoadDirty.Value)
            {
                indoorPot.bush.Value.loadSprite();
                bushLoadDirty.Value = false;
            }
        }
        /// <summary>
        /// Called after a game menu is opened, closed, or replaced.
        /// Responsible for displaying the actual content of a [Tool-Upgrade] mail, such as
        /// whether to show an attached tool, set the attached tool.
        /// </summary>
        /// <param name="sender">The event sender.</param>
        /// <param name="e">The event arguments.</param>
        private void OnMenuChanged(object sender, MenuChangedEventArgs e)
        {
            if (!(e.OldMenu is LetterViewerMenu) && e.NewMenu is LetterViewerMenu letterViewerMenu)
            {
                var mailTitle = reflectionHelper.GetField <string>(letterViewerMenu, "mailTitle").GetValue();
                if (mailTitle == null || !mailGenerator.IsToolMail(mailTitle))
                {
                    return;
                }

                ToolUpgradeInfo upgradeInfo = mailGenerator.GetMailAssignedToolUpgrade(mailTitle);
                if (upgradeInfo == null)
                {
                    monitor.Log("Failed to retrive tool data from mail!", LogLevel.Error);
                }

                Tool toolForMail = Game1.player.toolBeingUpgraded.Value;

                /*
                 * Check if the current upgrade tool matches with the tool which was assigned to this mail.
                 *
                 * Since the upgrade-mail content is generated when the mail is opened, the current upgrade tool
                 * could have changed in the meantime. In this case, no tool will be included in this mail.
                 */
                if (toolForMail != null && (toolForMail.GetType() != upgradeInfo.ToolType || toolForMail.UpgradeLevel != upgradeInfo.Level))
                {
                    toolForMail = null;
                }

                // Bonus: Set the water level to full for the upgraded watering can.
                if (toolForMail is WateringCan can)
                {
                    can.WaterLeft = can.waterCanMax;
                }

                var mailMessage = reflectionHelper.GetField <List <string> >(letterViewerMenu, "mailMessage").GetValue();

                var itemMenu = new ItemLetterMenuHelper(mailMessage[0], toolForMail);
                itemMenu.MenuClosed += OnToolMailClosed;

                itemMenu.Show();
            }
        }
示例#28
0
        public override void Activate()
        {
            Console.WriteLine($"Clicked bookmark: {ServerName} at {IP}");
            CoopMenu menu = TitleMenu.subMenu as CoopMenu;

            //IP in format of 127.0.0.1:1234
            var multiplayer   = reflection.GetField <Multiplayer>(typeof(Game1), "multiplayer");
            var setMenuMethod = reflection.GetMethod(menu, "setMenu", true);

            setMenuMethod.Invoke(new FarmhandMenu(multiplayer.GetValue().InitClient(new LidgrenClient(IP))));
        }
示例#29
0
        public void FillUIElements(CoopMenu menu)
        {
            //Add server buttons
            string  text  = "Add server";
            int     width = (int)Game1.dialogueFont.MeasureString(text).X + 64;
            Vector2 pos   = new Vector2(menu.backButton.bounds.Right - width, menu.backButton.bounds.Y - 128 - 150);

            addServerButton = new ClickableComponent(new Rectangle((int)pos.X, (int)pos.Y, width, 96), "", text);

            //Servers
            var menuSlotsField = reflection.GetField <List <MenuSlot> >(menu, "menuSlots");//menuSlots for Join, hostSlots for Host
            var list           = menuSlotsField.GetValue();

            list.RemoveAll((x) => x is ServerMenuSlot);//So there are no duplicates

            foreach (var x in bookmarks.Bookmarks)
            {
                list.Add(new ServerMenuSlot(menu, reflection, x.Key, x.Value));
            }
        }
示例#30
0
        public override void Resolve(GameLocation location, BaseFeatureSaveData featureSaveData)
        {
            Tree         currentTree  = location.terrainFeatures[featureSaveData.featurePosition] as Tree;
            TreeSaveData treeSaveData = featureSaveData as TreeSaveData;

            currentTree.stump  = false;
            currentTree.health = treeSaveData.health;
            reflectionHelper.GetField <bool>(currentTree, "falling").SetValue(false);

            monitor.Log($"Stopped {currentTree.GetType()} at position {featureSaveData.feature} from falling.", LogLevel.Trace);
        }