|
// 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; |
|
} |