예제 #1
0
        /// <summary>Get the locale codes (like <c>ja-JP</c>) used in asset keys.</summary>
        /// <param name="reflection">Simplifies access to private game code.</param>
        private IDictionary <string, LanguageCode> GetKeyLocales(Reflector reflection)
        {
            // get the private code field directly to avoid changed-code logic
            IPrivateField <LanguageCode> codeField = reflection.GetPrivateField <LanguageCode>(typeof(LocalizedContentManager), "_currentLangCode");

            // remember previous settings
            LanguageCode previousCode     = codeField.GetValue();
            string       previousOverride = this.LanguageCodeOverride;

            // create locale => code map
            IDictionary <string, LanguageCode> map = new Dictionary <string, LanguageCode>(StringComparer.InvariantCultureIgnoreCase);

            this.LanguageCodeOverride = null;
            foreach (LanguageCode code in Enum.GetValues(typeof(LanguageCode)))
            {
                codeField.SetValue(code);
                map[this.GetKeyLocale.Invoke <string>()] = code;
            }

            // restore previous settings
            codeField.SetValue(previousCode);
            this.LanguageCodeOverride = previousOverride;

            return(map);
        }
예제 #2
0
 public TVIntercept(TV tv)
     : base(tv.parentSheetIndex, tv.tileLocation)
 {
     this.tv   = tv;
     tvScreen  = CustomTVMod.Modhelper.Reflection.GetPrivateField <TemporaryAnimatedSprite>(tv, "screen");
     tvOverlay = CustomTVMod.Modhelper.Reflection.GetPrivateField <TemporaryAnimatedSprite>(tv, "screenOverlay");
 }
예제 #3
0
        public static void onUpdate(object sender, EventArgs args)
        {
            try
            {
                Multiplayer.update();

                // We need our load menu to be able to do things
                if (Game1.activeClickableMenu is TitleMenu)
                {
                    if (TitleMenu.subMenu != null && (TitleMenu.subMenu.GetType() == typeof(LoadGameMenu)))
                    {
                        LoadGameMenu oldLoadMenu = ( LoadGameMenu )TitleMenu.subMenu;
                        NewLoadMenu  newLoadMenu = new NewLoadMenu();

                        IPrivateField <object> task = instance.Helper.Reflection.GetPrivateField <object>(oldLoadMenu, "_initTask");
                        newLoadMenu._initTask = (Task <List <SFarmer> >)task.GetValue();

                        TitleMenu.subMenu = newLoadMenu;
                    }
                }
                prevMenu = Game1.activeClickableMenu;
            }
            catch (Exception e)
            {
                Log.error("Exception during update: " + e);
            }
        }
예제 #4
0
        /****
        ** Field values
        ** (shorthand since this is the most common case)
        ****/
        /// <summary>Get the value of a private instance field.</summary>
        /// <typeparam name="TValue">The field type.</typeparam>
        /// <param name="obj">The object which has the field.</param>
        /// <param name="name">The field name.</param>
        /// <param name="required">Whether to throw an exception if the private field is not found.</param>
        /// <returns>Returns the field value, or the default value for <typeparamref name="TValue"/> if the field wasn't found and <paramref name="required"/> is false.</returns>
        /// <remarks>
        /// This is a shortcut for <see cref="GetPrivateField{TValue}(object,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.
        /// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(object,string,bool)" /> instead.
        /// </remarks>
        public TValue GetPrivateValue <TValue>(object obj, string name, bool required = true)
        {
            IPrivateField <TValue> field = this.GetPrivateField <TValue>(obj, name, required);

            return(field != null
                ? field.GetValue()
                : default(TValue));
        }
예제 #5
0
        public TValue GetPrivateValue <TValue>(Type type, string name, bool required = true)
        {
            this.DeprecationManager.Warn($"{nameof(IReflectionHelper)}.GetPrivate*", "2.3", DeprecationLevel.Notice);
            IPrivateField <TValue> field = (IPrivateField <TValue>) this.GetField <TValue>(type, name, required);

            return(field != null
                ? field.GetValue()
                : default(TValue));
        }
예제 #6
0
        /// <summary>Get the value of a private static field.</summary>
        /// <typeparam name="TValue">The field type.</typeparam>
        /// <param name="type">The type which has the field.</param>
        /// <param name="name">The field name.</param>
        /// <param name="required">Whether to throw an exception if the private field is not found.</param>
        /// <returns>Returns the field value, or the default value for <typeparamref name="TValue"/> if the field wasn't found and <paramref name="required"/> is false.</returns>
        /// <remarks>
        /// This is a shortcut for <see cref="GetPrivateField{TValue}(Type,string,bool)"/> followed by <see cref="IPrivateField{TValue}.GetValue"/>.
        /// When <paramref name="required" /> is false, this will return the default value if reflection fails. If you need to check whether the field exists, use <see cref="GetPrivateField{TValue}(Type,string,bool)" /> instead.
        /// </remarks>
        public TValue GetPrivateValue <TValue>(Type type, string name, bool required = true)
        {
            this.AssertAccessAllowed(type);
            IPrivateField <TValue> field = this.GetPrivateField <TValue>(type, name, required);

            return(field != null
                ? field.GetValue()
                : default(TValue));
        }
예제 #7
0
        /// <summary>Get a private static field.</summary>
        /// <typeparam name="TValue">The field type.</typeparam>
        /// <param name="type">The type which has the field.</param>
        /// <param name="name">The field name.</param>
        /// <param name="required">Whether to throw an exception if the private field is not found.</param>
        public IPrivateField <TValue> GetPrivateField <TValue>(Type type, string name, bool required = true)
        {
            // get field from hierarchy
            IPrivateField <TValue> field = this.GetFieldFromHierarchy <TValue>(type, null, name, BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public);

            if (required && field == null)
            {
                throw new InvalidOperationException($"The {type.FullName} object doesn't have a private '{name}' static field.");
            }
            return(field);
        }
예제 #8
0
        private void GameEvents_UpdateTick(object sender, EventArgs e)
        {
            if (Game1.activeClickableMenu is CarpenterMenu carpenter)
            {
                if (carpenter.CurrentBlueprint.name == "Aquaponics")
                {
                    IPrivateField <Building> cBuilding = Helper.Reflection.GetPrivateField <Building>(carpenter, "currentBuilding");

                    if (!(cBuilding.GetValue() is Aquaponics))
                    {
                        cBuilding.SetValue(new Aquaponics(Vector2.Zero, Game1.getFarm()));
                    }
                }
            }
        }
예제 #9
0
        /*********
        ** Public methods
        *********/
        /****
        ** Fields
        ****/
        /// <summary>Get a private instance field.</summary>
        /// <typeparam name="TValue">The field type.</typeparam>
        /// <param name="obj">The object which has the field.</param>
        /// <param name="name">The field name.</param>
        /// <param name="required">Whether to throw an exception if the private field is not found.</param>
        /// <returns>Returns the field wrapper, or <c>null</c> if the field doesn't exist and <paramref name="required"/> is <c>false</c>.</returns>
        public IPrivateField <TValue> GetPrivateField <TValue>(object obj, string name, bool required = true)
        {
            // validate
            if (obj == null)
            {
                throw new ArgumentNullException(nameof(obj), "Can't get a private instance field from a null object.");
            }

            // get field from hierarchy
            IPrivateField <TValue> field = this.GetFieldFromHierarchy <TValue>(obj.GetType(), obj, name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            if (required && field == null)
            {
                throw new InvalidOperationException($"The {obj.GetType().FullName} object doesn't have a private '{name}' instance field.");
            }
            return(field);
        }
예제 #10
0
        private void OnPreRenderGuiEvent(object sender, EventArgs e)
        {
            if (Game1.activeClickableMenu is Billboard)
            {
                Billboard menu          = (Billboard)Game1.activeClickableMenu;
                FieldInfo calendarField = menu.GetType().GetField("calendarDays", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                if (calendarField == null)
                {
                    this.Monitor.Log("Could not find field 'calendarDays' in Billboard!", LogLevel.Error);
                    return;
                }
                List <ClickableTextureComponent> calendarDays = (List <ClickableTextureComponent>)calendarField.GetValue(menu);
                IPrivateField <string>           hoverField   = this.Helper.Reflection.GetPrivateField <string>(menu, "hoverText");
                string hoverText = hoverField.GetValue();
                if (calendarDays != null && !(hoverText.Contains("Shrooms") || hoverText.Contains("shrooms")))
                {
                    for (int day = 1; day <= 28; day++)
                    {
                        ClickableTextureComponent component = calendarDays[day - 1];
                        if (component.bounds.Contains(Game1.getMouseX(), Game1.getMouseY()))
                        {
                            List <int> shrooms = this.GetShroomLayers(day - Game1.dayOfMonth);

                            if (hoverText.Length > 0)
                            {
                                hoverText += "\n";
                            }

                            if (shrooms.Count > 0)
                            {
                                hoverText += "Shrooms: " + string.Join(", ", shrooms);
                            }
                            else
                            {
                                hoverText += "No shrooms";
                            }

                            break;
                        }
                    }

                    hoverField.SetValue(hoverText);
                }
            }
        }
예제 #11
0
        /// <summary>Temporarily dismount and set up the player to interact with a tile, then return it to the previous state afterwards.</summary>
        /// <param name="action">The action to perform.</param>
        private void TemporarilyFakeInteraction(Action action)
        {
            // get references
            SFarmer player = Game1.player;
            IPrivateField <Horse> mountField = this.Reflection.GetPrivateField <Horse>(Game1.player, "mount");

            // save current state
            Horse       mount            = mountField.GetValue();
            Vector2     mountPosition    = this.Current.position;
            WateringCan wateringCan      = player.CurrentTool as WateringCan;
            int         waterInCan       = wateringCan?.WaterLeft ?? 0;
            float       stamina          = player.stamina;
            Vector2     position         = player.position;
            int         facingDirection  = player.facingDirection;
            int         currentToolIndex = player.CurrentToolIndex;
            bool        canMove          = Game1.player.canMove; // fix player frozen due to animations when performing an action

            // move mount out of the way
            mountField.SetValue(null);
            this.Current.position = new Vector2(-5, -5);

            // perform action
            try
            {
                action();
            }
            finally
            {
                // move mount back
                this.Current.position = mountPosition;
                mountField.SetValue(mount);

                // restore previous state
                if (wateringCan != null)
                {
                    wateringCan.WaterLeft = waterInCan;
                }
                player.stamina          = stamina;
                player.position         = position;
                player.facingDirection  = facingDirection;
                player.CurrentToolIndex = currentToolIndex;
                Game1.player.canMove    = canMove;
            }
        }
예제 #12
0
        public void rebuild(Dictionary <string, string> additionalSaveData, object replacement)
        {
            tv       = new TV(((TV)replacement).parentSheetIndex, ((TV)replacement).tileLocation);
            tvScreen = CustomTVMod.Modhelper.Reflection.GetPrivateField <TemporaryAnimatedSprite>(tv, "screen");

            tileLocation     = tv.tileLocation;
            parentSheetIndex = tv.parentSheetIndex;
            name             = tv.name;

            furniture_type    = tv.furniture_type;
            defaultSourceRect = tv.defaultSourceRect;
            drawHeldObjectLow = tv.drawHeldObjectLow;

            sourceRect        = tv.sourceRect;
            defaultSourceRect = tv.defaultSourceRect;

            defaultBoundingBox = tv.defaultBoundingBox;
            boundingBox        = tv.boundingBox;

            updateDrawPosition();
            rotations = tv.rotations;
            price     = tv.price;
        }
예제 #13
0
        public static void onUpdate(object sender, EventArgs args)
        {
            if (DEBUG)
            {
                Game1.options.pauseWhenOutOfFocus = false;
            }
            try
            {
                IPlatform.instance.update();
                Multiplayer.update();

                // We need our load menu to be able to do things
                if (Game1.activeClickableMenu is TitleMenu)
                {
                    if (TitleMenu.subMenu is LoadGameMenu)
                    {
                        Log.debug("Found vanilla load game menu, replacing with ours.");

                        Multiplayer.lobby = true;

                        LoadGameMenu oldLoadMenu = ( LoadGameMenu )TitleMenu.subMenu;
                        NewLoadMenu  newLoadMenu = new NewLoadMenu();

                        IPrivateField <object> task = instance.Helper.Reflection.GetPrivateField <object>(oldLoadMenu, "_initTask");
                        newLoadMenu._initTask = (Task <List <SFarmer> >)task.GetValue();
                        Log.debug("Stole the save listing task, set it to: " + task);

                        TitleMenu.subMenu = newLoadMenu;
                    }
                }
                prevMenu = Game1.activeClickableMenu;
            }
            catch (Exception e)
            {
                Log.error("Exception during update: " + e);
            }
        }
예제 #14
0
 /*********
 ** Private methods
 *********/
 /// <summary>Assert that mods can use the reflection helper to access the given member.</summary>
 /// <typeparam name="T">The field value type.</typeparam>
 /// <param name="field">The field being accessed.</param>
 /// <returns>Returns the same field instance for convenience.</returns>
 private IPrivateField <T> AssertAccessAllowed <T>(IPrivateField <T> field)
 {
     this.AssertAccessAllowed(field?.FieldInfo);
     return(field);
 }
예제 #15
0
        /// <summary>Render the UI.</summary>
        /// <param name="spriteBatch">The sprite batch being drawn.</param>
        public override void draw(SpriteBatch spriteBatch)
        {
            this.Monitor.InterceptErrors("drawing the lookup info", () =>
            {
                ISubject subject = this.Subject;

                // disable when game is using immediate sprite sorting
                // (This prevents Lookup Anything from creating new sprite batches, which breaks its core rendering logic.
                // Fortunately this very rarely happens; the only known case is the Stardew Valley Fair, when the only thing
                // you can look up anyway is the farmer.)
                if (!this.ValidatedDrawMode)
                {
                    IPrivateField <SpriteSortMode> sortModeField =
                        this.Reflection.GetPrivateField <SpriteSortMode>(Game1.spriteBatch, "spriteSortMode", required: false) // XNA
                        ?? this.Reflection.GetPrivateField <SpriteSortMode>(Game1.spriteBatch, "_sortMode");                   // MonoGame
                    if (sortModeField.GetValue() == SpriteSortMode.Immediate)
                    {
                        this.Monitor.Log("Aborted the lookup 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);
                        this.exitThisMenu(playSound: false);
                        return;
                    }
                    this.ValidatedDrawMode = true;
                }

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

                // get font
                SpriteFont font  = Game1.smallFont;
                float lineHeight = font.MeasureString("ABC").Y;
                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.)
                using (SpriteBatch backgroundBatch = new SpriteBatch(Game1.graphics.GraphicsDevice))
                {
                    backgroundBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null);
                    backgroundBatch.DrawSprite(Sprites.Letter.Sheet, Sprites.Letter.Sprite, x, y, scale: this.width / (float)Sprites.Letter.Sprite.Width);
                    backgroundBatch.End();
                }

                // draw foreground
                // (This uses a separate sprite batch to set a clipping area for scrolling.)
                using (SpriteBatch contentBatch = new SpriteBatch(Game1.graphics.GraphicsDevice))
                {
                    // begin draw
                    GraphicsDevice device   = Game1.graphics.GraphicsDevice;
                    device.ScissorRectangle = new Rectangle(x + gutter, y + gutter, (int)contentWidth, (int)contentHeight);
                    contentBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, new RasterizerState {
                        ScissorTestEnable = true
                    });

                    // scroll view
                    this.CurrentScroll = Math.Max(0, this.CurrentScroll);              // don't scroll past top
                    this.CurrentScroll = Math.Min(this.MaxScroll, this.CurrentScroll); // don't scroll past bottom
                    topOffset         -= this.CurrentScroll;                           // scrolled down == move text up

                    // draw portrait
                    if (subject.DrawPortrait(contentBatch, new Vector2(x + leftOffset, y + topOffset), new Vector2(70, 70)))
                    {
                        leftOffset += 72;
                    }

                    // draw fields
                    float wrapWidth = this.width - leftOffset - gutter;
                    {
                        // draw name & item type
                        {
                            Vector2 nameSize = contentBatch.DrawTextBlock(font, $"{subject.Name}.", new Vector2(x + leftOffset, y + topOffset), wrapWidth, bold: Constant.AllowBold);
                            Vector2 typeSize = contentBatch.DrawTextBlock(font, $"{subject.Type}.", new Vector2(x + leftOffset + nameSize.X + spaceWidth, y + topOffset), wrapWidth);
                            topOffset       += Math.Max(nameSize.Y, typeSize.Y);
                        }

                        // draw description
                        if (subject.Description != null)
                        {
                            Vector2 size = contentBatch.DrawTextBlock(font, subject.Description?.Replace(Environment.NewLine, " "), new Vector2(x + leftOffset, y + topOffset), wrapWidth);
                            topOffset   += size.Y;
                        }

                        // draw spacer
                        topOffset += lineHeight;

                        // draw custom fields
                        if (this.Fields.Any())
                        {
                            ICustomField[] fields = this.Fields;
                            float cellPadding     = 3;
                            float labelWidth      = fields.Where(p => p.HasValue).Max(p => font.MeasureString(p.Label).X);
                            float valueWidth      = wrapWidth - labelWidth - cellPadding * 4 - tableBorderWidth;
                            foreach (ICustomField field in fields)
                            {
                                if (!field.HasValue)
                                {
                                    continue;
                                }

                                // draw label & value
                                Vector2 labelSize     = contentBatch.DrawTextBlock(font, field.Label, new Vector2(x + leftOffset + cellPadding, y + topOffset + cellPadding), wrapWidth);
                                Vector2 valuePosition = new Vector2(x + leftOffset + labelWidth + cellPadding * 3, y + topOffset + cellPadding);
                                Vector2 valueSize     =
                                    field.DrawValue(contentBatch, font, valuePosition, valueWidth)
                                    ?? contentBatch.DrawTextBlock(font, field.Value, valuePosition, valueWidth);
                                Vector2 rowSize = new Vector2(labelWidth + valueWidth + cellPadding * 4, Math.Max(labelSize.Y, valueSize.Y));

                                // draw table row
                                Color lineColor = Color.Gray;
                                contentBatch.DrawLine(x + leftOffset, y + topOffset, new Vector2(rowSize.X, tableBorderWidth), lineColor);                                // top
                                contentBatch.DrawLine(x + leftOffset, y + topOffset + rowSize.Y, new Vector2(rowSize.X, tableBorderWidth), lineColor);                    // bottom
                                contentBatch.DrawLine(x + leftOffset, y + topOffset, new Vector2(tableBorderWidth, rowSize.Y), lineColor);                                // left
                                contentBatch.DrawLine(x + leftOffset + labelWidth + cellPadding * 2, y + topOffset, new Vector2(tableBorderWidth, rowSize.Y), lineColor); // middle
                                contentBatch.DrawLine(x + leftOffset + rowSize.X, y + topOffset, new Vector2(tableBorderWidth, rowSize.Y), lineColor);                    // right

                                // track link area
                                if (field is ILinkField linkField)
                                {
                                    this.LinkFieldAreas[linkField] = new Rectangle((int)valuePosition.X, (int)valuePosition.Y, (int)valueSize.X, (int)valueSize.Y);
                                }

                                // update offset
                                topOffset += Math.Max(labelSize.Y, valueSize.Y);
                            }
                        }
                    }

                    // update max scroll
                    this.MaxScroll = Math.Max(0, (int)(topOffset - contentHeight + this.CurrentScroll));

                    // draw scroll icons
                    if (this.MaxScroll > 0 && this.CurrentScroll > 0)
                    {
                        this.ScrollUpButton.draw(contentBatch);
                    }
                    if (this.MaxScroll > 0 && this.CurrentScroll < this.MaxScroll)
                    {
                        this.ScrollDownButton.draw(spriteBatch);
                    }

                    // end draw
                    contentBatch.End();
                }

                // draw cursor
                this.drawMouse(Game1.spriteBatch);
            }, this.OnDrawError);
        }
예제 #16
0
        public CustomBobberBar(SFarmer user, int whichFish, float fishSize, bool treasure, int bobber, int waterDepth) : base(whichFish, fishSize, treasure, bobber)
        {
            this.User        = user;
            this._origStreak = FishHelper.GetStreak(user);

            /* Private field hooks */
            this._treasureField            = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <bool>(this, "treasure");
            this._treasureCaughtField      = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <bool>(this, "treasureCaught");
            this._treasurePositionField    = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "treasurePosition");
            this._treasureAppearTimerField = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "treasureAppearTimer");
            this._treasureScaleField       = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "treasureScale");

            this._distanceFromCatchingField = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "distanceFromCatching");
            this._treasureCatchLevelField   = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "treasureCatchLevel");

            this._bobberBarPosField = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "bobberBarPos");
            this._difficultyField   = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "difficulty");
            this._fishQualityField  = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <int>(this, "fishQuality");
            this._perfectField      = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <bool>(this, "perfect");

            this._sparkleTextField = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <SparklingText>(this, "sparkleText");

            this._lastDistanceFromCatching = this._distanceFromCatchingField.GetValue();
            this._lastTreasureCatchLevel   = this._treasureCatchLevelField.GetValue();

            /* Actual code */
            ConfigMain    config  = ModFishing.INSTANCE.Config;
            ConfigStrings strings = ModFishing.INSTANCE.Strings;

            // Choose a random fish, this time using the custom fish selector
            FishingRod rod = Game1.player.CurrentTool as FishingRod;
            //int waterDepth = rod != null ? ModEntry.INSTANCE.Helper.Reflection.GetPrivateValue<int>(rod, "clearWaterDistance") : 0;

            // Applies difficulty modifier, including if fish isn't paying attention
            float difficulty = this._difficultyField.GetValue() * config.BaseDifficultyMult;

            difficulty *= 1f + config.DifficultyStreakEffect * this._origStreak;
            double difficultyChance = config.UnawareChance + user.LuckLevel * config.UnawareLuckLevelEffect + Game1.dailyLuck * config.UnawareDailyLuckEffect;

            if (Game1.random.NextDouble() < difficultyChance)
            {
                Game1.showGlobalMessage(string.Format(strings.UnawareFish, 1f - config.UnawareMult));
                difficulty *= config.UnawareMult;
            }
            this._difficultyField.SetValue(difficulty);

            // Adjusts quality to be increased by streak
            int fishQuality = this._fishQualityField.GetValue();

            this._origQuality = fishQuality;
            int qualityBonus = (int)Math.Floor((double)this._origStreak / config.StreakForIncreasedQuality);

            fishQuality = Math.Min(fishQuality + qualityBonus, 3);
            if (fishQuality == 3)
            {
                fishQuality++;                   // Iridium-quality fish. Only possible through your perfect streak
            }
            this._fishQualityField.SetValue(fishQuality);

            // Increase the user's perfect streak (this will be dropped to 0 if they don't get a perfect catch)
            if (this._origStreak >= config.StreakForIncreasedQuality)
            {
                this._sparkleTextField.SetValue(new SparklingText(Game1.dialogueFont, string.Format(strings.StreakDisplay, this._origStreak), Color.Yellow, Color.White));
            }
            FishHelper.SetStreak(user, this._origStreak + 1);
        }
예제 #17
0
        private void CurrentLocationChanged(object sender, EventArgsCurrentLocationChanged e)
        {
            GameLocation loc = e.NewLocation;

            if (!Game1.killScreen && Game1.farmEvent == null && loc.currentEvent == null)
            {
                foreach (ModEvent ev in this.Events)
                {
                    int?id = ev.getID();
                    if (id == null)
                    {
                        continue;
                    }
                    if (id < 0)
                    {
                        continue;
                    }
                    if (ev.Location == loc.name)
                    {
                        this.Monitor.Log(id.ToString(), LogLevel.Trace);
                        if (ev.Repeatable)
                        {
                            Game1.player.eventsSeen.Remove((int)id);
                        }
                        int eventID = -1;

                        try {
                            eventID = this.Helper.Reflection.GetPrivateMethod(loc, "checkEventPrecondition").Invoke <int>(ev.Condition);
                        } catch {
                            this.Monitor.Log("Failed to check condition for event " + id + "(at '" + loc.name + "')", LogLevel.Error);
                        }

                        if (eventID != -1)
                        {
                            loc.currentEvent = new Event(ev.Data, eventID);

                            if (Game1.player.getMount() != null)
                            {
                                loc.currentEvent.playerWasMounted = true;
                                Game1.player.getMount().dismount();
                            }
                            foreach (NPC character in loc.characters)
                            {
                                character.clearTextAboveHead();
                            }
                            Game1.eventUp        = true;
                            Game1.displayHUD     = false;
                            Game1.player.CanMove = false;
                            Game1.player.showNotCarrying();

                            IPrivateField <List <Critter> > crittersF = this.Helper.Reflection.GetPrivateField <List <Critter> >(loc, "critters");
                            List <Critter> critters = crittersF.GetValue();
                            if (critters == null)
                            {
                                return;
                            }
                            critters.Clear();
                            crittersF.SetValue(critters);
                            break;
                        }
                    }
                }
            }
        }