--[====================================================================================================================[ I2 Cheat Engine Teleporter Version: 1.0.9 1.0.1: * Initial setup. 1.0.2: * Fixed saves memory record creation error. * Fixed memory record append on existing memory records. * Added "delete" and "rename" functions. 1.0.3: * Added Teleport Back Feature. Back values are saved in "writeToCoords". * Added optional camera rotation angle (Pitch, Yaw). Not used; if "ptrI2CETeleporterCamRotationAngle" is "nil" or 0 (zero), Not used; if "Pitch" and "Yaw" are not found in save, * Fixed default line end, changed to '\n'. 1.0.4: * Added optional player rotation angle (set from camera rotation angle). Not used; if "ptrI2CETeleporterPlayerRotationAngle" is "nil" or 0 (zero). Not used; if "ptrI2CETeleporterCamRotationAngle" is "nil" or 0 (zero), Not used; if "Pitch" and "Yaw" are not found in save, * Added "Debug" section to main memory records. * Added "WarnForNoSavesTableFile" setting. * Added "FlagPointerSymbol" to work with injected writes for the teleporter. 1.0.5: * First release. 1.0.6: * Fixed Auto Load to check for an attached process. 1.0.7: * Fixed bug in delete save function, where save name was being cleared on the request (first call). 1.0.8: * Fixed save name and new save name memory not getting allocated if auto allocate was false. 1.0.9: * Fixed error with "getAddress" needing to be "getAddressSafe". Author: Matt - TheyCallMeTim13 - MattI2.com Features: - Set an auto allocated pointer "ptrI2CETeleporterCoord" (user symbol), or "CoordPointerSymbol" (setting) can be set to a string used to get the address. - A timer is used for writing to coordinates and rotation angle, just writes multiple times for a second. - Writes to coordinates using a saved file with names for lookup. - Optionally writes to camera pitch and yaw, and player yaw. Note: Only camera pitch and yaw, is read and saved. - When writing to the coordinates a flag is set "flgI2CETeleporter" (user symbol), or "FlagPointerSymbol" (setting) can be set to a byte flag address/symbol string. This allows for injection based teleport writes, just set "CoordPointerSymbol" to allocated memory (i.e.: X @+0, Y @+4, Z @+8) to read from after byte flag is set to 1. - Same for camera rotation angle, but byte flag is offset by +1. - Includes a function ("generateMemoryRecords") to generate "Teleport to: ??" scripts, that are added to a "Saves" grouped section (memory record). Note: Memory records are looked up using the description, so duplicates aren't made, but if the description is changed then a new one will be generated. - I got these, Cheese Buggers Man! - Includes a "Helpers" and "Debug" sections in the default memory records that are generated. - A generate memory records script is included in the helpers section. - A rename save section is included in the helpers section. Note: Only renames the save; new "teleport to" scripts will need to be generated, and old "teleport to" scripts removed (manually). - A delete save script is included in the helpers section. - the script first requests a save (save name) to be deleted and is only deleted the second time it is enabled. - Delete function first requests a save to be deleted and is only deleted on second call, unless force equates to true. Getting Started: Symbols: Must be set: "ptrI2CETeleporterCoord" (with a base address), i.e.: "mov [ptrI2CETeleporterCoord],***" (ASM) or I2CETeleporter.CoordPointerSymbol (with a symbol/address string). i.e.: "I2CETeleporter.CoordPointerSymbol = 'ptrCoordHook'" (Lua) Symbols: Optionally set: "ptrI2CETeleporterCamRotationAngle" (with a base address), or "I2CETeleporter.CamRotationAnglePointerSymbol" (with a symbol/address string). "ptrI2CETeleporterPlayerRotationAngle" (with a base address), or "I2CETeleporter.PlayerRotationAnglePointerSymbol" (with a symbol/address string). Note: Only "Yaw" is set using camera yaw. "ptrI2CETeleporterWayPoint" (with a base address), or "I2CETeleporter.WayPointPointerSymbol" (with a symbol/address string). Offsets: Optionally set: "I2CETeleporter.Xoffset" (default: 0) "I2CETeleporter.Yoffset" (default: 4) "I2CETeleporter.Zoffset" (default: 8) "I2CETeleporter.WayXoffset" (default: 0) "I2CETeleporter.WayYoffset" (default: 4) "I2CETeleporter.WayZoffset" (default: 8) "I2CETeleporter.PlayerYawOffset" (default: 0) "I2CETeleporter.CamPitchOffset" (default: 0) "I2CETeleporter.CamYawOffset" (default: 4) Adjusters: Optionally set: "I2CETeleporter.XaddOnWrite" (default: 0) "I2CETeleporter.YaddOnWrite" (default: 0) "I2CETeleporter.ZaddOnWrite" (default: 0) "I2CETeleporter.XaddOnRead" (default: 0) "I2CETeleporter.YaddOnRead" (default: 0) "I2CETeleporter.ZaddOnRead" (default: 0) "I2CETeleporter.WayXaddOnRead" (default: 0) "I2CETeleporter.WayYaddOnRead" (default: 0) "I2CETeleporter.WayZaddOnRead" (default: 0) Examples: Starter Example: Code (Lua): dofile([[E:\Where\Ever\The\Module\Is\I2CETeleporter.Lua]]) I2CETeleporter.CoordPointerSymbol = '"Game.exe"+123ABC0' I2CETeleporter.Xoffset = 0x60 I2CETeleporter.Yoffset = 0x64 I2CETeleporter.Zoffset = 0x68 ---- Comment out or remove after starter memory records are generated. I2CETeleporter.generateMemoryRecords() ---- END: Comment out or remove after starter memory records are generated. Example: Code (Lua): require 'I2CETeleporter' I2CETeleporter.AutoAllocate = false I2CETeleporter.CoordPointerSymbol = '[["Game.exe"+123ABC0]+10]+5D0' Example: Code (Lua): require 'I2CETeleporter' I2CETeleporter.AutoAllocate = false I2CETeleporter.CoordPointerSymbol = 'ptrCoordHook' Example: Code (Lua): require 'I2CETeleporter' I2CETeleporter.Xoffset = 0x60 I2CETeleporter.Yoffset = 0x64 I2CETeleporter.Zoffset = 0x68 Code (ASM): ... mov [ptrI2CETeleporterCoord],rax ... Example: Code (Lua): require 'I2CETeleporter' Code (ASM): ... mov [ptrI2CETeleporterCoord],rax add [ptrI2CETeleporterCoord],60 ... Call to generate starter memory records: "I2CETeleporter.generateMemoryRecords()" Note: Form then on you can use the "Generate Memory Records" in the "Helpers" section. Settings: Symbol Names: FlagPointerSymbol (default: 'flgI2CETeleporter') CoordPointerSymbol (default: 'ptrI2CETeleporterCoord') PlayerRotationAnglePointerSymbol (default: 'ptrI2CETeleporterPlayerRotationAngle') CamRotationAnglePointerSymbol (default: 'ptrI2CETeleporterCamRotationAngle') WayPointPointerSymbol (default: 'ptrI2CETeleporterWayPoint') SaveNameStringSymbol (default: 'strI2CETeleporterSaveName') NewSaveNameStringSymbol (default: 'strI2CETeleporterSaveNameNew') MainMemoryRecordDescription (default: '_[ I2CETeleporter ]_') SavesMemoryRecordDescription (default: '_[ Saves ]_' [translated]) AutoLoad (default: true) AutoAllocate (default: true) AutoLoadAndSave (default: true) SavesFileName (default: 'I2CETeleporterSaves.txt') SavesFileAsTableFile (default: false) OverRideSaveMemoryRecords (default: false) AutoSaveSavesFile (default: true) WarnIfSavesTableFileNotFound (default: false) WriteToCoordsTimerInterval (default: 100) WriteToCoordsTimerTicksMax (default: 100) SetCamRotationAngleTimerInterval (default: 100) SetCamRotationAngleTimerTicksMax (default: 100) Xoffset (default: 0) Yoffset (default: 4) Zoffset (default: 8) XaddOnWrite (default: 0) YaddOnWrite (default: 0) ZaddOnWrite (default: 0) XaddOnRead (default: 0) YaddOnRead (default: 0) ZaddOnRead (default: 0) WayXoffset (default: 0) WayYoffset (default: 4) WayZoffset (default: 8) WayXaddOnRead (default: 0) WayYaddOnRead (default: 0) WayZaddOnRead (default: 0) PlayerYawOffset (default: 0) CamPitchOffset (default: 0) CamYawOffset (default: 4) SaveMemoryRecord (table) MainMemoryRecords (table) Symbol Addresses: FlagPointerAddress CoordPointerAddress PlayerRotationAnglePointerAddress CamRotationAnglePointerAddress WayPointPointerAddress SaveNameStringAddress NewSaveNameStringAddress Template Keys: - Keys to be used in script templates and memory record strings. format: ${TemplateKey} SaveName FlagPointerSymbol FlagPointerAddress CoordPointerSymbol CoordPointerAddress PlayerRotationAnglePointerSymbol PlayerRotationAnglePointerAddress CamRotationAnglePointerSymbol CamRotationAnglePointerAddress WayPointPointerSymbol WayPointPointerAddress SaveNameStringSymbol SaveNameStringAddress NewSaveNameStringSymbol NewSaveNameStringAddress Xoffset Yoffset Zoffset WayXoffset WayYoffset WayZoffset PlayerYawOffset CamPitchOffset CamYawOffset X Y Z WayX WayY WayZ CamPitch CamYaw ]====================================================================================================================]-- local NAME = 'I2 Cheat Engine Teleporter' local CLASS_NAME = 'I2CETeleporter' local VERSION = '1.0.9' local AUTHOR = 'Matt Irwin; Matt.Irwin.US@Gmail.com' local LICENSE = [=[MIT License Copyright (c) 2018 Matt Irwin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sub-license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]=] local format = string.format local strE = string.empty or STRING_EMPTY or '' local t = translate local DEBUG = DEBUG or false local LOGGER_LEVEL = 2 ---- WARN local LineEnd = '\n' local AutoLoad = true local AutoAllocate = AutoLoad local AutoLoadAndSave = true local SavesFileName = 'I2CETeleporterSaves.txt' local SavesFileAsTableFile = false local OverRideSaveMemoryRecords = false local AutoSaveSavesFile = true local WarnIfSavesTableFileNotFound = DEBUG local WriteToCoordsTimerInterval = 100 local WriteToCoordsTimerTicksMax = 100 local SetCamRotationAngleTimerInterval = 100 local SetCamRotationAngleTimerTicksMax = 100 local MainMemoryRecordDescription = '_[ I2CETeleporter ]_' local SavesMemoryRecordDescription = '_[ ' .. t('Saves') .. ' ]_' local FlagPointerSymbol = 'flgI2CETeleporter' local CoordPointerSymbol = 'ptrI2CETeleporterCoord' local PlayerRotationAnglePointerSymbol = 'ptrI2CETeleporterPlayerRotationAngle' local CamRotationAnglePointerSymbol = 'ptrI2CETeleporterCamRotationAngle' local WayPointPointerSymbol = 'ptrI2CETeleporterWayPoint' local SaveNameStringSymbol = 'strI2CETeleporterSaveName' local NewSaveNameStringSymbol = 'strI2CETeleporterSaveNameNew' local DataDelimiter = '' local SaveNameStringMax = 60 local Colors = { Black = 0x000000, White = 0xFFFFFF, Silver = 0xC0C0C0, Grey = 0x808080, Red = 0x0000FF, -- 0xFF0000 Maroon = 0x000080, -- 0x800000 Yellow = 0x00FFFF, -- 0xFFFF00 Olive = 0x008080, -- 0x808000 Lime = 0x00FF00, Green = 0x008000, Aqua = 0xFFFF00, -- 0x00FFFF Teal = 0x808000, -- 0x008080 Blue = 0xFF0000, -- 0x0000FF Navy = 0x800000, -- 0x000080 Fuchsia = 0xFF00FF, Purple = 0x800080, } -- -------- -------- -------- Logger -------- local Logger = { ClassName = 'I2Logger', Name = 'I2CETeleporter' } Logger.LEVELS = { OFF = 0, ERROR = 1, WARN = 2, INFO = 3, DEBUG = 4 } Logger.Level = LOGGER_LEVEL or Logger.LEVELS.WARN if DEBUG then Logger.Level = Logger.LEVELS.DEBUG end Logger.print = print function Logger.logEvent(level, msg, ex) if Logger.Level >= level then if Logger.Name ~= nil then msg = Logger.Name .. ': ' .. msg end if Logger.ClassName ~= nil then msg = Logger.ClassName .. '.' .. msg end Logger.print(msg) if ex then Logger.print('Exception: ' .. tostring(ex)) end end end for k,v in pairs(Logger.LEVELS) do if v > 0 then Logger[k:lower()] = function(msg, ex) return Logger.logEvent(v, msg, ex) end Logger[k:lower() .. 'f'] = function(msg, ... ) return Logger.logEvent(v, format(msg, ... )) end end end -------- -------- Logger -------- -------- local function split(s, delimiter) result = {} for match in (s .. delimiter):gmatch('(.-)' .. delimiter) do table.insert(result, match) end return result end local function interp(s, tbl) if s == nil then return end return (s:gsub('($%b{})', function(w) return tbl[w:sub(3, -2)] or w end)) end local function padR(str, len, char) if str == nil or len == nil then return str end if char == nil then char = ' ' end return str .. string.rep(char, len - #str) end local function titleCase(s, s_char) if type(s) ~= 'string' then return nil end local patt = '%S+' -- match every thing but spaces. local char = ' ' if s_char == '_' then patt = '[^_]+' -- match every thing but underscores. char = '_' elseif s_char == '.' then patt = '[^\\.]+' -- match every thing but periods. char = '.' elseif s_char == 'p' then patt = '%P+' -- match every thing but punctuation. char = '.' end local r = strE for w in s:gfind(patt) do local f = w:sub(1, 1) if #r > 0 then r = r..char end r = r..f:upper()..w:sub(2):lower() end if #r < 1 then r = s end return r end local function getPointerSize() aasStr = [====[ globalAlloc(memPointerTest, 0x8) memPointerTest: db FF FF FF FF FF FF FF FF ]====] local assembled = autoAssemble(aasStr) if assembled then local p1 = readQword('memPointerTest') local p2 = readPointer('memPointerTest') if p1 == p2 then return 0x8 else return 0x4 end end return nil end local function getPointerSizeStrs() local pointerSize = getPointerSize() local pointerSizeStr = format('0x%X', pointerSize or 0x8) local pointerFtmStr = '%016X' local pointerWordSize = 'dq' local pointerDefaultStr = 'dq 0' if pointerSize == 0x4 then pointerFtmStr = '%08X' pointerWordSize = 'dd' pointerDefaultStr = 'dd 0' end return pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr end --[====[ Keys: SaveName FlagPointerSymbol FlagPointerAddress CoordPointerSymbol CoordPointerAddress PlayerRotationAnglePointerSymbol PlayerRotationAnglePointerAddress CamRotationAnglePointerSymbol CamRotationAnglePointerAddress WayPointPointerSymbol WayPointPointerAddress SaveNameStringSymbol SaveNameStringAddress NewSaveNameStringSymbol NewSaveNameStringAddress Xoffset Yoffset Zoffset PlayerYawOffset CamPitchOffset CamYawOffset WayXoffset WayYoffset WayZoffset X Y Z CamPitch CamYaw WayX WayY WayZ ]====]-- local DEFAULT_SCRIPT_COLOR = Colors.Green local DEFAULT_SAVE_MR_DESCRIPTION = t('Teleport to') .. ': ${SaveName} ()->' local DEFAULT_SAVE_MR_SCRIPT = [==============================[ {$lua} ---- ${SaveName} ---- ${CoordPointerSymbol}: ${CoordPointerAddress} ---- ${X}, ${Y}, ${Z} [Enable] if syntaxcheck then return end I2CETeleporter.teleport('${SaveName}') [Disable] ]==============================] local SaveLocationScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.save() [Disable] ]==============================] local TeleportToSaveScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.teleport() [Disable] ]==============================] local TeleportBackScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.teleportBack() [Disable] ]==============================] local TeleportToWayPointScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.teleportToWayPoint() [Disable] ]==============================] local WriteSavesToFileScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.writeSavesToFile() [Disable] ]==============================] local ReadFromFileScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.readSavesFromFile() [Disable] ]==============================] local PrintSavesScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.printSaves() [Disable] ]==============================] local generateMemoryRecordsScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.generateMemoryRecords() [Disable] ]==============================] local DeleteSaveScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.delete() [Disable] ]==============================] local RenameSaveScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.rename() [Disable] ]==============================] local ZeroCamRotationAngleScript = [==============================[ {$lua} [Enable] if syntaxcheck then return end I2CETeleporter.zeroCamRotationAngle() [Disable] ]==============================] I2CETeleporter = { MainMemoryRecordDescription = MainMemoryRecordDescription, SavesMemoryRecordDescription = SavesMemoryRecordDescription, FlagPointerSymbol = FlagPointerSymbol, -- FlagPointerAddress = 0, CoordPointerSymbol = CoordPointerSymbol, -- CoordPointerAddress = 0, PlayerRotationAnglePointerSymbol = PlayerRotationAnglePointerSymbol, -- PlayerRotationAnglePointerAddress = 0, CamRotationAnglePointerSymbol = CamRotationAnglePointerSymbol, -- CamRotationAnglePointerAddress = 0, WayPointPointerSymbol = WayPointPointerSymbol, -- WayPointPointerAddress = 0, SaveNameStringSymbol = SaveNameStringSymbol, -- SaveNameStringAddress = 0, NewSaveNameStringSymbol = NewSaveNameStringSymbol, -- NewSaveNameStringAddress = 0, AutoLoad = AutoLoad, AutoAllocate = AutoAllocate, AutoLoadAndSave = AutoLoadAndSave, SavesFileName = SavesFileName, SavesFileAsTableFile = SavesFileAsTableFile, OverRideSaveMemoryRecords = OverRideSaveMemoryRecords, AutoSaveSavesFile = AutoSaveSavesFile, WriteToCoordsTimerInterval = WriteToCoordsTimerInterval, WriteToCoordsTimerTicksMax = WriteToCoordsTimerTicksMax, SetCamRotationAngleTimerInterval = SetCamRotationAngleTimerInterval, SetCamRotationAngleTimerTicksMax = SetCamRotationAngleTimerTicksMax, WarnIfSavesTableFileNotFound = WarnIfSavesTableFileNotFound, ---- Xoffset = 0, Yoffset = 4, Zoffset = 8, ---- PlayerYawOffset = 4, ---- CamPitchOffset = 0, CamYawOffset = 4, ---- XaddOnWrite = 0, YaddOnWrite = 0, ZaddOnWrite = 0, ---- XaddOnRead = 0, YaddOnRead = 0, ZaddOnRead = 0, ---- WayXoffset = 0, WayYoffset = 4, WayZoffset = 8, ---- WayXaddOnRead = 0, WayYaddOnRead = 0, WayZaddOnRead = 0, ---- SaveMemoryRecord = { Description = DEFAULT_SAVE_MR_DESCRIPTION, Type = vtAutoAssembler, Script = DEFAULT_SAVE_MR_SCRIPT, Color = DEFAULT_SCRIPT_COLOR, }, ---- MainMemoryRecords = { Description = MainMemoryRecordDescription, IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { { Description = '** ' .. t('See "Saves" section for stored saves.') .. ' **', IsGroupHeader = true, Color = Colors.Maroon, }, { Description = t('Save Name'), Type = vtString, Address = '${SaveNameStringSymbol}', Color = Colors.Blue, String = { Size = SaveNameStringMax, }, }, { Description = t('Save Location') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = SaveLocationScript, }, { Description = t('Teleport To: Save (Save Name)') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = TeleportToSaveScript, }, { Description = t('Teleport To: Way Point') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = TeleportToWayPointScript, }, { Description = t('Teleport: Back') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = TeleportBackScript, }, { Description = SavesMemoryRecordDescription, IsGroupHeader = true, options = "[moHideChildren]", AppendSaves = true, }, { Description = '_[ Helpers - I2CETeleporter ]_', IsGroupHeader = true, options = "[moHideChildren]", Color = Colors.Grey, MemoryRecords = { { Description = t('Generate Memory Records') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = generateMemoryRecordsScript, }, { Description = t('Zero Camera Rotation Angle') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = ZeroCamRotationAngleScript, }, { Description = t('Write Saves To File') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = WriteSavesToFileScript, }, { Description = t('Print Saves') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = PrintSavesScript, }, { Description = '_[ Rename Save ]_', IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { { Description = t('Save Name (to rename)'), Type = vtString, Address = '${SaveNameStringSymbol}', Color = Colors.Blue, String = { Size = SaveNameStringMax, }, }, { Description = t('New Save Name'), Type = vtString, Address = '${NewSaveNameStringSymbol}', Color = Colors.Blue, String = { Size = SaveNameStringMax, }, }, { Description = t('Rename Save') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = RenameSaveScript, }, }, }, { Description = t('Read From File') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = ReadFromFileScript, }, { Description = t('Delete Save ** Must Enable 2 Times **') .. ' ()->', Type = vtAutoAssembler, Color = DEFAULT_SCRIPT_COLOR, Script = DeleteSaveScript, }, }, }, { Description = '_[ Debug - I2CETeleporter ]_', IsGroupHeader = true, options = "[moHideChildren]", Color = Colors.Grey, MemoryRecords = { { Description = '${SaveNameStringSymbol}', Type = vtString, Address = '${SaveNameStringSymbol}', Color = Colors.Fuchsia, String = { Size = SaveNameStringMax, }, }, { Description = '${NewSaveNameStringSymbol}', Type = vtString, Address = '${NewSaveNameStringSymbol}', Color = Colors.Fuchsia, String = { Size = SaveNameStringMax, }, }, { Description = '$I2CETeleporter.FlagPointerSymbol', Address = '$I2CETeleporter.FlagPointerSymbol', Color = Colors.Fuchsia, Type = vtByte, ShowAsHex = true, DropDownList = { Text = '00:' .. t('Disabled') .. '\n01:' .. t('Enabled') .. '\n', }, DropDownReadOnly = true, ---- Disallow manual user input DropDownDescriptionOnly = true, ---- Only show the description part DisplayAsDropDownListItem = true, ---- Make the record display values like the dropdownlist }, { Description = '$I2CETeleporter.FlagPointerSymbol+1', Address = '$I2CETeleporter.FlagPointerSymbol+1', Color = Colors.Fuchsia, Type = vtByte, ShowAsHex = true, DropDownList = { Text = '00:' .. t('Disabled') .. '\n01:' .. t('Enabled') .. '\n', }, DropDownReadOnly = true, ---- Disallow manual user input DropDownDescriptionOnly = true, ---- Only show the description part DisplayAsDropDownListItem = true, ---- Make the record display values like the dropdownlist }, { Description = '$I2CETeleporter.CoordPointerSymbol', Type = 'Pointer', Address = '$I2CETeleporter.CoordPointerSymbol', Color = Colors.Grey, ShowAsHex = true, IsGroupHeader = true, MemoryRecords = { { Description = 'X Coord.', Type = vtSingle, Address = '$I2CETeleporter.CoordPointerSymbol', Color = Colors.Fuchsia, ShowAsHex = true, OffsetText = { '$I2CETeleporter.Xoffset', }, }, { Description = 'Y Coord.', Type = vtSingle, Address = '$I2CETeleporter.CoordPointerSymbol', Color = Colors.Fuchsia, ShowAsHex = true, OffsetText = { '$I2CETeleporter.Yoffset', }, }, { Description = 'Z Coord.', Type = vtSingle, Address = '$I2CETeleporter.CoordPointerSymbol', Color = Colors.Fuchsia, ShowAsHex = true, OffsetText = { '$I2CETeleporter.Zoffset', }, }, }, }, { Description = '$I2CETeleporter.PlayerRotationAnglePointerSymbol', Type = 'Pointer', Address = '$I2CETeleporter.PlayerRotationAnglePointerSymbol', Color = Colors.Grey, ShowAsHex = true, }, { Description = '$I2CETeleporter.CamRotationAnglePointerSymbol', Type = 'Pointer', Address = '$I2CETeleporter.CamRotationAnglePointerSymbol', Color = Colors.Grey, ShowAsHex = true, }, { Description = '$I2CETeleporter.WayPointPointerSymbol', Type = 'Pointer', Address = '$$I2CETeleporter.WayPointPointerSymbol', Color = Colors.Grey, ShowAsHex = true, }, }, }, }, }, ---- DataDelimiter = DataDelimiter, LineEnd = LineEnd, ---- -- Finalized = false, ---- -- Saves = { -- ['Save Name'] = { -- X = #f.9, -- Y = #f.9, -- Z = #f.9, -- CamPitch = #f.9, -- CamYaw = #f.9, -- }, -- }, Logger = Logger, } function I2CETeleporter.CamYawToPlayerYaw(cY) -- Set for conversions. return cY end function I2CETeleporter.initialize() Logger.debug('initialize: initializing') local function I2CETeleporterInitMemoryTimer_tick(timer) if process ~= nil then Logger.debugf('initialize: killing timer: %s', timer) timer.destroy() if I2CETeleporter.AutoLoad then Logger.info('initialize: auto loading') I2CETeleporter.initMemory() if I2CETeleporter.AutoLoadAndSave then Logger.debugf('initialize: hooking main form "OnClose": "%s"', MainForm.OnClose) I2CETeleporter.readSavesFromFile() I2CETeleporter.MainFormOnClose = MainForm.OnClose MainForm.OnClose = I2CETeleporter.OnClose end end Logger.infof('initialize: initialized') end end local intervals = 1000 local timer = createTimer(MainForm) timer.Interval = intervals timer.OnTimer = I2CETeleporterInitMemoryTimer_tick Logger.info('initialize: timer started') end function I2CETeleporter.finalize() Logger.debug('finalize: finalizing') if I2CETeleporter.AutoLoadAndSave then --- Can't save table file on close with out forcing table save. I2CETeleporter.writeSavesToFile() end I2CETeleporter.finaMemory() end function I2CETeleporter.OnClose(sender) if not I2CETeleporter.Finalized then Logger.infof('OnClose: calling main form "OnClose"') MainForm.OnClose = I2CETeleporter.MainFormOnClose I2CETeleporter.Finalized = true closeCE() end end function I2CETeleporter.initMemory() Logger.debug('initMemory: initializing memory') local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() if I2CETeleporter.AutoAllocate then if getAddressSafe(I2CETeleporter.FlagPointerSymbol) then deAlloc(I2CETeleporter.FlagPointerSymbol) unregisterSymbol(I2CETeleporter.FlagPointerSymbol) end I2CETeleporter.FlagPointerAddress = allocateSharedMemory(I2CETeleporter.FlagPointerSymbol, getPointerSize() or 0x8) if I2CETeleporter.FlagPointerAddress then Logger.debugf('initMemory: memory allocated: %s, ' .. pointerFtmStr, I2CETeleporter.FlagPointerSymbol, I2CETeleporter.FlagPointerAddress) registerSymbol(I2CETeleporter.FlagPointerSymbol, I2CETeleporter.FlagPointerAddress, true) else Logger.debugf('initMemory: memory allocation failed: %s', I2CETeleporter.FlagPointerSymbol) end local addrF = getAddressSafe(I2CETeleporter.FlagPointerSymbol) if addrF ~= nil and addrF ~= 0 then writeBytes(addrF, 0, 0) end if getAddressSafe(I2CETeleporter.CoordPointerSymbol) then deAlloc(I2CETeleporter.CoordPointerSymbol) unregisterSymbol(I2CETeleporter.CoordPointerSymbol) end I2CETeleporter.CoordPointerAddress = allocateSharedMemory(I2CETeleporter.CoordPointerSymbol, getPointerSize() or 0x8) if I2CETeleporter.CoordPointerAddress then Logger.debugf('initMemory: memory allocated: %s, ' .. pointerFtmStr, I2CETeleporter.CoordPointerSymbol, I2CETeleporter.CoordPointerAddress) registerSymbol(I2CETeleporter.CoordPointerSymbol, I2CETeleporter.CoordPointerAddress, true) else Logger.debugf('initMemory: memory allocation failed: %s', I2CETeleporter.CoordPointerSymbol) end if getAddressSafe(I2CETeleporter.PlayerRotationAnglePointerSymbol) then deAlloc(I2CETeleporter.PlayerRotationAnglePointerSymbol) unregisterSymbol(I2CETeleporter.PlayerRotationAnglePointerSymbol) end I2CETeleporter.PlayerRotationAnglePointerAddress = allocateSharedMemory(I2CETeleporter.PlayerRotationAnglePointerSymbol, getPointerSize() or 0x8) if I2CETeleporter.PlayerRotationAnglePointerAddress then Logger.debugf('initMemory: memory allocated: %s, ' .. pointerFtmStr, I2CETeleporter.PlayerRotationAnglePointerSymbol, I2CETeleporter.PlayerRotationAnglePointerAddress) registerSymbol(I2CETeleporter.PlayerRotationAnglePointerSymbol, I2CETeleporter.PlayerRotationAnglePointerAddress, true) else Logger.debugf('initMemory: memory allocation failed: %s', I2CETeleporter.PlayerRotationAnglePointerSymbol) end if getAddressSafe(I2CETeleporter.CamRotationAnglePointerSymbol) then deAlloc(I2CETeleporter.CamRotationAnglePointerSymbol) unregisterSymbol(I2CETeleporter.CamRotationAnglePointerSymbol) end I2CETeleporter.CamRotationAnglePointerAddress = allocateSharedMemory(I2CETeleporter.CamRotationAnglePointerSymbol, getPointerSize() or 0x8) if I2CETeleporter.CamRotationAnglePointerAddress then Logger.debugf('initMemory: memory allocated: %s, ' .. pointerFtmStr, I2CETeleporter.CamRotationAnglePointerSymbol, I2CETeleporter.CamRotationAnglePointerAddress) registerSymbol(I2CETeleporter.CamRotationAnglePointerSymbol, I2CETeleporter.CamRotationAnglePointerAddress, true) else Logger.debugf('initMemory: memory allocation failed: %s', I2CETeleporter.CamRotationAnglePointerSymbol) end if getAddressSafe(I2CETeleporter.WayPointPointerSymbol) then deAlloc(I2CETeleporter.WayPointPointerSymbol) unregisterSymbol(I2CETeleporter.WayPointPointerSymbol) end I2CETeleporter.WayPointPointerAddress = allocateSharedMemory(I2CETeleporter.WayPointPointerSymbol, getPointerSize() or 0x8) if I2CETeleporter.WayPointPointerAddress then Logger.debugf('initMemory: memory allocated: %s, ' .. pointerFtmStr, I2CETeleporter.WayPointPointerSymbol, I2CETeleporter.WayPointPointerAddress) registerSymbol(I2CETeleporter.WayPointPointerSymbol, I2CETeleporter.WayPointPointerAddress, true) else Logger.debugf('initMemory: memory allocation failed: %s', I2CETeleporter.WayPointPointerSymbol) end end if getAddressSafe(I2CETeleporter.SaveNameStringSymbol) then deAlloc(I2CETeleporter.SaveNameStringSymbol) unregisterSymbol(I2CETeleporter.SaveNameStringSymbol) end local size = SaveNameStringMax * 2 if size < 0x100 then size = 0x100 end I2CETeleporter.SaveNameStringAddress = allocateSharedMemory(I2CETeleporter.SaveNameStringSymbol, size or 0x100) if I2CETeleporter.SaveNameStringAddress then Logger.debugf('initMemory: memory allocated: %s, ' .. pointerFtmStr, I2CETeleporter.SaveNameStringSymbol, I2CETeleporter.SaveNameStringAddress) registerSymbol(I2CETeleporter.SaveNameStringSymbol, I2CETeleporter.SaveNameStringAddress, true) local bytes = { string.byte(t('Starting location'), 1, -1) } bytes[#bytes + 1] = 0x00 writeBytes(I2CETeleporter.SaveNameStringSymbol, bytes) else Logger.debugf('initMemory: memory allocation failed: %s', I2CETeleporter.SaveNameStringSymbol) end if getAddressSafe(I2CETeleporter.NewSaveNameStringSymbol) then deAlloc(I2CETeleporter.NewSaveNameStringSymbol) unregisterSymbol(I2CETeleporter.NewSaveNameStringSymbol) end local size = SaveNameStringMax * 2 if size < 0x100 then size = 0x100 end I2CETeleporter.NewSaveNameStringAddress = allocateSharedMemory(I2CETeleporter.NewSaveNameStringSymbol, size or 0x100) if I2CETeleporter.NewSaveNameStringAddress then Logger.debugf('initMemory: memory allocated: %s, ' .. pointerFtmStr, I2CETeleporter.NewSaveNameStringSymbol, I2CETeleporter.NewSaveNameStringAddress) registerSymbol(I2CETeleporter.NewSaveNameStringSymbol, I2CETeleporter.NewSaveNameStringAddress, true) writeBytes(I2CETeleporter.NewSaveNameStringSymbol, 0) else Logger.debugf('initMemory: memory allocation failed: %s', I2CETeleporter.NewSaveNameStringSymbol) end Logger.infof('InitMemory: memory initialized') end function I2CETeleporter.finaMemory() Logger.debug('finaMemory: finalizing') if I2CETeleporter.AutoAllocate then deAlloc(I2CETeleporter.FlagPointerSymbol) Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.FlagPointerSymbol) deAlloc(I2CETeleporter.CoordPointerSymbol) Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.CoordPointerSymbol) deAlloc(I2CETeleporter.PlayerRotationAnglePointerSymbol) Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.PlayerRotationAnglePointerSymbol) deAlloc(I2CETeleporter.CamRotationAnglePointerSymbol) Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.CamRotationAnglePointerSymbol) deAlloc(I2CETeleporter.WayPointPointerSymbol) Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.WayPointPointerSymbol) unregisterSymbol(I2CETeleporter.FlagPointerSymbol) unregisterSymbol(I2CETeleporter.CoordPointerSymbol) unregisterSymbol(I2CETeleporter.PlayerRotationAnglePointerSymbol) unregisterSymbol(I2CETeleporter.CamRotationAnglePointerSymbol) unregisterSymbol(I2CETeleporter.WayPointPointerSymbol) end deAlloc(I2CETeleporter.SaveNameStringSymbol) Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.SaveNameStringSymbol) deAlloc(I2CETeleporter.NewSaveNameStringSymbol) Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.NewSaveNameStringSymbol) unregisterSymbol(I2CETeleporter.SaveNameStringSymbol) unregisterSymbol(I2CETeleporter.NewSaveNameStringSymbol) end function I2CETeleporter.writeSavesToFile(fileName) local del = I2CETeleporter.DataDelimiter local le = I2CETeleporter.LineEnd if type(fileName) ~= 'string' then fileName = I2CETeleporter.SavesFileName or 'I2CETeleporterSaves.txt' end if I2CETeleporter.Saves == nil then local msg = 'writeSavesToFile: no saves to write' Logger.error(msg) return end local fileStr = strE for k, v in pairs(I2CETeleporter.Saves) do fileStr = fileStr .. k:gsub('\r', strE):gsub('\n', strE) .. del .. v.X .. del .. v.Y .. del .. v.Z if v.CamPitch ~= nil and v.CamYaw ~= nil then fileStr = fileStr .. del .. v.CamPitch .. del .. v.CamYaw end fileStr = fileStr .. le end if I2CETeleporter.SavesFileAsTableFile then local tableFile = findTableFile(fileName) if tableFile == nil then tableFile = createTableFile(fileName) end if tableFile == nil then local msg = format('writeSavesToFile: Error opening table file, "%s"', fileName) Logger.error(msg) return end local stream = tableFile.getData() local bytes = { string.byte(fileStr, 1, -1) } stream.write(bytes) Logger.infof('writeSavesToFile: table file saved, "%s"', fileName) else local f, err = io.open(I2CETeleporter.SavesFileName, 'w') if err then Logger.errorf('writeSavesToFile: the local file could not be opened, "%s"', fileName) elseif f and not err then f:write(fileStr) f:close() end end return fileName end function I2CETeleporter.readSavesFromFile(fileName) local del = I2CETeleporter.DataDelimiter if type(fileName) ~= 'string' then fileName = I2CETeleporter.SavesFileName or 'I2CETeleporterSaves.txt' end local fileStr = nil local f, err = io.open(I2CETeleporter.SavesFileName, 'r') if err then --Logger.debugf('readSavesFromFile: the local file could not be opened, "%s"', fileName) local tableFile = findTableFile(fileName) if tableFile == nil then local msg = format('readSavesFromFile: table file not found, "%s"', fileName) if I2CETeleporter.WarnIfSavesTableFileNotFound then Logger.warn(msg) else Logger.info(Logger.LEVELS.WARN, msg) end return end local stream = tableFile.getData() local bytes = stream.read(stream.Size) for i = 1, #bytes do if fileStr == nil then fileStr = strE end fileStr = fileStr .. string.char(bytes[i]) end elseif f and not err then fileStr = f:read('*all') f:close() end if fileStr == nil then return end if I2CETeleporter.Saves == nil then I2CETeleporter.Saves = {} end fileStr = fileStr:gsub('\r\n', '\n'):gsub('\r', '\n') local lines = split(fileStr, '\n') local lastSave = nil for i, line in ipairs(lines) do if line ~= nil then local save = split(line, del) if save ~= nil and save[1] ~= nil and save[2] ~= nil and save[3] ~= nil and save[4] ~= nil then I2CETeleporter.Saves[save[1]] = { Name = save[1], X = tonumber(save[2]), Y = tonumber(save[3]), Z = tonumber(save[4]), } if save[5] ~= nil and save[6] ~= nil then I2CETeleporter.Saves[save[1]].CamPitch = tonumber(save[5]) I2CETeleporter.Saves[save[1]].CamYaw = tonumber(save[6]) end lastSave = save[1] if save[5] ~= nil and save[6] ~= nil then Logger.debugf('readSavesFromFile: loading save: %s, %s, %s, %s; %s, %s', save[1], save[2], save[3], save[4], save[5], save[6]) else Logger.debugf('readSavesFromFile: loading save: %s, %s, %s, %s', save[1], save[2], save[3], save[4]) end end end end if lastSave ~= nil then local bytes = { string.byte(lastSave, 1, -1) } bytes[#bytes + 1] = 0x00 writeBytes(I2CETeleporter.SaveNameStringSymbol, bytes) end Logger.infof('readSavesFromFile: table file loaded, "%s"', fileName) return I2CETeleporter.Saves end function I2CETeleporter.printSaves() if I2CETeleporter.Saves == nil then local msg = 'printSaves: no saves to write' Logger.error(msg) return end for k, v in pairs(I2CETeleporter.Saves) do if v.CamPitch ~= nil and v.CamYaw ~= nil then print(format('%s : %f9, %f9, %f9; %f9, %f9', padR(k, 25), v.X, v.Y, v.Z, v.CamPitch, v.CamYaw)) else print(format('%s : %f9, %f9, %f9', padR(k, 25), v.X, v.Y, v.Z)) end end Logger.debug('printSaves: saves printed') end function I2CETeleporter.writeToCoords(x, y, z, cP, cY) local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() if type(x) ~= 'number' or type(y) ~= 'number' or type(z) ~= 'number' then local msg = format('writeToCoords: write canceled, coordinate must be a number: %s, %s, %s', type(x), type(y), type(z)) Logger.error(msg) error(msg) return end if (math.type(x) == 'integer' and x == 0) or (math.type(y) == 'integer' and y == 0) or (math.type(z) == 'integer' and z == 0) then local msg = format('writeToCoords: write canceled, coordinate zero: %f9, %f9, %f9', x, y, z) Logger.error(msg) error(msg) return end local base = getAddressSafe('[' .. I2CETeleporter.CoordPointerSymbol .. ']') if base == nil or base == 0 then local msg = format('writeToCoords: write canceled, no address at base: %s', I2CETeleporter.CoordPointerSymbol) Logger.error(msg) error(msg) return end local addrF = getAddressSafe(I2CETeleporter.FlagPointerSymbol) local baseCra = getAddressSafe('[' .. I2CETeleporter.CamRotationAnglePointerSymbol .. ']') local basePra = getAddressSafe('[' .. I2CETeleporter.PlayerRotationAnglePointerSymbol .. ']') local function writeToCoordsTimer_tick(timer) if I2CETeleporter.WriteToCoordsTimerTicksMax == nil or I2CETeleporter.WriteToCoordsTimerTicks == nil then I2CETeleporter.WriteToCoordsTimerTicksMax = 0 I2CETeleporter.WriteToCoordsTimerTicks = 0 elseif I2CETeleporter.WriteToCoordsTimerTicks > I2CETeleporter.WriteToCoordsTimerTicksMax then timer.destroy() I2CETeleporter.WriteToCoordsTimerTicks = 0 else I2CETeleporter.WriteToCoordsTimerTicks = I2CETeleporter.WriteToCoordsTimerTicks + 1 end Logger.debugf('writeToCoords: writing: ' .. pointerFtmStr .. ' : %f9', base + I2CETeleporter.Xoffset, x) Logger.debugf('writeToCoords: writing: ' .. pointerFtmStr .. ' : %f9', base + I2CETeleporter.Yoffset, y) Logger.debugf('writeToCoords: writing: ' .. pointerFtmStr .. ' : %f9', base + I2CETeleporter.Zoffset, z) writeFloat(base + I2CETeleporter.Xoffset, x + I2CETeleporter.XaddOnWrite) writeFloat(base + I2CETeleporter.Yoffset, y + I2CETeleporter.YaddOnWrite) writeFloat(base + I2CETeleporter.Zoffset, z + I2CETeleporter.ZaddOnWrite) if cP ~= nil and cY ~= nil then if baseCra ~= nil and baseCra ~= 0 then writeFloat(baseCra + I2CETeleporter.CamPitchOffset, cP) writeFloat(baseCra + I2CETeleporter.CamYawOffset, cY) end if basePra ~= nil and basePra ~= 0 then writeFloat(basePra + I2CETeleporter.PlayerYawOffset, I2CETeleporter.CamYawToPlayerYaw(cY)) end end if addrF ~= nil and addrF ~= 0 then writeBytes(addrF, 1) end end local bX = readFloat(base + I2CETeleporter.Xoffset) + I2CETeleporter.XaddOnRead local bY = readFloat(base + I2CETeleporter.Yoffset) + I2CETeleporter.YaddOnRead local bZ = readFloat(base + I2CETeleporter.Zoffset) + I2CETeleporter.ZaddOnRead local bcP = nil local bcY = nil if baseCra ~= nil and baseCra ~= 0 then bcP = readFloat(baseCra + I2CETeleporter.CamPitchOffset) bcY = readFloat(baseCra + I2CETeleporter.CamYawOffset) end I2CETeleporter.Back = { X = bX, Y = bY, Z = bZ, CamPitch = bcP, CamYaw = bcY } local intervals = I2CETeleporter.WriteToCoordsTimerInterval local timer = createTimer(MainForm, true) timer.Interval = intervals timer.OnTimer = writeToCoordsTimer_tick return x, y, z, cP, cY end function I2CETeleporter.setCamRotationAngle(cP, cY) local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() local baseCra = getAddressSafe('[' .. I2CETeleporter.CamRotationAnglePointerSymbol .. ']') if baseCra == nil or baseCra == 0 then local msg = format('setCamRotationAngle: write canceled, no address at base: %s', I2CETeleporter.CamRotationAnglePointerSymbol) Logger.error(msg) error(msg) return end local addrF = getAddressSafe(I2CETeleporter.FlagPointerSymbol) local basePra = getAddressSafe('[' .. I2CETeleporter.PlayerRotationAnglePointerSymbol .. ']') local function setCamRotationAngleTimer_tick(timer) if I2CETeleporter.SetCamRotationAngleTimerTicksMax == nil or I2CETeleporter.SetCamRotationAngleTimerTicks == nil then I2CETeleporter.SetCamRotationAngleTimerTicksMax = 0 I2CETeleporter.SetCamRotationAngleTimerTicks = 0 elseif I2CETeleporter.SetCamRotationAngleTimerTicks > I2CETeleporter.SetCamRotationAngleTimerTicksMax then timer.destroy() I2CETeleporter.SetCamRotationAngleTimerTicks = 0 else I2CETeleporter.SetCamRotationAngleTimerTicks = I2CETeleporter.SetCamRotationAngleTimerTicks + 1 end if cP ~= nil and cY ~= nil and baseCra ~= nil and baseCra ~= 0 then writeFloat(baseCra + I2CETeleporter.CamPitchOffset, cP) writeFloat(baseCra + I2CETeleporter.CamYawOffset, cY) end if cP ~= nil and cY ~= nil and basePra ~= nil and basePra ~= 0 then writeFloat(basePra + I2CETeleporter.PlayerYawOffset, I2CETeleporter.CamYawToPlayerYaw(cY)) end if addrF ~= nil and addrF ~= 0 then writeBytes(addrF + 1, 1) end end local intervals = I2CETeleporter.SetCamRotationAngleTimerInterval local timer = createTimer(MainForm, true) timer.Interval = intervals timer.OnTimer = setCamRotationAngleTimer_tick return cP, cY end function I2CETeleporter.zeroCamRotationAngle() return I2CETeleporter.setCamRotationAngle(0, 0) end function I2CETeleporter.readFromCoords() local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() local base = getAddressSafe('[' .. I2CETeleporter.CoordPointerSymbol .. ']') if base == nil or base == 0 then local msg = format('readFromCoords: read canceled, no address at base: %s', I2CETeleporter.CoordPointerSymbol) Logger.error(msg) error(msg) return end local baseCra = getAddressSafe('[' .. I2CETeleporter.CamRotationAnglePointerSymbol .. ']') local x = readFloat(base + I2CETeleporter.Xoffset) + I2CETeleporter.XaddOnRead local y = readFloat(base + I2CETeleporter.Yoffset) + I2CETeleporter.YaddOnRead local z = readFloat(base + I2CETeleporter.Zoffset) + I2CETeleporter.ZaddOnRead local z = readFloat(base + I2CETeleporter.Zoffset) + I2CETeleporter.ZaddOnRead local cP = nil local cY = nil if baseCra ~= nil and baseCra ~= 0 then cP = readFloat(baseCra + I2CETeleporter.CamPitchOffset) cY = readFloat(baseCra + I2CETeleporter.CamYawOffset) end Logger.debugf('readFromCoords: read: ' .. pointerFtmStr .. ' : %f9', base + I2CETeleporter.Xoffset, x) Logger.debugf('readFromCoords: read: ' .. pointerFtmStr .. ' : %f9', base + I2CETeleporter.Yoffset, y) Logger.debugf('readFromCoords: read: ' .. pointerFtmStr .. ' : %f9', base + I2CETeleporter.Zoffset, z) if cP ~= nil and cY ~= nil then Logger.debugf('readFromCoords: read: ' .. pointerFtmStr .. ' : %f9', baseCra + I2CETeleporter.CamPitchOffset, cP) Logger.debugf('readFromCoords: read: ' .. pointerFtmStr .. ' : %f9', baseCra + I2CETeleporter.CamYawOffset, cY) end return x, y, z, cP, cY end function I2CETeleporter.readFromWayPoint() local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() local base = getAddressSafe('[' .. I2CETeleporter.WayPointPointerSymbol .. ']') if base == nil or base == 0 then local msg = format('readFromWayPoint: read canceled, no address at base: %s', I2CETeleporter.WayPointPointerSymbol) Logger.error(msg) error(msg) return end x = readFloat(base + I2CETeleporter.WayXoffset) + I2CETeleporter.WayXaddOnRead y = readFloat(base + I2CETeleporter.WayYoffset) + I2CETeleporter.WayYaddOnRead z = readFloat(base + I2CETeleporter.WayZoffset) + I2CETeleporter.WayZaddOnRead Logger.debugf('readFromWayPoint: read: ' .. pointerFtmStr .. ' : %f9', base + I2CETeleporter.WayXoffset, x) Logger.debugf('readFromWayPoint: read: ' .. pointerFtmStr .. ' : %f9', base + I2CETeleporter.WayYoffset, y) Logger.debugf('readFromWayPoint: read: ' .. pointerFtmStr .. ' : %f9', base + I2CETeleporter.WayZoffset, z) return x, y, z end function I2CETeleporter.teleport(name) if name == nil then name = readString(I2CETeleporter.SaveNameStringSymbol, SaveNameStringMax) end if type(name) ~= 'string' then local msg = format('teleport: teleport canceled, "name" must be a string: %s', type(name)) Logger.error(msg) error(msg) return end local save = I2CETeleporter.Saves[name] if save == nil then local msg = format('teleport: teleport canceled, save not found: %s', name) Logger.error(msg) error(msg) return end Logger.debugf('teleport: teleporting to save: %s', name) local bytes = { string.byte(name, 1, -1) } bytes[#bytes + 1] = 0x00 writeBytes(I2CETeleporter.SaveNameStringSymbol, bytes) return I2CETeleporter.writeToCoords(save.X, save.Y, save.Z, save.CamPitch, save.CamYaw) end function I2CETeleporter.save(name) if name == nil then name = readString('strI2CETeleporterSaveName', SaveNameStringMax) end if type(name) ~= 'string' then local msg = format('save: save canceled, "name" must be a string: %s', type(name)) Logger.error(msg) error(msg) return end local x, y, z, cP, cY = I2CETeleporter.readFromCoords() if type(x) ~= 'number' or type(y) ~= 'number' or type(z) ~= 'number' then local msg = format('save: save canceled, coordinate must be a number: %s, %s, %s', type(x), type(y), type(z)) Logger.error(msg) error(msg) return end if (math.type(x) == 'integer' and x == 0) or (math.type(y) == 'integer' and y == 0) or (math.type(z) == 'integer' and z == 0) then local msg = format('save: save canceled, coordinate zero: %f9, %f9, %f9', x, y, z) Logger.error(msg) error(msg) return end if I2CETeleporter.Saves == nil then I2CETeleporter.Saves = {} end if cP ~= nil and cY ~= nil then Logger.debugf('save: saving: %s, %f9, %f9, %f9, %f9, %f9', name, x, y, z, cP, cY) else Logger.debugf('save: saving: %s, %f9, %f9, %f9', name, x, y, z) end I2CETeleporter.Saves[name] = { Name = name, X = x, Y = y, Z = z, CamPitch = cP, CamYaw = cY } if I2CETeleporter.AutoSaveSavesFile then I2CETeleporter.writeSavesToFile() end return I2CETeleporter.Saves[name] end function I2CETeleporter.teleportBack() if I2CETeleporter.Back ~= nil then return I2CETeleporter.writeToCoords(I2CETeleporter.Back.X, I2CETeleporter.Back.Y, I2CETeleporter.Back.Z, I2CETeleporter.Back.CamPitch, I2CETeleporter.Back.CamYaw) end end function I2CETeleporter.delete(name, force) if name == nil then name = readString('strI2CETeleporterSaveName', SaveNameStringMax) end if type(name) ~= 'string' then local msg = format('delete: delete canceled, "name" must be a string: %s', type(name)) Logger.error(msg) error(msg) return end if I2CETeleporter.Saves == nil then local msg = 'delete: no saves to delete' Logger.error(msg) return end if force or I2CETeleporter.DeleteRequest == I2CETeleporter.Saves[name] then I2CETeleporter.Saves[name] = nil Logger.infof('delete: save deleted: %s', name) writeBytes(I2CETeleporter.SaveNameStringSymbol, 0) else I2CETeleporter.DeleteRequest = I2CETeleporter.Saves[name] Logger.debugf('delete: delete request set for: %s', name) end if I2CETeleporter.AutoSaveSavesFile then I2CETeleporter.writeSavesToFile() end end function I2CETeleporter.rename(name, newName) if name == nil then name = readString('strI2CETeleporterSaveName', SaveNameStringMax) end if type(name) ~= 'string' then local msg = format('rename: rename canceled, "name" must be a string: %s', type(name)) Logger.error(msg) error(msg) return end if newName == nil then newName = readString('strI2CETeleporterSaveNameNew', SaveNameStringMax) end if type(newName) ~= 'string' then local msg = format('rename: rename canceled, "newName" must be a string: %s', type(newName)) Logger.error(msg) error(msg) return end if I2CETeleporter.Saves == nil then local msg = 'rename: no saves to rename' Logger.error(msg) return end I2CETeleporter.Saves[newName] = I2CETeleporter.Saves[name] I2CETeleporter.Saves[name] = nil local bytes = { string.byte(newName, 1, -1) } bytes[#bytes + 1] = 0x00 writeBytes(I2CETeleporter.SaveNameStringSymbol, bytes) writeBytes(I2CETeleporter.NewSaveNameStringSymbol, 0) if I2CETeleporter.AutoSaveSavesFile then I2CETeleporter.writeSavesToFile() end return I2CETeleporter.Saves[newName] end function I2CETeleporter.teleportToWayPoint() local x, y, z = I2CETeleporter.readFromWayPoint() Logger.debugf('teleportToWayPoint: teleporting to way point: %f9, %f9, %f9', x, y, z) return I2CETeleporter.writeToCoords(x, y, z) end function I2CETeleporter.createMR(mrTbl, interpTbl, appendMr) if mrTbl == nil then return end local memoryRecord = nil local memoryRecordCreated = false if mrTbl.Description ~= nil then memoryRecord = AddressList.getMemoryRecordByDescription(interp(mrTbl.Description, interpTbl)) end if memoryRecord == nil then memoryRecord = AddressList.createMemoryRecord() memoryRecord.Description = interp(mrTbl.Description, interpTbl) memoryRecordCreated = true Logger.debug('createMR: creating new memory record.') else Logger.debug('createMR: memory record found.') end local isScript = false local scriptStr = nil for k, v in pairs(mrTbl) do if k == 'MemoryRecords' and type(v) == 'table' then Logger.debug('createMR: generating child memory records.') for i = 1, #v do if not I2CETeleporter.OverRideSaveMemoryRecords and v[i].Description ~= nil and v[i].Description ~= I2CETeleporter.SavesMemoryRecordDescription and AddressList.getMemoryRecordByDescription(interp(v[i].Description, interpTbl)) ~= nil then Logger.debugf('createMR: child memory record found: %s', interp(v[i].Description, interpTbl)) --break else I2CETeleporter.createMR(v[i], interpTbl, memoryRecord) end end else if type(v) == 'table' and memoryRecord[k] ~= nil then if k == 'Hotkey' then for v_k, v_v in pairs(v) do if v_v ~= nil then memoryRecord[k][v_k] = v_v end end elseif (k == 'Offset' or k == 'OffsetText') then for v_k, v_v in ipairs(v) do memoryRecord.setOffsetCount(#v) if v_v ~= nil then memoryRecord.setOffset(v_k - 1, tonumber(interp(v_v, interpTbl), 16)) Logger.debugf('createMR: memoryRecord Offset set: %d, %X', v_k - 1, tonumber(interp(v_v, interpTbl), 16)) end end else for v_k, v_v in pairs(v) do if v_v ~= nil then memoryRecord[k][v_k] = v_v end end end else if k == 'AppendSaves' then Logger.debug('createMR: found "AppendSaves"') if I2CETeleporter.Saves ~= nil then local tbl = {} for k, v in pairs(interpTbl) do tbl[k] = v end for k, v in pairs(I2CETeleporter.Saves) do Logger.debugf('createMR: creating child memory record: %s', k) tbl.SaveName = k tbl.X = format('%f9', v.X) tbl.Y = format('%f9', v.Y) tbl.Z = format('%f9', v.Z) I2CETeleporter.createMR(I2CETeleporter.SaveMemoryRecord, tbl, memoryRecord) end end else if k == 'Type' and v == vtAutoAssembler then isScript = true elseif k == 'Script' and type(v) == 'string' then scriptStr = interp(v, interpTbl) end if k == 'Type' and type(v) == 'string' and (v:lower() == 'pointer' or v:lower() == 'ptr' or v:lower() == 'p') then if interpTbl.PointerSize == '0x4' then memoryRecord[k] = vtDword else memoryRecord[k] = vtQword end else if type(v) == 'string' then v = interp(v, interpTbl) end memoryRecord[k] = v end end end end end if appendMr ~= nil and memoryRecordCreated then memoryRecord.appendToEntry(appendMr) end if isScript and scriptStr == nil then memoryRecord.Script = interpTbl.Script elseif scriptStr ~= nil then memoryRecord.Script = scriptStr end local lDStr = memoryRecord.Description:sub(1, 40) Logger.debugf('createMR: done: memory record: ID: % 3d, Type: % 2d, "%s".', memoryRecord.ID, memoryRecord.Type, lDStr) return memoryRecord end function I2CETeleporter.generateMemoryRecords(mainMemoryRecordsTbl) local selMR = AddressList.getSelectedRecord() local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() Logger.info('generateMemoryRecords: generating memory records.') local mrTbl = mainMemoryRecordsTbl or I2CETeleporter.MainMemoryRecords local createdMemoryRecordsTbl = { } local saveName = readString(I2CETeleporter.SaveNameStringSymbol, SaveNameStringMax) local interpTbl = { SaveName = saveName, FlagPointerSymbol = I2CETeleporter.FlagPointerSymbol, FlagPointerAddress = format(pointerFtmStr, I2CETeleporter.FlagPointerAddress or 0), CoordPointerSymbol = I2CETeleporter.CoordPointerSymbol, CoordPointerAddress = format(pointerFtmStr, I2CETeleporter.CoordPointerAddress or 0), PlayerRotationAnglePointerSymbol = I2CETeleporter.PlayerRotationAnglePointerSymbol, PlayerRotationAnglePointerAddress = format(pointerFtmStr, I2CETeleporter.PlayerRotationAnglePointerAddress or 0), CamRotationAnglePointerSymbol = I2CETeleporter.CamRotationAnglePointerSymbol, CamRotationAnglePointerAddress = format(pointerFtmStr, I2CETeleporter.CamRotationAnglePointerAddress or 0), WayPointPointerSymbol = I2CETeleporter.WayPointPointerSymbol, WayPointPointerAddress = format(pointerFtmStr, I2CETeleporter.WayPointPointerAddress or 0), SaveNameStringSymbol = I2CETeleporter.SaveNameStringSymbol, SaveNameStringAddress = format(pointerFtmStr, I2CETeleporter.SaveNameStringAddress or 0), NewSaveNameStringSymbol = I2CETeleporter.NewSaveNameStringSymbol, NewSaveNameStringAddress = format(pointerFtmStr, I2CETeleporter.NewSaveNameStringAddress or 0), Xoffset = format('%X', I2CETeleporter.Xoffset or 0), Yoffset = format('%X', I2CETeleporter.Yoffset or 0), Zoffset = format('%X', I2CETeleporter.Zoffset or 0), WayXoffset = format('%X', I2CETeleporter.WayXoffset or 0), WayYoffset = format('%X', I2CETeleporter.WayYoffset or 0), WayZoffset = format('%X', I2CETeleporter.WayZoffset or 0), X = strE, Y = strE, Z = strE, CamPitch = strE, CamYaw = strE, } if I2CETeleporter.Saves ~= nil and I2CETeleporter.Saves[saveName] ~= nil then interpTbl.X = format('%f9', I2CETeleporter.Saves[saveName].X or 0) interpTbl.Y = format('%f9', I2CETeleporter.Saves[saveName].Y or 0) interpTbl.Z = format('%f9', I2CETeleporter.Saves[saveName].Z or 0) if I2CETeleporter.Saves[saveName].CamPitch ~= nil and I2CETeleporter.Saves[saveName].CamYaw ~= nil then interpTbl.CamPitch = format('%f9', I2CETeleporter.Saves[saveName].CamPitch) interpTbl.CamYaw = format('%f9', I2CETeleporter.Saves[saveName].CamYaw) end end if mrTbl.Description ~= nil then createdMemoryRecordsTbl[1] = I2CETeleporter.createMR(mrTbl, interpTbl) else for i = 1, #mrTbl do createdMemoryRecordsTbl[i] = I2CETeleporter.createMR(mrTbl[i], interpTbl) end end if selMR ~= nil then AddressList.setSelectedRecord(selMR) end return createdMemoryRecordsTbl end function I2CETeleporter.autoLoad() local function I2CETeleporterAutoLoadTimer_tick(timer) if I2CETeleporter.AutoLoad then if process ~= nil and getAddressSafe(process) ~= 0 then Logger.info('autoLoad: auto loading') Logger.debugf('autoLoad: killing timer: %s', timer) timer.destroy() I2CETeleporter.initialize() end else Logger.debugf('autoLoad: killing timer: %s', timer) timer.destroy() end end local intervals = 100 local timer = createTimer(MainForm) timer.Interval = intervals timer.OnTimer = I2CETeleporterAutoLoadTimer_tick Logger.info('autoLoad: timer started') end I2CETeleporter.autoLoad() return I2CETeleporter