-- ver 7.8e.2 --== Change this to another character you can use to test the userfunction, function will basically think it is a GM. ==-- local testcharname = "testchar" -- Must be exactly as the character's name, any capitals and any special letters. --=== New feature ===-- -- this is for monitoring players who may be following you. local ignoreplayertime = 30 -- time in seconds when alarm will be sounded for a player "following" you local clearplayertime = 60 -- time in seconds for players to be removed from table -- when the ignoreplayertime time is reached it will play the alarm sound -- if you want your own code performed then create a function named beingfollowed() and that code will be done instead. --Minimum Level for a GM local gmMinLevel = 86; --List of the known GM Names; local gmNameList = {"Thepit","Rhakara","Tohros","Saitomentor","Rakymos","Galorian","Inyrion", "Riujnara","Lulyane","Akasha","Vayus","Tathros","Ciarog","Aranrod" ,"Nohdrael","Kiareko","Adelynne","Rednaltor","Shenarah","Lonarhune" ,"Rismak","Rakymos","Ketagos","Golightly","Minutal","Farodin","Jyskal","Temper4nce"}; --On which Level search for GM's in the List?' "memory","server","" in last case it is deactivated local gmSearchMethode = "memory" --How often should the bot max response until it gives up. Make sure you have equal or more answer text then maxResponses local maxResponses = 1; -- ignores whispers by characters in the friends table, the names must be exact. local friends = {"someone","someoneelse","whoever"} --Pattern List for recognize a message from a GM local gmPattern = {gmMinLevel,testcharname,"GM","Moderator","Game Master","Gamemaster","WARNING GM DETECTED"} --Setting if you want relog when you find a GM with server search mode local loginClient = "Client" --Interval time config -- local checkmemory = 5; local checkserver = 180; local standard_pausetime = 180; --in s local standard_logouttime = 900; -- in s local waitduration = 5; --in s --config end-- --------------------------------------------------------------------------------------------------- local gm_detected = false; local last_gm_name = ""; local soundresource = nil; local logg,gmreply,gmname,playerexists,_time,printtime,pause_start,time_remaining local ResponseTable = {} local valid_chars = {} local wp = {} local wp2 = {} local ResponseUsed = {} local ResponseUsed2 = {} local lastGM_message ="" if( soundLoad ) then soundresource = soundLoad(getExecutionPath() .. "/alarm.wav"); if( soundresource == nil ) then warning("Failed to load sound file \'alarm.wav\'"); end end local function microcount(tableT) local count = 0; for _,v in pairs(tableT) do count = count + 1; end return count; end local function messagereply() -- You can write pretty much anything you want as the response -- but don't use any ' as it will mess with the code and just error out local randomResponseID; ResponseTable = { [1] = "Help me Alien from outer space are coming", [2] = "Some one is on the door outside", [3] = "My baby is crying", [4] = "My PC is smoking", [5] = "I have a lot of bullshot going that need my help ", [6] = "My wife slammed the pc I cant answer" } print("Response to Message \n"); if(chatbot ~= nil)then gmreply = chatbot(lastGM_message) sendMacro("SendChatMessage(\'"..gmreply.."\', 'WHISPER', 0, \'"..gmname.."\');"); if logg then logInfo(player.Name,"Answer to GM: "..gmname.." with: "..gmreply.."",true,"GM") end else if(ResponseUsed[gmname])then -- only to make sure that not some dum users end up in a infinity loop assert(#ResponseTable >= maxResponses,"The bot cant give more responses then messages,please check it") local testvar = microcount(ResponseUsed2[gmname]) if( microcount(ResponseUsed2[gmname]) < maxResponses)then --Not very effective, in true its a joke in computer science and quantum physic but its do the job IMO repeat randomResponseID = math.random(#ResponseTable); until not ResponseUsed2[gmname][randomResponseID.."Index"] gmreply = ResponseTable[randomResponseID] sendMacro("SendChatMessage(\'"..gmreply.."\', 'WHISPER', 0, \'"..gmname.."\');"); if logg then logInfo(player.Name,"Answer to GM: "..gmname.." with: "..gmreply.."",true,"GM") end ResponseUsed[gmname] = true; if(ResponseUsed2[gmname] == nil)then ResponseUsed2[gmname] = {}; end ResponseUsed2[gmname][randomResponseID.."Index"] = true; end else randomResponseID = math.random(#ResponseTable); gmreply = ResponseTable[randomResponseID] sendMacro("SendChatMessage(\'"..gmreply.."\', 'WHISPER', 0, \'"..gmname.."\');"); if logg then logInfo(player.Name,"Answer GM: "..gmname.." with: "..gmreply.."",true,"GM") end ResponseUsed[gmname] = true; if(ResponseUsed2[gmname] == nil)then ResponseUsed2[gmname] = {}; end ResponseUsed2[gmname][randomResponseID.."Index"] = true; end end local time, moreToCome, name, msg = EventMonitorCheck("GMdetect", "4,1") local msgtime = os.time() if( microcount(ResponseUsed2[gmname]) < maxResponses)then repeat if(msg)then yrest(5000) gmname = name; messagereply() end time, moreToCome, name, msg = EventMonitorCheck("GMdetect", "4,1") until (os.time() - msgtime) > 30 end end local valid_chars = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'Ä', 'ä', 'Ç', 'ç', 'Ü', 'ü', 'Ö', 'ö', 'ë', 'ÿ', 'ñ', }; local function sleep(duration) -- the bot will sleep but still fight back attackers local sleep_start = os.time(); -- calculate the sleep time player.Sleeping = true; -- we are sleeping cprintf(cli.yellow, language[89], os.date(), getKeyName(getStartKey()) ); local hf_key = ""; local loopcounter = 0; while(true) do local hf_key_pressed = false; if( keyPressedLocal(getStartKey()) ) then -- start key pressed hf_key_pressed = true; hf_key = "AWAKE"; end; if( hf_key_pressed == false ) then -- key released, do the work -- START Key: wake up if( hf_key == "AWAKE" ) then hf_key = " "; -- clear last pressed key cprintf(cli.yellow, language[90], getKeyName(getStartKey()), os.date() ); player.Sleeping = false; -- we are awake break; end; hf_key = " "; -- clear last pressed key end; if duration and os.time()-sleep_start > duration then player.Sleeping = false; -- we are awake break; end; player:updateBattling(); -- wake up if aggro, but we don't clear the sleeping flag if( player.Battling ) then -- we get aggro, player:clearTarget(); -- get rid of mob to be able to target attackers cprintf(cli.yellow, language[91], os.date() ); -- Awake from sleep because of aggro break; end; if(loopcounter % (checkmemory * 10) == 0)then GMdetection() end rest(100) loopcounter = loopcounter + 1; player:logoutCheck(); -- check logout timer end -- end of while -- count the sleeping time player.Sleeping_time = player.Sleeping_time + os.difftime(os.time(), sleep_start); end local function valid_name(name) -- Checks to make sure only valid characters are in the name. for i = 1,#name do local char = string.sub(name, i, i); if( not table.contains(valid_chars, char) ) then printf("Had a detection but the characters dont match up, probably a bug, ignoring it.\n") return false; end end return true; end local function searchGM(pawnNameorMsg,gmPatternList) if(gmSearchMethode == "")then if (gmPatternList == gmNameList)then return false; end end for _,v in pairs(gmPatternList) do if v and v ~= "" and string.find(pawnNameorMsg,v)then --print("Pawn Name: "..pawnNameorMsg.." name in table: "..v) return true; end end return false; end function searchGMList() local found = false local offline = getTEXT("SYS_ASK_PLAYER_INFO_NOT_FIND") EventMonitorStart("detectGMast", "CHAT_MSG_SYSTEM"); for _,v in pairs(gmNameList) do local foundmsg = false local waitstart = os.time() sendMacro("AskPlayerInfo(\'"..v.."\');"); repeat local time, moreToCome, msg = EventMonitorCheck("detectGMast", "1") --check if we found infos about the GM, so the GM is online if msg and string.find(msg, ".*%(.*%).*%(.*%)") then -- found a GM found = true -- leave inner loop break; end --check if we got a offline message if msg and msg == offline then -- timer reset just in cases waitstart = os.time() -- end loop flag foundmsg = true end -- timer so we have a time out if( waitduration <= (os.time() - waitstart))then -- we found a GM because no valid message was replied in time found = true -- leave inner loop because we found a GM (missed that in the previous version) break; end --check if we got no more messages and found at least one message until moreToCome ~= true and foundmsg -- check GM flag "found" if found == true then -- leave outer loop because we found a GM break; end end EventMonitorStop("detectGMast") if( not settings.profile.options.GMonServer)then print("No settings.profile.options.GMonServer specified answer is only a return value"); return found; end if( found and settings.profile.options.GMonServer == "logout")then keyboardRelease( settings.hotkeys.MOVE_FORWARD.key ); releaseKeys(); RoMScript("Logout();"); local PID = findProcessByWindow(getWin()); -- Get process ID os.execute("TASKKILL /PID " .. PID .. " /F"); while(true) do -- Wait for process to close... if( findProcessByWindow(__WIN) ~= PID ) then printf(language[88]); break; end; rest(100); end error("Logged out because GM whispered, used recall.") elseif(found and settings.profile.options.GMonServer == "pause")then if(settings.profile.options.GMPAUSETIME == nil)then print("GM online, make "..standard_pausetime.." sec pause and then recheck") sleep(standard_pausetime) else print("GM online, make "..settings.profile.options.GMPAUSETIME.." sec pause and then recheck") sleep(settings.profile.options.GMPAUSETIME) end player:updateBattling(); if(player.Battling)then player:fight(); end searchGMList(); elseif(found and settings.profile.options.GMonServer == "relog")then print("GM online, go off and relog after some time") if(getAcc == nil or getChar == nil)then error("GM Detection missing Userfunction LoginNextChar for RELOG") end local acc = getAcc() local char = getChar() keyboardRelease( settings.hotkeys.MOVE_FORWARD.key ); releaseKeys(); RoMScript("Logout();"); local PID = findProcessByWindow(getWin()); -- Get process ID os.execute("TASKKILL /PID " .. PID .. " /F"); while(true) do -- Wait for process to close... if( findProcessByWindow(__WIN) ~= PID ) then printf(language[88]); break; end; rest(100); end if(settings.profile.options.GMRELOGTIME == nil)then print("GM online,logout for "..standard_logouttime.." sec and then relog and recheck ") rest(standard_logouttime*1000) -- we wait for a half hour else print("GM online,logout for "..settings.profile.options.GMRELOGTIME.." sec and then relog and recheck ") rest(settings.profile.options.GMRELOGTIME*1000) end if(login ~= nil)then login(char, acc, loginClient); else error("GM Detection missing Userfunction Login for RELOG") end player:updateBattling(); if(player.Battling)then return found end searchGMList(); else return found; end return found end function GMdetection() --printf("Searching GMs \n"); local obj = nil; local objectList = CObjectList(); objectList:update(); gm_detected = false; for i = 0,objectList:size() do obj = objectList:getObject(i); if obj and obj.Type == PT_PLAYER and obj.Name ~= "" then local pawn = CPawn(obj.Address); if pawn and pawn.Name ~= player.Name and pawn.InParty ~= true then if ( pawn.Class1 == 0 or pawn.Class2 == 0 or pawn.Level >= gmMinLevel or pawn.Name == testcharname or searchGM(pawn.Name,gmNameList))then if( valid_name(pawn.Name) ) then gm_detected = true; if( pawn.Name ~= last_gm_name ) then logMessage(sprintf("A Game Master (%s) has been detected near your character.", pawn.Name)); end pawn:update(); printf("\n\nGM detected! Name: %s, Class IDs: %d/%d\n", tostring(pawn.Name), pawn.Class1, pawn.Class2); if logg then logInfo(player.Name,"GM detected! Name: "..tostring(pawn.Name)..", class IDs: "..pawn.Class1.."/"..pawn.Class2,true,"GM") end break; end last_gm_name = pawn.Name else --players if settings.profile.options.playerDETECT == true then for k,v in pairs(playertable) do if v.Name == obj.Name then --name in table already playerexists = true end end if playerexists ~= true then table.insert(playertable,{Name = pawn.Name, ptime = os.time(), alarmsounded = 0}) else for k,v in pairs(playertable) do if v.Name == obj.Name and (os.time() - v.ptime >= ignoreplayertime) and 3 >= v.alarmsounded then -- someone is following us if logg then logInfo(player.Name,"Followed by "..obj.Name.." Class IDs: "..pawn.Class1.."/"..pawn.Class2,true,"GM") end print("Followed by "..obj.Name) if beingfollowed then beingfollowed(obj,v.alarmsounded) else if playalarm then playalarm() else if( soundresource == nil ) then printf("\a\a\a"); else if( soundGetState(soundresource) ~= "playing" ) then soundPlay(soundresource); end end end end v.alarmsounded = v.alarmsounded + 1 end end end --=== clear out old names ===-- for k,v in pairs(playertable) do if os.time() - v.ptime >= clearplayertime then table.remove(playertable,k) end end end end end end end if( gm_detected ) then if playalarm then playalarm() else if( soundresource == nil ) then printf("\a\a\a"); else if( soundGetState(soundresource) ~= "playing" ) then soundPlay(soundresource); end end end if settings.profile.options.GMnearbylogout == true then RoMScript("Logout();"); error("Logging out because GM detected.") elseif gmnearby then gmnearby() end else last_gm_name = ""; end repeat local time, moreToCome, name, msg = EventMonitorCheck("GMdetect", "4,1") if msg ~= nil and name ~= "Newbie Pet" then -- make sure something was returned for k,v in pairs(friends) do if name == v then return end end if logg then logInfo(player.Name,"Char name: " ..name.. " Message: " ..msg,true,"GM") end EventMonitorStart("GMdetect2", "CHAT_MSG_SYSTEM"); local _ttime = RoMScript("GetTime()") if _ttime and time and 30 >= ( _ttime - time ) then sendMacro("AskPlayerInfo(\'"..name.."\');") rest(500) printf("\nYou have been whispered by: " ..name.. "\n") gmname = name local time, moreToCome, msg = EventMonitorCheck("GMdetect2", "1") if msg ~= nil then if logg then logInfo(player.Name,"Char name: " ..name.. " Message: " ..msg,true,"GM") end if searchGM(msg,gmPattern)then print("Found GM Message \n"); lastGM_message = msg; if playalarm then playalarm() playalarm() end if settings.profile.options.PAUSEONGM ~= 0 and settings.profile.options.PAUSEONGM ~= nil then keyboardRelease( settings.hotkeys.MOVE_FORWARD.key ); _time = settings.profile.options.PAUSEONGM pause_start = os.time() printtime = os.time() printf("Pausing for ".._time.." seconds. Press "..getKeyName(settings.hotkeys.START_BOT.key).." to stop the pause.\n") repeat if keypress ~= true then keyboardRelease( settings.hotkeys.MOVE_FORWARD.key ); keypress = true end player:update(); time_remaining = (pause_start + _time - os.time()) if (printed ~= true and (pause_start + 10) == os.time()) then printf("Time remaining "..time_remaining.." seconds.\n") printed = true printtime = os.time() end if printtime ~= nil then if (os.time() == printtime + 10) then printf("Time remaining "..time_remaining.." seconds.\n") printed = true printtime = os.time() end end if( player.Battling ) then -- we get aggro, printf("We got aggro, skipping pause and logging out.\n") player:update(); if settings.profile.options.RECALL == true then local cooldown, remaining = sendMacro("GetSkillCooldown(1,2);") if remaining > 1 then messagereply() keyboardRelease( settings.hotkeys.MOVE_FORWARD.key ); releaseKeys(); RoMScript("Logout();"); error("Recall was on cooldown, so logged out in mob area.") else player:update() local X = player.X local Z = player.Z repeat sendMacro("UseSkill(1,2);"); rest(1000) player:update() until memoryReadBytePtr(getProc(), addresses.loadingScreenPtr, addresses.loadingScreen_offset) ~= 0 or distance(player.X, player.Z, X, Z) > 100 or keyPressedLocal(settings.hotkeys.START_BOT.key) end if memoryReadBytePtr(getProc(), addresses.loadingScreenPtr, addresses.loadingScreen_offset) ~= 0 then waitForLoadingScreen() end yrest(5000) messagereply() keyboardRelease( settings.hotkeys.MOVE_FORWARD.key ); releaseKeys(); RoMScript("Logout();"); error("Logging out because GM whispered, used recall.") else yrest(5000) messagereply() keyboardRelease( settings.hotkeys.MOVE_FORWARD.key ); releaseKeys(); RoMScript("Logout();"); error("Logging out because GM whispered, used recall.") end end until os.time() == (pause_start + _time) or keyPressedLocal(settings.hotkeys.START_BOT.key) player:update() wp = __WPL:getNextWaypoint(); _distance = distance(player.X, player.Z, player.Y, wp.X, wp.Z, wp.Y); --printf(_distance.."\n") if _distance > 50 then -- we have been ported elsewhere __WPL:setWaypointIndex(__WPL:getNearestWaypoint(player.X, player.Z, player.Y)); player:update() wp2 = __WPL:getNextWaypoint(); _distance2 = distance(player.X, player.Z, player.Y, wp2.X, wp2.Z, wp2.Y); if _distance2 > 150 then RoMScript("Logout();"); if logg then logInfo(player.Name,"We were moved by a GM, WTF",true,"GM") end error("Logging out because we were moved by GM.") end end printf("reseting monitor\n") break else rest(5000) messagereply() keyboardRelease( settings.hotkeys.MOVE_FORWARD.key ); releaseKeys(); RoMScript("Logout();"); error("Logging out because GM whispered.") end end end end else break end if moreToCome == false then EventMonitorStop("GMdetect2") end until moreToCome == false end function startGMDetect() if logInfo then logg = true end playertable = {} if settings.profile.options.GMDETECT == true then printf("GM detection started\n"); EventMonitorStart("GMdetect", "CHAT_MSG_WHISPER"); registerTimer("GMdetection", secondsToTimer(checkmemory), GMdetection); if(gmSearchMethode == "server")then registerTimer("ServerDetection",secondsToTimer(checkserver),searchGMList) end end end function stopGMDetect() playertable = {} gmtimer = os.time() if settings.profile.options.GMDETECT == true then EventMonitorStop("GMdetect"); unregisterTimer("GMdetection"); printf("GM detection stopped\n"); if(gmSearchMethode == "server")then unregisterTimer("ServerDetection") end end end function restartGMDetect() printf("Going to restart GM detection \n"); stopGMDetect() startGMDetect() end