Example #1
0
        // To support the decay delay, we will use the HoeDirt.state variable to track how many days the patch has gone without being watered.
        // For example: 'state == -3' indicates that the tile hasn't been watered in the past 3 days.
        void HoeDirt_dayUpdate()
        {
            // Find: if (crop != null)
            var dayUpdate = BeginCode();
            var begin     = AttachLabel(dayUpdate[0]);

            dayUpdate.Prepend(
                // if (crop == null
                Instructions.Ldarg_0(),
                Instructions.Callvirt_get(typeof(HoeDirt), nameof(HoeDirt.crop)),
                Instructions.Brtrue(begin),
                //   && state <= 0) {
                Instructions.Ldarg_0(),
                Instructions.Ldfld(typeof(HoeDirt), nameof(HoeDirt.state)),
                Instructions.Call_get(typeof(NetInt), nameof(NetInt.Value)),
                Instructions.Ldc_I4_0(),
                Instructions.Bgt(begin),
                //   state--;
                Instructions.Ldarg_0(),
                Instructions.Ldfld(typeof(HoeDirt), nameof(HoeDirt.state)),
                Instructions.Dup(),
                Instructions.Call_get(typeof(NetInt), nameof(NetInt.Value)),
                Instructions.Ldc_I4_1(),
                Instructions.Sub(),
                Instructions.Call_set(typeof(NetInt), nameof(NetInt.Value)),
                //   return;
                Instructions.Ret()
                // }
                );
        }
Example #2
0
        void HoeDirt_dayUpdate()
        {
            // Find: if (crop != null)
            var dayUpdate = BeginCode();
            var begin     = AttachLabel(dayUpdate[0]);

            dayUpdate.Prepend(
                // if (crop == null
                Instructions.Ldarg_0(),
                Instructions.Callvirt_get(typeof(StardewValley.TerrainFeatures.HoeDirt), "crop"),
                Instructions.Brtrue(begin),
                //   && state <= 0) {
                Instructions.Ldarg_0(),
                Instructions.Ldfld(typeof(StardewValley.TerrainFeatures.HoeDirt), "state"),
                Instructions.Call_get(typeof(Netcode.NetInt), "Value"),
                Instructions.Ldc_I4_0(),
                Instructions.Bgt(begin),
                //   state--;
                Instructions.Ldarg_0(),
                Instructions.Ldfld(typeof(StardewValley.TerrainFeatures.HoeDirt), "state"),
                Instructions.Dup(),
                Instructions.Call_get(typeof(Netcode.NetInt), "Value"),
                Instructions.Ldc_I4_1(),
                Instructions.Sub(),
                Instructions.Call_set(typeof(Netcode.NetInt), "Value"),
                //   return;
                Instructions.Ret()
                // }
                );
        }
Example #3
0
        void Tree_DayUpdate()
        {
            // Erase code related to tree spreading.
            var spread = FindCode(
                // if ((int)growthStage >= 5
                OpCodes.Ldarg_0,
                Instructions.Ldfld(typeof(StardewValley.TerrainFeatures.Tree), "growthStage"),
                OpCodes.Call,
                OpCodes.Ldc_I4_5,
                OpCodes.Blt,
                // && environment is Farm ...
                OpCodes.Ldarg_1,
                Instructions.Isinst(typeof(StardewValley.Farm)),
                OpCodes.Brfalse
                );

            spread.Extend(
                // hasSeed.Value = false;
                OpCodes.Ldarg_0,
                Instructions.Ldfld(typeof(StardewValley.TerrainFeatures.Tree), "hasSeed"),
                OpCodes.Ldc_I4_0,
                OpCodes.Callvirt
                );
            spread.length -= 4;
            if (config.OnlyPreventTapped)
            {
                spread.Prepend(
                    // if (!tapped)
                    Instructions.Ldarg_0(),
                    Instructions.Ldfld(typeof(StardewValley.TerrainFeatures.Tree), "tapped"),
                    Instructions.Call_get(typeof(Netcode.NetBool), "Value"),
                    Instructions.Brtrue(AttachLabel(spread.End[0]))
                    );
                spread.ReplaceJump(4, spread[0]);
                spread = spread.End;
            }
            else
            {
                spread.Remove();

                // Don't remove seeds when on the farm
                // if (!environment is Farm)
                spread.Append(
                    Instructions.Ldarg_1(),
                    Instructions.Isinst(typeof(StardewValley.Farm)),
                    Instructions.Brtrue(AttachLabel(spread[4]))
                    );
            }

            // Increase chance that tree has a seed.
            var seed = spread.FindNext(
                OpCodes.Ldsfld,
                OpCodes.Callvirt,
                OpCodes.Ldc_R8,
                OpCodes.Bge_Un
                );

            seed[2].operand = config.SeedChance;
        }
Example #4
0
        // Change the behavior of the grass growth & spreading.
        void GameLocation_growWeedGrass()
        {
            // Stop grass from growing & spreading.
            AllCode().Prepend(
                Instructions.Call(GetType(), nameof(getDisableGrowth)),
                Instructions.Brfalse(AttachLabel(AllCode()[0])),
                Instructions.Ret()
                );

            // Change grass growth to spread mostly everywhere.
            var growWeedGrass = BeginCode();

            // For each of the 4 directions
            for (int i = 0; i < 4; i++)
            {
                growWeedGrass = growWeedGrass.FindNext(
                    OpCodes.Ldarg_0,
                    null,
                    null,
                    null,
                    null,
                    Instructions.Ldstr("Diggable"),
                    Instructions.Ldstr("Back"),
                    Instructions.Call(typeof(GameLocation), nameof(GameLocation.doesTileHaveProperty), typeof(int), typeof(int), typeof(string), typeof(string)),
                    OpCodes.Brfalse
                    );
                growWeedGrass.Prepend(
                    Instructions.Call(GetType(), nameof(getGrowEverywhere)),
                    Instructions.Brtrue(AttachLabel(growWeedGrass.End[0]))
                    );
            }

            // Growth chance
            FindCode(
                Instructions.Ldc_R8(0.65),
                OpCodes.Bge_Un,
                OpCodes.Ldloca_S
                )[0] = Instructions.Call(GetType(), nameof(getGrowthChance));

            // Spread
            var spreadGrass = BeginCode();

            // For each of the 4 directions
            for (int i = 0; i < 4; i++)
            {
                spreadGrass = spreadGrass.FindNext(
                    Instructions.Ldc_R8(0.25),
                    OpCodes.Bge_Un,
                    OpCodes.Ldarg_0
                    );
                spreadGrass[0] = Instructions.Call(GetType(), nameof(getSpreadChance));
            }
        }
Example #5
0
        void HoeDirt_performUseAction()
        {
            var harvest_hand = FindCode(
                OpCodes.Ldarg_0,
                OpCodes.Call,
                OpCodes.Ldfld,
                OpCodes.Call,
                OpCodes.Brtrue
                );

            // Logic here depends on whether flowers can be harvested by scythe.
            if (config.ScytheHarvestFlowers)
            {
                // Entirely remove logic related to harvesting by hand.
                harvest_hand.Extend(
                    OpCodes.Ldarg_0,
                    OpCodes.Call,
                    OpCodes.Ldfld,
                    OpCodes.Call,
                    OpCodes.Ldc_I4_1,
                    OpCodes.Bne_Un
                    );
                harvest_hand.Remove();
            }
            else
            {
                // Only allow harvesting by hand for flowers. Otherwise those would not be harvestable.
                harvest_hand.Replace(
                    harvest_hand[0],
                    harvest_hand[1],
                    Instructions.Ldfld(typeof(Crop), nameof(Crop.programColored)),
                    Instructions.Call_get(typeof(NetBool), nameof(NetBool.Value)),
                    Instructions.Brfalse((Label)harvest_hand[4].operand)
                    );
                var harvest_scythe = FindCode(
                    OpCodes.Ldarg_0,
                    OpCodes.Call,
                    OpCodes.Ldfld,
                    OpCodes.Call,
                    OpCodes.Ldc_I4_1,
                    OpCodes.Bne_Un
                    );
                harvest_scythe.Replace(
                    harvest_scythe[0],
                    harvest_scythe[1],
                    Instructions.Ldfld(typeof(Crop), nameof(Crop.programColored)),
                    Instructions.Call_get(typeof(NetBool), nameof(NetBool.Value)),
                    Instructions.Brtrue((Label)harvest_scythe[5].operand)
                    );
            }
        }
Example #6
0
        void Game1_UpdateViewPort()
        {
            var range = FindCode(
                // if (!Game1.viewportFreeze ...
                Instructions.Ldsfld(typeof(StardewValley.Game1), "viewportFreeze")
                );

            range.Extend(
                // if (Game1.currentLocation.forceViewportPlayerFollow)
                Instructions.Ldsfld(typeof(StardewValley.Game1), "currentLocation"),
                Instructions.Ldfld(typeof(StardewValley.GameLocation), "forceViewportPlayerFollow"),
                OpCodes.Brfalse
                );
            // Encapsulate with if (!State.Enabled) {
            range.Prepend(
                Instructions.Call(typeof(StardewHack.AlwaysScrollMap.State), "Enabled"),
                Instructions.Brtrue(AttachLabel(range.End[0]))
                );
        }
Example #7
0
        void Game1_UpdateViewPort()
        {
            var range = FindCode(
                // if (!Game1.viewportFreeze ...
                Instructions.Ldsfld(typeof(Game1), nameof(Game1.viewportFreeze))
                );

            range.Extend(
                // if (Game1.currentLocation.forceViewportPlayerFollow)
                Instructions.Ldsfld(typeof(Game1), nameof(Game1.currentLocation)),
                Instructions.Ldfld(typeof(GameLocation), nameof(GameLocation.forceViewportPlayerFollow)),
                OpCodes.Brfalse
                );
            // Encapsulate with if (!State.Enabled) {
            range.Prepend(
                Instructions.Call(typeof(State), nameof(State.Enabled)),
                Instructions.Brtrue(AttachLabel(range.End[0]))
                );
        }
Example #8
0
        void Game1_UpdateViewPort()
        {
            var range = FindCode(
                // if (!Game1.viewportFreeze ...
                Instructions.Ldsfld(typeof(Game1), nameof(Game1.viewportFreeze))
                );

            range.Extend(
                // if (Game1.currentLocation.forceViewportPlayerFollow)
                // (Note: currentLocation is a field on PC and a property on android).
                Instructions.Ldfld(typeof(GameLocation), nameof(GameLocation.forceViewportPlayerFollow)),
                OpCodes.Brfalse
                );
            // Encapsulate with if (!State.Enabled) {
            range.Prepend(
                Instructions.Call(typeof(ModEntry), nameof(ModEntry.Enabled)),
                Instructions.Brtrue(AttachLabel(range.End[0]))
                );
            range.ReplaceJump(2, range[0]);
        }
Example #9
0
        void Shears_beginUsing()
        {
            var halt = FindCode(
                OpCodes.Ldarg_S,
                Instructions.Callvirt(typeof(StardewValley.Character), "Halt")
                );

            halt.Replace(
                halt[0],
                // if (this.animal == null) {
                Instructions.Ldarg_0(),
                Instructions.Ldfld(typeof(StardewValley.Tools.Shears), "animal"),
                Instructions.Brtrue(AttachLabel(halt[1])),
                //    who.forceCanMove();
                Instructions.Callvirt(typeof(StardewValley.Farmer), "forceCanMove"),
                //    return false;
                Instructions.Ldc_I4_0(),
                Instructions.Ret(),
                // }
                halt[1]
                );
        }
Example #10
0
        void MilkPail_beginUsing()
        {
            // Find the first animal != null check.
            var hasAnimal = FindCode(
                OpCodes.Ldarg_0,
                Instructions.Ldfld(typeof(StardewValley.Tools.MilkPail), "animal"),
                OpCodes.Brfalse
                );

            hasAnimal.Replace(
                // if (this.animal == null) {
                hasAnimal[0],
                hasAnimal[1],
                Instructions.Brtrue(AttachLabel(hasAnimal[3])),
                //    who.forceCanMove();
                Instructions.Ldarg_S(4),
                Instructions.Callvirt(typeof(StardewValley.Farmer), "forceCanMove"),
                //    return false;
                Instructions.Ldc_I4_0(),
                Instructions.Ret()
                // }
                );
        }
Example #11
0
        void Tree_DayUpdate()
        {
            // Erase code related to tree spreading.
            var spread = FindCode(
                // if ((int)growthStage >= 5
                OpCodes.Ldarg_0,
                Instructions.Ldfld(typeof(Tree), nameof(Tree.growthStage)),
                OpCodes.Call,
                OpCodes.Ldc_I4_5,
                OpCodes.Blt,
                // && environment is Farm ...
                OpCodes.Ldarg_1,
                Instructions.Isinst(typeof(Farm)),
                OpCodes.Brfalse
                );

            spread.Extend(
                // hasSeed.Value = false;
                OpCodes.Ldarg_0,
                Instructions.Ldfld(typeof(Tree), nameof(Tree.hasSeed)),
                OpCodes.Ldc_I4_0,
                OpCodes.Callvirt
                );
            spread.length -= 4;
            if (config.OnlyPreventTapped)
            {
                spread.Prepend(
                    // if (!tapped)
                    Instructions.Ldarg_0(),
                    Instructions.Ldfld(typeof(Tree), nameof(Tree.tapped)),
                    Instructions.Call_get(typeof(NetBool), nameof(NetBool.Value)),
                    Instructions.Brtrue(AttachLabel(spread.End[0]))
                    );
                spread.ReplaceJump(4, spread[0]);
                spread = spread.End;
            }
            else
            {
                spread.Remove();

                // Don't remove seeds when on the farm
                // if (!environment is Farm)
                spread.Append(
                    Instructions.Ldarg_1(),
                    Instructions.Isinst(typeof(Farm)),
                    Instructions.Brtrue(AttachLabel(spread[4]))
                    );
            }

            // Increase chance that tree has a seed.
            // hasSeed.Value = false;
            // float num3 = 0.05f;
            var seed = spread.FindNext(
                OpCodes.Ldarg_0,
                Instructions.Ldfld(typeof(Tree), nameof(Tree.hasSeed)),
                OpCodes.Ldc_I4_0,
                OpCodes.Callvirt,
                Instructions.Ldc_R4(0.05f),
                OpCodes.Stloc_1
                );

            seed[4].operand = config.SeedChance;
        }
Example #12
0
        void Tree_DayUpdate()
        {
            // Erase code related to tree spreading.
            var spread = FindCode(
                // if ((int)growthStage >= 5
                OpCodes.Ldarg_0,
                Instructions.Ldfld(typeof(Tree), nameof(Tree.growthStage)),
                OpCodes.Call,
                OpCodes.Ldc_I4_5,
                OpCodes.Blt,
                // && environment is Farm ...
                OpCodes.Ldarg_1,
                Instructions.Isinst(typeof(Farm)),
                OpCodes.Brfalse
                );

            spread.Extend(
                // hasSeed.Value = false;
                OpCodes.Ldarg_0,
                Instructions.Ldfld(typeof(Tree), nameof(Tree.hasSeed)),
                OpCodes.Ldc_I4_0,
                OpCodes.Callvirt
                );
            spread.length -= 4;

            spread.Prepend(
                // if (!tapped && config.OnlyPreventTapped)
                Instructions.Ldarg_0(),
                Instructions.Ldfld(typeof(Tree), nameof(Tree.tapped)),
                Instructions.Call_get(typeof(NetBool), nameof(NetBool.Value)),
                Instructions.Brtrue(AttachLabel(spread.End[0])),
                Instructions.Call(GetType(), nameof(isOnlyPreventTapped)),
                Instructions.Brfalse(AttachLabel(spread.End[0]))
                );
            spread.ReplaceJump(6, spread[0]);

            // if RetainSeed: Don't remove seeds when on the farm
            var remove_seed = spread.End;

            remove_seed.length += 4;

            // if (!config.RetainSeed || !environment is Farm)
            var lbl = generator.DefineLabel();

            remove_seed.Prepend(
                Instructions.Call(GetType(), nameof(isRetainSeed)),
                Instructions.Brfalse(lbl),
                Instructions.Ldarg_1(),
                Instructions.Isinst(typeof(Farm)),
                Instructions.Brtrue(AttachLabel(remove_seed.End[0]))
                );
            remove_seed.ReplaceJump(5, remove_seed[0]);
            remove_seed[5].labels.Add(lbl);

            // Increase chance that tree has a seed.
            // float num3 = 0.05f;
            var seed = remove_seed.FindNext(
                Instructions.Ldc_R4(0.05f),
                OpCodes.Stloc_1
                );

            seed[0] = Instructions.Call(GetType(), nameof(getSeedChance));
        }