Farming improvements

White Berry Bushes can now be protected
Giant Ent properly increases Belladonna yield
Mushrooms now disease properly
Fixed various bush bugs
Fruit Trees can now be chopped
Fixed Scarecrow needing to grow to work
Mushrooms should now visually update as each mushroom is picked from the patch
Poison Ivy Bushes are now disease immune
Poison Ivy Berries picked in the Champion's Guild Patch now finishes a Varrock Diary task
This commit is contained in:
Syndromeramo 2025-06-18 13:35:50 +00:00 committed by Ryan
parent 91f3a70f75
commit e8c3f31786
8 changed files with 137 additions and 23 deletions

View file

@ -15,7 +15,7 @@ import core.plugin.Plugin
import org.rs09.consts.Items import org.rs09.consts.Items
import org.rs09.consts.Sounds import org.rs09.consts.Sounds
val livesBased = arrayOf(PatchType.HERB_PATCH, PatchType.CACTUS_PATCH, PatchType.BELLADONNA_PATCH, PatchType.HOPS_PATCH, PatchType.ALLOTMENT, PatchType.EVIL_TURNIP_PATCH) val livesBased = arrayOf(PatchType.HERB_PATCH, PatchType.CACTUS_PATCH, PatchType.HOPS_PATCH, PatchType.ALLOTMENT)
@Initializable @Initializable
class CropHarvester : OptionHandler() { class CropHarvester : OptionHandler() {
@ -43,14 +43,16 @@ class CropHarvester : OptionHandler() {
override fun pulse(): Boolean { override fun pulse(): Boolean {
var reward = Item(crop) var reward = Item(crop)
val familiar = player.familiarManager.familiar
if (familiar != null && familiar is GiantEntNPC) {
familiar.modifyFarmingReward(fPatch, reward)
}
if (!hasSpaceFor(player, reward)) { if (!hasSpaceFor(player, reward)) {
sendMessage(player, "You have run out of inventory space.") sendMessage(player, "You have run out of inventory space.")
return true return true
} }
val familiar = player.familiarManager.familiar
if (familiar != null && familiar is GiantEntNPC) {
familiar.modifyFarmingReward(fPatch, reward)
}
var requiredItem = when (fPatch.type) { var requiredItem = when (fPatch.type) {
PatchType.TREE_PATCH -> Items.SECATEURS_5329 PatchType.TREE_PATCH -> Items.SECATEURS_5329
else -> Items.SPADE_952 else -> Items.SPADE_952
@ -92,7 +94,7 @@ class CropHarvester : OptionHandler() {
// TODO: If a flower patch is being harvested, delay the clearing of the // TODO: If a flower patch is being harvested, delay the clearing of the
// patch until after the animation has played - https://youtu.be/lg4GktlVNUY?t=75 // patch until after the animation has played - https://youtu.be/lg4GktlVNUY?t=75
delay = 2 delay = 2
addItem(player, reward.id) addItemOrDrop(player, reward.id,reward.amount)
rewardXP(player, Skills.FARMING, plantable.harvestXP) rewardXP(player, Skills.FARMING, plantable.harvestXP)
if (patch.patch.type in livesBased) { if (patch.patch.type in livesBased) {
patch.rollLivesDecrement( patch.rollLivesDecrement(
@ -104,6 +106,9 @@ class CropHarvester : OptionHandler() {
if (patch.harvestAmt <= 0 && crop == plantable.harvestItem) { if (patch.harvestAmt <= 0 && crop == plantable.harvestItem) {
patch.clear() patch.clear()
} }
else if (fPatch.type == PatchType.MUSHROOM_PATCH){
patch.setCurrentState(patch.getCurrentState() + 1)
}
} }
if (sendHarvestMessages && (patch.cropLives <= 0 || patch.harvestAmt <= 0)) { if (sendHarvestMessages && (patch.cropLives <= 0 || patch.harvestAmt <= 0)) {
sendMessage(player, "The $patchName is now empty.") sendMessage(player, "The $patchName is now empty.")

View file

@ -30,6 +30,14 @@ class DigUpPatchDialogue(player: Player? = null) : DialoguePlugin(player) {
return true return true
} }
} }
if (patch?.patch?.type == PatchType.FRUIT_TREE_PATCH) {
val isTreeStump = patch?.getCurrentState() == patch?.plantable!!.value + 25
if (patch!!.isGrown() && !isTreeStump) {
sendMessage(player, "You need to chop this tree down first.") // this message is not authentic
stage = 1000
return true
}
}
sendDialogueOptions(player, "Are you sure you want to dig up this patch?", "Yes, I want to clear it for new crops.", "No, I want to leave it as it is.") sendDialogueOptions(player, "Are you sure you want to dig up this patch?", "Yes, I want to clear it for new crops.", "No, I want to leave it as it is.")
stage = 0 stage = 0
return true return true

View file

@ -6,6 +6,7 @@ import core.game.interaction.OptionHandler
import core.game.node.Node import core.game.node.Node
import content.global.skill.summoning.familiar.GiantEntNPC import content.global.skill.summoning.familiar.GiantEntNPC
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.entity.skill.Skills import core.game.node.entity.skill.Skills
import core.game.node.item.Item import core.game.node.item.Item
import core.game.system.task.Pulse import core.game.system.task.Pulse
@ -86,6 +87,10 @@ class FruitAndBerryPicker : OptionHandler() {
sendMessage(player, "You pick $determiner ${reward.name.lowercase()}.") sendMessage(player, "You pick $determiner ${reward.name.lowercase()}.")
} }
if (plantable == Plantable.POISON_IVY_SEED && patch.patch == FarmingPatch.CHAMPIONS_GUILD_BUSH){
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 2, 0)
}
return patch.getFruitOrBerryCount() == 0 return patch.getFruitOrBerryCount() == 0
} }
}) })

View file

@ -0,0 +1,57 @@
package content.global.skill.farming
import content.data.skill.SkillingTool
import core.api.*
import core.cache.def.impl.SceneryDefinition
import core.game.interaction.OptionHandler
import core.game.node.Node
import core.game.node.entity.player.Player
import core.game.system.task.Pulse
import core.plugin.Initializable
import core.plugin.Plugin
import core.tools.RandomFunction
import org.rs09.consts.Sounds
@Initializable
class FruitTreeChopper : OptionHandler() {
override fun newInstance(arg: Any?): Plugin<Any> {
SceneryDefinition.setOptionHandler("chop-down",this)
SceneryDefinition.setOptionHandler("chop down",this)
return this
}
override fun handle(player: Player?, node: Node?, option: String?): Boolean {
player ?: return false
node ?: return false
val fPatch = FarmingPatch.forObject(node.asScenery())
fPatch ?: return false
val patch = fPatch.getPatchFor(player)
val plantable = patch.plantable
plantable ?: return false
val animation = SkillingTool.getHatchet(player).animation
submitIndividualPulse(player, object : Pulse(animation.duration) {
override fun pulse(): Boolean {
animate(player, animation)
val soundIndex = RandomFunction.random(0, woodcuttingSounds.size)
playAudio(player, woodcuttingSounds[soundIndex])
patch.setCurrentState(patch.getCurrentState() + 19)
sendMessage(player, "You chop down the ${plantable.displayName.lowercase().removeSuffix(" sapling")}.")
return true
}
})
return true
}
private val woodcuttingSounds = intArrayOf(
Sounds.WOODCUTTING_HIT_3038,
Sounds.WOODCUTTING_HIT_3039,
Sounds.WOODCUTTING_HIT_3040,
Sounds.WOODCUTTING_HIT_3041,
Sounds.WOODCUTTING_HIT_3042
)
}

View file

@ -29,7 +29,11 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
Plantable.WILLOW_SAPLING -> 0 Plantable.WILLOW_SAPLING -> 0
else -> 1 else -> 1
} }
if(plantable != null && plantable?.applicablePatch != PatchType.FLOWER_PATCH) { if(plantable != null
&& plantable?.applicablePatch != PatchType.FLOWER_PATCH
&& plantable?.applicablePatch != PatchType.BELLADONNA_PATCH
&& plantable?.applicablePatch != PatchType.MUSHROOM_PATCH
&& plantable?.applicablePatch != PatchType.EVIL_TURNIP_PATCH) {
harvestAmt += compostMod harvestAmt += compostMod
} }
cropLives = 3 + compostMod cropLives = 3 + compostMod
@ -70,8 +74,6 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
var chance = when(patch.type){ var chance = when(patch.type){
PatchType.ALLOTMENT -> 8 //average of 8 per life times 3 lives = average 24 PatchType.ALLOTMENT -> 8 //average of 8 per life times 3 lives = average 24
PatchType.HOPS_PATCH -> 6 //average of 6 per life times 3 lives = 18 PatchType.HOPS_PATCH -> 6 //average of 6 per life times 3 lives = 18
PatchType.BELLADONNA_PATCH -> 2 //average of 2 per life times 3 lives = 6
PatchType.EVIL_TURNIP_PATCH -> 2 //average 2 per, same as BELLADONNA
PatchType.CACTUS_PATCH -> 3 //average of 3 per life times 3 lives = 9 PatchType.CACTUS_PATCH -> 3 //average of 3 per life times 3 lives = 9
else -> 0 // nothing should go here, but if it does, do not give extra crops amd decrement cropLives else -> 0 // nothing should go here, but if it does, do not give extra crops amd decrement cropLives
} }
@ -88,6 +90,11 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
return getCurrentState() in 0..2 return getCurrentState() in 0..2
} }
fun isChoppedFruitTree(): Boolean {
return (patch.type == PatchType.FRUIT_TREE_PATCH)
&& getCurrentState() == (plantable?.value ?: 0) + 25
}
fun isEmptyAndWeeded(): Boolean { fun isEmptyAndWeeded(): Boolean {
return getCurrentState() == 3 return getCurrentState() == 3
} }
@ -198,6 +205,10 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
else if(isDiseased && !isDead) setVisualState(getHerbDiseaseValue()) else if(isDiseased && !isDead) setVisualState(getHerbDiseaseValue())
else setVisualState((plantable?.value ?: 0) + currentGrowthStage) else setVisualState((plantable?.value ?: 0) + currentGrowthStage)
} }
PatchType.MUSHROOM_PATCH -> {
if(isDead) setVisualState(getMushroomDeathValue())
else if(isDiseased && !isDead) setVisualState(getMushroomDiseaseValue())
}
else -> {} else -> {}
} }
} }
@ -221,16 +232,27 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
private fun getBushDiseaseValue(): Int{ private fun getBushDiseaseValue(): Int{
if(plantable == Plantable.POISON_IVY_SEED){ if(plantable == Plantable.POISON_IVY_SEED){
return (plantable?.value ?: 0) + currentGrowthStage + 12 return (plantable?.value ?: 0) + currentGrowthStage + 12
} else { }
else if (plantable == Plantable.REDBERRY_SEED
|| plantable == Plantable.CADAVABERRY_SEED){
return (plantable?.value ?: 0) + currentGrowthStage + 65
}
else {
return (plantable?.value ?: 0) + currentGrowthStage + 64 return (plantable?.value ?: 0) + currentGrowthStage + 64
} }
} }
private fun getBushDeathValue(): Int{ private fun getBushDeathValue(): Int{
if(plantable == Plantable.POISON_IVY_SEED){ if(plantable == Plantable.POISON_IVY_SEED){
return (plantable?.value ?: 0) + currentGrowthStage + 22 return (plantable?.value ?: 0) + currentGrowthStage + 20
} else { }
return (plantable?.value ?: 0) + currentGrowthStage + 126 else if (plantable == Plantable.REDBERRY_SEED
|| plantable == Plantable.CADAVABERRY_SEED
|| plantable == Plantable.WHITEBERRY_SEED){
return (plantable?.value ?: 0) + currentGrowthStage + 129
}
else {
return (plantable?.value ?: 0) + currentGrowthStage + 128
} }
} }
@ -258,6 +280,14 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
return (plantable?.value ?: 0) + currentGrowthStage + 16 return (plantable?.value ?: 0) + currentGrowthStage + 16
} }
private fun getMushroomDiseaseValue(): Int {
return (plantable?.value ?: 0) + currentGrowthStage + 11
}
private fun getMushroomDeathValue(): Int {
return (plantable?.value ?: 0) + currentGrowthStage + 16
}
private fun getHerbDiseaseValue(): Int { private fun getHerbDiseaseValue(): Int {
return if (plantable?.value ?: -1 <= 103) { return if (plantable?.value ?: -1 <= 103) {
128 + (((plantable?.ordinal ?: 0) - Plantable.GUAM_SEED.ordinal) * 3) + currentGrowthStage - 1 128 + (((plantable?.ordinal ?: 0) - Plantable.GUAM_SEED.ordinal) * 3) + currentGrowthStage - 1
@ -275,7 +305,7 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
} }
private fun grow(){ private fun grow(){
if((isWeedy() || isEmptyAndWeeded()) && getCurrentState() > 0) { if((isWeedy() || isEmptyAndWeeded() || (plantable == Plantable.SCARECROW && !isGrown())) && getCurrentState() > 0) {
nextGrowth = System.currentTimeMillis() + 60000 nextGrowth = System.currentTimeMillis() + 60000
setCurrentState(getCurrentState() - 1) setCurrentState(getCurrentState() - 1)
currentGrowthStage-- currentGrowthStage--
@ -294,7 +324,14 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
CompostType.SUPERCOMPOST -> 13 CompostType.SUPERCOMPOST -> 13
} }
if(patch != FarmingPatch.TROLL_STRONGHOLD_HERB && RandomFunction.random(128) <= (17 - diseaseMod) && !isWatered && !isGrown() && !protectionPaid && !isFlowerProtected() && patch.type != PatchType.EVIL_TURNIP_PATCH && currentGrowthStage != 0){ if(patch != FarmingPatch.TROLL_STRONGHOLD_HERB
&& RandomFunction.random(128) <= (17 - diseaseMod)
&& !isWatered && !isGrown()
&& !protectionPaid
&& !isFlowerProtected()
&& patch.type != PatchType.EVIL_TURNIP_PATCH
&& plantable != Plantable.POISON_IVY_SEED
&& currentGrowthStage != 0){
isDiseased = true isDiseased = true
// If we manually set disease mod reset it back to 0 so that crops can naturally grow after being treated/accidentally attempted to disease when they cannot be // If we manually set disease mod reset it back to 0 so that crops can naturally grow after being treated/accidentally attempted to disease when they cannot be
if (diseaseMod < 0) diseaseMod = 0 if (diseaseMod < 0) diseaseMod = 0
@ -389,7 +426,9 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
else -> return false else -> return false
}.getPatchFor(player, false) }.getPatchFor(player, false)
return (fpatch.plantable != null && if (fpatch.plantable == Plantable.SCARECROW && fpatch.plantable == plantable?.protectionFlower){
return true
} else return (fpatch.plantable != null &&
(fpatch.plantable == plantable?.protectionFlower || fpatch.plantable == Plantable.forItemID(Items.WHITE_LILY_SEED_14589)) (fpatch.plantable == plantable?.protectionFlower || fpatch.plantable == Plantable.forItemID(Items.WHITE_LILY_SEED_14589))
&& fpatch.isGrown()) && fpatch.isGrown())
} }

View file

@ -14,7 +14,7 @@ enum class Plantable(val itemID: Int, val displayName: String, val value: Int, v
WHITE_LILY_SEED(Items.WHITE_LILY_SEED_14589,"white lily seed",37,4,42.0,250.0,0.0,52,PatchType.FLOWER_PATCH,Items.WHITE_LILY_14583), WHITE_LILY_SEED(Items.WHITE_LILY_SEED_14589,"white lily seed",37,4,42.0,250.0,0.0,52,PatchType.FLOWER_PATCH,Items.WHITE_LILY_14583),
// Flower (technically) // Flower (technically)
SCARECROW(Items.SCARECROW_6059,"scarecrow",33,3,0.0,0.0,0.0,23,PatchType.FLOWER_PATCH,Items.SCARECROW_6059), SCARECROW(Items.SCARECROW_6059,"scarecrow",36,-3,0.0,0.0,0.0,23,PatchType.FLOWER_PATCH,Items.SCARECROW_6059),
// Allotments // Allotments
POTATO_SEED(Items.POTATO_SEED_5318, "potato seed", 6, 4, 8.0, 9.0, 0.0, 1, PatchType.ALLOTMENT, Items.POTATO_1942,Item(Items.COMPOST_6032,2),MARIGOLD_SEED), POTATO_SEED(Items.POTATO_SEED_5318, "potato seed", 6, 4, 8.0, 9.0, 0.0, 1, PatchType.ALLOTMENT, Items.POTATO_1942,Item(Items.COMPOST_6032,2),MARIGOLD_SEED),
@ -53,9 +53,9 @@ enum class Plantable(val itemID: Int, val displayName: String, val value: Int, v
// Bushes // Bushes
REDBERRY_SEED(Items.REDBERRY_SEED_5101,"redberry bush seed",5,5,11.5,4.5,64.0,10,PatchType.BUSH_PATCH,Items.REDBERRIES_1951,Item(Items.CABBAGES10_5478,4)), REDBERRY_SEED(Items.REDBERRY_SEED_5101,"redberry bush seed",5,5,11.5,4.5,64.0,10,PatchType.BUSH_PATCH,Items.REDBERRIES_1951,Item(Items.CABBAGES10_5478,4)),
CADAVABERRY_SEED(Items.CADAVABERRY_SEED_5102,"cadavaberry bush seed",15,6,18.0,7.0,102.5,22,PatchType.BUSH_PATCH,Items.CADAVA_BERRIES_753,Item(Items.TOMATOES5_5968,3)), CADAVABERRY_SEED(Items.CADAVABERRY_SEED_5102,"cadavaberry bush seed",15,6,18.0,7.0,102.5,22,PatchType.BUSH_PATCH,Items.CADAVA_BERRIES_753,Item(Items.TOMATOES5_5968,3)),
DWELLBERRY_SEED(Items.DWELLBERRY_SEED_5103,"dwellberry bush seed",26,27,31.5,12.0,177.5,36,PatchType.BUSH_PATCH,Items.DWELLBERRIES_2126,Item(Items.STRAWBERRIES5_5406,3)), DWELLBERRY_SEED(Items.DWELLBERRY_SEED_5103,"dwellberry bush seed",26,7,31.5,12.0,177.5,36,PatchType.BUSH_PATCH,Items.DWELLBERRIES_2126,Item(Items.STRAWBERRIES5_5406,3)),
JANGERBERRY_SEED(Items.JANGERBERRY_SEED_5104,"jangerberry bush seed",38,8,50.5,19.0,284.5,48,PatchType.BUSH_PATCH,Items.JANGERBERRIES_247,Item(Items.WATERMELON_5982,6)), JANGERBERRY_SEED(Items.JANGERBERRY_SEED_5104,"jangerberry bush seed",38,8,50.5,19.0,284.5,48,PatchType.BUSH_PATCH,Items.JANGERBERRIES_247,Item(Items.WATERMELON_5982,6)),
WHITEBERRY_SEED(Items.WHITEBERRY_SEED_5105,"whiteberry bush seed",51,8,78.0,29.0,437.5,59,PatchType.BUSH_PATCH,Items.WHITE_BERRIES_239,null), WHITEBERRY_SEED(Items.WHITEBERRY_SEED_5105,"whiteberry bush seed",51,8,78.0,29.0,437.5,59,PatchType.BUSH_PATCH,Items.WHITE_BERRIES_239,Item(Items.MUSHROOM_6004,8)),
POISON_IVY_SEED(Items.POISON_IVY_SEED_5106,"poison ivy bush seed",197,8,120.0,45.0,675.0,70,PatchType.BUSH_PATCH,Items.POISON_IVY_BERRIES_6018,null), POISON_IVY_SEED(Items.POISON_IVY_SEED_5106,"poison ivy bush seed",197,8,120.0,45.0,675.0,70,PatchType.BUSH_PATCH,Items.POISON_IVY_BERRIES_6018,null),
// Herbs // Herbs
@ -78,7 +78,7 @@ enum class Plantable(val itemID: Int, val displayName: String, val value: Int, v
// Special // Special
BELLADONNA_SEED(Items.BELLADONNA_SEED_5281, "belladonna seed", 4, 4, 91.0, 128.0, 0.0, 63, PatchType.BELLADONNA_PATCH, Items.CAVE_NIGHTSHADE_2398), BELLADONNA_SEED(Items.BELLADONNA_SEED_5281, "belladonna seed", 4, 4, 91.0, 128.0, 0.0, 63, PatchType.BELLADONNA_PATCH, Items.CAVE_NIGHTSHADE_2398),
MUSHROOM_SPORE(Items.MUSHROOM_SPORE_5282, "mushroom spore", 6, 7, 61.5, 57.7, 0.0, 53, PatchType.MUSHROOM_PATCH, Items.MUSHROOM_6004), MUSHROOM_SPORE(Items.MUSHROOM_SPORE_5282, "mushroom spore", 4, 6, 61.5, 57.7, 0.0, 53, PatchType.MUSHROOM_PATCH, Items.MUSHROOM_6004),
CACTUS_SEED(Items.CACTUS_SEED_5280, "cactus seed", 8, 7, 66.5, 25.0, 374.0, 55, PatchType.CACTUS_PATCH, Items.CACTUS_SPINE_6016), CACTUS_SEED(Items.CACTUS_SEED_5280, "cactus seed", 8, 7, 66.5, 25.0, 374.0, 55, PatchType.CACTUS_PATCH, Items.CACTUS_SPINE_6016),
EVIL_TURNIP_SEED(Items.EVIL_TURNIP_SEED_12148, "evil turnip seed", 4, 1, 41.0, 46.0, 0.0, 42, PatchType.EVIL_TURNIP_PATCH, Items.EVIL_TURNIP_12134) EVIL_TURNIP_SEED(Items.EVIL_TURNIP_SEED_12148, "evil turnip seed", 4, 1, 41.0, 46.0, 0.0, 42, PatchType.EVIL_TURNIP_PATCH, Items.EVIL_TURNIP_12134)
; ;

View file

@ -235,7 +235,7 @@ class UseWithPatchHandler : InteractionListener {
} }
val p = patch.getPatchFor(player) val p = patch.getPatchFor(player)
if (p.getCurrentState() < 3 && p.isWeedy() && plantable != Plantable.SCARECROW) { if (p.getCurrentState() < 3 && p.isWeedy()) {
sendMessage(player, "This patch needs weeding first.") sendMessage(player, "This patch needs weeding first.")
return@onUseWith true return@onUseWith true
} else if (p.getCurrentState() > 3) { } else if (p.getCurrentState() > 3) {

View file

@ -41,7 +41,7 @@ class CropGrowth : PersistTimer (500, "farming:crops", isSoft = true) {
//Another more extreme example is if you planted something at 10:31 that takes 5 minutes to grow. 10:35 comes around, it hasn't been 5 minutes, so it doesn't grow, meaning //Another more extreme example is if you planted something at 10:31 that takes 5 minutes to grow. 10:35 comes around, it hasn't been 5 minutes, so it doesn't grow, meaning
//it actually grows at 10:40, an extra 4 minutes. //it actually grows at 10:40, an extra 4 minutes.
//this code makes it so crops planted both at 10:31 and 10:34 grow at 10:35 if they are supposed to take 5 minutes for each stage. //this code makes it so crops planted both at 10:31 and 10:34 grow at 10:35 if they are supposed to take 5 minutes for each stage.
if(patch.nextGrowth < (System.currentTimeMillis() + 240_000L) && !patch.isDead){ if(patch.nextGrowth < (System.currentTimeMillis() + 240_000L) && !patch.isDead && !patch.isChoppedFruitTree()){
patch.nextGrowth = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(patch.getStageGrowthMinutes().toLong()) patch.nextGrowth = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(patch.getStageGrowthMinutes().toLong())
patch.update() patch.update()
} }
@ -58,7 +58,7 @@ class CropGrowth : PersistTimer (500, "farming:crops", isSoft = true) {
for ((_, patch) in patchMap) { for ((_, patch) in patchMap) {
val type = patch.patch.type val type = patch.patch.type
val shouldPlayCatchup = !patch.isGrown() || (type == PatchType.BUSH_PATCH && patch.getFruitOrBerryCount() < 4) || (type == PatchType.FRUIT_TREE_PATCH && patch.getFruitOrBerryCount() < 6) val shouldPlayCatchup = !patch.isGrown() || (type == PatchType.BUSH_PATCH && patch.getFruitOrBerryCount() < 4) || (type == PatchType.FRUIT_TREE_PATCH && patch.getFruitOrBerryCount() < 6)
if (shouldPlayCatchup && !patch.isDead) { if (shouldPlayCatchup && !patch.isDead && !patch.isChoppedFruitTree()) {
var stagesToSimulate = if (!patch.isGrown()) { var stagesToSimulate = if (!patch.isGrown()) {
if (patch.isWeedy() || patch.isEmptyAndWeeded()) patch.currentGrowthStage % 4 if (patch.isWeedy() || patch.isEmptyAndWeeded()) patch.currentGrowthStage % 4
else patch.plantable!!.stages - patch.currentGrowthStage else patch.plantable!!.stages - patch.currentGrowthStage