All scripts

Coal Miner Mining guild

by SolemnVanguard ·Mining

Coal Miner Mining guild

0

Installed

1.0

Version

21 Aug 2026

Updated

About this script

Coal Miner Mining guild with banking, sleeping and mod protection. Only mines coal, not addy and mith.

Builds

VersionKindPublishedSizeWhat changed
1.0 current text script 21 Aug 2026 7 KB First upload.

Source of 1.0

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

script "Coal Miner Guild"
author "SolemnVanguard"
version "1.0"
every 600

# Mines Coal rock (id 110 or 111) in the guild mine. When the inventory
# is full, walks the path across Ladder (id 198 up / id 223 down) between
# tile(275, 3397) (mine side) and tile(281, 570) (bank side), finds a
# Bank Chest within 20 tiles, deposits all Coal (id 155), Uncut Sapphire
# (id 160), Uncut Emerald (id 159), and ids 154, 153, 157, then walks
# back down and resumes mining. Uses Sleeping Bag (id 1263) at 100%
# fatigue.
#
# Fatigue failsafe: if fatigue jumps more than 25 points in a single
# pass, that is treated as suspicious (e.g. a mod forcing it up to test
# you) and the script halts (shows an orange warning) instead of using
# the Sleeping Bag as if it were normal. No teleport protection.
#
# Mining does not use the batch system, so batchActive() never fires for
# it. Instead, a swing is tracked as "in progress" until the server's own
# chat message reports its outcome (success or a scratch/miss), and only
# then does the script click again - this stops it from spamming clicks
# on the same rock mid-swing, and reacts to a rock depleting almost
# instantly since the very next pass re-evaluates which rock to click.

var miningActive = false
var lastAttemptedTile = tile(0, 0)
var emptyRockTile = tile(0, 0)
var emptyRockUntil = 0

var prevFatigueVal = -1
var haltedFatigueJump = false
var FatigueJumpLimit = 25

fun fatigueSuspiciousCheck() {
    let curFatigue = fatigue()
    if prevFatigueVal >= 0 {
        let jump = curFatigue - prevFatigueVal
        if jump > FatigueJumpLimit {
            print("Fatigue spike detected:", prevFatigueVal, "->", curFatigue, "- halting")
            haltedFatigueJump = true
        }
    }
    prevFatigueVal = curFatigue
}

on message(line, from) {
    if contains(line, "You only succeed in scratching the rock") {
        miningActive = false
    }
    if contains(line, "You manage to obtain some coal") {
        miningActive = false
    }
    if contains(line, "You just found a ruby") {
        miningActive = false
    }
    if contains(line, "You just found a emerald") {
        miningActive = false
    }
    if contains(line, "You just found a sapphire") {
        miningActive = false
    }
    if contains(line, "You just found a diamond") {
        miningActive = false
    }
    if contains(line, "There is currently no ore available in this rock") {
        miningActive = false
        emptyRockTile = lastAttemptedTile
        emptyRockUntil = nowMillis() + 15000   # avoid it for ~15s, then retry
    }
}

on start {
    if not bankAvailable() {
        print("Bank not available")
    }
    if not minimapAvailable() {
        print("Warning: minimap hooks not ready yet - walkPath may misbehave")
    }

    pathStart("guild", "mine", tile(275, 3397))
    pathObject("guild", "Ladder", "Climb-up", "Climb-down", within: 10)
    pathFinish("guild", "bank", tile(281, 570))
}

state mining {
    fatigueSuspiciousCheck()
    if haltedFatigueJump { return 999999 }

    if isSleeping() {
        print("Sleeping, fatigue left to sleep off:", sleepFatigue())
        return 2000
    }
    if fatigue() >= 100 {
        print("Fatigue is 100 - using Sleeping Bag")
        let bag = invItem(1263)
        if bag != none {
            interact(bag, "Sleep")
        }
        return random(600, 900)
    }

    if invIsFull() { become goingToBank }

    if miningActive { return 300 }   # swing still resolving - don't reclick

    let skipEmpty = nowMillis() < emptyRockUntil

    for rock in objectsByDistance(within: 15) {
        if rock.id == 110 or rock.id == 111 {
            if skipEmpty and rock.tile == emptyRockTile {
                continue
            }
            if reach(rock) == "DRAWN" {
                lastAttemptedTile = rock.tile
                if interact(rock, "Mine") {
                    miningActive = true
                }
            }
            return random(300, 600)
        }
    }

    print("No coal rock found nearby - waiting")
    return 1000
}

state goingToBank {
    fatigueSuspiciousCheck()
    if haltedFatigueJump { return 999999 }

    if isSleeping() {
        print("Sleeping, fatigue left to sleep off:", sleepFatigue())
        return 2000
    }
    if fatigue() >= 100 {
        print("Fatigue is 100 - using Sleeping Bag")
        let bag = invItem(1263)
        if bag != none {
            interact(bag, "Sleep")
        }
        return random(600, 900)
    }

    let how = walkPath("guild", "bank")
    print("walkPath to bank =", how)

    if how == "ARRIVED" {
        become banking
    } else if how == "WALKING" {
        return 900
    } else if how == "CROSSING" {
        return 1500
    } else if how == "STUCK" or how == "BLOCKED" {
        print("Stuck going to bank - resetting path")
        pathReset("guild")
        return 1200
    } else {
        print("goingToBank status:", how)
        return 1000
    }
}

state banking {
    fatigueSuspiciousCheck()
    if haltedFatigueJump { return 999999 }

    if isSleeping() {
        print("Sleeping, fatigue left to sleep off:", sleepFatigue())
        return 2000
    }
    if fatigue() >= 100 {
        if bankIsOpen() {
            bankClose()
            return 600
        }
        print("Fatigue is 100 - using Sleeping Bag")
        let bag = invItem(1263)
        if bag != none {
            interact(bag, "Sleep")
        }
        return random(600, 900)
    }

    let chest = nearestObject(id: 942, within: 20)
    if chest == none {
        print("No Bank Chest (942) found within 20 tiles")
        return 1000
    }

    if not bankIsOpen() {
        if reach(chest) == "DRAWN" {
            interact(chest, "open")
            wait until bankIsOpen() timeout 2000 else { return 300 }
        }
        return 1000
    }

    bankDepositAll(155)
    bankDepositAll(160)
    bankDepositAll(159)
    bankDepositAll(154)
    bankDepositAll(153)
    bankDepositAll(157)
    bankClose()
    become goingToMine
}

state goingToMine {
    fatigueSuspiciousCheck()
    if haltedFatigueJump { return 999999 }

    if isSleeping() {
        print("Sleeping, fatigue left to sleep off:", sleepFatigue())
        return 2000
    }
    if fatigue() >= 100 {
        print("Fatigue is 100 - using Sleeping Bag")
        let bag = invItem(1263)
        if bag != none {
            interact(bag, "Sleep")
        }
        return random(600, 900)
    }

    let how = walkPath("guild", "mine")
    print("walkPath to mine =", how)

    if how == "ARRIVED" {
        miningActive = false
        become mining
    } else if how == "WALKING" {
        return 900
    } else if how == "CROSSING" {
        return 1500
    } else if how == "STUCK" or how == "BLOCKED" {
        print("Stuck going to mine - resetting path")
        pathReset("guild")
        return 1200
    } else {
        print("goingToMine status:", how)
        return 1000
    }
}

on render {
    if haltedFatigueJump {
        let flashOn = wrap(nowMillis(), 0, 999) < 500
        let bg = "#cc6600ee"
        if not flashOn { bg = "#663300ee" }
        paintRoundFill(4, 300, 220, 60, 12, bg)
        paintTextCenteredSized(114, 322, "FATIGUE SPIKE", "white", 16)
        paintTextCenteredSized(114, 344, "SCRIPT STOPPED", "white", 12)
    }
}