mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-09 16:45:44 -07:00
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:
parent
91f3a70f75
commit
e8c3f31786
8 changed files with 137 additions and 23 deletions
|
|
@ -15,7 +15,7 @@ import core.plugin.Plugin
|
|||
import org.rs09.consts.Items
|
||||
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
|
||||
class CropHarvester : OptionHandler() {
|
||||
|
|
@ -43,14 +43,16 @@ class CropHarvester : OptionHandler() {
|
|||
override fun pulse(): Boolean {
|
||||
var reward = Item(crop)
|
||||
|
||||
val familiar = player.familiarManager.familiar
|
||||
if (familiar != null && familiar is GiantEntNPC) {
|
||||
familiar.modifyFarmingReward(fPatch, reward)
|
||||
}
|
||||
if (!hasSpaceFor(player, reward)) {
|
||||
sendMessage(player, "You have run out of inventory space.")
|
||||
return true
|
||||
}
|
||||
|
||||
val familiar = player.familiarManager.familiar
|
||||
if (familiar != null && familiar is GiantEntNPC) {
|
||||
familiar.modifyFarmingReward(fPatch, reward)
|
||||
}
|
||||
|
||||
var requiredItem = when (fPatch.type) {
|
||||
PatchType.TREE_PATCH -> Items.SECATEURS_5329
|
||||
else -> Items.SPADE_952
|
||||
|
|
@ -92,7 +94,7 @@ class CropHarvester : OptionHandler() {
|
|||
// 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
|
||||
delay = 2
|
||||
addItem(player, reward.id)
|
||||
addItemOrDrop(player, reward.id,reward.amount)
|
||||
rewardXP(player, Skills.FARMING, plantable.harvestXP)
|
||||
if (patch.patch.type in livesBased) {
|
||||
patch.rollLivesDecrement(
|
||||
|
|
@ -104,6 +106,9 @@ class CropHarvester : OptionHandler() {
|
|||
if (patch.harvestAmt <= 0 && crop == plantable.harvestItem) {
|
||||
patch.clear()
|
||||
}
|
||||
else if (fPatch.type == PatchType.MUSHROOM_PATCH){
|
||||
patch.setCurrentState(patch.getCurrentState() + 1)
|
||||
}
|
||||
}
|
||||
if (sendHarvestMessages && (patch.cropLives <= 0 || patch.harvestAmt <= 0)) {
|
||||
sendMessage(player, "The $patchName is now empty.")
|
||||
|
|
|
|||
|
|
@ -30,6 +30,14 @@ class DigUpPatchDialogue(player: Player? = null) : DialoguePlugin(player) {
|
|||
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.")
|
||||
stage = 0
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import core.game.interaction.OptionHandler
|
|||
import core.game.node.Node
|
||||
import content.global.skill.summoning.familiar.GiantEntNPC
|
||||
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.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
|
|
@ -86,6 +87,10 @@ class FruitAndBerryPicker : OptionHandler() {
|
|||
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
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
@ -29,7 +29,11 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
|
|||
Plantable.WILLOW_SAPLING -> 0
|
||||
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
|
||||
}
|
||||
cropLives = 3 + compostMod
|
||||
|
|
@ -70,8 +74,6 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
|
|||
var chance = when(patch.type){
|
||||
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.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
|
||||
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
|
||||
}
|
||||
|
||||
fun isChoppedFruitTree(): Boolean {
|
||||
return (patch.type == PatchType.FRUIT_TREE_PATCH)
|
||||
&& getCurrentState() == (plantable?.value ?: 0) + 25
|
||||
}
|
||||
|
||||
fun isEmptyAndWeeded(): Boolean {
|
||||
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 setVisualState((plantable?.value ?: 0) + currentGrowthStage)
|
||||
}
|
||||
PatchType.MUSHROOM_PATCH -> {
|
||||
if(isDead) setVisualState(getMushroomDeathValue())
|
||||
else if(isDiseased && !isDead) setVisualState(getMushroomDiseaseValue())
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
|
@ -221,16 +232,27 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
|
|||
private fun getBushDiseaseValue(): Int{
|
||||
if(plantable == Plantable.POISON_IVY_SEED){
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBushDeathValue(): Int{
|
||||
if(plantable == Plantable.POISON_IVY_SEED){
|
||||
return (plantable?.value ?: 0) + currentGrowthStage + 22
|
||||
} else {
|
||||
return (plantable?.value ?: 0) + currentGrowthStage + 126
|
||||
return (plantable?.value ?: 0) + currentGrowthStage + 20
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
private fun getMushroomDiseaseValue(): Int {
|
||||
return (plantable?.value ?: 0) + currentGrowthStage + 11
|
||||
}
|
||||
|
||||
private fun getMushroomDeathValue(): Int {
|
||||
return (plantable?.value ?: 0) + currentGrowthStage + 16
|
||||
}
|
||||
|
||||
private fun getHerbDiseaseValue(): Int {
|
||||
return if (plantable?.value ?: -1 <= 103) {
|
||||
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(){
|
||||
if((isWeedy() || isEmptyAndWeeded()) && getCurrentState() > 0) {
|
||||
if((isWeedy() || isEmptyAndWeeded() || (plantable == Plantable.SCARECROW && !isGrown())) && getCurrentState() > 0) {
|
||||
nextGrowth = System.currentTimeMillis() + 60000
|
||||
setCurrentState(getCurrentState() - 1)
|
||||
currentGrowthStage--
|
||||
|
|
@ -294,7 +324,14 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
|
|||
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
|
||||
// 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
|
||||
|
|
@ -389,7 +426,9 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
|
|||
else -> return 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.isGrown())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
||||
// 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
|
||||
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
|
||||
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)),
|
||||
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)),
|
||||
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),
|
||||
|
||||
// Herbs
|
||||
|
|
@ -78,7 +78,7 @@ enum class Plantable(val itemID: Int, val displayName: String, val value: Int, v
|
|||
|
||||
// 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),
|
||||
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),
|
||||
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)
|
||||
;
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ class UseWithPatchHandler : InteractionListener {
|
|||
}
|
||||
|
||||
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.")
|
||||
return@onUseWith true
|
||||
} else if (p.getCurrentState() > 3) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//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.
|
||||
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.update()
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ class CropGrowth : PersistTimer (500, "farming:crops", isSoft = true) {
|
|||
for ((_, patch) in patchMap) {
|
||||
val type = patch.patch.type
|
||||
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()) {
|
||||
if (patch.isWeedy() || patch.isEmptyAndWeeded()) patch.currentGrowthStage % 4
|
||||
else patch.plantable!!.stages - patch.currentGrowthStage
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue