Skip to content

Add pickable banana trees on Karamja - #1200

Merged
GregHib merged 4 commits into
GregHib:mainfrom
HarleyGilpin:feat/pick-banana-trees
Aug 22, 2026
Merged

Add pickable banana trees on Karamja#1200
GregHib merged 4 commits into
GregHib:mainfrom
HarleyGilpin:feat/pick-banana-trees

Conversation

@HarleyGilpin

@HarleyGilpin HarleyGilpin commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

What

The Musa Point plantation banana trees (objects 2073-2078, 32 of them in region 11569) were unnamed scenery, so their Pick option did nothing, and Luthas had no dialogue.

Picking

  • Names the five-stage chain karamja_banana_tree_5karamja_banana_tree_0 in musa_point.objs.toml. banana_tree_1..5 was already taken by the farming fruit tree patch (7994-7998), hence the prefix.
  • Adds BananaTrees - picking gives a banana, plays anim 832 and sound 2581, prints "You pick a banana.", and steps the tree down one stage. The tree regrows to full after world.objs.bananaTree.regrowTicks (300 by default).
  • Object 2078 (empty tree) carries a Search option rather than Pick, so it gets its own "There are no bananas left on the tree." handler. Note 2078 is also placed as jungle scenery in regions 12844/13100/13101, where that message reads correctly too.
  • Hooks the previously unused Karamja easy task Five a day (varbit 3566) with a new persisted five_a_day_progress counter.

Luthas and the export crate

  • Adds Luthas dialogue. The opening choice is either asking for employment on the plantation, or the conversation about the customs officer who no longer searches his export crates and the shop in Port Sarim they get shipped to.
  • Taking the job sets banana_plantation_job. While employed, Luthas asks whether the task is done; once the crate holds ten bananas he pays 30 coins and clears both the counter and the job. Payment aborts cleanly on a full inventory rather than emptying the crate for nothing.
  • The crate supports Search, Fill, and banana-on-crate, capacity 10, anim 832 on each. Without the job every interaction answers "I don't know what goes in there."
  • Object 2072 is the shared crate_14 definition and is also placed on Ape Atoll (2746, 2768), so the handlers are gated to the plantation crate's tile to leave that one inert.

Rum smuggling is deliberately left out - Pirate's Treasure isn't implemented, so stashing rum in the crate would be a dead end.

Why the regrow isn't a plain replace chain

GameObjects.replace(original, replacement, ticks) registers one timer over setOf(original, replacement) whose revert re-adds the immediately previous object, and GameObjectTimers.add cancels any timer touching either object. Chained across five stages, a rapidly-picked tree reverts one stage and is then left with no timer at all - permanently stranded mid-chain.

Since GameObjectHashMap.add(obj, REPLACED) only ORs a flag and never overwrites the stored map value, the original is always recoverable. So each pick replaces permanently and re-arms a single timer that removes the replacement, reverting straight back to the full tree.

Testing

BananaTreesTest covers picking one banana, emptying a tree (and the diary task firing), the empty-tree message, full regrowth after the timer, and a full inventory being rejected.

LuthasTest covers both dialogue branches, taking the job, filling the crate, packing a single banana, getting paid, and the crate staying inert without the job.

BushPickingTest, ObjectTest and CustomsOfficerTest still pass.

The Musa Point plantation banana trees (objects 2073-2078) were unnamed
scenery, so their Pick option did nothing.

Name the five-stage chain karamja_banana_tree_5..0 and add a handler that
gives a banana, steps the tree down one stage, and regrows it back to full
after world.objs.bananaTree.regrowTicks (300 by default). The empty tree
2078 carries a Search option rather than Pick, so it gets its own message.

Each pick replaces permanently and re-arms a single timer instead of
chaining temporary replacements: GameObjectTimers cancels any timer
touching either object, so a chain would revert one stage and then strand
a part-picked tree. Removing the replacement reverts to the original full
tree.

Also hooks the previously unused Karamja easy task "Five a day" (varbit
3566) via a new persisted five_a_day_progress counter.
Talking to Luthas offers the plantation job or the conversation about the
customs officer no longer searching his export crates. Once employed, his
crate at Musa Point accepts bananas via Search, Fill, and banana-on-crate,
and Luthas pays 30 coins for a full crate of ten.

Object 2072 is the shared crate_14 definition and is also placed on Ape
Atoll, so the crate handlers are gated to the plantation crate's tile to
leave that one inert.

Also switches the banana picking animation to 832.
Comment thread game/src/main/kotlin/content/area/karamja/musa_point/BananaTrees.kt
Comment thread game/src/main/kotlin/content/area/karamja/musa_point/Luthas.kt Outdated
}
animDelay("take")
inc("banana_crate_bananas", packed)
if (packed == carrying) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (packed == carrying) {
if (!inventory.contains("banana")) {

@HarleyGilpin HarleyGilpin Aug 22, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied. Pairs with removeToLimit above, since the carried count is no longer needed.

Comment thread game/src/main/kotlin/content/area/karamja/musa_point/BananaTrees.kt Outdated
Replacing a replacement registered a revert that re-added the previous
replacement rather than the object set on game load, and since
GameObjectTimers.add cancels any timer touching either object, the earlier
revert was dropped. An object replaced twice reverted one step and then had
no timer left at all, stranding it in that state.

Removing a same-tile replacement already re-adds the original, because
GameObjectHashMap.add only ORs the REPLACED flag and never overwrites the
stored value. So skip adding the original back in that case. Replacements on
a different tile, and objects with no original to fall back on, still need it.
Clear five_a_day_progress once the task completes, and use removeToLimit
when filling the export crate.

Banana trees now use a plain timed replace; reverting to the original is
handled by the engine rather than by re-arming a timer here.
@HarleyGilpin
HarleyGilpin force-pushed the feat/pick-banana-trees branch from f351e6a to 4e5b861 Compare August 22, 2026 13:19
@GregHib
GregHib merged commit 06847f5 into GregHib:main Aug 22, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants