Code: Select all
--[[ MACRO FORMAT:
(8 byte head)
(4 byte size of MACRO DATA [currently 1288])(4 byte NUM OF MACROS)
(1288 byte MACRO DATA)
LOOP:
(4 byte INDEX[0-55])(4byte ICON)
(256 byte UNKNOWN)
(256 byte MACRO TEXT)
(768 byte PADDING?)
ENDLOOP
--]]
local MACRO_SIZE = 1288;
local MACRO_COUNT = 56;
local MACRO_UNKNOWNSIZE = 0x100;
local MACRO_TEXTSIZE = 0x100; -- Size including NULL terminator
local MACRO_PADDINGSIZE = 0x300;
local MACRO_ICONMAX = 60;
local MACRO_NULLICON = 0XFFFFFFFF;
local userprofilePath = os.getenv("USERPROFILE");
local documentPaths = {
userprofilePath .. "\\My Documents\\" .. "Runes of Magic", -- English
userprofilePath .. "\\Eigene Dateien\\" .. "Runes of Magic", -- German
userprofilePath .. "\\Mes Documents\\" .. "Runes of Magic", -- French
userprofilePath .. "\\Omat tiedostot\\" .. "Runes of Magic", -- Finish
userprofilePath .. "\\Belgelerim\\" .. "Runes of Magic", -- Turkish
userprofilePath .. "\\Mina Dokument\\" .. "Runes of Magic", -- Swedish
userprofilePath .. "\\Dokumenter\\" .. "Runes of Magic", -- Danish
userprofilePath .. "\\Documenti\\" .. "Runes of Magic", -- Italian
userprofilePath .. "\\Mijn documenten\\" .. "Runes of Magic", -- Dutch
userprofilePath .. "\\Moje dokumenty\\" .. "Runes of Magic", -- Polish
userprofilePath .. "\\Mis documentos\\" .. "Runes of Magic", -- Spanish
};
-- Select the first path that exists
function findMacroBsd(charName)
for i,v in pairs(documentPaths) do
if( string.sub(v, -1 ) ~= "\\" and string.sub(v, -1 ) ~= "/" ) then
v = v .. "\\"; -- Append the trailing backslash if necessary.
end
local filename = v .. charName .. "/Macro.bsd";
if( fileExists(filename) ) then
return filename;
end
end
return nil;
end
-- Convert a Lua number to 4 bytes
function intToBytes(int)
--int = tonumber( string.format("%u", int), 10);
local a,b,c,d = math.mod(int, 256),
math.mod(int, 65536) / 256,
math.mod(int, 16777216) / 65536,
int / 16777216;
-- Some weird Lua bug with unsigned ints...
-- It pretends it's positive, but will cause
-- errors for being negitive in some functions (ie. string.char)
-- This is a hackish work-around.
if( a < 0 ) then a = math.max(a, 0); end;
if( a > 255 ) then a = math.min(a, 255); end;
if( b < 0 ) then b = math.max(b, 0); end;
if( b > 255 ) then b = math.min(b, 255); end;
if( c < 0 ) then c = math.max(c, 0); end;
if( c > 255 ) then c = math.min(c, 255); end;
if( d < 0 ) then d = math.max(d, 0); end;
if( d > 255 ) then d = math.min(d, 255); end;
return string.char(a, b, c, d);
end
function bytesToInt(a, b, c, d)
return tonumber( string.format("%02x%02x%02x%02x", d, c, b, a), 16);
end
local macroData;
function initializeMacroData()
macroData = {};
for i = 1,MACRO_COUNT do
macroData[i - 1] = {
["icon"] = intToBytes(MACRO_NULLICON);
["unknown"] = string.rep( string.char(0x0), MACRO_UNKNOWNSIZE );
["text"] = string.rep( string.char(0x0), MACRO_TEXTSIZE );
["padding"] = string.rep( string.char(0x0), MACRO_PADDINGSIZE );
};
end
end
function readMacroData(fname)
local infile = io.open(fname, "rb");
-- Read (but discard) the header; assume our own values
--MACRO_SIZE = bytesToInt(string.byte(infile:read(4), 1, 4));
infile:read(4); infile:read(4);
for i = 1,MACRO_COUNT do
local index = i - 1;
local icon, unknown, text, padding;
-- Read (and discard) index
infile:read(4);
-- Read icon
icon = bytesToInt(string.byte(infile:read(4), 1, 4));
-- Force it to a valid value
if( icon ~= MACRO_NULLICON ) then
icon = math.min(icon, MACRO_ICONMAX);
icon = math.max(icon, 0);
end
-- Read (and discard) UNKNOWN data
infile:read(MACRO_UNKNOWNSIZE);
unknown = string.rep(string.char(0x0), MACRO_UNKNOWNSIZE);
-- Read macro text
text = infile:read(MACRO_TEXTSIZE);
-- Force a NULL terminator
text = string.sub(text, 1, text:len()-1) .. string.char(0x0);
-- Read (and discard) padding
infile:read(MACRO_PADDINGSIZE);
padding = string.rep(string.char(0x0), MACRO_PADDINGSIZE);
macroData[index].icon = icon;
macroData[index].unknown = unknown;
macroData[index].text = text;
macroData[index].padding = padding;
end
infile:close();
end
function writeMacroData(fname)
local outfile = io.open(fname, "wb");
-- Write the header
outfile:write( intToBytes(MACRO_SIZE) );
outfile:write( intToBytes(MACRO_COUNT) );
-- Write each macro
for i = 1,MACRO_COUNT do
local index = i - 1;
outfile:write( intToBytes(i - 1) ); -- Write index
outfile:write( intToBytes(macroData[index].icon) );
outfile:write( macroData[index].unknown );
outfile:write( macroData[index].text );
outfile:write( macroData[index].padding );
end
outfile:close();
end
-- Prompt for character name
local charName, fname;
cprintf(cli.red, "MAKE SURE YOU ARE LOGGED OFF BEFORE RUNNING THIS SCRIPT!\n");
printf("Please input the character's name.\n>");
charName = string.gsub(io.read("*l"), "([%w%s%p]+)\n", "%0");
printf("Char name: \'%s\'\n", charName);
fname = findMacroBsd(charName);
if( fname == nil ) then
printf("We were unable to find your Macro.bsd file.\n" ..
"Try manually deleting Macro.bsd from My Documents/CharacterName/Macro.bsd");
else
initializeMacroData();
readMacroData(fname);
writeMacroData("Macro.bsd");
printf("Macro.bsd file rewritten. You can log in now.\n");
end