RW hats geschafft die Action.bsd zu töten.
Wenn ein Item in nem Aktionsleistenslot war und danach ein skill hingelegt wird, wird der skill danach dauerhaft rot angezeigt.
in der zip ist ne exe. die einfach in den Runes of Magic Savevariables Ordner (Dokumente/Runes of Magic) legen und ausführen.
Vor dem ausführen der EXE müssen die chars ausgeloggt werden!
C++ Quellcode ist im spoiler wer das selbst kompilieren will (C++17 oder neuer). Wer python installiert hat kann auch das script verwenden.
Commandline arguments für die exe:
- --nobackup -> kein backup der action.bsd erstellen
- --force -> 2. mal überschreiben (alternative action.backup.bsd im charakterordner löschen)
Edit: Ein backup des Savevariable Ordners ist natürlich auch zu empfehlen
Edit2: Das ist nur ein temprorärer fix, sobald man wieder nen item in nen slot legt und danach nen skill ists logischerweise wieder kaputt
same in english:
RW managed to destroy the Action.bsd.
if an item is moved into a actionbar slot and you then move a skill into the same slot, they skill will be permanently red.
in the attached zip file is an executable. copy/move that one into the Runes of Magic Savevariables directory(Documents/Runes of Magic) and execute it.
Logout all characters before you do that!.
C++ sourcecode is attached in the spoiler below. you need a compiler for c++17 or newer if you want to compile it yourself. if you have python installed the script works as well,
Command line arguments for the exe:
- --nobackup -> don't create a backup of the action.bsd
- --force -> run the script a second time (you can also just delete the action.backup.bsd in the character directory)
edit: Create a backup of your Savevariables directory before you use it
edit2: this fix works only temporarily. if you move an item into a slot and then a skill in the same slot it will be broken again.
- #include <iostream>
- #include <filesystem>
- #include <fstream>
- #include <chrono>
- struct Header {
- std::uint32_t version;
- std::uint32_t size;
- std::uint32_t classNum;
- std::uint32_t itemNum;
- };
- struct Entry {
- std::uint32_t type;
- std::uint32_t id;
- std::uint32_t data[3];
- };
- namespace fs = std::filesystem;
- void fix(bool force, bool nobackup) {
- auto start = std::chrono::high_resolution_clock::now();
- auto count = 0;
- for (const auto& entry : fs::directory_iterator(".")) {
- if (!entry.is_directory()) { continue; }
- const auto& path = entry.path();
- auto action = path / "Action.bsd";
- if (!fs::is_regular_file(action)) {
- std::cout << "Action.bsd not found! " << entry << "\n";
- continue;
- }
- auto backup = path / "Action.backup.bsd";
- if (!force && fs::is_regular_file(backup)) {
- std::cout << "Backup exists! " << entry << "\n";
- continue;
- }
- if (!nobackup) {
- std::cout << "Creating Backup! " << backup << "\n";
- fs::copy(action, backup, fs::copy_options::overwrite_existing);
- }
- auto tmp = path / "Action.tmp.bsd";
- std::ifstream infile(action, std::ios::binary);
- std::ofstream outfile(tmp, std::ios::binary);
- Header actionHeader{};
- infile.read(reinterpret_cast<char*>(&actionHeader), sizeof(actionHeader));
- outfile.write(reinterpret_cast <char*>(&actionHeader), sizeof(actionHeader));
- for (auto i = 0; i < actionHeader.classNum * actionHeader.itemNum; ++i) {
- Entry actionEntry{};
- infile.read(reinterpret_cast<char*>(&actionEntry), sizeof(actionEntry));
- if (actionEntry.type == 3 || actionEntry.type == 7 || actionEntry.type == 8) {
- memset(&actionEntry.data, 0, sizeof(actionEntry.data));
- }
- outfile.write(reinterpret_cast <char*>(&actionEntry), sizeof(actionEntry));
- }
- infile.close();
- outfile.close();
- fs::copy(tmp, action, fs::copy_options::overwrite_existing);
- fs::remove(tmp);
- std::cout << "Succesfully fixed! " << entry << "\n";
- ++count;
- }
- auto end = std::chrono::high_resolution_clock::now();
- auto duration = static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()) / 1000;
- std::cout << "Duration: " << duration << "s\n";
- std::cout << "Fixed " << count << " files!\n";
- }
- int main(int argc, char** argv)
- {
- bool force = false;
- bool nobackup = false;
- for (auto i = 1; i < argc; ++i) {
- if (_stricmp(argv[i], "--force") == 0) force = true;
- if (_stricmp(argv[i], "--nobackup") == 0) nobackup = true;
- }
- try {
- fix(force, nobackup);
- }
- catch (const fs::filesystem_error& e) {
- std::cout << e.what() << "\n";
- }
- catch (const std::exception& e) {
- std::cout << e.what() << "\n";
- }
- system("pause");
- }
Display More
- import struct, os
- def doSingle(path="."):
- action = os.path.join(path, "Action.bsd")
- backup = os.path.join(path, "Action.backup.bsd")
- if not os.path.exists(action):
- print(f"No Action.bsd found {action}")
- return
- if os.path.exists(backup):
- print(f"Action.backup.bsd found...ignoring {backup}")
- return
- data = None
- with open(action, "rb") as f:
- data = f.read()
- with open(backup, "wb") as f:
- f.write(data)
- with open(action, "wb") as f:
- f.write(data[0:16])
- for i in range(int((len(data)-16)/20)):
- (t, id, v1, v2, v3) = struct.unpack_from('<iiiii', data, i*20+16)
- if t in (3,7,8):
- v1 = 0
- v2 = 0
- v3 = 0
- f.write(struct.pack("<iiiii", t,id,v1,v2,v3))
- print(f"fixed {action}")
- def doAll():
- dirs = os.listdir()
- for dir in dirs:
- if os.path.isdir(dir):
- doSingle(dir)
- doAll()
Display More