コード例 #1
0
 public RichEvent(string?simpleLabel, IEnumerable <IFlowNode>?advancedLabel = null, SpriteInfo?sprite = null, Item?item = null)
 {
     SimpleLabel   = simpleLabel;
     AdvancedLabel = advancedLabel;
     Sprite        = sprite;
     Item          = item;
 }
コード例 #2
0
 public SpriteNode(
     SpriteInfo?sprite,
     float scale,
     Alignment?align = null,
     Func <IFlowNodeSlice, int, int, bool>?onClick      = null,
     Func <IFlowNodeSlice, int, int, bool>?onHover      = null,
     Func <IFlowNodeSlice, int, int, bool>?onRightClick = null,
     bool noComponent = false,
     float size       = 16,
     int frame        = -1,
     object?extra     = null,
     string?id        = null
     )
 {
     Sprite       = sprite;
     Scale        = scale;
     Size         = size;
     Alignment    = align ?? Alignment.None;
     OnClick      = onClick;
     OnHover      = onHover;
     OnRightClick = onRightClick;
     NoComponent  = noComponent;
     Frame        = frame;
     Extra        = extra;
     UniqueId     = id;
 }
コード例 #3
0
 public SpriteNode(SpriteInfo?sprite, float scale = 4f, string?label = null, int quantity = 0, Alignment alignment = Alignment.None)
 {
     Sprite    = sprite;
     Scale     = scale;
     Label     = label;
     Quantity  = quantity;
     Alignment = alignment;
 }
コード例 #4
0
 /*********
 ** Private methods
 *********/
 /// <summary>Get the internal drop list entries.</summary>
 /// <param name="drops">The possible drops.</param>
 /// <param name="gameHelper">Provides utility methods for interacting with the game code.</param>
 private IEnumerable <Tuple <ItemDropData, SObject, SpriteInfo?> > GetEntries(IEnumerable <ItemDropData> drops, GameHelper gameHelper)
 {
     foreach (ItemDropData drop in drops)
     {
         SObject    item   = this.GameHelper.GetObjectBySpriteIndex(drop.ItemID);
         SpriteInfo?sprite = gameHelper.GetSprite(item);
         yield return(Tuple.Create(drop, item, sprite));
     }
 }
コード例 #5
0
 /*********
 ** Private methods
 *********/
 /// <summary>Get a fish pond's possible drops by population.</summary>
 /// <param name="currentPopulation">The current population for showing unlocked drops.</param>
 /// <param name="data">The fish pond data.</param>
 /// <param name="gameHelper">Provides utility methods for interacting with the game code.</param>
 /// <remarks>Derived from <see cref="FishPond.dayUpdate"/> and <see cref="FishPond.GetFishProduce"/>.</remarks>
 private IEnumerable <FishPondDrop> GetEntries(int currentPopulation, FishPondData data, GameHelper gameHelper)
 {
     foreach (FishPondDropData drop in gameHelper.GetFishPondDrops(data))
     {
         bool       isUnlocked = currentPopulation >= drop.MinPopulation;
         SObject    item       = this.GameHelper.GetObjectBySpriteIndex(drop.ItemID);
         SpriteInfo?sprite     = gameHelper.GetSprite(item);
         yield return(new FishPondDrop(drop, item, sprite, isUnlocked));
     }
 }
コード例 #6
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="gameHelper">Provides utility methods for interacting with the game code.</param>
        /// <param name="label">A short field label.</param>
        /// <param name="item">The item for which to display an icon.</param>
        /// <param name="codex">Provides subject entries to create a link, if applicable.</param>
        /// <param name="text">The text to display (if not the item name).</param>
        public ItemIconField(GameHelper gameHelper, string label, Item?item, ISubjectRegistry?codex, string?text = null)
            : base(label, hasValue: item != null)
        {
            this.Sprite = gameHelper.GetSprite(item);

            if (item != null)
            {
                this.LinkSubject = codex?.GetByEntity(item, null);

                text = !string.IsNullOrWhiteSpace(text) ? text : item.DisplayName;
                Color?color = this.LinkSubject != null ? Color.Blue : null;
                this.Value = new IFormattedText[] { new FormattedText(text, color) };
            }
        }
コード例 #7
0
    public void AddCrop(
        string id,

        Item item,
        string name,
        SpriteInfo?sprite,

        bool isTrellisCrop,
        bool isGiantCrop,
        SpriteInfo?giantSprite,
        Item[]?seeds,
        bool isPaddyCrop,

        IEnumerable <int> phases,
        IEnumerable <SpriteInfo?>?phaseSprites,

        int regrow,

        WorldDate start,
        WorldDate end
        )
    {
        Crops[id] = new CropInfo(
            Id: id,
            Item: item,
            Name: name,
            Sprite: sprite,
            IsTrellisCrop: isTrellisCrop,
            IsGiantCrop: isGiantCrop,
            GiantSprite: giantSprite,
            Seeds: seeds,
            Phases: phases.ToArray(),
            PhaseSprites: phaseSprites?.ToArray(),
            Regrow: regrow,
            IsPaddyCrop: isPaddyCrop,
            StartDate: start,
            EndDate: end
            );
    }
コード例 #8
0
        /// <summary>Create a recipe item model.</summary>
        /// <param name="name">The display name for the item.</param>
        /// <param name="item">The instance of the item.</param>
        /// <param name="sprite">The item sprite, or <c>null</c> to generate it automatically.</param>
        /// <param name="minCount">The minimum number of items needed or created.</param>
        /// <param name="maxCount">The maximum number of items needed or created.</param>
        /// <param name="chance">The chance of creating an output item.</param>
        /// <param name="isOutput">Whether the item is output or input.</param>
        private RecipeItemEntry CreateItemEntry(string name, Item?item = null, SpriteInfo?sprite = null, int minCount = 1, int maxCount = 1, decimal chance = 100, bool isOutput = false)
        {
            // get display text
            string text;

            {
                // name + count
                if (minCount != maxCount)
                {
                    text = I18n.Item_RecipesForMachine_MultipleItems(name: name, count: I18n.Generic_Range(min: minCount, max: maxCount));
                }
                else if (minCount > 1)
                {
                    text = I18n.Item_RecipesForMachine_MultipleItems(name: name, count: minCount);
                }
                else
                {
                    text = name;
                }

                // chance
                if (chance is > 0 and < 100)
                {
                    text += $" ({I18n.Generic_Percent(chance)})";
                }

                // output suffix
                if (isOutput)
                {
                    text += ":";
                }
            }

            return(new RecipeItemEntry(
                       Sprite: sprite ?? this.GameHelper.GetSprite(item),
                       DisplayText: text
                       ));
        }
コード例 #9
0
 /// <summary>Draw a sprite to the screen scaled and centered to fit the given dimensions.</summary>
 /// <param name="spriteBatch">The sprite batch being drawn.</param>
 /// <param name="sprite">The sprite to draw.</param>
 /// <param name="x">The X-position at which to draw the sprite.</param>
 /// <param name="y">The X-position at which to draw the sprite.</param>
 /// <param name="size">The size to draw.</param>
 /// <param name="color">The color to tint the sprite.</param>
 public static void DrawSpriteWithin(this SpriteBatch spriteBatch, SpriteInfo?sprite, float x, float y, Vector2 size, Color?color = null)
 {
     sprite?.Draw(spriteBatch, (int)x, (int)y, size, color);
 }
コード例 #10
0
 public SimpleBuilder Sprite(SpriteInfo?sprite, float scale = 4f, string?label = null, int quantity = 0, Alignment align = Alignment.None)
 {
     AssertState();
     Nodes.Add(new SpriteNode(sprite, scale, label, quantity, align));
     return(this);
 }
コード例 #11
0
        /// <summary>Draw text with an icon.</summary>
        /// <param name="batch">The sprite batch.</param>
        /// <param name="font">The sprite font.</param>
        /// <param name="position">The position at which to draw the text.</param>
        /// <param name="absoluteWrapWidth">The width at which to wrap the text.</param>
        /// <param name="text">The block of text to write.</param>
        /// <param name="textColor">The text color.</param>
        /// <param name="icon">The sprite to draw.</param>
        /// <param name="iconSize">The size to draw.</param>
        /// <param name="iconColor">The color to tint the sprite.</param>
        /// <param name="probe">Whether to calculate the positions without actually drawing anything to the screen.</param>
        /// <returns>Returns the drawn size.</returns>
        private Vector2 DrawIconText(SpriteBatch batch, SpriteFont font, Vector2 position, float absoluteWrapWidth, string text, Color textColor, SpriteInfo?icon = null, Vector2?iconSize = null, Color?iconColor = null, bool probe = false)
        {
            // draw icon
            int textOffset = 0;

            if (icon != null && iconSize.HasValue)
            {
                if (!probe)
                {
                    batch.DrawSpriteWithin(icon, position.X, position.Y, iconSize.Value, iconColor);
                }
                textOffset = this.IconMargin;
            }
            else
            {
                iconSize = Vector2.Zero;
            }

            // draw text
            Vector2 textSize = probe
                ? font.MeasureString(text)
                : batch.DrawTextBlock(font, text, position + new Vector2(iconSize.Value.X + textOffset, 0), absoluteWrapWidth - position.X, textColor);

            // get drawn size
            return(new Vector2(
                       x: iconSize.Value.X + textSize.X,
                       y: Math.Max(iconSize.Value.Y, textSize.Y)
                       ));
        }
コード例 #12
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="gameHelper">Provides utility methods for interacting with the game code.</param>
 /// <param name="value">The underlying in-game entity.</param>
 /// <param name="tilePosition">The object's tile position in the current location (if applicable).</param>
 /// <param name="reflection">Simplifies access to private game code.</param>
 /// <param name="getSubject">Get the subject info about the target.</param>
 public ObjectTarget(GameHelper gameHelper, SObject value, Vector2 tilePosition, IReflectionHelper reflection, Func <ISubject> getSubject)
     : base(gameHelper, SubjectType.Object, value, tilePosition, getSubject)
 {
     this.Reflection   = reflection;
     this.CustomSprite = gameHelper.GetSprite(value, onlyCustom: true); // only get sprite if it's custom; else we'll use contextual logic (e.g. for fence direction)
 }
コード例 #13
0
    private CropInfo?GetCropInfo(int id, string data)
    {
        // TODO: Create Crop instances so we can
        // lean more on vanilla logic.

        string[] bits = data.Split('/');
        if (bits.Length < 5)
        {
            return(null);
        }

        int sprite  = Convert.ToInt32(bits[2]);
        int harvest = Convert.ToInt32(bits[3]);
        int regrow  = Convert.ToInt32(bits[4]);

        bool isTrellisCrop = bits.Length > 7 && bits[7].Equals("true");

        if (!Game1.objectInformation.ContainsKey(harvest))
        {
            return(null);
        }

        string[] seasons = bits[1].Split(' ', StringSplitOptions.RemoveEmptyEntries);

        WorldDate?startDate = null;
        WorldDate?endDate   = null;

        // TODO: Handle weird crops with a gap.

        foreach (string season in seasons)
        {
            WorldDate start;
            WorldDate end;

            try {
                start = new(1, season, 1);
                end   = new(1, season, ModEntry.DaysPerMonth);
            } catch (Exception) {
                ModEntry.Instance.Log($"Invalid season for crop {id} (harvest:{harvest}): {season}", LogLevel.Warn);
                return(null);
            }

            if (startDate == null || startDate > start)
            {
                startDate = start;
            }
            if (endDate == null || endDate < end)
            {
                endDate = end;
            }
        }


        // Skip crops that don't have any valid seasons.
        // Who knows what else isn't valid?
        if (startDate == null || endDate == null)
        {
            return(null);
        }

        // Skip crops that are always active.
        if (startDate.SeasonIndex == 0 && startDate.DayOfMonth == 1 && endDate.SeasonIndex == (WorldDate.MonthsPerYear - 1) && endDate.DayOfMonth == ModEntry.DaysPerMonth)
        {
            return(null);
        }

        // If the sprite is 23, it's a seasonal multi-seed
        // so we want to show that rather than the seed.
        Item item = new SObject(sprite == 23 ? id : harvest, 1).getOne();

        // Phases
        int[] phases = bits[0].Split(' ').Select(val => Convert.ToInt32(val)).ToArray();

        // Stupid hard coded bullshit.
        bool paddyCrop = harvest == 271 || harvest == 830;

        // Phase Sprites
        // We need an extra sprite for the finished crop,
        // as well as one for regrow if that's enabled.
        SpriteInfo[] sprites = new SpriteInfo[phases.Length + 1 + (regrow > 0 ? 1 : 0)];

        // Are we dealing with colors?
        Color?color = null;

        string[]? colorbits = regrow <= 0 && bits.Length > 8 ? bits[8].Split(' ') : null;
        if (colorbits != null && colorbits.Length >= 4 && colorbits[0].Equals("true"))
        {
            // Technically there could be many colors, but we just use
            // the first one.
            color = new(
                Convert.ToByte(colorbits[1]),
                Convert.ToByte(colorbits[2]),
                Convert.ToByte(colorbits[3])
                );
        }

        for (int i = 0; i < sprites.Length; i++)
        {
            bool final = i == (sprites.Length - (regrow > 0 ? 2 : 1));

            sprites[i] = new(
                Game1.cropSpriteSheet,
                new Rectangle(
                    Math.Min(240, (i + 1) * 16 + (sprite % 2 != 0 ? 128 : 0)),
                    sprite / 2 * 16 * 2,
                    16, 32
                    ),
                overlaySource : final && color.HasValue ? new Rectangle(
                    Math.Min(240, (i + 2) * 16 + (sprite % 2 != 0 ? 128 : 0)),
                    sprite / 2 * 16 * 2,
                    16, 32
                    ) : null,
                overlayColor : final ? color : null
                );
        }

        bool       isGiantCrop = false;
        SpriteInfo?giantSprite = null;

        // Vanilla Giant Crops
        if (harvest == 190 || harvest == 254 || harvest == 276)
        {
            isGiantCrop = true;

            int which;
            if (harvest == 190)
            {
                which = 0;
            }
            else if (harvest == 254)
            {
                which = 1;
            }
            else
            {
                which = 2;
            }

            giantSprite = new(
                Game1.cropSpriteSheet,
                new Rectangle(112 + which * 48, 512, 48, 64)
                );
        }

        // JsonAssets Giant Crops
        if (!isGiantCrop && Mod.intJA != null && Mod.intJA.IsLoaded)
        {
            Texture2D?tex = Mod.intJA.GetGiantCropTexture(harvest);
            if (tex != null)
            {
                isGiantCrop = true;
                giantSprite = new(tex, tex.Bounds);
            }
        }

        // MoreGiantCrops Giant Crops
        if (!isGiantCrop && Mod.intMGC != null && Mod.intMGC.IsGiantCrop(harvest))
        {
            isGiantCrop = true;
            Texture2D?tex = Mod.intMGC.GetGiantCropTexture(harvest);
            if (tex != null)
            {
                giantSprite = new(tex, tex.Bounds);
            }
        }

        return(new(
                   Id: Convert.ToString(id),
                   Item : item,
                   Name : item.DisplayName,
                   Sprite : SpriteHelper.GetSprite(item),
                   IsTrellisCrop : isTrellisCrop,
                   IsGiantCrop : isGiantCrop,
                   GiantSprite : giantSprite,
                   Seeds : new Item[] {
            new SObject(id, 1)
        },
                   Phases : phases,
                   PhaseSprites : sprites,
                   Regrow : regrow,
                   IsPaddyCrop : paddyCrop,
                   StartDate : startDate,
                   EndDate : endDate
                   ));
    }