Jump to content
  • Create New...

[On Hold] Scripter application - ImPoob


Recommended Posts

Hi guys, I've spent a few days making an ammonite crab script. I've made a few scripts before on EB, but this is my first attempt here at powbot.

Currently, the script does the following:

- Travel to a specified ammonite crab spot (out of about 8 or so the script supports) from anywhere in the game, provided you have a digsite pendant in your inventory and access to the required mushroom tree teleports.

- It tracks the "agro zones" as I call them which are just the areas you must step outside of to reset your NPC aggression. It uses these zones alongside a heuristic to reset NPC aggression in a "smart" manner.

- It eats and drinks potions and attacks the NPC afterwards instead of just waiting for auto-retaliate.

- It loots specified items within a "loot zone" (preventing people from luring your account away) and then returns to the correct tile you are meant to be standing on.

In my code I use my own class "Zone" which replaces the powbot "Area" because the Area class was buggy when I started this project. There is some artifact code remaining in the project which isn't being used from previous implementations etc. Finally, there are still some minor bugs to iron out but I really wanted to get this application out as I have just started an internship and wanted to get this out before things started getting a bit hectic for me.

Any questions please let me know. You can find this project here: https://github.com/AbhiRehal/PowbotAmmoniteScript/tree/main


Finally, here are just some gifs showing the script in action so you don't have to go run it if you don't want to 😛

Here is the script starting up and running over to the spot I chose.


Here is the script resetting agro:


Here is the script drinking potions and re-attacking the NPC afterwards. I'll fix it immediately trying to drink potion after potion at some point haha.


Finally here is the looting. Here I pause the script, drop the volcanic ash OUTSIDE of the "loot zone" and drop the fossil inside. When I unpause the script, you can see it yoinks the fossil but not the ash and it returns to where it's supposed to be.


Link to post
Share on other sites

Oh and to any regular users that happen to stumble upon this script, if you do use it, be careful as it hasn't been tested thoroughly and it's unlikely that the one on github will be the most up to date version.

Link to post
Share on other sites

  • Moderators

Great script choice, and thanks for the application.
Before I go through your code, I'm really not a fan of you using your old 'zones' class rather than trying to help fix the areas if they were buggy.. Ignoring any issues in the api and working around them is literally the opposite to what we should be doing. Most of the devs don't necessarily play or bot heavily or varied, so if we wait for them to find the issues to fix, we'll be waiting a long time for things to get done. 

Anyway, onto the script.

A couple pointers here. You've got quite a few variables dumped in here and seems a little messy. Imo, you can split these out into their own file, whether that be a constants class or variables class, whatever you need them for, it just makes it easier, tidier and sensical to have them in their own obvious class.

You use current system time in your script rather than script runtime, ScriptManager.INSTANCE.getRuntime(bool) may well be useful for you here.

You mentioned 8 spots but no way for a user to select which one?

Straight forward class, does what it needs to. Except I don't understand your usage of the for loop. Your poll() itself loops, so if it failed to drink the potion, your activate would remain true and then loop back around to this task, thus no need for the for loop.

Also, I know you've commented it but would be good to have some sort of user input on when to re-pot etc as currently, there's no user interface/input at all.

Same as drink attack.

Add user input for when to eat.

No activate clause cause you always want to loot? Well that's not true.
You don't want to loot if you're not in the crab area, i.e. walking to the crabs
You don't want to loot if there's nothing to loot
Seems an abuse of the task framework to unnecessarily have tasks return true, otherwise, why not just have get rid of the activate and just loop execute() and put  your conditionals into the execute..

  public boolean activate(){
        return main.lootZone.contains(Players.local()) && GroundItems.stream().within(main.lootZone).id(main.itemIds).isNotEmpty();

or something along those lines.

Similarly, your execute is unnecessarily complicated, suggestion below.

GroundItems.stream().within(main.lootZone).id(main.itemIds).forEach(groundItem -> { 
                    Condition.wait(()->!groundItem.valid(), 50, 50);
///// alternatively if you aren't comfortable with streaming for each;

for(GroundItem g:GroundItems.stream().within(main.lootZone).id(main.itemIds).list()){
  Condition.wait(()->!g.valid(), 50, 50);


Again I'm not sure why you're using for loops here to teleport? if it's to find the charge number from the pendant you can do that in a number of different ways, regex is probably the easiest. However if it's just to interact, you don't need to know it.

//to get the item
Item pendant = Inventory.stream().filtered(i->i.name().contains("Digsite pendant")).first();
//to get the charges
int charges = pendant.name().replaceAll("[^0-9]", "");


Try and not use magic numbers. (Where no variables are used) it makes it incredibly hard to maintain when you come to look at it next and have no idea what widget 600 is for example or where tile 3764 3879 1 is
This becomes easier when you have a constants/variables file as mentioned above.


Overall, it's not a bad script by any means. Just some minor tweaking really.

  • Refactor zones to areas; if areas are still buggy, report it to get it fixed.
  • Add user interfaces for things like eating levels, potion levels etc
  • Remove unnecessary for loops in things like looting, teleporting and drinking potions
    • Try to utilise the api a bit more to make your life easier and less resource on the users end; that's what it's there for.
  • Validate your looting task, what I gave was only a suggestion, but there's unlikely going to be a time when a task doesn't need validation to execute.
  • Optional : create a vars/const class to keep them all in, rather than have them in main.
Link to post
Share on other sites

Thanks for the advice Dan 🙂

When I began this script, Areas were bugged and Proto opened a thread for the issue when I reported it. Presumably it's been fixed now so I wouldn't have an issue refactoring it.

Sorry for my wording, when I talk about the user having an option etc it's for the future when the scripts logic is more robust, currently it's just me changing variables haha.

As for unnecessary looping, no validating in loot and magic numbers, I completely agree. I just got a bit lazy in the latter half which is where a lot of questionable choices were made haha.

Oh also, I'm manually tracking time for when a new zone is calculated as it resets the agro timer. Could definitely check NPC aggression in a more secure way than just a blanket 10 mins = NPC unaggressive for sure.

Edited by ImPoob
Link to post
Share on other sites

Just checking back in. From last time the script has the following changes:

- GUI so the user can actually setup the script to their liking with the option of controlling; crab location (8 options, currently doesn't support the ones in the cave), eating (whether to eat, when to eat and what food to use), drinking potions (whether/when to drink super att/str pots) and looting (allows user to type the loot they want to pick up)

- Uses Constants class to tidy up the code/general clean up and efficiency changes Dan mentioned

- Some validation work on tasks and interactions

- Script stops if the player dies

- Areas are still bugged, so it still uses my zones (there is an archived thread for it so I guess it's been noted by the devs)

I had to delete the first repo because I accidentally uploaded the code with my accounts name. You can find the updated script here: https://github.com/AbhiRehal/PowbotAmmoniteScript

Link to post
Share on other sites

  • Moderators

Hi mate,

thanks for updating. If areas are still bugged and the old thread is archived it’s unlikely to be worked on, if you’ve tested recently an you create a new thread detailing what exactly is bugged? Never gunna fix it otherwise..


also as I suggested in discord you have an old sdk which is why your within() methods are throwing errors in ground items.


im curious why you’re still trying to keep your loot validation as loose as possible? You’re asking the task to execute every like 50ms given that you’re inside the loot area, and still aren’t checking if there’s lootable items before execution, why, did I miss something?


Your conditional waits for drinking potions are still static, if the user has a thread hold higher than 10, your attack potion wait is useless fyi.


i see you commented out some attempts to use the builder to enable run, but still aren’t enabling run, there’s a method in the Movment api for toggling and providing run energy.


your teleport to digsite class has a cached component, after discussing it on discord, I was expecting you to change it. While you’ve moved the caching if that component to a looped task, to update the cached component, you’re still caching it in the wrong place. When you cache it, there’s no validation that the component is valid/visible so you’re caching an old state and then asking what it’s state is later on after it’s changed.


imo it should be something like this



If(Condition.wait(Widgets.widget(c.digsitePendantTeleportWidget).component(c.chatBoxMenu).component(c.fossilIslandOption).visible(), 100, 20);


(sorry for the formatting I’m on my phone) here you’re not accessing a cached version of the component, you’re calling it live to get its current state and compare if it’s visible.


you do a similar thing with non-validated component caching in your tree teleporting too.


Dont get me wrong, it’s a good script and I don’t want you to give up, you’ll make a great addition to the team, I just think you need a bit of time to understand the API a bit more. Will ask the others if they want to offer any more feedback.

For now, id suggest taking a few weeks/months, get more familiar with the api, explore and experiment and then come back to your application.

Link to post
Share on other sites

Hey @ImPoob, as an ex-EB scripter myself, I can see there are a couple of things you're trying to get used to :classic_biggrin: Apart from the comments that Dan made, it does seem you are finding it hard to understand the differences between cached and live version of anything. So let me give you a quick run down:


Let's pretend you have an API call that gets the nearest chicken.

Npc chicken = Npcs.stream().name("Chicken").nearest().first();

This line of code will get the current state of the closest NPC, and save it to a variable named chicken.  (Emphasis on current) 
This is not a constant, meaning that by the time you call the variable in another class after doing other actions, things such as position, animation, or even existence can change, causing that variable to be out of date.

Remember, when you assign a line of code to a variable, you're not assigning the API call, you're calling that method, and saving the results of it. Constants are things that will NEVER change. Like an Item ID, or Area.


For example, as Dan suggested, 


        Npc chicken = Npcs.stream().name("Chicken").nearest().first();

        if(chicken.valid() && chicken.interact("Attack")) {
            Condition.wait(() -> Npcs.stream().name("Chicken").interactingWithMe().first().valid(), 200, 20);

Pay attention to the condition.wait(). I'm not calling the saved chicken variable, as it is not the live version of the NPC. If I was to do that, that condition would not work as when you saved the 'chicken' variable, it was not interacting with you. Instead, you are calling the API method directly to check if there is a chicken that is interacting with you, meaning you're getting the live version of all the NPCs every 200ms and checking for one that meets the conditions that are set in the Npc.stream method. 

The same applies for nearly anything that has the possibility to change states. 


I hope this example helps a bit in understanding, reach out to us on discord if you want to go over it a bit more, I'm free to VC later if you also want to get some live help/explanations


Link to post
Share on other sites

First of all thanks for the feedback, it's so helpful! Proto's example definitely cleared up a misconception that I had *cough* EB habits *cough*. This was my first attempt at a script with the PB api so I was just learning on the fly so I'll definitely have a play around with a few different scripts and take some time to learn the api properly 🙂. I'll come back to you when I have something worth showing. Again, thanks for the help guys, it's awesome how freely you guys give your time ❤️

Oh and I downloaded the SDK's when we were told to redownload them, but since my within() was bugged I think it's safe to assume that my SDK's are out of date, or at least I compiled against the out of date ones on my pc. I'll have a play around with it today and see if it fixes some other issues I was having too!

Edited by ImPoob
Link to post
Share on other sites

  • Dan changed the title to [On Hold] Scripter application - ImPoob
  • 1 month later...
  • 2 weeks later...
  • Dan locked this topic
This topic is now closed to further replies.