All scripts

AIO Fighter

by ArcaneOxbow ·Combat

AIO Fighter

6

Installed

1.0.1

Version

18 Aug 2026

Updated

About this script

AIO Fighter

Step 1 — Targets. Every npc near you appears as a tick-list, live. Tick the ones you want to fight.
Step 2 — Loot. Search the entire item cache by name, paged 20 at a time, and tick what to pick up. Your picks survive paging and searching.
Step 3 — Options. Toggle bury-bones, eat-when-low and sleep-off-fatigue, set your working range with + / − buttons, and press Start.
Where you press Start becomes the centre of the bot's world. It fights, loots and buries only within the range you set, and it tells you what it's doing at every moment — "Attacking Goblin", "Looting Bones", "Sleeping — 42 fatigue left".
What it does, in priority order
[list]
[*] Sleeps off fatigue with a sleeping bag before it caps out
[*] Eats when your health drops below 25%
[*] Never interrupts a fight it's already in
[*] Picks up your chosen drops, nearest first
[*] Buries any bones it's carrying (finds them by their Bury option, so it works with any bone)
[*] Attacks the nearest of your chosen npcs in range
Requirements
A sleeping bag (id 1263) if you want fatigue handled, food with an Eat option if you want auto-eat, and a target worth hitting. Works anywhere with npcs — goblins, cows, chickens, whatever you tick.

Builds

VersionKindPublishedSizeWhat changed
1.0.1 current text script 18 Aug 2026 8 KB First upload.

Source of 1.0.1

Published by the author. This is the current build, exactly as it will be delivered.

script "Fight Setup Wizard"
author "Mark"
version "1.0.1"
every 600

enum Stage { NPCS, ITEMS, OPTIONS, RUN }

var stage = Stage.NPCS

# ---- npc picking
var seenNpcs = ""
var foundNpcs = 0
var pickedNpcs = ""
var npcCount = 0
var maxNpcId = 0

# ---- item picking
var query = ""
var page = 0
var matchTotal = 0
var pickedItems = ""
var itemCount = 0

# ---- options
var doBury = false
var doEat = false
var doSleep = false
var range = 12
var anchor = tile(0, 0)

on start {
    uiTab("Fight Setup")
    header1()
}

fun header1() {
    uiHeader("Step 1  -  Choose your targets")
    uiLabel("hint1", "Tick every npc you want to fight, then press Next.")
    uiLabel("found", "Scanning for nearby npcs...")
    uiButton("Next  >", "onNpcsDone")
}

fun onNpcsDone() {
    pickedNpcs = ""
    npcCount = 0
    let id = 0
    while id <= maxNpcId {
        if contains(seenNpcs, "[" + str(id) + "]") {
            if uiToggled("npc-" + str(id)) {
                pickedNpcs = pickedNpcs + "[" + str(id) + "]"
                npcCount = npcCount + 1
            }
        }
        id = id + 1
    }
    if npcCount == 0 {
        uiLabel("found", "Pick at least one npc before continuing.")
        return
    }
    stage = Stage.ITEMS
    query = ""
    page = 0
    renderItems()
}

fun renderItems() {
    uiClear()
    uiHeader("Step 2  -  Loot table")
    uiLabel("hint2", "Search the item cache and tick what to pick up.")
    uiInput("search", "Search", query)

    let shown = 0
    let matched = 0
    let id = 0
    let total = itemDefCount()
    while id < total {
        let def = itemDef(id)
        if def.known and contains(lower(def.name), lower(query)) {
            if matched >= page * 20 and shown < 20 {
                uiToggle("item-" + str(id), def.name + "  (" + str(id) + ")", contains(pickedItems, "[" + str(id) + "]"))
                shown = shown + 1
            }
            matched = matched + 1
        }
        id = id + 1
    }
    matchTotal = matched

    let pages = (matched + 19) / 20
    if pages < 1 { pages = 1 }
    uiProgress("pagebar", page + 1, pages)
    uiLabel("pageinfo", "Page " + str(page + 1) + " of " + str(pages) + "  -  " + str(matched) + " match  -  " + str(itemCount) + " picked")
    uiButton("<  Prev", "onPrev")
    uiButton("Next  >", "onNext")
    uiButton("Continue", "onItemsDone")
}

fun captureItems() {
    let shown = 0
    let matched = 0
    let id = 0
    let total = itemDefCount()
    while id < total {
        let def = itemDef(id)
        if def.known and contains(lower(def.name), lower(query)) {
            if matched >= page * 20 and shown < 20 {
                let key = "[" + str(id) + "]"
                if uiHas("item-" + str(id)) {
                    if uiToggled("item-" + str(id)) {
                        if not contains(pickedItems, key) {
                            pickedItems = pickedItems + key
                            itemCount = itemCount + 1
                        }
                    } else {
                        if contains(pickedItems, key) {
                            pickedItems = replace(pickedItems, key, "")
                            itemCount = itemCount - 1
                        }
                    }
                }
                shown = shown + 1
            }
            matched = matched + 1
        }
        id = id + 1
    }
}

fun onPrev() {
    captureItems()
    if page > 0 { page = page - 1 }
    renderItems()
}

fun onNext() {
    captureItems()
    if (page + 1) * 20 < matchTotal { page = page + 1 }
    renderItems()
}

fun onItemsDone() {
    captureItems()
    stage = Stage.OPTIONS
    renderOptions()
}

fun renderOptions() {
    uiClear()
    uiHeader("Step 3  -  Options")
    uiLabel("summary", str(npcCount) + " targets, " + str(itemCount) + " loot items selected.")
    uiToggle("opt-bury", "Bury bones", false)
    uiToggle("opt-eat", "Eat when low", false)
    uiToggle("opt-sleep", "Sleep off fatigue", false)
    uiHeader("Working range")
    uiButton("-  Range", "onRangeDown")
    uiLabel("range", "Working range: " + str(range) + " tiles")
    uiButton("+  Range", "onRangeUp")
    uiButton("Start  >", "onRun")
}

fun onRangeDown() {
    if range > 1 { range = range - 1 }
    uiLabel("range", "Working range: " + str(range) + " tiles")
}

fun onRangeUp() {
    if range < 20 { range = range + 1 }
    uiLabel("range", "Working range: " + str(range) + " tiles")
}

fun onRun() {
    doBury = uiToggled("opt-bury")
    doEat = uiToggled("opt-eat")
    doSleep = uiToggled("opt-sleep")
    stage = Stage.RUN
    anchor = myTile()

    let bury = "off"
    if doBury { bury = "on" }
    let eat = "off"
    if doEat { eat = "on" }
    let sleep = "off"
    if doSleep { sleep = "on" }

    uiClear()
    uiHeader("Running")
    uiLabel("t", "Targets: " + str(npcCount) + "   Loot: " + str(itemCount))
    uiLabel("o", "Bury " + bury + "   Eat " + eat + "   Sleep " + sleep)
    uiLabel("r", "Working range: " + str(range) + " tiles")
    uiLabel("live", "Starting...")
}

on loop {
    if stage == Stage.NPCS {
        for n in npcs(within: 12) {
            if not contains(seenNpcs, "[" + str(n.id) + "]") {
                seenNpcs = seenNpcs + "[" + str(n.id) + "]"
                foundNpcs = foundNpcs + 1
                uiToggle("npc-" + str(n.id), n.name + "  (" + str(n.id) + ")", false)
                if n.id > maxNpcId { maxNpcId = n.id }
            }
        }
        uiLabel("found", str(foundNpcs) + " npcs nearby - tick your targets")
        return 800
    }

    if stage == Stage.ITEMS {
        if uiHas("search") {
            let q = uiText("search")
            if q != query {
                captureItems()
                query = q
                page = 0
                renderItems()
            }
        }
        return 400
    }

    if stage == Stage.RUN {
        # Asleep: wait it out, reporting how much fatigue is left.
        if isSleeping() {
            uiLabel("live", "Sleeping - " + str(sleepFatigue()) + " fatigue left")
            return 2000
        }

        # Sleep off fatigue (if chosen) at 91% before it caps at 100.
        if doSleep and fatigue() >= 91 {
            uiLabel("live", "Fatigue " + str(fatigue()) + " - using the sleeping bag")
            let bag = invItem(1263)
            if bag != none {
                interact(bag, "Sleep")
            }
            return random(600, 900)
        }

        # Eat when low (if chosen) - can happen mid-fight, so it is not
        # gated on combat. Any inventory item that offers "Eat".
        if doEat and healthPercent() < 25 {
            for food in inv() {
                if defHasCommand(itemDef(food.id), "Eat") {
                    uiLabel("live", "Health low - eating")
                    interact(food, "Eat")
                    return random(600, 900)
                }
            }
        }

        # Everything below only while we are NOT already fighting.
        if inCombat() {
            uiLabel("live", "In combat")
            return 600
        }

        # 1) Pick up a selected drop within range of the anchor, nearest first.
        for d in dropsByDistance(within: 15) {
            if contains(pickedItems, "[" + str(d.id) + "]") and distance(anchor, d.tile) <= range {
                uiLabel("live", "Looting " + d.name)
                interact(d, "Take")
                return random(600, 900)
            }
        }

        # 2) Bury bones (if chosen): any inventory item offering "Bury".
        if doBury {
            for b in inv() {
                if defHasCommand(itemDef(b.id), "Bury") {
                    uiLabel("live", "Burying bones")
                    interact(b, "Bury")
                    return random(300, 600)
                }
            }
        }

        # 3) Nothing else to do - attack the nearest selected npc in range.
        for n in npcsByDistance(within: 15) {
            if contains(pickedNpcs, "[" + str(n.id) + "]") and distance(anchor, n.tile) <= range {
                uiLabel("live", "Attacking " + n.name)
                interact(n, "Attack")
                return random(1200, 1800)
            }
        }

        uiLabel("live", "Idle - no target in range")
        return 800
    }

    return 600
}