chore: rewrite directory name & feat: add lol sulaunchhelper2.sh
This commit is contained in:
0
games/Arena_of_Valor/.gitkeep
Normal file
0
games/Arena_of_Valor/.gitkeep
Normal file
114
games/Arena_of_Valor/AWC_AutoSpin.js
Normal file
114
games/Arena_of_Valor/AWC_AutoSpin.js
Normal file
@ -0,0 +1,114 @@
|
||||
// Fetch jQuery
|
||||
await fetch("https://code.jquery.com/jquery-3.6.0.min.js").then(x => x.text()).then(y => eval(y))
|
||||
// Wait for jQuery to be loaded.
|
||||
{
|
||||
// From https://stackoverflow.com/a/53914092
|
||||
class ClassWatcher {
|
||||
|
||||
constructor(targetNode, classToWatch, classAddedCallback, classRemovedCallback) {
|
||||
this.targetNode = targetNode
|
||||
this.classToWatch = classToWatch
|
||||
this.classAddedCallback = classAddedCallback
|
||||
this.classRemovedCallback = classRemovedCallback
|
||||
this.observer = null
|
||||
this.lastClassState = targetNode.classList.contains(this.classToWatch)
|
||||
|
||||
this.init()
|
||||
}
|
||||
|
||||
init() {
|
||||
this.observer = new MutationObserver(this.mutationCallback)
|
||||
this.observe()
|
||||
}
|
||||
|
||||
observe() {
|
||||
this.observer.observe(this.targetNode, { attributes: true })
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.observer.disconnect()
|
||||
}
|
||||
|
||||
mutationCallback = mutationsList => {
|
||||
for(let mutation of mutationsList) {
|
||||
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
||||
let currentClassState = mutation.target.classList.contains(this.classToWatch)
|
||||
if(this.lastClassState !== currentClassState) {
|
||||
this.lastClassState = currentClassState
|
||||
if(currentClassState) {
|
||||
this.classAddedCallback()
|
||||
}
|
||||
else {
|
||||
this.classRemovedCallback()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var disableChest = false
|
||||
function clickFirstButtonByClassName(className) {
|
||||
let btn = document.getElementsByClassName(className)[0]
|
||||
if (!(typeof btn === "undefined")) {
|
||||
btn.dispatchEvent(new MouseEvent("click"));
|
||||
}
|
||||
}
|
||||
// Click the spin button
|
||||
function spin() {
|
||||
clickFirstButtonByClassName("wheel__main--note")
|
||||
if (!disableChest) {
|
||||
clickFirstButtonByClassName("chest")
|
||||
}
|
||||
}
|
||||
|
||||
function pickCard() {
|
||||
let teams = document.getElementsByClassName("popup-draw__card")
|
||||
for (let i = 0; i < 3; i++) {
|
||||
teams[i].dispatchEvent(new MouseEvent("click"));
|
||||
}
|
||||
setTimeout(() => jQuery(".ReactModal__Overlay").trigger("click"), 2000)
|
||||
}
|
||||
// Check for dialog message then close
|
||||
function closeSwalDialog() {
|
||||
clickFirstButtonByClassName("swal2-close")
|
||||
if (document.getElementsByClassName("swal2-close").length > 0) {
|
||||
setTimeout(closeSwalDialog, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function Swal2Dialog() {
|
||||
if (document.getElementsByClassName("popup-draw__card").length > 0) {
|
||||
pickCard()
|
||||
}
|
||||
else {
|
||||
let swal2msg = document.getElementsByClassName("popup-alert__message")
|
||||
if (swal2msg.length > 0) {
|
||||
console.log(swal2msg[0].innerHTML)
|
||||
if (swal2msg[0].innerHTML == "Đã đạt đến giới hạn Rương đếm ngược hàng ngày") {
|
||||
disableChest = true
|
||||
}
|
||||
else if (swal2msg[0].innerHTML == "Bạn đã hết lượt quay trong ngày") {
|
||||
closeAutoFarm()
|
||||
}
|
||||
}
|
||||
}
|
||||
closeSwalDialog()
|
||||
}
|
||||
|
||||
// Watch for SweetAlert 2
|
||||
let swal2Watcher = new ClassWatcher(document.body, 'swal2-shown', Swal2Dialog, spin);
|
||||
|
||||
function closeAutoFarm() {
|
||||
swal2Watcher.disconnect()
|
||||
}
|
||||
|
||||
spin()
|
||||
// Disable window change
|
||||
jQuery("window").off("mouseup")
|
||||
jQuery("document").off("visibilitychange")
|
||||
// Remove video player (so it isnt annoying to me and save CPU by a lot)
|
||||
Array.from(document.getElementsByTagName("iframe")).forEach((iframe) => {
|
||||
iframe.remove()
|
||||
})
|
||||
}
|
||||
4
games/Arena_of_Valor/README.md
Normal file
4
games/Arena_of_Valor/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Scripts for Arena of Valor
|
||||
Scripts I created for this game, thats it. (Not cheating scripts in-game tho)
|
||||
## Scripts
|
||||
+ [AWC_AutoSpin.sh](./AWC_AutoSpin.sh) - Auto spin the wheel in AWC website (Works in Vietnamese AOV only, other region need to tweak some string into their language)
|
||||
40
games/Cities_Skylines/NotParadoxLauncher_Win_Proton.sh
Normal file
40
games/Cities_Skylines/NotParadoxLauncher_Win_Proton.sh
Normal file
@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
NPL_WIN_DL='https://github.com/shusaura85/notparadoxlauncher/releases/download/v1.3.1/Windows.Not.Paradox.Launcher.v1.3.1.x64.zip'
|
||||
|
||||
echo "NotParadoxLauncher for Cities: Skylines (Windows version running in Proton)"
|
||||
echo "Type your Cities:Skylines location (default is $HOME/.local/share/Steam/steamapps/common/Cities_Skylines/):"
|
||||
read CS_LOCATION
|
||||
[ -z "$CS_LOCATION" ] && CS_LOCATION="$HOME/.local/share/Steam/steamapps/common/Cities_Skylines/"
|
||||
echo "Changing directory to Cities: Skylines..."
|
||||
cd "$CS_LOCATION"
|
||||
rm -rf NPX_WIN.zip
|
||||
rm -rf NotParadoxLauncher
|
||||
echo "Downloading NotParadoxLauncher (Windows version)..."
|
||||
wget -O NPX_WIN.zip "$NPL_WIN_DL"
|
||||
echo "Extracting NotParadoxLauncher..."
|
||||
mkdir -p ./NotParadoxLauncher
|
||||
unzip ./NPX_WIN.zip -d NotParadoxLauncher
|
||||
rm -rf NPX_WIN.zip
|
||||
echo "Detecting installed Proton..."
|
||||
PROTONS=()
|
||||
for steam_apps in ./../*/; do
|
||||
if [[ $steam_apps == *"Proton"* ]];then
|
||||
echo "Found Proton: $steam_apps"
|
||||
PROTONS+=("$steam_apps")
|
||||
fi
|
||||
done
|
||||
echo "Available Proton:"
|
||||
for idx in ${!PROTONS[@]}; do
|
||||
echo "[$idx]: ${PROTONS[idx]}"
|
||||
done
|
||||
echo "Select: "
|
||||
read PROTON_SEL_INT
|
||||
PROTON_SEL_slash=${PROTONS[PROTON_SEL_INT]}
|
||||
PROTON_SEL=${PROTON_SEL_slash%?}
|
||||
echo "Selected $PROTON_SEL, processing..."
|
||||
echo "Creating NotParadoxLauncher script..."
|
||||
PREFIXPATH=$(realpath "./../../compatdata/255710/pfx")
|
||||
echo "WINEPREFIX=\"$PREFIXPATH\" \"$PROTON_SEL/files/bin/wine\" ./NotParadoxLauncher/bootstrapper-v2.exe" > launcher.sh
|
||||
chmod +x launcher.sh
|
||||
echo "Done! You can launch NotParadoxLauncher by doing './launcher.sh' in Cities: Skylines dir."
|
||||
9
games/Cities_Skylines/README.md
Normal file
9
games/Cities_Skylines/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Scripts for [Cities: Skylines](https://www.citiesskylines.com/)
|
||||
Scripts I created for this game, thats it.
|
||||
|
||||
### Scripts
|
||||
+ [NotParadoxLauncher_Win_Proton.sh](./NotParadoxLauncher_Win_Proton.sh) - Install [Not Paradox Launcher] to Cities: Skylines (Windows version running in Linux using Proton)
|
||||
+ [Win_Proton_dowser_patch.sh](./Win_Proton_dowser_patch.sh) - Replace dowser.exe with Cities.exe so the game can launch without using bloated launcher (for CS Windows version running in Proton)
|
||||
|
||||
#### Note
|
||||
These script I created for my friend because I don't play this game, so if it has any problem then feel free to open a issue, thanks.
|
||||
33
games/Cities_Skylines/Win_Proton_dowser_patch.sh
Normal file
33
games/Cities_Skylines/Win_Proton_dowser_patch.sh
Normal file
@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Cities: Skylines no launcher patch (dowser.exe replacing method)"
|
||||
echo "Type your Cities:Skylines location (default is $HOME/.local/share/Steam/steamapps/common/Cities_Skylines/):"
|
||||
read CS_LOCATION
|
||||
[ -z "$CS_LOCATION" ] && CS_LOCATION="$HOME/.local/share/Steam/steamapps/common/Cities_Skylines/"
|
||||
echo "Changing directory..."
|
||||
cd "$CS_LOCATION"
|
||||
PROTON6=false
|
||||
for steam_apps in ./../*/; do
|
||||
if [[ $steam_apps == *"Proton 6"* || $steam_apps == *"Proton - Experimental"* ]]; then
|
||||
PROTON6=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ $PROTON6 == false ]]; then
|
||||
echo "Proton 6/Proton - Experimental not found!"
|
||||
echo "Make sure you installed Proton 6+ for the game to launch properly."
|
||||
echo "Proton 5 may work for Intel, but not for NVIDIA (it hang)"
|
||||
read -p "Do you want to proceed? [Y/n] " -n 1 -r
|
||||
echo
|
||||
if ! [[ $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "Patching dowser.exe --> Cities.exe"
|
||||
mv dowser.exe dowser.exe.bak
|
||||
ln -sf Cities.exe dowser.exe
|
||||
ln -sf Cities_Data dowser_Data
|
||||
echo "Done! You can now launch the game in Steam."
|
||||
xdg-open https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
||||
neofetch
|
||||
16
games/LoL/linux/README.md
Normal file
16
games/LoL/linux/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# leagueoflinux scripts
|
||||
## `sulaunchhelper2.sh`
|
||||
This script is a wrapper for `sulaunchhelper2.py` and `syscall_check.sh`, for use with Lutris pre-game launch script.
|
||||
+ To install you must have `sulaunchhelper2.py` and `syscall_check.sh` present, if not you can execute these to quickly download them (to current directory):
|
||||
```sh
|
||||
curl -OL sulaunchhelper2.py
|
||||
curl -OL syscall_check.sh
|
||||
chmod +x sulaunchhelper2.py syscall_check.sh
|
||||
```
|
||||
+ Then to download `sulaunchhelper2.sh` itself:
|
||||
```sh
|
||||
curl -OL sulaunchhelper2.sh
|
||||
chmod +x sulaunchhelper2.sh
|
||||
```
|
||||
+ After that, copy all these files to the game prefix you want to use, then set pre-launch script in Lutris to where `sulaunchhelper2.sh` is located.
|
||||
+ Enjoy your LoL experience :P
|
||||
199
games/LoL/linux/sulaunchhelper2.py
Normal file
199
games/LoL/linux/sulaunchhelper2.py
Normal file
@ -0,0 +1,199 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import frida
|
||||
import socket
|
||||
import ssl
|
||||
import psutil
|
||||
import time
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
"""
|
||||
requires psutil, frida (pip install psutil frida)
|
||||
|
||||
suLaunchhelper2 will try to lauch the League of Legends client by instrumenting frida (https://frida.re/)
|
||||
This version requires sudo or `sysctl kernel.yama.ptrace_scope=0`.
|
||||
It will launch frida directly from outside of wine.
|
||||
"""
|
||||
|
||||
WINEDUMP = 'winedump' # path to winedump, does not necessarily need to be the same version as wine
|
||||
|
||||
SELECT_SIGNATURE = "'long', ['long', 'pointer', 'pointer', 'pointer'], 'stdcall'" # return type, [arg types...], abi
|
||||
|
||||
sleep_time = 1
|
||||
timeout = 0 # 0 to disable
|
||||
|
||||
hide_backtrace = True
|
||||
|
||||
|
||||
class FridaWrapper():
|
||||
def __init__(self, process, module=None, export=None, position=None, signature=None):
|
||||
self.session = None
|
||||
self.process = process
|
||||
self.module = module
|
||||
self.export = export
|
||||
self.position = position
|
||||
self.signature = signature
|
||||
|
||||
def get_location(self):
|
||||
if self.module and self.export:
|
||||
return f"Process.getModuleByName('{self.module}').getExportByName('{self.export}')"
|
||||
if self.position and self.signature:
|
||||
return f"new NativeFunction(ptr({hex(self.position)}), {self.signature})"
|
||||
|
||||
def attach(self):
|
||||
if self.session: return
|
||||
self.session = frida.attach(self.process)
|
||||
|
||||
|
||||
script = self.session.create_script("""
|
||||
Interceptor.attach(
|
||||
""" + self.get_location() + """, {
|
||||
onEnter: function(args) {
|
||||
args[4].writeInt(0x0);
|
||||
}
|
||||
}
|
||||
);
|
||||
""")
|
||||
script.load()
|
||||
|
||||
def detach(self):
|
||||
if not self.session: return
|
||||
script = self.session.create_script("Interceptor.detachAll();")
|
||||
script.load()
|
||||
self.session.detach()
|
||||
self.session = None
|
||||
|
||||
def attached(self):
|
||||
return self.session is not None
|
||||
|
||||
class TimeoutException(Exception):
|
||||
pass
|
||||
|
||||
class Process:
|
||||
def __init__(self, name, internal=None):
|
||||
self.name = name
|
||||
self.internal = internal or name
|
||||
self.process = None
|
||||
|
||||
def find(self):
|
||||
if p := find_process_by_name(self.internal):
|
||||
self.process = p
|
||||
return True
|
||||
return False
|
||||
|
||||
def wait_for(self, tsleep=1, timeout=0):
|
||||
start = time.time()
|
||||
while not self.find():
|
||||
time.sleep(sleep_time)
|
||||
if timeout and time.time() - start > timeout:
|
||||
raise TimeoutException(f'Timeout while waiting for {self.name}')
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
class Symbol:
|
||||
def __init__(self, offset, position, name):
|
||||
self.offset = offset if type(offset) == int else int(offset, 16)
|
||||
self.position = int(position)
|
||||
self.name = name
|
||||
|
||||
def __repr__(self):
|
||||
return f'Symbol(offset={hex(self.offset)}, position={self.position}, name=\'{self.name}\')'
|
||||
|
||||
def check_ssl_connect(host, port, verify=True):
|
||||
ctx = ssl.create_default_context()
|
||||
if not verify:
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
try:
|
||||
with socket.create_connection((host, port)) as sock:
|
||||
with ctx.wrap_socket(sock) as ssock:
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def find_process_by_name(name):
|
||||
for p in psutil.process_iter(attrs=['pid', 'name']):
|
||||
if p.info['name'] == name:
|
||||
return p
|
||||
|
||||
def find_section(proc, name):
|
||||
for m in proc.memory_maps(grouped=False):
|
||||
if m.path.lower().endswith(name.lower()):
|
||||
return int(m.addr.split('-')[0], 16), m
|
||||
|
||||
def get_dll_exports(dll):
|
||||
exports = subprocess.run(['winedump', '-j', 'export', dll], stdout=subprocess.PIPE).stdout
|
||||
exports = str(exports, 'utf-8')
|
||||
exports = exports.split('\n')
|
||||
exports = exports[19:-3] # everything before this is just the pretext
|
||||
exports = [Symbol(sym[0], sym[1], sym[2]) for sym in [e.strip().split() for e in exports]]
|
||||
return exports
|
||||
|
||||
def find_dll_export(dll, export):
|
||||
exports = get_dll_exports(dll)
|
||||
for e in exports:
|
||||
if e.name == export:
|
||||
return e
|
||||
|
||||
if __name__ == '__main__':
|
||||
# hide backtrace
|
||||
if hide_backtrace:
|
||||
sys.tracebacklimit = None
|
||||
|
||||
rclient = Process('RiotClientServices.exe', 'RiotClientServi')
|
||||
lclient = Process('LeagueClient.exe')
|
||||
lclientux = Process('LeagueClientUx.exe')
|
||||
|
||||
# Wait for RiotClientServices.exe
|
||||
print(f'Waiting for {rclient}')
|
||||
rclient.wait_for(tsleep=sleep_time, timeout=timeout)
|
||||
print(f'Found {rclient}: pid {rclient.process.pid}')
|
||||
|
||||
base, module = find_section(rclient.process, 'ws2_32.dll')
|
||||
exp_select = find_dll_export(module.path, 'select')
|
||||
|
||||
# Wait for LeagueClient.exe
|
||||
print(f'Waiting for {lclient}')
|
||||
lclient.wait_for(tsleep=sleep_time, timeout=timeout)
|
||||
print(f'Found {lclient}: pid {lclient.process.pid}')
|
||||
|
||||
f = FridaWrapper(rclient.process.pid, position = base + exp_select.offset, signature = SELECT_SIGNATURE)
|
||||
|
||||
# Wait for LeagueClientUx.exe
|
||||
print(f'Waiting for {lclientux}')
|
||||
start = time.time()
|
||||
while not lclientux.find():
|
||||
if not f.attached():
|
||||
print('Attaching...')
|
||||
f.attach()
|
||||
time.sleep(sleep_time)
|
||||
if timeout and time.time() - start > timeout:
|
||||
f.detach()
|
||||
raise TimeoutException(f'Timeout while waiting for {lclientux}')
|
||||
print(f'Found {lclientux}: pid {lclientux.process.pid}')
|
||||
|
||||
# Find app-port
|
||||
port_xarg = next(x for x in lclientux.process.cmdline() if '--app-port=' in x)
|
||||
port = port_xarg.split('=')[1]
|
||||
|
||||
# Wait for SSL response on app-port
|
||||
print(f'Waiting for port {port}')
|
||||
start = time.time()
|
||||
while not check_ssl_connect('127.0.0.1', port, verify=False):
|
||||
if not f.attached():
|
||||
print('Attaching...')
|
||||
f.attach()
|
||||
time.sleep(sleep_time)
|
||||
if timeout and time.time() - start > timeout:
|
||||
f.detach()
|
||||
raise TimeoutException(f'Timeout while waiting for SSL response')
|
||||
|
||||
if f.attached():
|
||||
print('Detaching...')
|
||||
f.detach()
|
||||
else:
|
||||
print('Nothing to do')
|
||||
|
||||
print('Done')
|
||||
54
games/LoL/linux/sulaunchhelper2.sh
Executable file
54
games/LoL/linux/sulaunchhelper2.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# This script is a wrapper for sulaunchhelper2.py and somewhat based on syscall_check.sh for kernel.yama.ptrace_scope wrapper
|
||||
# Because this is for Lutris pre-launch script, you're required to have both sulaunchhelper2.py and syscall_check.sh
|
||||
# present in the game' wineprefix
|
||||
|
||||
SCC_SH='syscall_check.sh'
|
||||
SULH_PY='sulaunchhelper2.py'
|
||||
|
||||
dialog() {
|
||||
zenity "$@" --icon-name='lutris' --width="400" --title="League of Legends launch helper (root version)"
|
||||
}
|
||||
|
||||
own_dir="$(realpath .)"
|
||||
# try to call syscall_check.sh
|
||||
if ! [ -x "${own_dir}/${SCC_SH}" ]; then
|
||||
dialog "Please place this script into the same directory as '${SCC_SH}'!"
|
||||
else
|
||||
sh "${own_dir}/${SCC_SH}"
|
||||
fi
|
||||
|
||||
|
||||
if [ "$(cat /proc/sys/kernel/yama/ptrace_scope)" -ne 0 ]; then
|
||||
once="Change setting until next reboot"
|
||||
persist="Change setting and persist after reboot"
|
||||
manual="Show me the commands; I'll handle it myself"
|
||||
|
||||
if dialog --question --text="League of Legends' client UI launch much faster with some modification to your system. but as far as this script can detect, the setting has not been changed yet.\n\nWould you like to change the setting now?"
|
||||
then
|
||||
# I tried to embed the command in the dialog and run the output, but
|
||||
# parsing variables with embedded quotes is an excercise in frustration.
|
||||
RESULT=$(dialog --list --radiolist --height="200" \
|
||||
--column="" --column="Command" \
|
||||
"TRUE" "$once" \
|
||||
"FALSE" "$persist" \
|
||||
"FALSE" "$manual")
|
||||
|
||||
case "$RESULT" in
|
||||
"$once")
|
||||
pkexec sysctl -w kernel.yama.ptrace_scope=0
|
||||
;;
|
||||
"$persist")
|
||||
pkexec sh -c 'echo "kernel.yama.ptrace_scope=0" >> /etc/sysctl.conf && sysctl -p'
|
||||
;;
|
||||
"$manual")
|
||||
dialog --info --no-wrap --text="To change the setting (a kernel parameter) until next boot, run:\n\nsudo sh -c 'sysctl -w kernel.yama.ptrace_scope=0'\n\nTo persist the setting between reboots, run:\n\nsudo sh -c 'echo \"kernel.yama.ptrace_scope=0\" >> /etc/sysctl.conf && sysctl -p'\nChange the setting then press OK or script will NOT work."
|
||||
;;
|
||||
*)
|
||||
echo "Dialog canceled or unknown option selected: $RESULT"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
python3 "${own_dir}/${SULH_PY}"
|
||||
58
games/LoL/linux/syscall_check.sh
Executable file
58
games/LoL/linux/syscall_check.sh
Executable file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# If abi.vsyscall32=0 is already set, no need to do anything
|
||||
if [ "$(cat /proc/sys/abi/vsyscall32)" -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
dialog() {
|
||||
zenity "$@" --icon-name='lutris' --width="400" --title="League of Legends anticheat compatibility check"
|
||||
}
|
||||
|
||||
final_check() {
|
||||
if [ "$(cat /proc/sys/abi/vsyscall32)" -ne 0 ]; then
|
||||
dialog --warning --text="As far as this script can detect, your system is not configured to work with League's anticheat. Please verify that you can get into the practice too before playing a multiplayer game."
|
||||
fi
|
||||
}
|
||||
|
||||
trap final_check EXIT
|
||||
|
||||
if grep -E -x -q "abi.vsyscall32( )?=( )?0" /etc/sysctl.conf; then
|
||||
if dialog --question --text="It looks like you already configured your system to work with League anticheat, and saved the setting to persist across reboots. However, for some reason the persistence part did not work.\n\nFor now, would you like to enable the setting again until the next reboot?"
|
||||
then
|
||||
pkexec sh -c 'sysctl -w abi.vsyscall32=0'
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
once="Change setting until next reboot"
|
||||
persist="Change setting and persist after reboot"
|
||||
manual="Show me the commands; I'll handle it myself"
|
||||
|
||||
if dialog --question --text="League of Legends' anticheat requires using a modified version of wine and changing a system setting. Otherwise, the game will crash after champion select. Wine-lol comes with the Lutris installer, but as far as this script can detect, the setting has not been changed yet.\nNote: The setting (abi.vsyscall32=0) may reduce the performance of some 32 bit applications.\n\nWould you like to change the setting now?"
|
||||
then
|
||||
# I tried to embed the command in the dialog and run the output, but
|
||||
# parsing variables with embedded quotes is an excercise in frustration.
|
||||
RESULT=$(dialog --list --radiolist --height="200" \
|
||||
--column="" --column="Command" \
|
||||
"TRUE" "$once" \
|
||||
"FALSE" "$persist" \
|
||||
"FALSE" "$manual")
|
||||
|
||||
case "$RESULT" in
|
||||
"$once")
|
||||
pkexec sh -c 'sysctl -w abi.vsyscall32=0'
|
||||
;;
|
||||
"$persist")
|
||||
pkexec sh -c 'echo "abi.vsyscall32 = 0" >> /etc/sysctl.conf && sysctl -p'
|
||||
;;
|
||||
"$manual")
|
||||
dialog --info --no-wrap --text="To change the setting (a kernel parameter) until next boot, run:\n\nsudo sh -c 'sysctl -w abi.vsyscall32=0'\n\nTo persist the setting between reboots, run:\n\nsudo sh -c 'echo \"abi.vsyscall32 = 0\" >> /etc/sysctl.conf && sysctl -p'"
|
||||
# Anyone who wants to do it manually doesn't need another warning
|
||||
trap - EXIT
|
||||
;;
|
||||
*)
|
||||
echo "Dialog canceled or unknown option selected: $RESULT"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
Reference in New Issue
Block a user