program ClarityEsswraith; {$DEFINE SMART} {$I SRL-6/SRL.simba} {ClarityEsswraith v1.18} const scriptVersion = '1.18'; showSRLDebug = false; usingDirectX = true; type esswraithProperties = record ewName: string; ewColor, ewTolerance, ewRuneSlot: integer; ewHue, ewSat, ewRCXP, ewPoints: extended; end; var desiredEsswraith: esswraithProperties; debugCount, scriptPaintBMP, runesAlreadyPresent, runesSiphoned, essenceAmount, islandTol, islandColor, resetWaitTime, islandSizeInt: integer; pointsCount, pointsPerHour, gainedXP, xpPerHour, islandHue, islandSat: extended; showScriptDebug, showScriptPaint, useRightClick, resetEsswraith: boolean; islandSize: String; currentTargetLoc: TPoint; failsafeTimer, wraithResetTimer, statsTimer: TTimeMarker; newValues, oldValues: array [0..2] of Integer; procedure declarePlayers; begin setLength(players, 1); with players[0] do begin //Standard Info loginName := 'Username'; password := '********'; isActive := true; isMember := true; world := 35; //Script-Specific Info strings[0] := 'Soul'; //replace with "Soul", "Blood", or "Death" for desired esswraith showScriptDebug := true; //do you want to see my script's debug messages? showScriptPaint := true; //do you want to see my script's paint? useRightClick := false; //do you want to left or right click esswraiths? resetEsswraith := false; //a more guaranteed method that yields slightly faster XP, also configure wait time below. resetWaitTime := 25000; //wait time before choosing another esswraith. islandSize := 'Small'; //what size island are you on? Write 'Small' or 'Big' - Small is highly recommended! {METHOD EXPLANATION 1. resetEsswraith := false - this method will detect when your player has stopped siphoning, and then begin to look for a new esswraith to siphon. This is perhaps a more humanlike approach, but slower as there is a small delay time between esswraiths. Expect 45k XP/HR at level 99 Soul Esswraiths with this method. 2. resetEsswraith := true - this method will look for a new esswraith after the wait time specified as "resetWaitTime" plus or minus a gauss range random amount. This has faster, more guaranteed XP but may appear more botlike. You will need a reserve of rune essence to use this method. The wait time will need to be adjusted based on your RC level, as you will want a time that expires just before esswraith death but not after. XP rates can indeed be lowered by other players fully draining the esswraiths, so use the former method if you are in a crowded world. Expect 55k XP/HR at level 99 Soul Esswraiths with this method.} {== The best island to run this script is detailed in the forum post! ==} end; currentPlayer := 0; end; {=== End of User Information, Beginning of Script ===} {PROCEDURE -- freeBMPs Purpose: Memory management procedure, expected to have extra things added in the future. Comments: None.} procedure freeBMPs; begin freeBitmap(scriptPaintBMP); end; {PROCEDURE -- setupPlayer Purpose: Starting procedure to make sure the camera and orientation is okay. Comments: None.} procedure setupPlayer; begin wait(gaussRangeInt(500, 3000)); minimap.clickCompass; wait(gaussRangeInt(200, 1500)); mainscreen.setAngle(MS_ANGLE_HIGH); wait(gaussRangeInt(500, 1000)); end; {PROCEDURE -- ClarityDebug Purpose: Custom debug procedure for my scripts. Comments: None.} procedure ClarityDebug(message: string); begin if showScriptDebug then writeln(ToStr(debugCount) + ' | == ClarityDebug == | ' + message); inc(debugCount); end; {PROCEDURE -- scriptStatus Purpose: Paints current script activity onto the client if paint is enabled. Comments: Thanks to The Mayor for the idea!} procedure scriptStatus(status: string); begin if showScriptPaint then begin try smartImage.clearArea(mainscreen.getBounds()); smartImage.drawText('STATUS: ', point(actionbar.x1 + 5, actionbar.y1 - 20), 'loginchars', true, clWhite); smartImage.drawText(status, point(actionbar.x1 + 68, actionbar.y1 - 20), 'loginchars', true, clYellow); smartImage.drawText(ToStr(Round(wraithResetTimer.getTime() / 1000)) + ' sec', point(mainscreen.x2 - 90, mainscreen.y1 + 12), 'loginchars', true, clWhite); except end; end; end; {PROCEDURE -- assignColorInfo Purpose: Assigns color data based on the user's desired esswraith. Comments: None.} procedure assignColorInfo; begin case players[CurrentPlayer].strings[0] of 'Death': begin with desiredEsswraith do begin ewName := 'eath'; ewColor := 7522995; ewTolerance := 14; ewHue := 0.03; ewSat := 1.72; ewRCXP := 60.0; ewRuneSlot := 8; ewPoints := 2.5; end; end; 'Blood': begin with desiredEsswraith do begin ewName := 'lood'; ewColor := 11565738; ewTolerance := 16; ewHue := 0.06; ewSat := 0.78; ewRCXP := 73.1; ewRuneSlot := 14; ewPoints := 3.0; end; end; 'Soul': begin with desiredEsswraith do begin ewName := 'oul'; ewColor := 14861862; ewTolerance := 17; ewHue := 0.13; ewSat := 1.43; ewRCXP := 106.5; ewRuneSlot := 15; ewPoints := 3.5; end; end; else begin ClarityDebug('Chosen esswraith not recognized. Ending script.'); terminateScript; end; end; case islandSize of 'Small': islandSizeInt := 35; 'Big': islandSizeInt := 80; end; end; {PROCEDURE -- calculateStats Purpose: Calculates stats for the stats commit. Comments: None.} procedure calculateStats(); var i, gainedXPInt: integer; calcValues: Array [0..2] of integer; begin gainedXPInt := round(gainedXP); calcValues := [round(getTimeRunning() / 60000), runesSiphoned, gainedXPInt]; for i := 0 to high(NewValues) do begin newValues[i] := calcValues[i] - oldValues[i]; oldValues[i] := calcValues[i]; end; end; {PROCEDURE -- sendStats Purpose: Sends stats to Clarity Live Stats Comments: None.} function sendStats(): boolean; var c, i: integer; statVars: Array [0..2] of string; begin statVars := ['Time', 'Bones', 'XP']; c := initializeHTTPClient(false); for i := 0 to high(statVars) do addPostVariable(c, statVars[i], intToStr(newValues[i])); result := pos('true', lowercase(postHTTPPageEx(c, 'http://srlclarity.com/commit/ClarityRunespanCommit.php'))) <> 0; freeHTTPClient(c); if result then calculateStats(); end; {PROCEDURE -- paintProgress Purpose: Paints progress on SMART client. Comments: None.} procedure paintProgress; var x, y: Integer; xpExt, xpPerHourExt: extended; xpString, xpPerHourString: string; xpArray, xpPerHourArray: array [0..1] of variant; begin if showScriptPaint then begin runesSiphoned := getItemAmount(tabBackpack.getSlotBox(desiredEsswraith.ewRuneSlot)) - runesAlreadyPresent; gainedXP := runesSiphoned * desiredEsswraith.ewRCXP; xpPerHour := Round(gainedXP * (3600.0 / (GetTimeRunning / 1000.0))); pointsCount := runesSiphoned * desiredEsswraith.ewPoints; pointsPerHour := Round(pointsCount * (3600.0 / (GetTimeRunning / 1000.0))); xpExt := gainedXP; xpPerHourExt := xpPerHour; xpArray[0] := xpExt; xpPerHourArray[0] := xpPerHourExt; xpString := Format('%n', xpArray); delete(xpString, length(xpString) - 3, 3); xpPerHourString := Format('%n', xpPerHourArray); delete(xpPerHourString, length(xpPerHourString) - 3, 3); smartImage.drawBitmap(scriptPaintBMP, Point(3, 461)); smartImage.drawText(ToStr(TimeRunning), Point(120, 520), 'smallChars', true, clWhite); smartImage.drawText(ToStr(pointsCount), Point(108, 542), 'smallChars', true, clWhite); smartImage.drawText(ToStr(pointsPerHour), Point(143, 564), 'smallChars', true, clWhite); smartImage.drawText(xpString + ' XP', Point(455, 481), 'smallChars', true, clLime); smartImage.drawText(xpPerHourString + ' XP/hr', Point(455, 497), 'smallChars', true, clLime); ClarityDebug('Our progress was painted.'); scriptStatus('Updated progress report.'); disguise('ClarityRunespan v' + ToStr(scriptVersion) + ' - ' + xpString + ' XP, ' + xpPerHourString + ' XP/hr'); if statsTimer.getTime() > 300000 then if sendStats() then begin ClarityDebug('Successfully committed usage statistics.'); scriptStatus('Committed usage stats to SRL Clarity Live Stats!'); wait(gaussRangeInt(500, 1500)); statsTimer.reset(); statsTimer.start(); end else begin ClarityDebug('Failed to commit usage statistics.'); scriptStatus('Failed to commit usage statistics.'); end; end; end; {PROCEDURE -- antiBan Purpose: Make us look more like a human and less like a bot. Comments: A standard random case antiban. I personally think camera rotation looks bad so I did not include it as a possible action.} procedure antiBan; var i: integer; begin if not isLoggedIn then exit; ClarityDebug('Antiban was initiated.'); scriptStatus('Performing antiban.'); i := random(610); case i of 1..40: smallRandomMouse(); 41..74: pickUpMouse(); 75..120: sleepAndMoveMouse(random(4000) + 1000); 121..250: mouseOffClient(OFF_CLIENT_RANDOM); 251..260: hoverSkill(SKILL_RUNECRAFTING); end; end; {FUNCTION -- getIslandGeography Purpose: Gets information about our island. Comments: None.} function getIslandGeography: TBox; var x, y, i: Integer; TPA, invertedTPA, currentIslandTPA, mainscreenTPA: TPointArray; ATPA: T2DPointArray; begin scriptStatus('Analyzing island layout.'); if findColorsSpiralTolerance(x, y, TPA, 9013865, minimap.getBounds(), 16, colorSetting(2, 3.10, 0.79)) then begin TPAtoATPAWrap(TPA, islandSizeInt, ATPA); ATPA.sortFromMidPoint(point(minimap.cx, minimap.cy)); currentIslandTPA := ATPA[0]; mainscreenTPA := minimap.pointsToMainscreen(currentIslandTPA); smartImage.debugTPA(mainscreenTPA); result := mainscreenTPA.getBounds(); end; end; {FUNCTION -- findEsswraith Purpose: Search for NPC colors, sort them, select siphon option. Comments: None.} function findEsswraith: boolean; var x, y, i, attempts: integer; TPA: TPointArray; ATPA: T2DPointArray; begin if not isLoggedIn then exit; ClarityDebug('FindEsswraith was initiated.'); while attempts < 15 do begin if findColorsSpiralTolerance(x, y, TPA, desiredEsswraith.ewColor, mainScreen.getBounds(), desiredEsswraith.ewTolerance, colorSetting(2, desiredEsswraith.ewHue, desiredEsswraith.ewSat)) then begin TPA.filterPointsBox(getIslandGeography); mainscreen.filterPointsPlayer(TPA); TPAtoATPAWrap(TPA, 40, ATPA); ATPA.sortFromMidPoint(mainscreen.playerPoint); if showScriptDebug then smartImage.debugATPA(ATPA); for i := 0 to high(ATPA) do begin mouse(ATPA[i].getMiddle, MOUSE_MOVE, MOUSE_HUMAN); if isMouseOverText([desiredEsswraith.ewName], 500) then begin if useRightClick then begin fastClick(MOUSE_RIGHT); if not chooseOption.optionsExist(['iphon']) then begin ClarityDebug('Siphon option not present.'); scriptStatus('Siphon option not present - retrying.'); chooseOption.close(); continue; end; result := chooseOption.select(['iphon', 'raith']); scriptStatus('Esswraith search and siphon successful.'); failsafeTimer.reset; failsafeTimer.start; wraithResetTimer.reset; wraithResetTimer.start; smallRandomMouse; antiban; wait(gaussRangeInt(2000,3000)); exit; end else begin if didClick(true, gaussRangeInt(900,1100)) then begin scriptStatus('Esswraith search and siphon successful.'); result := true; failsafeTimer.reset; failsafeTimer.start; wraithResetTimer.reset; wraithResetTimer.start; smallRandomMouse; antiban; wait(gaussRangeInt(2000,3000)); exit; end else continue; end; end else continue; end; end else ClarityDebug('Unable to successfully click on an esswraith.'); inc(attempts); end; end; {FUNCTION -- findWizard Purpose: Search for NPC colors, sort them, select siphon option. Comments: IN PROGRESS} {function findWizard: boolean; var x, y, i, attempts: integer; TPA: TPointArray; ATPA: T2DPointArray; begin if not isLoggedIn then exit; ClarityDebug('FindWizard was initiated.'); while attempts < 15 do begin if findColorsSpiralTolerance(x, y, TPA, 7332076, mainScreen.getBounds(), 13, colorSetting(2, 0.12, 1.86)) then begin TPA.filterPointsBox(getIslandGeography); mainscreen.filterPointsPlayer(TPA); TPAtoATPAWrap(TPA, 30, ATPA); ATPA.sortFromMidPoint(mainscreen.playerPoint); if showScriptDebug then smartImage.debugATPA(ATPA); for i := 0 to high(ATPA) do begin mouse(ATPA[i].getMiddle, MOUSE_MOVE, MOUSE_HUMAN); if isMouseOverText(['izard'], 500) then begin if useRightClick then begin fastClick(MOUSE_RIGHT); if not chooseOption.optionsExist(['alk to']) then begin ClarityDebug('Talk option not present.'); scriptStatus('Talk option not present - retrying.'); chooseOption.close(); continue; end; result := chooseOption.select(['alk to']); scriptStatus('Wizard search and talk successful.'); failsafeTimer.reset; failsafeTimer.start; wraithResetTimer.reset; wraithResetTimer.start; smallRandomMouse; antiban; wait(gaussRangeInt(2000,3000)); exit; end else begin if didClick(true, gaussRangeInt(900,1100)) then begin scriptStatus('Wizard search and talk successful.'); result := true; failsafeTimer.reset; failsafeTimer.start; wraithResetTimer.reset; wraithResetTimer.start; smallRandomMouse; antiban; wait(gaussRangeInt(2000,3000)); exit; end else continue; end; end else continue; end; end else ClarityDebug('Unable to successfully click on a wizard.'); inc(attempts); end; end;} {FUNCTION -- areWeSiphoning Purpose: Determines whether player is siphoning. Comments: None.} function areWeSiphoning: boolean; var shift: Integer; begin shift := getPixelShift(mainscreen.playerBox, 2000); ClarityDebug(ToStr(shift)); if shift > 235 then begin result := true; ClarityDebug('We are siphoning.'); scriptStatus('Currently siphoning an esswraith.'); end else begin result := false; ClarityDebug('We are not siphoning.'); scriptStatus('We are no longer siphoning.'); end; end; {Procedure AutoupdateMe; By: Shuttleu Edited By: Ashaman88 & Clarity Purpose: Autoupdates Script.} procedure AutoUpdateMe; var Neifile: Integer; OnlineVersion, NewScript, NeiFeilNennen: string; begin ClarityDebug('Checking for script updates...'); OnlineVersion := GetPage('http://pastebin.com/raw.php?i=6qTEF8hv'); ClarityDebug('Online Script Version: ' + OnlineVersion); ClarityDebug('Local Script Version: ' + ScriptVersion) if (trim(OnlineVersion) > ScriptVersion) then begin ClarityDebug('Newer script version online!'); ClarityDebug('Autoupdating to newer version.'); NewScript := GetPage('http://pastebin.com/raw.php?i=UP6FB4WJ'); NeiFeilNennen := ScriptPath + 'ClarityEsswraith v' + OnlineVersion + '.simba'; Neifile := Rewritefile(NeiFeilNennen, true); try WriteFileString(Neifile, NewScript); except begin ClarityDebug('Fatal error writing to ' + NeiFeilNennen + '!'); Terminatescript; end; end; CloseFile(Neifile); ClarityDebug('New script downloaded to ' + NeiFeilNennen + '! Terminating old script, please use the new version.'); TerminateScript; end else ClarityDebug('You have the latest version of the script!'); end; {Procedure checkForFiles; By: Kevin Edited By: Clarity Purpose: Checks/downloads files.} procedure checkForFiles(filePath, message, link: string); var progFile: longInt; fileName: string; begin fileName := AppPath + filePath; try if not fileExists(fileName) then begin ClarityDebug('-- INSTALLATION STATUS: ' + message + ' does not exist - Downloading now.'); progFile := createFile(fileName); end else begin ClarityDebug('-- INSTALLATION STATUS: ' + message + ' exists.'); exit; end; closeFile(progFile); progFile := rewriteFile(fileName, false); writeFileString(progFile, getPage(link)); ClarityDebug('-- INSTALLATION STATUS: ' + message + ' has been downloaded.'); finally if (progFile > 0) then closeFile(progFile); end; end; {PROCEDURE -- installClarityEsswraithAssets Purpose: Determines whether files exist and dictates their installation. Comments: None.} procedure InstallClarityEsswraithAssets; begin ClarityDebug('Please wait...now installing ClarityEsswraith image assets to your computer...'); if not directoryExists(appPath + 'scripts/ClarityEsswraithImages/') then begin try createDirectory(appPath + 'scripts/ClarityEsswraithImages/'); ClarityDebug('Created a new folder in Simba/Scripts/'); except end; end; checkForFiles('scripts/ClarityEsswraithImages/esswraithpaint2.png', 'Script Paint', 'http://i.imgur.com/koBCgOr.png'); end; {PROCEDURE -- mainLoop Purpose: Script's main loop. Checks if we are gaining XP before calling the findEsswraith; function. Comments: None.} procedure mainLoop; var x, y: Integer; ticketLoc, failurePoint: TPoint; failureBox: TBox; begin if findSpinTicket(ticketLoc) then mouse(ticketLoc, MOUSE_LEFT, MOUSE_HUMAN); if not resetEsswraith then begin if not areWeSiphoning then begin ClarityDebug('No longer gaining RC XP.'); findEsswraith; paintProgress; end; if (failsafeTimer.getTime() > 60000) and areWeSiphoning then begin ClarityDebug('Failsafe timer expired.'); scriptStatus('Nothing happened for awhile, walking somewhere.'); failureBox := getIslandGeography; failurePoint := failureBox.getRandomPoint(); mouse(failurePoint, MOUSE_MOVE, MOUSE_HUMAN); fastClick(MOUSE_LEFT); failsafeTimer.reset; failsafeTimer.start; end; end; if (wraithResetTimer.getTime > (resetWaitTime + gaussRangeInt(-5000,5000))) and resetEsswraith then begin findEsswraith; paintProgress; end; end; begin clearDebug; writeLn('ClarityEsswraith v' + scriptVersion); writeLn('Initializing script...'); smartEnableDrawing := true; disableSRLDebug := not showSRLDebug; addOnTerminate('freeBMPs'); if usingDirectX then smartPlugins := ['d3d9.dll']; setupsrl; declarePlayers; assignColorInfo; autoUpdateMe; installClarityEsswraithAssets; runesAlreadyPresent := getItemAmount(tabBackpack.getSlotBox(desiredEsswraith.ewRuneSlot)); ClarityDebug('ClarityEsswraith initiated. Enjoy free RC experience!'); ClarityDebug(''); ClarityDebug('Using Esswraith OverText: ' + desiredEsswraith.ewName); ClarityDebug('Using Esswraith Color: ' + IntToStr(desiredEsswraith.ewColor)); ClarityDebug('Using Esswraith Tolerance: ' + IntToStr(desiredEsswraith.ewTolerance)); if showScriptPaint then scriptPaintBMP := loadBitmap(appPath + '/Scripts/ClarityEsswraithImages/esswraithpaint2.png'); if not isLoggedIn then if players[currentPlayer].login then setupPlayer; statsTimer.start(); while players.getActive > 0 do mainLoop; end.