Merge 2009scape updates #19

Open
randy wants to merge 204 commits from 2009Scape:master into upstream
8 changed files with 137 additions and 23 deletions
Showing only changes of commit e8c3f31786 - Show all commits

View file

@ -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.")

View file

@ -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

View file

@ -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
}
})

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
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())
}

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),
// 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)
;

View file

@ -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) {

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
//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