  | 
				
				Cheat Engine The Official Site of Cheat Engine   
				
 
				 | 
			 
		 
		 
	
		| View previous topic :: View next topic   | 
	 
	
	
		| Author | 
		Message | 
	 
	
		XaneXXXX Expert Cheater
  Reputation: 0
  Joined: 29 Nov 2012 Posts: 212
 
  | 
		
			
				 Posted: Fri Mar 09, 2018 1:04 pm    Post subject: Metal Gear Survive (Single Player Mode) Teleport to waypoint | 
				       | 
			 
			
				
  | 
			 
			
				So I'm back again, I have made a script for pretty much everything in this game. The only one that always confuses me is teleport to waypoint. And not just in this game but in every other game too.
 
 
In another game (can't remember which atm) ++METHOS helped me when i made my first teleport to waypoint script, and with helped i mean that he did 90% of the work and explained why and how he did it etc.
 
 
So i was thinking, Is it possible to make some kind of "template" that works with most of the games since the procedure is similar? 
 
 
1. Find the waypoint coordinates = DONE
 
2. Fine the player coordinates = DONE.
 
 
Write a script that loads the waypoint coordinates into the player coords and then execute = profit.
 
 
Can anyone give me some tips on how i can write a script like that (if it's possible of course) Cheers!  
 
 
 
 
 
(And yes, the waypoint actually shows the Z coordinate when placed) hehe
 | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		TheyCallMeTim13 Wiki Contributor
  Reputation: 51
  Joined: 24 Feb 2017 Posts: 976 Location: Pluto
  | 
		
			
				 Posted: Fri Mar 09, 2018 5:02 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Well I'm doing some more work on it this week end but as of last light this was working pretty well.
 
 
The plain is to post this in the "Lua Extensions" section at some point.
 
But basically (for the tested version) you set "ptrI2CETeleporterCoord" to "+0" of the X coordinate (or set the offset settings); and optionally "ptrI2CETeleporterCamRotationAngle" and 	"ptrI2CETeleporterWayPoint".
 
Then call "I2CETeleporter.generateMemoryRecords()" to generate starter memory records. You'll have to read the code to get most of it for now, but working on the Doc string is on the list.
 
 
 
 	  | Code: | 	 		  --[====================================================================================================================[
 
 
   I2 Cheat Engine Teleporter
 
 
 
   Version: 1.0.3
 
      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.
 
            Not used; if "ptrI2CETeleporterCamRotationAngle" is "nil" or 0 (zero), 
 
                     or if not found in old version's saves.
 
         * Fixed default line end, changed to '\n'.
 
 
 
 
   Author: Matt - TheyCallMeTim13 - MattI2.com
 
 
 
   Features:
 
      - Delete first requests a save to be deleted and is deleted on second call, unless force equates to true.
 
 
 
   Getting Started:
 
      ptrI2CETeleporterCoord (Must be set, i.e.: "mov [ptrI2CETeleporterCoord],***"
 
      ptrI2CETeleporterCamRotationAngle (Optional)
 
      ptrI2CETeleporterWayPoint (Optional)
 
      I2CETeleporter.generateMemoryRecords() (call to generate starter memory records)
 
 
]====================================================================================================================]--
 
 
local NAME = 'I2 Cheat Engine Teleporter'
 
local CLASS_NAME = 'I2CETeleporter'
 
local VERSION = '1.0.3'
 
local AUTHOR = 'Matt Irwin; [email protected]'
 
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 writeToCoordsTimerTicksMax = 100
 
 
local MainMemoryRecordDescription = '_[  I2CETeleporter  ]_'
 
local SavesMemoryRecordDescription = '_[  ' .. t('Saves') .. '  ]_'
 
local CoordPointerSymbol = 'ptrI2CETeleporterCoord'
 
local CamRotationAnglePointerSymbol = 'ptrI2CETeleporterCamRotationAngle'
 
local WayPointPointerSymbol = 'ptrI2CETeleporterWayPoint'
 
local SaveNameStringSymbol = 'strI2CETeleporterSaveName'
 
local NewSaveNameStringSymbol = 'strI2CETeleporterSaveNameNew'
 
local DataDelimiter = '<sep>'
 
 
local SaveNameStringMax = 60
 
 
local AutoSaveSavesFile = true
 
 
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.debugf('Loaded', Logger.ClassName)
 
--------
 
-------- 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
 
   CoordPointerSymbol
 
   CoordPointerAddress
 
   CamRotationAnglePointerSymbol
 
   CamRotationAnglePointerAddress
 
   WayPointPointerSymbol
 
   WayPointPointerAddress
 
   SaveNameStringSymbol
 
   SaveNameStringAddress
 
   NewSaveNameStringSymbol
 
   NewSaveNameStringAddress
 
   Xoffset
 
   Yoffset
 
   Zoffset
 
   WayXoffset
 
   WayYoffset
 
   WayZoffset
 
   X
 
   Y
 
   Z
 
   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, 
 
   CoordPointerSymbol = CoordPointerSymbol, 
 
   -- CoordPointerAddress = 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, 
 
   writeToCoordsTimerTicksMax = writeToCoordsTimerTicksMax,
 
   ----
 
   Xoffset = 0, 
 
   Yoffset = 4, 
 
   Zoffset = 8, 
 
   ----
 
   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  ]_', 
 
            IsGroupHeader = true, 
 
            options = "[moHideChildren]", 
 
            Color = Colors.Grey, 
 
            MemoryRecords = {
 
               {
 
                  Description = t('Zero Camera Rotation Angle') .. '  ()->', 
 
                  Type = vtAutoAssembler, 
 
                  Color = DEFAULT_SCRIPT_COLOR, 
 
                  Script = ZeroCamRotationAngleScript, 
 
               }, 
 
               {
 
                  Description = t('Generate Memory Records') .. '  ()->', 
 
                  Type = vtAutoAssembler, 
 
                  Color = DEFAULT_SCRIPT_COLOR, 
 
                  Script = generateMemoryRecordsScript, 
 
               }, 
 
               {
 
                  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, 
 
               }, 
 
            }, 
 
         },
 
      }, 
 
   },
 
   ----
 
   DataDelimiter = DataDelimiter, 
 
   LineEnd = LineEnd, 
 
   ----
 
   -- Finalized = false, 
 
   -- Saves = {
 
   --    ['Save Name'] = {
 
   --       X = 0.000000000, 
 
   --       Y = 0.000000000, 
 
   --       Z = 0.000000000, 
 
   --       CamYaw = 0.000000000, 
 
   --    }, 
 
   -- }, 
 
   Logger = Logger,
 
}
 
 
function I2CETeleporter.initialize()
 
   Logger.debug('initialize: initializing')
 
   if I2CETeleporter.AutoAllocate then
 
      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
 
         end
 
      end
 
      local intervals = 1000
 
      local timer = createTimer(MainForm)
 
      timer.Interval = intervals
 
      timer.OnTimer = I2CETeleporterInitMemoryTimer_tick
 
      Logger.info('initialize: timer started')
 
   end
 
   Logger.infof('Init: initialized')
 
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
 
   if I2CETeleporter.AutoAllocate then
 
      I2CETeleporter.finaMemory()
 
   end
 
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 getAddressSafe(I2CETeleporter.CoordPointerSymbol) then
 
      deAlloc(I2CETeleporter.CoordPointerSymbol)
 
      unregisterSymbol(I2CETeleporter.CoordPointerSymbol)
 
   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.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
 
 
   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')
 
   deAlloc(I2CETeleporter.CoordPointerSymbol)
 
   Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.CoordPointerSymbol)
 
   deAlloc(I2CETeleporter.CamRotationAnglePointerSymbol)
 
   Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.CamRotationAnglePointerSymbol)
 
   deAlloc(I2CETeleporter.WayPointPointerSymbol)
 
   Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.WayPointPointerSymbol)
 
   deAlloc(I2CETeleporter.SaveNameStringSymbol)
 
   Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.SaveNameStringSymbol)
 
   deAlloc(I2CETeleporter.NewSaveNameStringSymbol)
 
   Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.NewSaveNameStringSymbol)
 
   unregisterSymbol(I2CETeleporter.CoordPointerSymbol)
 
   unregisterSymbol(I2CETeleporter.CamRotationAnglePointerSymbol)
 
   unregisterSymbol(I2CETeleporter.WayPointPointerSymbol)
 
   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
 
         --Logger.warnf('readSavesFromFile: the local file could not be opened, "%s"', fileName)
 
         Logger.warnf('readSavesFromFile: table file not found, "%s"', fileName)
 
         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 = getAddress('[' .. 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 baseCra = getAddress('[' .. I2CETeleporter.CamRotationAnglePointerSymbol .. ']')
 
 
   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 and baseCra ~= nil and baseCra ~= 0 then
 
         writeFloat(baseCra + I2CETeleporter.CamPitchOffset, cP)
 
         writeFloat(baseCra + I2CETeleporter.CamYawOffset, cY)
 
      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 = 100
 
   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 = getAddress('[' .. 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 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
 
   end
 
   local intervals = 100
 
   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 = getAddress('[' .. 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 = getAddress('[' .. 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 = getAddress('[' .. 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)
 
   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()
 
   local selMR = AddressList.getSelectedRecord()
 
   local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs()
 
   Logger.info('generateMemoryRecords: generating memory records.')
 
   local mrTbl = I2CETeleporter.MainMemoryRecords
 
   local createdMemoryRecordsTbl = { }
 
   local saveName = readString(I2CETeleporter.SaveNameStringSymbol, SaveNameStringMax)
 
   local interpTbl = {
 
      SaveName = saveName, 
 
      CoordPointerSymbol = I2CETeleporter.CoordPointerSymbol, 
 
      CoordPointerAddress = format(pointerFtmStr, I2CETeleporter.CoordPointerAddress), 
 
      WayPointPointerSymbol = I2CETeleporter.WayPointPointerSymbol, 
 
      WayPointPointerAddress = format(pointerFtmStr, I2CETeleporter.WayPointPointerAddress), 
 
      SaveNameStringSymbol = I2CETeleporter.SaveNameStringSymbol, 
 
      SaveNameStringAddress = format(pointerFtmStr, I2CETeleporter.SaveNameStringAddress), 
 
      NewSaveNameStringSymbol = I2CETeleporter.NewSaveNameStringSymbol, 
 
      NewSaveNameStringAddress = format(pointerFtmStr, I2CETeleporter.NewSaveNameStringAddress), 
 
      Xoffset = format('%X', I2CETeleporter.Xoffset), 
 
      Yoffset = format('%X', I2CETeleporter.Yoffset), 
 
      Zoffset = format('%X', I2CETeleporter.Zoffset), 
 
      WayXoffset = format('%X', I2CETeleporter.WayXoffset), 
 
      WayYoffset = format('%X', I2CETeleporter.WayYoffset), 
 
      WayZoffset = format('%X', I2CETeleporter.WayZoffset), 
 
      X = strE, 
 
      Y = strE, 
 
      Z = strE, 
 
   }
 
   if I2CETeleporter.Saves ~= nil and I2CETeleporter.Saves[saveName] ~= nil then
 
      interpTbl.X = format('%f9', I2CETeleporter.Saves[saveName].X)
 
      interpTbl.Y = format('%f9', I2CETeleporter.Saves[saveName].Y)
 
      interpTbl.Z = format('%f9', I2CETeleporter.Saves[saveName].Z)
 
   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)
 
      Logger.debugf('autoLoad: killing timer: %s', timer)
 
      timer.destroy()
 
      if I2CETeleporter.AutoLoad then
 
         Logger.info('autoLoad: auto loading')
 
         I2CETeleporter.initialize()
 
      end
 
   end
 
   local intervals = 20
 
   local timer = createTimer(MainForm)
 
   timer.Interval = intervals
 
   timer.OnTimer = I2CETeleporterAutoLoadTimer_tick
 
   Logger.info('autoLoad: timer started')
 
end
 
 
I2CETeleporter.autoLoad()
 
 
return I2CETeleporter
 
 | 	  
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		XaneXXXX Expert Cheater
  Reputation: 0
  Joined: 29 Nov 2012 Posts: 212
 
  | 
		
			
				 Posted: Fri Mar 09, 2018 5:11 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Thanks for your answer! but this is waaay too advanced for me   haha
 
 
Could you explain how i can use this? I really wanna test it out  
 | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		TheyCallMeTim13 Wiki Contributor
  Reputation: 51
  Joined: 24 Feb 2017 Posts: 976 Location: Pluto
  | 
		
			
				 Posted: Fri Mar 09, 2018 5:44 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				 	  | XaneXXXX wrote: | 	 		  Thanks for your answer! but this is waaay too advanced for me   haha
 
 
Could you explain how i can use this? I really wanna test it out   | 	  
 
 
So for some working examples:
 
Metal Gear Solid 5 Phantom Pain - table v: 2.0.9 CT
 
Dying Light - table v: 1.0.3 CT
 
Dead Island DE - table v: 1.0.1 CT
 
 
1:
 
But basically in the cheat table Lua script (Ctr+Alt+L):
 
 	  | Code: | 	 		  require 'I2CETeleporter'
 
 
---- And optionally set offsets as needed, else they are "0, 4, 8".
 
I2CETeleporter.Xoffset = 0x60
 
I2CETeleporter.Yoffset = 0x64
 
I2CETeleporter.Zoffset = 0x68
 
 
---- And optionally any adjusters needed
 
-- I2CETeleporter.XaddOnWrite
 
-- I2CETeleporter.YaddOnWrite
 
-- I2CETeleporter.ZaddOnWrite
 
-- I2CETeleporter.XaddOnRead
 
-- I2CETeleporter.YaddOnRead = 0.1
 
-- I2CETeleporter.ZaddOnRead
 
 
---- And optionally set the way point settings.
 
-- I2CETeleporter.WayXoffset
 
-- I2CETeleporter.WayYoffset
 
-- I2CETeleporter.WayZoffset
 
 
---- And optionally set the camera rotation angle settings.
 
I2CETeleporter.CamPitchOffset = 0x80
 
I2CETeleporter.CamYawOffset = 0x84
 
 | 	  
 
 
 
2:
 
Then in some injected code set "ptrI2CETeleporterCoord".
 
 	  | Code: | 	 		  ...
 
mov [ptrI2CETeleporterCoord],rax //// or what ever registry has the base in the injection.
 
... | 	  
 
So by default (if you don't change any offset settings) "[ptrI2CETeleporterCoord]" should be X, then "[ptrI2CETeleporterCoord]+4" Y, and "[ptrI2CETeleporterCoord]+8" Z
 
"[ptrI2CETeleporterWayPoint]" X
 
"[ptrI2CETeleporterWayPoint]+4" Y
 
"[ptrI2CETeleporterWayPoint]+8" Z
 
 
And optionally set your waypoint base.
 
 	  | Code: | 	 		  ...
 
mov [ptrI2CETeleporterWayPoint],rax //// or what ever registry has the base in the injection.
 
... | 	  
 
optional: "[ptrI2CETeleporterWayPoint]" way point X
 
optional: "[ptrI2CETeleporterWayPoint]+4" way point Y
 
optional: "[ptrI2CETeleporterWayPoint]+8" way point Z
 
 
 
And optionally use camera rotation angle.
 
 	  | Code: | 	 		  ...
 
mov [ptrI2CETeleporterCamRotationAngle],rax //// or what ever registry has the base in the injection.
 
... | 	  
 
optional: "[ptrI2CETeleporterCamRotationAngle]" camera pitch
 
optional: "[ptrI2CETeleporterCamRotationAngle]+4" camera yaw
 
 
 
3:
 
Then in the Lua engine window input this:
 
 	  | Code: | 	 		  | I2CETeleporter.generateMemoryRecords() | 	  
 
And hit execute. You should get a grouped memory record "_[  I2CETeleporter  ]_", just check the box to expand it. Set the save name  string (must be unique strings), then enable the "Save" script to save the location. You should find the save file in the same directory the cheat table is in (just open CE from a cheat table and not the CE directory). Then when you have all the saves add it as a table file and then no need for the local file. But new saves will be written to the local file.
 
 
4:
 
EDIT:
 
Then in the "_[  Helpers  ]_" section use the "Generate memory records" to auto create scripts that are added to the "_[  Saves  ]_" section. You can call this after every new save if you want. And even move then in to other sections; just don't rename the scripts, new ones will be generated.
 
 
5:
 
Then use these scripts to teleport to a saved location.
 
 
 
EDIT:
 
Just let me know if you have any other questions, I would love to have this tested a bit more. I will hopefully be posting a release of it before to long, with some real instructions and a completed Doc string.
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		XaneXXXX Expert Cheater
  Reputation: 0
  Joined: 29 Nov 2012 Posts: 212
 
  | 
		
			
				 Posted: Fri Mar 09, 2018 6:51 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Thanks you very much! This looks very promising. But since I'm not very experienced with LUA (and cheat engine). I know pretty much the basics of memory editing, I know how opcodes/offsets etc work. But to the "issue". 
 
 
I copied the script you pasted above and placed it in a file: I2CETeleporter.lua
 
 
When I'm trying to execute i get:
 
 
 
 
 
The solution is obviously simple, I know I'm doing this wrong haha. Any noobtips for me? I would love to get this to work! Then i can use it in more games too!  
 
 
EDIT: Of course i will change the offsets etc for the corrects ones. I just wanted to see if it would execute.
 
 
EDIT2: To be exact. I'm confused what to put in the Lua window and what i need to type in the script itself.
 | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		TheyCallMeTim13 Wiki Contributor
  Reputation: 51
  Joined: 24 Feb 2017 Posts: 976 Location: Pluto
  | 
		
			
				 Posted: Fri Mar 09, 2018 7:27 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				So for the first error, I'm betting you just opened CE so the working directory is the CE exe directory. So for a cheat table this would work but for testing use "dofile" (instead of "require") and an absolute path, some thing like this.
 
 	  | Code: | 	 		  | dofile([[E:\luaFiles\I2CETeleporter.lua]]) | 	  
 
 
And the second one, I just need to change how it's logging there, just add a blank local file to the cheat table named "I2CETeleporterSaves.txt" or ignore it tell you make your first save and a file is created. But it's just not finding a local saves file or a saves table file.
 
But oddly this error says the module loaded at some point.
 
 
 
EDIT:
 
In the input section on the window on the right, in the picture you posted, input this:
 
 	  | Code: | 	 		  | I2CETeleporter.generateMemoryRecords() | 	  
 
And hit execute in that window, this is only needed once as a script with this in it will be generated.
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		XaneXXXX Expert Cheater
  Reputation: 0
  Joined: 29 Nov 2012 Posts: 212
 
  | 
		
			
				 Posted: Fri Mar 09, 2018 7:49 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Thanks! I sent you a PM.
 
 
In the meantime I'm gonna try that out!  
 | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		TheyCallMeTim13 Wiki Contributor
  Reputation: 51
  Joined: 24 Feb 2017 Posts: 976 Location: Pluto
  | 
		
			
				 Posted: Fri Mar 09, 2018 8:00 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				If you still didn't get it, try "Ctrl+Alt+A" and paste this in and Hit "Execute".
 
 	  | Code: | 	 		  | luaCall(I2CETeleporter.generateMemoryRecords()) | 	  
 
But basically any where, so the cheat table Lua script is fine, just remove (or comment out) that line after the helper scripts are generated.
 
 
 
And here's an updated and tested version (still working on the Doc string):
 
 	  | Code: | 	 		  --[====================================================================================================================[
 
 
   I2 Cheat Engine Teleporter
 
 
 
   Version: 1.0.4
 
      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.
 
 
 
 
   Author: Matt - TheyCallMeTim13 - MattI2.com
 
 
 
   Features:
 
      - Offsets start at "0" then progress at "+4" increments.
 
      - Delete first requests a save to be deleted and is deleted on second call, unless force equates to true.
 
 
 
   Getting Started:
 
 
      Must be set with base address:
 
         ptrI2CETeleporterCoord
 
            i.e.: "mov [ptrI2CETeleporterCoord],***"
 
 
      Optionally set with base address:
 
         ptrI2CETeleporterCamRotationAngle
 
         ptrI2CETeleporterPlayerRotationAngle (Only is "Yaw" set with camera yaw)
 
         ptrI2CETeleporterWayPoint
 
 
      Call to generate starter memory records:
 
         I2CETeleporter.generateMemoryRecords()
 
 
      Settings:
 
         Symbol Names:
 
            CoordPointerSymbol
 
            PlayerRotationAnglePointerSymbol
 
            CamRotationAnglePointerSymbol
 
            WayPointPointerSymbol
 
            SaveNameStringSymbol
 
            NewSaveNameStringSymbol
 
         MainMemoryRecordDescription
 
         SavesMemoryRecordDescription
 
         AutoLoad
 
         AutoAllocate
 
         AutoLoadAndSave
 
         SavesFileName
 
         SavesFileAsTableFile
 
         OverRideSaveMemoryRecords
 
         AutoSaveSavesFile
 
         writeToCoordsTimerTicksMax
 
         Xoffset
 
         Yoffset
 
         Zoffset
 
         XaddOnWrite
 
         YaddOnWrite
 
         ZaddOnWrite
 
         XaddOnRead
 
         YaddOnRead
 
         ZaddOnRead
 
         WayXoffset
 
         WayYoffset
 
         WayZoffset
 
         WayXaddOnRead
 
         WayYaddOnRead
 
         WayZaddOnRead
 
         PlayerYawOffset
 
         CamPitchOffset
 
         CamYawOffset
 
         SaveMemoryRecord
 
         MainMemoryRecords
 
 
      Symbol Addresses:
 
         CoordPointerAddress
 
         PlayerRotationAnglePointerAddress
 
         CamRotationAnglePointerAddress
 
         WayPointPointerAddress
 
         SaveNameStringAddress
 
         NewSaveNameStringAddress
 
 
      Template Keys:
 
         SaveName
 
         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.4'
 
local AUTHOR = 'Matt Irwin; [email protected]'
 
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 writeToCoordsTimerTicksMax = 100
 
 
local MainMemoryRecordDescription = '_[  I2CETeleporter  ]_'
 
local SavesMemoryRecordDescription = '_[  ' .. t('Saves') .. '  ]_'
 
local CoordPointerSymbol = 'ptrI2CETeleporterCoord'
 
local PlayerRotationAnglePointerSymbol = 'ptrI2CETeleporterPlayerRotationAngle'
 
local CamRotationAnglePointerSymbol = 'ptrI2CETeleporterCamRotationAngle'
 
local WayPointPointerSymbol = 'ptrI2CETeleporterWayPoint'
 
local SaveNameStringSymbol = 'strI2CETeleporterSaveName'
 
local NewSaveNameStringSymbol = 'strI2CETeleporterSaveNameNew'
 
local DataDelimiter = '<sep>'
 
 
local SaveNameStringMax = 60
 
 
local AutoSaveSavesFile = true
 
 
local WarnIfSavesTableFileNotFound = false -- (not DEBUG)
 
 
 
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.debugf('Loaded', Logger.ClassName)
 
--------
 
-------- 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
 
   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, 
 
   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, 
 
   writeToCoordsTimerTicksMax = writeToCoordsTimerTicksMax,
 
   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('Zero Camera Rotation Angle') .. '  ()->', 
 
                  Type = vtAutoAssembler, 
 
                  Color = DEFAULT_SCRIPT_COLOR, 
 
                  Script = ZeroCamRotationAngleScript, 
 
               }, 
 
               {
 
                  Description = t('Generate Memory Records') .. '  ()->', 
 
                  Type = vtAutoAssembler, 
 
                  Color = DEFAULT_SCRIPT_COLOR, 
 
                  Script = generateMemoryRecordsScript, 
 
               }, 
 
               {
 
                  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 = '${CoordPointerSymbol}', 
 
                  Type = 'Pointer', 
 
                  Address = '${CoordPointerSymbol}', 
 
                  Color = Colors.Fuchsia, 
 
                  ShowAsHex = true, 
 
               }, 
 
               {
 
                  Description = '${PlayerRotationAnglePointerSymbol}', 
 
                  Type = 'Pointer', 
 
                  Address = '${PlayerRotationAnglePointerSymbol}', 
 
                  Color = Colors.Fuchsia, 
 
                  ShowAsHex = true, 
 
               }, 
 
               {
 
                  Description = '${CamRotationAnglePointerSymbol}', 
 
                  Type = 'Pointer', 
 
                  Address = '${CamRotationAnglePointerSymbol}', 
 
                  Color = Colors.Fuchsia, 
 
                  ShowAsHex = true, 
 
               }, 
 
               {
 
                  Description = '${WayPointPointerSymbol}', 
 
                  Type = 'Pointer', 
 
                  Address = '${WayPointPointerSymbol}', 
 
                  Color = Colors.Fuchsia, 
 
                  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')
 
   if I2CETeleporter.AutoAllocate then
 
      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
 
         end
 
      end
 
      local intervals = 1000
 
      local timer = createTimer(MainForm)
 
      timer.Interval = intervals
 
      timer.OnTimer = I2CETeleporterInitMemoryTimer_tick
 
      Logger.info('initialize: timer started')
 
   end
 
   Logger.infof('Init: initialized')
 
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
 
   if I2CETeleporter.AutoAllocate then
 
      I2CETeleporter.finaMemory()
 
   end
 
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 getAddressSafe(I2CETeleporter.CoordPointerSymbol) then
 
      deAlloc(I2CETeleporter.CoordPointerSymbol)
 
      unregisterSymbol(I2CETeleporter.CoordPointerSymbol)
 
   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
 
 
   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')
 
   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)
 
   deAlloc(I2CETeleporter.SaveNameStringSymbol)
 
   Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.SaveNameStringSymbol)
 
   deAlloc(I2CETeleporter.NewSaveNameStringSymbol)
 
   Logger.debugf('finaMemory: memory deallocated: %s', I2CETeleporter.NewSaveNameStringSymbol)
 
   unregisterSymbol(I2CETeleporter.CoordPointerSymbol)
 
   unregisterSymbol(I2CETeleporter.PlayerRotationAnglePointerSymbol)
 
   unregisterSymbol(I2CETeleporter.CamRotationAnglePointerSymbol)
 
   unregisterSymbol(I2CETeleporter.WayPointPointerSymbol)
 
   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 = getAddress('[' .. 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 baseCra = getAddress('[' .. I2CETeleporter.CamRotationAnglePointerSymbol .. ']')
 
   local basePra = getAddress('[' .. 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
 
   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 = 100
 
   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 = getAddress('[' .. 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 basePra = getAddress('[' .. 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
 
   end
 
   local intervals = 100
 
   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 = getAddress('[' .. 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 = getAddress('[' .. 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 = getAddress('[' .. 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)
 
   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()
 
   local selMR = AddressList.getSelectedRecord()
 
   local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs()
 
   Logger.info('generateMemoryRecords: generating memory records.')
 
   local mrTbl = I2CETeleporter.MainMemoryRecords
 
   local createdMemoryRecordsTbl = { }
 
   local saveName = readString(I2CETeleporter.SaveNameStringSymbol, SaveNameStringMax)
 
   local interpTbl = {
 
      SaveName = saveName, 
 
      CoordPointerSymbol = I2CETeleporter.CoordPointerSymbol, 
 
      CoordPointerAddress = format(pointerFtmStr, I2CETeleporter.CoordPointerAddress), 
 
      PlayerRotationAnglePointerSymbol = I2CETeleporter.PlayerRotationAnglePointerSymbol, 
 
      PlayerRotationAnglePointerAddress = format(pointerFtmStr, I2CETeleporter.PlayerRotationAnglePointerAddress), 
 
      CamRotationAnglePointerSymbol = I2CETeleporter.CamRotationAnglePointerSymbol, 
 
      CamRotationAnglePointerAddress = format(pointerFtmStr, I2CETeleporter.CamRotationAnglePointerAddress), 
 
      WayPointPointerSymbol = I2CETeleporter.WayPointPointerSymbol, 
 
      WayPointPointerAddress = format(pointerFtmStr, I2CETeleporter.WayPointPointerAddress), 
 
      SaveNameStringSymbol = I2CETeleporter.SaveNameStringSymbol, 
 
      SaveNameStringAddress = format(pointerFtmStr, I2CETeleporter.SaveNameStringAddress), 
 
      NewSaveNameStringSymbol = I2CETeleporter.NewSaveNameStringSymbol, 
 
      NewSaveNameStringAddress = format(pointerFtmStr, I2CETeleporter.NewSaveNameStringAddress), 
 
      Xoffset = format('%X', I2CETeleporter.Xoffset), 
 
      Yoffset = format('%X', I2CETeleporter.Yoffset), 
 
      Zoffset = format('%X', I2CETeleporter.Zoffset), 
 
      WayXoffset = format('%X', I2CETeleporter.WayXoffset), 
 
      WayYoffset = format('%X', I2CETeleporter.WayYoffset), 
 
      WayZoffset = format('%X', I2CETeleporter.WayZoffset), 
 
      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)
 
      interpTbl.Y = format('%f9', I2CETeleporter.Saves[saveName].Y)
 
      interpTbl.Z = format('%f9', I2CETeleporter.Saves[saveName].Z)
 
      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)
 
      Logger.debugf('autoLoad: killing timer: %s', timer)
 
      timer.destroy()
 
      if I2CETeleporter.AutoLoad then
 
         Logger.info('autoLoad: auto loading')
 
         I2CETeleporter.initialize()
 
      end
 
   end
 
   local intervals = 20
 
   local timer = createTimer(MainForm)
 
   timer.Interval = intervals
 
   timer.OnTimer = I2CETeleporterAutoLoadTimer_tick
 
   Logger.info('autoLoad: timer started')
 
end
 
 
I2CETeleporter.autoLoad()
 
 
return I2CETeleporter
 
 | 	  
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		XaneXXXX Expert Cheater
  Reputation: 0
  Joined: 29 Nov 2012 Posts: 212
 
  | 
		
			
				 Posted: Fri Mar 09, 2018 8:08 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Awesome! So far so good. I got this after i executed it:
 
 
 
 
 
But where/in which file do i actually change the settings? And with settings i mean the offsets etc.
 
 
For simplicity, here is my script for actually finding my coordinates:
 
 
 
 	  | Code: | 	 		  [ENABLE]
 
 
aobscanmodule(cords,mgv.exe,0F 28 40 20 0F 29 4F 10) // should be unique
 
alloc(newmem,$100,"mgv.exe"+A9F292)
 
 
label(code)
 
label(return)
 
globalalloc(_findcordz,4)
 
newmem:
 
 
code:
 
push rbx
 
mov rbx,_findcordz
 
mov [rbx],rax
 
pop rbx
 
  movaps xmm0,[rax+20]
 
  movaps [rdi+10],xmm1
 
  jmp return
 
 
cords:
 
  jmp newmem
 
  nop
 
  nop
 
  nop
 
return:
 
registersymbol(cords)
 
 
[DISABLE]
 
 
cords:
 
  db 0F 28 40 20 0F 29 4F 10
 
 
unregistersymbol(cords)
 
dealloc(newmem) | 	  
 
 
EDIT: Do you have any cheat table with only this method? I checked your dying light/mgsv tables but i got a bit confused with all the code etc. I thought if you have the dying light table for example but with everything removed except the teleporter function? Maybe that way i can look  it through and maybe get the hang of it quicker  
 | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		TheyCallMeTim13 Wiki Contributor
  Reputation: 51
  Joined: 24 Feb 2017 Posts: 976 Location: Pluto
  | 
		
			
				 Posted: Fri Mar 09, 2018 9:17 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				 	  | XaneXXXX wrote: | 	 		  | ...Do you have any cheat table with only this method?... | 	  
 
 
Here this is a stripped down table with just the teleporter (No auto attach, just whats needed for importing and the teleporter it self).
 
 
Can't post tables/files here.
 
 
Posted at FCE:
 
http://fearlessrevolution.com/viewtopic.php?f=4&t=6181&p=36553#p36553
 
 
 
 
EDIT:
 
 	  | Code: | 	 		  [ENABLE] 
 
 
aobscanmodule(cords,mgv.exe,0F 28 40 20 0F 29 4F 10) // should be unique 
 
alloc(newmem,$100,"mgv.exe"+A9F292) 
 
 
label(code) 
 
label(return) 
 
globalalloc(_findcordz, 8)
 
newmem: 
 
 
code: 
 
  mov [_findcordz],rax
 
 
  mov [ptrI2CETeleporterCoord],rax
 
 
  add [ptrI2CETeleporterCoord],20
 
  //// Or what ever the X offset is if you don't want to set the offset settings 
 
  //// It's how I've been doing it so far.
 
 
  movaps xmm0,[rax+20] 
 
  movaps [rdi+10],xmm1 
 
  jmp return 
 
 
cords: 
 
  jmp newmem 
 
  nop 
 
  nop 
 
  nop 
 
return: 
 
registersymbol(cords) 
 
 
[DISABLE] 
 
 
cords: 
 
  db 0F 28 40 20 0F 29 4F 10 
 
 
unregistersymbol(cords) 
 
dealloc(newmem) | 	  
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		XaneXXXX Expert Cheater
  Reputation: 0
  Joined: 29 Nov 2012 Posts: 212
 
  | 
		
			
				 Posted: Sat Mar 10, 2018 11:20 am    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Thank you very much! I will look that through, and test the script you posted and report back!  
 
 
Update: Hmm weird, the script won't activate. Do i have to execute something in the lua (CTRL + ALT + L) before trying to activate it?
 
 
Hm weird. my original script "Find coordinates" won't activate either. Gonna restart the game haha
 
 
Alright, so i had some code in the lua window which i deleted. Now my original script will activate again, but not the one you posted. any ideas? cheers.
 
 
 
 
 
Another update:
 
 
 
 
 
I guess that's the reason it won't activate. hmm
 | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		TheyCallMeTim13 Wiki Contributor
  Reputation: 51
  Joined: 24 Feb 2017 Posts: 976 Location: Pluto
  | 
		
			
				 Posted: Sat Mar 10, 2018 1:03 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				I posted a release in the "Lua Extensions" section:
 
I2 CE Teleporter
 
 
It has a little more in the Doc string, but still needs some work.
 
 
 
EDIT:
 
Basically the memory isn't allocated.
 
 
 	  | XaneXXXX wrote: | 	 		  | ...Hmm weird, the script won't activate. Do i have to execute something in the lua (CTRL + ALT + L) before trying to activate it?... | 	  
 
 
Yes, if "I2CETeleporter.AutoLoad" and "I2CETeleporter.AutoAllocate" are the defaults, then you really just need to attach to the game (give it a second) and then "dofile" or "require" the module, then it allocates the memory.
 
 
I have it setup in my table script this way, I see it's not right and will be updating it to use local CE memory, or check for an attached process.
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		XaneXXXX Expert Cheater
  Reputation: 0
  Joined: 29 Nov 2012 Posts: 212
 
  | 
		
			
				 Posted: Sat Mar 10, 2018 1:21 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Nice!
 
 
Alright, So this is what i have done atm.
 
 
I downloaded I2CETeleporter.lua and placed it in a folder. Then in CE i tried:
 
 
Table > Add File > I2CETeleporter.lua.
 
(Atm I'm just trying to get the Teleporter to activate).
 
 
I usually don't like asking people to spoonfeed me and especially you since you have already answered all of my questions and helped me.
 
 
But do you think that you could add a small step by step guide in your DOC to get started?
 
 
Like:
 
1. download my lua file and place it somewhere.
 
2. Execute this in the CE lua window etc.
 
 
It would really help me out! Thanks again  
 
 
EDIT: When i get this to work, Maybe i could write a detailed step by step later to help others that are beginners like me!  
 | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		TheyCallMeTim13 Wiki Contributor
  Reputation: 51
  Joined: 24 Feb 2017 Posts: 976 Location: Pluto
  | 
		
			
				 Posted: Sat Mar 10, 2018 2:16 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				 	  | XaneXXXX wrote: | 	 		  ...
 
But do you think that you could add a small step by step guide in your DOC to get started?
 
 
Like:
 
1. download my lua file and place it somewhere.
 
2. Execute this in the CE lua window etc.... | 	  
 
 
I update the post and module, there are some basic instructions. Let me now if it helps. I will try and add some for doing it with a table file later, but just wanted to explain the basics first.
 
I2 CE Teleporter
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		XaneXXXX Expert Cheater
  Reputation: 0
  Joined: 29 Nov 2012 Posts: 212
 
  | 
		
			
				 Posted: Sat Mar 10, 2018 2:32 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Thank you very much!
 
 
so i followed the steps but at step 8:
 
 
Enable the injection script and let it run to set the coordinate base. 
 
 
Same "issue" as before. The script won't activate.
 
 
 	  | Code: | 	 		  [ENABLE]
 
 
aobscanmodule(cords,mgv.exe,0F 28 40 20 0F 29 4F 10) // should be unique
 
alloc(newmem,$100,"mgv.exe"+A9F292)
 
 
label(code)
 
label(return)
 
newmem:
 
 
code:
 
mov [ptrI2CETeleporterCoord],rax //// Change *** to the registry of the coordinates base.
 
add [ptrI2CETeleporterCoord],0 //// Change 0000 to the offset of the first aligned coordinate (i.e.: X coord. offset).
 
 
  movaps xmm0,[rax+20]
 
  movaps [rdi+10],xmm1
 
  jmp return
 
 
cords:
 
  jmp newmem
 
  nop
 
  nop
 
  nop
 
return:
 
registersymbol(cords)
 
 
[DISABLE]
 
 
cords:
 
  db 0F 28 40 20 0F 29 4F 10
 
 
unregistersymbol(cords)
 
dealloc(newmem) | 	  
 
 
As soon as i remove the:
 
 
mov [ptrI2CETeleporterCoord],rax 
 
add [ptrI2CETeleporterCoord],0
 
 
The script activates. hmm
 | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
	 
	    
	   | 
	
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
  | 
   
 
		 |