1b4e0aafaa
Reorganised imports Removed redundant qualifiers
255 lines
9.3 KiB
Kotlin
255 lines
9.3 KiB
Kotlin
package content.global.bots
|
|
|
|
import core.game.interaction.DestinationFlag
|
|
import core.game.interaction.MovementPulse
|
|
import core.game.node.entity.skill.Skills
|
|
import core.game.node.item.Item
|
|
import core.game.system.task.Pulse
|
|
import core.game.world.map.Location
|
|
import core.game.world.map.zone.ZoneBorders
|
|
import core.tools.RandomFunction
|
|
import org.rs09.consts.Items
|
|
import core.game.bots.AIRepository
|
|
import core.game.bots.Script
|
|
|
|
/**
|
|
* A bot that does various random slayer tasks throughout the game and sells the loot on the GE.
|
|
* @author Ceikry
|
|
*/
|
|
class GenericSlayerBot : Script() {
|
|
var state = State.GETTING_TASK
|
|
var task = Task.CAVE_CRAWLER //default value to ensure non-nullability
|
|
var assignment = Assignment("",0) //same as above
|
|
var teleportFlag = false //have we teleported?
|
|
val FOOD_ID = Items.LOBSTER_379
|
|
val varrockBankBorders = ZoneBorders(3184, 3435,3187, 3441)
|
|
|
|
|
|
|
|
/**
|
|
* Per-tick actions (they don't run if the bot already has a pulse running, such as moving or combat.)
|
|
*/
|
|
override fun tick() {
|
|
scriptAPI.eat(FOOD_ID) //try to eat every tick (does nothing if health isn't low enough)
|
|
|
|
when(state){
|
|
|
|
/**
|
|
* State that handles getting a new task
|
|
*/
|
|
State.GETTING_TASK -> {
|
|
populateTaskAndAssignment()
|
|
state = State.GOING_TO_HUB //switch states
|
|
}
|
|
|
|
/**
|
|
* State that handles going to the "hub" for the task. Such as fremmy slayer cave or slayer tower.
|
|
*/
|
|
State.GOING_TO_HUB -> {
|
|
when(task.hub){
|
|
|
|
TaskHub.FREMENNIK_CAVE -> {
|
|
if(!teleportFlag) {
|
|
scriptAPI.teleport(Location.create(2781, 3615, 0)) //tele -> fremennik fairy ring
|
|
teleportFlag = !teleportFlag //teleportFlag -> true
|
|
}
|
|
else {
|
|
val entrance = scriptAPI.getNearestNode(4499,true) //returns the object if within render distance, null if not.
|
|
if(entrance == null || !entrance.location.withinDistance(bot.location,2)) {
|
|
scriptAPI.walkTo(Location.create(2796, 3615, 0))
|
|
} else {
|
|
entrance.interaction.handle(bot,entrance.interaction[0]) //bot -> use interaction [0] of cave object
|
|
teleportFlag = !teleportFlag //teleportFlag -> false
|
|
state = State.KILLING_ENEMY //switch states
|
|
}
|
|
}
|
|
}
|
|
else -> {}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* State used for combat. Handles moving the bot back into the zone for the monster and looting as well.
|
|
*/
|
|
State.KILLING_ENEMY -> {
|
|
val items = AIRepository.groundItems.get(bot) //retrieve drops that belong to this bot
|
|
if(items != null && items.isNotEmpty()){ //if we have loot...
|
|
if(bot.inventory.freeSlots() == 0){
|
|
if(bot.inventory.contains(FOOD_ID,1)){
|
|
scriptAPI.forceEat(FOOD_ID)
|
|
return
|
|
}
|
|
}
|
|
scriptAPI.takeNearestGroundItem(items.get(0).id)
|
|
if(bot.inventory.getAmount(Item(FOOD_ID)) == 0){
|
|
state = State.GOING_TO_BANK
|
|
}
|
|
return
|
|
}
|
|
|
|
if(assignment.amount > 0) {
|
|
if (task.borders.insideBorder(bot)) { //make sure bot is within the borders of the task's zone.
|
|
scriptAPI.attackNpcInRadius(bot, task.npc_name, 20) //attack nearest NPC with given task name within radius.
|
|
assignment.amount--
|
|
} else {
|
|
scriptAPI.walkTo(task.borders.randomLoc)
|
|
}
|
|
} else {
|
|
state = State.GOING_TO_BANK //switch states and bank.
|
|
}
|
|
}
|
|
|
|
/**
|
|
* State used to handle traveling to a bank. Due to the dynamic nature of where these bots might be
|
|
* in this state, they simply teleport to Varrock and then walk to the west bank to bank.
|
|
*/
|
|
State.GOING_TO_BANK -> {
|
|
if(!teleportFlag){
|
|
scriptAPI.teleport(Location.create(3213, 3426, 0))
|
|
teleportFlag = !teleportFlag
|
|
} else {
|
|
if(!varrockBankBorders.insideBorder(bot)) {
|
|
scriptAPI.walkTo(varrockBankBorders.randomLoc)
|
|
} else {
|
|
val bank = scriptAPI.getNearestNode("Bank Booth",true)
|
|
bank ?: return
|
|
/**
|
|
* Run a pulse that moves the bot to the bank booth and then faces it, and then swaps to the actual banking state
|
|
*/
|
|
bot.pulseManager.run(object: MovementPulse(bot,bank, DestinationFlag.OBJECT){
|
|
override fun pulse(): Boolean {
|
|
bot.faceLocation(bank.location)
|
|
state = State.BANKING
|
|
teleportFlag = !teleportFlag
|
|
return true
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* State used to handle banking itself. Runs a pulse with a delay of 10 (to make it look like the bot is idling at the bank booth a bit.)
|
|
* the pulse adds every item in the bot's inventory to its bank and then clears the bot's inventory. Re-adds lobsters to the inventory afterwords.
|
|
*/
|
|
State.BANKING -> {
|
|
bot.pulseManager.run(object: Pulse(10){
|
|
override fun pulse(): Boolean {
|
|
for(item in bot.inventory.toArray()){
|
|
item ?: continue
|
|
if(item.checkIgnored()) continue
|
|
bot.bank.add(item)
|
|
}
|
|
bot.inventory.clear()
|
|
for(item in inventory)
|
|
bot.inventory.add(item)
|
|
scriptAPI.withdraw(Items.LOBSTER_379,10)
|
|
bot.fullRestore()
|
|
|
|
if(assignment.amount <= 0){
|
|
state = State.GOING_TO_GE
|
|
} else {
|
|
state = State.GOING_TO_HUB
|
|
}
|
|
|
|
return true
|
|
}
|
|
})
|
|
}
|
|
|
|
|
|
/**
|
|
* State used to handle travelling to the GE.
|
|
*/
|
|
State.GOING_TO_GE -> {
|
|
if(bot.location != Location.create(3165, 3487, 0)) {
|
|
scriptAPI.walkTo(Location.create(3165, 3487, 0))
|
|
} else {
|
|
state = State.SELLING
|
|
}
|
|
}
|
|
|
|
/**
|
|
* State used to handle selling items on the GE
|
|
*/
|
|
State.SELLING -> {
|
|
scriptAPI.sellAllOnGe()
|
|
state = State.GETTING_TASK
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Called when a bot needs to be regenerated, like when a bot dies.
|
|
*/
|
|
override fun newInstance(): Script {
|
|
TODO("Not yet implemented")
|
|
}
|
|
|
|
/**
|
|
* Populate task and assignment vars
|
|
*/
|
|
fun populateTaskAndAssignment() {
|
|
task = Task.values().random() //get a new random task from the enum
|
|
assignment = Assignment(task.npc_name, RandomFunction.random(task.minAmt, task.maxAmt + 1)) //produce a new Assignment class with values from our Task.
|
|
}
|
|
|
|
|
|
/**
|
|
* Item extension function to check for ignored items when banking.
|
|
*/
|
|
fun Item.checkIgnored(): Boolean {
|
|
if(name.toLowerCase().contains("charm")) return true
|
|
if(name.toLowerCase().contains("lobster")) return true
|
|
if(name.toLowerCase().contains("clue")) return true
|
|
if(!definition.isTradeable) return true
|
|
return when(id){
|
|
Items.BONES_2530 -> true
|
|
995 -> true
|
|
else -> false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The state enums
|
|
*/
|
|
enum class State {
|
|
GETTING_TASK,
|
|
GOING_TO_HUB,
|
|
KILLING_ENEMY,
|
|
GOING_TO_BANK,
|
|
BANKING,
|
|
GOING_TO_GE,
|
|
SELLING
|
|
}
|
|
|
|
/**
|
|
* Assign default skills and initial inventory
|
|
*/
|
|
init {
|
|
skills[Skills.SLAYER] = 99
|
|
inventory.add(Item(Items.LOBSTER_379,10))
|
|
|
|
}
|
|
|
|
/**
|
|
* List of tasks that this bot can receive
|
|
*/
|
|
enum class Task(val npc_name: String, val minAmt: Int, val maxAmt: Int, val hub: TaskHub, val borders: ZoneBorders) {
|
|
CAVE_CRAWLER("Cave crawler",20,100, TaskHub.FREMENNIK_CAVE, ZoneBorders(2778, 9988,2798, 10002))
|
|
}
|
|
|
|
/**
|
|
* The task hubs
|
|
*/
|
|
enum class TaskHub {
|
|
FREMENNIK_CAVE,
|
|
SLAYER_TOWER,
|
|
TAVERLY_DUNGEON
|
|
}
|
|
|
|
class Assignment(val npc_name: String, var amount: Int) //class used to keep track of current assignment and how many are left.
|
|
} |