lpbrown Posted June 13, 2015 Share Posted June 13, 2015 Hey all, trying to get back into scripting. I scripted some in the days of kbot but havent since then. Trying to make a basic smithing bot but I am running into trouble when interacting with the smelting menu. Anly help would be appreciated. Heres my code for the smelting case case SMITH: log("smithing"); if (!myPlayer().isAnimating()) { RS2Object furnace = objects.closest(FURNACE_ID); if (furnace != null) { furnace.interact("Smelt"); log("smelting 1 complete"); } RS2Widget menu = widgets.get(311,6); if (menu != null){ log("menu detected"); menu.interact("Smelt X"); log("menu interacted"); sleep(random(200,500)); keyboard.typeString("100", true); } } And using the logs as debugs, it just loops between "smithing" and "smelting 1 complete". What is wrong with my widget detection? Is that not the correct usage? I am trying to get menu to refer to the iron ore sub widget on the smihting menu, and then interact with it using the smetl x option. However it appears that the widget is always null. Heres a picture of the widget I am trying to use. Quote Link to comment Share on other sites More sharing options...
Flamezzz Posted June 13, 2015 Share Posted June 13, 2015 (edited) Well... for me it seems to work just fine lolAs for the interaction. This widget doesn't seem to support that. So you could just use widget.hover(), mouse.click(true) and check if the menu (there's a menu api) is open, if it's open use menu.selectAction("action"). Edited June 13, 2015 by Flamezzz 1 Quote Link to comment Share on other sites More sharing options...
Twin Posted June 13, 2015 Share Posted June 13, 2015 (edited) Well... for me it seems to work just fine lol As for the interaction. This widget doesn't seem to support that. So you could just use widget.hover(), mouse.click(true) and check if the menu (there's a menu api) is open, if it's open use menu.selectAction("action"). Just from looking at the code, isn't this just the script not having a sleep timer? I feel like if you added a sleep timer right before it checks for the widget, it would go through it. case SMITH: RS2Widget menu = widgets.get(311,6); RS2Object furnace = objects.closest(FURNACE_ID); log("smithing"); if (!myPlayer().isAnimating()&&menu==null) { if (furnace != null) { furnace.interact("Smelt"); sleep(random(500,1000)); log("smelting 1 complete"); } if (menu != null){ log("menu detected"); menu.interact("Smelt X"); log("menu interacted"); sleep(random(500,1000)); keyboard.typeString(""+28, true); } } Edited June 13, 2015 by twin 763 Quote Link to comment Share on other sites More sharing options...
Apaec Posted June 13, 2015 Share Posted June 13, 2015 I think you're trying to do too much at once. The implementation looks fine, however It would either be a good idea to search for the interface seperately in a different part of your code (such as if you're using a state machine, using a new state), or adding a conditional sleep to wait until the interface is interactable, or just using a static sleep (probably not recommended) to give the game time to load the interface before trying to nullcheck/interact it. 1 Quote Link to comment Share on other sites More sharing options...
lpbrown Posted June 13, 2015 Author Share Posted June 13, 2015 (edited) I think you're trying to do too much at once. The implementation looks fine, however It would either be a good idea to search for the interface seperately in a different part of your code (such as if you're using a state machine, using a new state), or adding a conditional sleep to wait until the interface is interactable, or just using a static sleep (probably not recommended) to give the game time to load the interface before trying to nullcheck/interact it. Just from looking at the code, isn't this just the script not having a sleep timer? I feel like if you added a sleep timer right before it checks for the widget, it would go through it. case SMITH: RS2Widget menu = widgets.get(311,6); RS2Object furnace = objects.closest(FURNACE_ID); log("smithing"); if (!myPlayer().isAnimating()&&menu==null) { if (furnace != null) { furnace.interact("Smelt"); sleep(random(500,1000)); log("smelting 1 complete"); } if (menu != null){ log("menu detected"); menu.interact("Smelt X"); log("menu interacted"); sleep(random(500,1000)); keyboard.typeString(""+28, true); } } Well... for me it seems to work just fine lol As for the interaction. This widget doesn't seem to support that. So you could just use widget.hover(), mouse.click(true) and check if the menu (there's a menu api) is open, if it's open use menu.selectAction("action"). Thanks for the input everyone. Still havent managed to get this working. I have gone ahead and made two different states as suggested case OPEN_FURNACE: log("OPEN FURNACE"); if (!myPlayer().isAnimating()) { RS2Object furnace = objects.closest(FURNACE_ID); if (furnace != null) { furnace.interact("Smelt"); sleep(2000); } } break; case SMELT: log("smelt"); RS2Widget options = widgets.get(311,8); if (options != null){ options.interact("Smelt X"); sleep(300); keyboard.typeString("" + random(29,99), true); } sleep(100); break; but this doesnt work. It simply does not interact with the widget. I also tried forcing the menu to open via a random click within the bounds of the desired area, and then using a menu method to get the smelt X option. this didnt work either, but it looks like this: case SMELT: log("smelt"); RS2Widget options = widgets.get(311,8); if (options != null){ mouse.click(random(240,270),random(393,420), true); sleep(random(300,500)); menu.selectAction("Smelt X"); sleep(300); keyboard.typeString("" + random(29,99), true); } sleep(100); break; Debating on continuing with this method and then just applying an offest to the random coords i use to open the menu. What is wrong with the above code though? really dont know Edited June 13, 2015 by lpbrown Quote Link to comment Share on other sites More sharing options...
Apaec Posted June 13, 2015 Share Posted June 13, 2015 done use mouse.click for this! I suggest debugging it. Also we need to see how you called your seperate state (what are the conditions) try opening the menu manually and seeing if it recognises it Quote Link to comment Share on other sites More sharing options...
lpbrown Posted June 13, 2015 Author Share Posted June 13, 2015 (edited) done use mouse.click for this! I suggest debugging it. Also we need to see how you called your seperate state (what are the conditions) try opening the menu manually and seeing if it recognises it private State getState() { if (!inventory.contains(453) && SMELT_AREA.contains(myPlayer())) return State.WALK_TO_BANK; if (inventory.contains(453) && inventory.contains(440) && BANK_AREA.contains(myPlayer())) return State.WALk_TO_FURNACE; if (!inventory.contains(453) && BANK_AREA.contains(myPlayer())) return State.BANK; if (widgets.get(311,8) != null) return State.SMELT; return State.OPEN_FURNACE; } Heres my state machine. Heres the basic logic (note this is for only steel at the moment, I am going to change it to smelt whatever using a gui once i get the smelting to actually work. thats why the ids are hardcoded atm) 1) if there is no coal in our inventory, and we are at the furnace -> walk to the bank 2) if there is coal and iron in our inventory, and we are at the bank - > walk to the furnace 3) if there is no coal in our inventory and we are at the bank (this implies we have finished smelting) -> do the bank routine (Considering making this check if there ARE bars instead of there ARE NOT ores. thoughts?) 4) if the widget menu for smelting bars is open -> attempt to select (smelt x option) (only step that isnt working so far.) 5) default case of clicking the furnace if no other cases are true. EDIT HOLY FUCKING WOW All I had to do was make change options.interact("Smelt X"); to options.interact("Smelt X Steel"); Why the hell is this? When I made a miner bot you just had to use "mine" for the menu interaction, not "mine ore" or whatever. doesnt make much sense. Edited June 13, 2015 by lpbrown Quote Link to comment Share on other sites More sharing options...
Apaec Posted June 13, 2015 Share Posted June 13, 2015 private State getState() { if (!inventory.contains(453) && SMELT_AREA.contains(myPlayer())) return State.WALK_TO_BANK; if (inventory.contains(453) && inventory.contains(440) && BANK_AREA.contains(myPlayer())) return State.WALk_TO_FURNACE; if (!inventory.contains(453) && BANK_AREA.contains(myPlayer())) return State.BANK; if (widgets.get(311,8) != null) return State.SMELT; return State.OPEN_FURNACE; } Heres my state machine. Heres the basic logic (note this is for only steel at the moment, I am going to change it to smelt whatever using a gui once i get the smelting to actually work. thats why the ids are hardcoded atm) 1) if there is no coal in our inventory, and we are at the furnace -> walk to the bank 2) if there is coal and iron in our inventory, and we are at the bank - > walk to the furnace 3) if there is no coal in our inventory and we are at the bank (this implies we have finished smelting) -> do the bank routine (Considering making this check if there ARE bars instead of there ARE NOT ores. thoughts?) 4) if the widget menu for smelting bars is open -> attempt to select (smelt x option) (only step that isnt working so far.) 5) default case of clicking the furnace if no other cases are true. EDIT HOLY FUCKING WOW All I had to do was make change options.interact("Smelt X"); to options.interact("Smelt X Steel"); Why the hell is this? When I made a miner bot you just had to use "mine" for the menu interaction, not "mine ore" or whatever. doesnt make much sense. Glad you got it figured! You need the exact interaction line haha Quote Link to comment Share on other sites More sharing options...
FrostBug Posted June 16, 2015 Share Posted June 16, 2015 options.interact() would probably work as well. I think it just clicks the first option if the vararg is empty Quote Link to comment Share on other sites More sharing options...