Skip to content

Instantly share code, notes, and snippets.

@exsilium
Last active July 21, 2026 08:39
Show Gist options
  • Select an option

  • Save exsilium/cd2ef4cbe61024c16e3fb56e33a4854c to your computer and use it in GitHub Desktop.

Select an option

Save exsilium/cd2ef4cbe61024c16e3fb56e33a4854c to your computer and use it in GitHub Desktop.
Automated Rune Farming in Elden Ring

Elden Ring - Boulder Chase Farming 🪨 🧺

Indiana Jones and the Raiders of the Lost Ark, a 1981 movie, included an iconic Boulder Chase scene, where the main protagoonist "Indiana" narrowly escapes a massive rolling rock. An echo to a similar scene is built into FromSoftware's 2022 blockbuster video game, Elden Ring.

Located northeast of Greyoll’s Dragonbarrow, at a place known as Lenne’s Rise—a suitably elevated terrain—the game introduces a similar challenge. As players descend from this location, a huge boulder mysteriously spawns and rolls down after the hero. Defying typical physics as one might expect in a fantasy setting, the boulder specifically targets the player in a heart-pounding pursuit. If the player is able to quickly dodge this lethal trap, the boulder crashes down a cliff and shatters, rewarding the player with +1952 runes for their quick reflexes.

If you are just starting your adventure in Elden Ring, this is one of the easiest ways to quickly acquire Runes to level up.

This GPC is a personilised macro implementation to automate the farming cycle. A GPC is a C-based language implemented and executed within Cronus Zen universal adapter by Collective Minds. This macro has been developed and tested by using PS5 version of Elden Ring.

Setup requirements

  1. Cronus Zen device to execute the GPC;
  2. Elden Ring must be set to prioritize frame rate / performance within the game's system settings. This adjustment is crucial as settings focused on high quality can alter the handling of input timings due to varying frame rates, which may fluctuate depending on the game’s weather conditions;
  3. Upper quick slot should be set to empty;
  4. Spirit horse, Torrent, summoning must be mapped to Triangle + UP shortcut;

Gameplay requirements

  1. You need to have progressed the game to the point where you have gained access to your spirit horse, Torrent;
  2. You need to ride and unlock the Lenne's Rise Site of Grace. An excellent Youtube guide can be found here that covers the location and the farming aspect: https://www.youtube.com/watch?v=xDR4kWFIfPU ;

How to run

The macro must be started when fast traveled to the Lenne's Rise, without prior camera or character movement. The macro can be started and stopped pressing the UP directional button.

Statistics

Farming rate: ~240 000 runes / hour. ✨

Click the below image to see a run in action. 👇
Sample Farming Run

// Elden Ring - Boulder Chase Farming Script at Lenne's Rise for PS5/PC
// Version: 1.1.0, Created for Cronus Zen
// Copyright (c) 2026, Sten Feldman
// License SPDX identifier: BSD-2-Clause
/*
███████╗██╗ ██████╗ ███████╗███╗ ██╗ ██████╗ ██╗███╗ ██╗ ██████╗
██╔════╝██║ ██╔══██╗██╔════╝████╗ ██║ ██╔══██╗██║████╗ ██║██╔════╝
█████╗ ██║ ██║ ██║█████╗ ██╔██╗ ██║ ██████╔╝██║██╔██╗ ██║██║ ███╗
██╔══╝ ██║ ██║ ██║██╔══╝ ██║╚██╗██║ ██╔══██╗██║██║╚██╗██║██║ ██║
███████╗███████╗██████╔╝███████╗██║ ╚████║ ██║ ██║██║██║ ╚████║╚██████╔╝
╚══════╝╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝
___ _ _ ___ _ ___ _
| _ ) ___ _ _| |__| |___ _ _ / __| |_ __ _ ___ ___ | __|_ _ _ _ _ __ (_)_ _ __ _
| _ \/ _ \ || | / _` / -_) '_| | (__| ' \/ _` (_-</ -_) | _/ _` | '_| ' \| | ' \/ _` |
|___/\___/\_,_|_\__,_\___|_| \___|_||_\__,_/__/\___| |_|\__,_|_| |_|_|_|_|_||_\__, |
|___/
Prerequisites:
- Tested on PS5, you need to be running Elden Ring in Performance Mode prioritising frame-rate;
- You need to have reached the Lenne's Rise Site of Grace;
- Keep the upper equipment slot empty;
- Map your Spirit Horse Torrent summoning to TRIANGLE + UP;
- Freshly teleport to Lenne's Rise Site of Grace, do not move the camera;
- Press UP crosshair once to start farming, press it again to stop;
Changelog:
- v1.1.0: Restructuring, OLED screen status, experimental Death Detection;
Adjust timings and button mappings as needed
*/
define TORRENT_TIME = 2040; // Time it takes to wait for Torrent before starting to turn
define TURN_TIME = 1475; // Time it takes to turn with Torrent to the correct path
define RUN_HALF_TIME = 5240; // Time to reach half-way for course correction
define RUN_END_TIME = 5040; // Time to reach the ball spawn point
define DODGE_TIME = 300; // Time to delay the ball dodge
define BALL_DROP_TIME = 3800; // Time to wait until the ball drops
define RESET_TIME = 7000; // Time to load the Site of Grace to begin a new run
define RUMBLE_MIN = 100; // Minimum rumble level to detect Death
define AUTORUN = FALSE; // Auto-start the script on selection
const string OLED_Strings[] = {
"Elden Ring:Boulder",
"RA:",
"RB:",
"Run State:",
"On ", // The extra space is to completely overwrite Off string
"Off",
"--Death Detected--",
" "
}
int on, reset, rumbleA, rumbleB;
int runPrint = 0;
int presumeDead = 0;
init {
cls_oled(OLED_BLACK);
print(0, 0, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[0]);
print(0, 20, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[1]);
print(0, 30, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[2]);
print(0, 50, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[3]);
if(AUTORUN) {
on = 1;
}
}
main {
runPrint += get_rtime();
if (event_press(PS5_UP)) {
if(presumeDead) {
print(0, 40, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[7]);
presumeDead = 0;
reset = 1;
}
on = !on; // Toggle the on/not on variable
}
rumbleA = get_rumble(RUMBLE_A);
rumbleB = get_rumble(RUMBLE_B);
if(rumbleA >= RUMBLE_MIN || rumbleB >= RUMBLE_MIN) {
presumeDead = 1;
}
if(runPrint >= 200) {
if(on) {
print(70, 50, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[4]);
if(rumbleA == 0) {
print(70, 20, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[5]);
}
else {
print(70, 20, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[4]);
}
if(rumbleB == 0) {
print(70, 30, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[5]);
}
else {
print(70, 30, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[4]);
}
if(rumbleA >= RUMBLE_MIN || rumbleB >= RUMBLE_MIN || presumeDead) {
// We dead?
print(0, 40, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[6]);
on = !on;
}
}
else {
print(70, 50, OLED_FONT_SMALL, OLED_WHITE, OLED_Strings[5]);
}
runPrint = 0;
}
if(reset) {
combo_run(reset_sequence);
}
if(on && !reset) {
combo_run(main_sequence);
}
else {
combo_stop(main_sequence);
}
}
// Combo to execute the chain of events
combo main_sequence {
set_val(PS5_TRIANGLE, 100);
set_val(PS5_UP, 100);
wait(TORRENT_TIME);
set_val(PS5_LX, 100);
set_val(PS5_CIRCLE, 100);
wait(TURN_TIME);
set_val(PS5_LY, -100);
set_val(PS5_CIRCLE, 100);
wait(RUN_HALF_TIME);
// Half-way point, make a small correction to the left
set_val(PS5_LX, -40);
set_val(PS5_LY, -100);
set_val(PS5_CIRCLE, 100);
wait(200)
// Run until the spawning point
set_val(PS5_LY, -100);
set_val(PS5_CIRCLE, 100);
wait(RUN_END_TIME);
set_val(PS5_LX, 100);
wait(500);
// Wait for the ball and dodge
wait(DODGE_TIME);
set_val(PS5_LX, 100);
wait(500);
set_val(PS5_CIRCLE, 100);
wait(200);
set_val(PS5_CIRCLE, 0);
wait(200)
set_val(PS5_CIRCLE, 100);
wait(200);
set_val(PS5_CIRCLE, 0);
wait(200);
set_val(PS5_CIRCLE, 100);
wait(200);
set_val(PS5_CIRCLE, 0);
wait(200);
set_val(PS5_CIRCLE, 100);
wait(200);
set_val(PS5_CIRCLE, 0);
wait(200);
set_val(PS5_CIRCLE, 100);
wait(200);
// Acquire materials?
set_val(PS5_TRIANGLE, 100);
wait(200);
// Wait for reward
wait(BALL_DROP_TIME);
// Reset
reset = 1;
}
combo reset_sequence {
set_val(PS5_TOUCH, 100);
wait(100);
set_val(PS5_TOUCH, 0);
wait(500);
set_val(PS5_TRIANGLE, 100);
wait(100);
set_val(PS5_TRIANGLE, 0);
wait(100);
set_val(PS5_CROSS, 100);
wait(100);
set_val(PS5_CROSS, 0);
wait(300);
set_val(PS5_CROSS, 100);
wait(100);
set_val(PS5_CROSS, 0);
wait(RESET_TIME);
reset = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment