Author |
Message |
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
yes .. more from what i understood was for general card box so i can set up these variables .. i did it manually .. however n ´taking the lvl
yes .. more from what i understood was for general card box so i can set up these variables .. i did it manually .. however n ´taking the lvl
|
|
|
|
Posted: Mon Dec 28, 2020 3:25 am |
|
|
|
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
Yea, you need to fill it in before it will compile. You either need to add: "yes" or "no" (in quotes) ...for whether or not to complete the current iteration before breaking from the loop
Yea, you need to fill it in before it will compile. You either need to add: "yes" or "no" (in quotes) ...for whether or not to complete the current iteration before breaking from the loop
|
|
|
|
Posted: Sun Dec 27, 2020 12:43 pm |
|
|
|
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
Quote: begin // // For help using/configuring this bot, please refer to http://www.blueeye-macro.com/viewtopic.php?f=269&t=885 // // Note: Make sure to ALWAYS set the location of the "Coordinates Assistant" to the top left corner before starting the macro! // The location of the dialog will be remembered the next time you start the game, so you just need to do this once // // USER CONFIGURATION START // // Key bindings: Set your key bindings in the lower left corner variables // Example: To set a keybinding to the F1-Key, enter: {<F1>} // Example: To set a keybinding to the numeric 1-key, enter: 1 // // The filepath to your leveling paths file e.g. c:\leveling path.txt (See/share examples of this file at http://www.blueeye-macro.com) Variable.Set("LevelPath", "c:\Perfect World Path.txt") // If you die this many times, the macro will automatically abort Variable.Set("StopMacroIfDeadTimes", "10") // Only run the macro for the following amount of minutes (How long does your armor and weapon durability last? (if you care)) Variable.Set("WarpToTownAndStopMacroAfterMinutes", "120") // How often (in %) should a a single pre-attack spell be cast, before finishing off the monster with your primary attack (Good for a slowing spell) Variable.Set("PreAttackPercentage", "90") // How often (in %) should a human-like pause be inserted between monsters? (Makes you appear less bot-like) Variable.Set("HumanPausePercentage", "5") // At which percentage of your full HP / MP should meditation begin (Set HP to 0 if you dont want to use meditation for HP regen (if you have healing spell)) Variable.Set("MeditateAtHPPercentage", "40") Variable.Set("MeditateAtMPPercentage", "30") // Between each monster, use healing spell if your HP gets bellow this percentage Variable.Set("UseHealingSpellAtHPPercentage", "85") // If you have a healing spell, how long does it take to cast? (in ms. 1000 ms = 1 sec. 1500 ms = 1,5 sec etc.) Variable.Set("HealingSpellCastTime", "1000") // During fights, at which HP / MP percentage should potions be used Variable.Set("UseHealthPotionAtHPPercentage", "35") Variable.Set("UseManaPotionAtMPPercentage", "70") // // USER CONFIGURATION END // // Static configuration Variable.Set("processName", "elementclient") Variable.Set("windowName", "Element Client") // Store memory addresses / window name in variables, to make it easier to update if the memory addresses change with a game update Variable.Set("maxHPMemoryAddress", "elementclient.exe+65BFCC,20,4b4") Variable.Set("maxMPMemoryAddress", "elementclient.exe+65BFCC,20,4b8") Variable.Set("currentHPMemoryAddress", "elementclient.exe+65BFCC,20,474") Variable.Set("currentMPMemoryAddress", "elementclient.exe+65BFCC,20,478") Variable.Set("currentLevelMemoryAddress", "elementclient.exe+65BFCC,20,46c") Variable.Set("currentLocationXMemoryAddress", "elementclient.exe+65bfcc,20,384,3c") Variable.Set("currentLocationYMemoryAddress", "elementclient.exe+65bfcc,20,384,44") Variable.Set("currentLocationHeightMemoryAddress", "elementclient.exe+65bfcc,20,384,40") Variable.Set("hasTargetMemoryAddress", "elementclient.exe+65BFCC,20,1088,38") Variable.Set("topMostDialogLocationXMemoryAddress", "elementclient.exe+0065BFCC,4,8,70,98") Variable.Set("topMostDialogLocationYMemoryAddress", "elementclient.exe+0065BFCC,4,8,70,9c") Variable.Set("deathDialogLocationXMemoryAddress", "elementclient.exe+0065BFCC,4,8,4a0,98") Variable.Set("deathDialogLocationYMemoryAddress", "elementclient.exe+0065BFCC,4,8,4a0,9c") Variable.Set("reachDestinationCheckBoxMemoryAddress", "elementclient.exe+65BFE4,270,2bc,1f0,119") Variable.Set("windowActiveMemoryAddress", "elementclient.exe+65B90C,48c") // Adjust variables Variable.Set("deathCount", "0") Variable.Set("killCount", "0") Variable.Add (Math)("HealingSpellCastTime", "750") // Convert minutes into milliseconds Variable.Multiply (Math)("WarpToTownAndStopMacroAfterMinutes", "60000") // Make sure the required key bindings have been set Function.Execute("Check keybindings") // Make sure the window doesnt freeze when it looses focus (to support playing with the game minimized and without focus) Memory.Freeze value("{processName}", "{windowActiveMemoryAddress}", "4", "1") // Make sure to reset targets when starting the bot by pressing escape Window.Send press keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("750") if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Window.Display message box("Please make sure you dont have an npc targeted when starting the Macro! the Macro will now exit", "no") Macro.Abort() end // Activate our buffs before starting, and start the stop watches, keeping track of the buff durations Function.Execute("Init buffs") begin loop() Function.Execute("Output status") Function.Execute("Use potions") Function.Execute("Ensure buffs are still active") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute with timeout("Ensure within specified hunting ground", "300000") Function.Execute("Output status") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute("Perform healing if required") Function.Execute("Output status") Function.Execute with timeout("Get target", "2500") if Function.Did not timeout("Get target") begin Function.Execute("Release corpse, heal and fly back if dead") Function.Execute with timeout("Kill target", "60000") Function.Execute("Perform healing if required") if Function.Did timeout("Kill target") begin // If the target does not die within 1 minute, the monster probably cant get to us, so it cant die, select a new target Window.Send press keys("{windowName}", "yes", "0", "{targetKey}") Macro.Pause("250") Function.Execute with timeout("Kill target", "60000") Function.Execute("Perform healing if required") end end Function.Execute with timeout("Get loot", "10000") Function.Execute("Output status") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute("Output status") Function.Execute("Meditate if required") Function.Execute("Simulate human pause") if Macro.Execution time has exceeded("{WarpToTownAndStopMacroAfterMinutes}") begin Window.Send press keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("1000") Window.Send press keys("{windowName}", "yes", "0", "{TownPortalKey}") Macro.Pause("500") Macro.Abort() end end end function("Simulate human pause") if Random.Maybe("{HumanPausePercentage}") begin Variable.Set random number("pauseTimes", "5", "15") begin loop("{pauseTimes}") Macro.Pause("500") // If we are attacked, abort human pause to be able to defend ourselves first if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end end end function function("Use potions") if Variable.Is not empty("HealthPotionKey") begin Function.Execute("Calculate current HP percentage") if Variable.Is less than (Math)("currentHPpercentage", "{UseHealthPotionAtHPPercentage}") begin Window.Send press keys("{windowName}", "yes", "0", "{HealthPotionKey}") end end if Variable.Is not empty("ManaPotionKey") begin Function.Execute("Calculate current MP percentage") if Variable.Is less than (Math)("currentMPpercentage", "{UseManaPotionAtMPPercentage}") begin Window.Send press keys("{windowName}", "yes", "0", "{ManaPotionKey}") end end function function("Check keybindings") if Variable.Is empty("AttackKey") or Variable.Is empty("LootKey") or Variable.Is empty("MeditateKey") or Variable.Is empty("TownPortalKey") or Variable.Is empty("TargetKey") begin Window.Display message box("Please 'Right click' --> 'Edit Macro' and make sure to specify key bindings for at least: Target, Attack, Loot, Town portal and Meditation", "no") Macro.Abort() end function function("Init buffs") if Variable.Is not empty("Buff1Key") and Variable.Is not empty("Buff1Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff1Key}") if Variable.Is less than (Math)("Buff1Duration", "1000") begin // Convert the duration from minutes to milliseconds Variable.Evaluate (Math)("({Buff1Duration}*60)*1000", "Buff1Duration") end Macro.Restart stopwatch("Buff1Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff2Key") and Variable.Is not empty("Buff2Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff2Key}") if Variable.Is less than (Math)("Buff2Duration", "1000") begin Variable.Evaluate (Math)("({Buff2Duration}*60)*1000", "Buff2Duration") end Macro.Restart stopwatch("Buff2Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff3Key") and Variable.Is not empty("Buff3Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff3Key}") if Variable.Is less than (Math)("Buff3Duration", "1000") begin Variable.Evaluate (Math)("({Buff3Duration}*60)*1000", "Buff3Duration") end Macro.Restart stopwatch("Buff3Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff4Key") and Variable.Is not empty("Buff4Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff4Key}") if Variable.Is less than (Math)("Buff4Duration", "1000") begin Variable.Evaluate (Math)("({Buff4Duration}*60)*1000", "Buff4Duration") end Macro.Restart stopwatch("Buff4Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff5Key") and Variable.Is not empty("Buff5Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff5Key}") if Variable.Is less than (Math)("Buff5Duration", "1000") begin Variable.Evaluate (Math)("({Buff5Duration}*60)*1000", "Buff5Duration") end Macro.Restart stopwatch("Buff5Watch") Macro.Pause("2000") end function function("Ensure buffs are still active") // If we are attacked, abort to be able to defend ourselves first if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end if Macro.Stopwatch exists("Buff1Watch") begin Macro.Read stopwatch("Buff1Watch", "buff1Time") if Variable.Is greater than (Math)("buff1Time", "{Buff1Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff1Key}") Macro.Restart stopwatch("Buff1Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff2Watch") begin Macro.Read stopwatch("Buff2Watch", "buff2Time") if Variable.Is greater than (Math)("buff2Time", "{Buff2Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff2Key}") Macro.Restart stopwatch("Buff2Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff3Watch") begin Macro.Read stopwatch("Buff3Watch", "buff3Time") if Variable.Is greater than (Math)("buff3Time", "{Buff3Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff3Key}") Macro.Restart stopwatch("Buff3Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff4Watch") begin Macro.Read stopwatch("Buff4Watch", "buff4Time") if Variable.Is greater than (Math)("buff4Time", "{Buff4Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff4Key}") Macro.Restart stopwatch("Buff4Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff5Watch") begin Macro.Read stopwatch("Buff5Watch", "buff5Time") if Variable.Is greater than (Math)("buff5Time", "{Buff5Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff5Key}") Macro.Restart stopwatch("Buff5Watch") Macro.Pause("2000") end end function function("Output status") begin Memory.Get value("{processName}", "{currentLevelMemoryAddress}", "4", "outputLvl") Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "outputHP") Memory.Get value("{processName}", "{currentMPMemoryAddress}", "4", "outputMP") Variable.Evaluate (Text)("Level: {outputLvl}, Kills: {killCount}, Deaths: {deathCount}, HP: {outputHP}, MP: {outputMP}", "statusOutput") Macro.Report progress("{statusOutput}") end function function("Calculate current HP percentage") begin Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "currentHP") Memory.Get value("{processName}", "{maxHPMemoryAddress}", "4", "maxHP") Variable.Evaluate (Math)("({currentHP}/{maxHP})*100", "currentHPpercentage") end function function("Calculate current MP percentage") begin Memory.Get value("{processName}", "{currentMPMemoryAddress}", "4", "currentMP") Memory.Get value("{processName}", "{maxMPMemoryAddress}", "4", "maxMP") Variable.Evaluate (Math)("({currentMP}/{maxMP})*100", "currentMPpercentage") end function function("Meditate if required") // If we are attacked, abort to be able to defend ourselves if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin Function.Execute("Calculate current HP percentage") Function.Execute("Calculate current MP percentage") end if Variable.Is less than (Math)("currentHPpercentage", "{MeditateAtHPPercentage}") or Variable.Is less than (Math)("currentMPpercentage", "{MeditateAtMPPercentage}") begin Window.Send press keys("{windowName}", "yes", "0", "{MeditateKey}") begin loop() Macro.Pause("750") Function.Execute("Output status") Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "hpCheckCurrent") // If we are attacked, or at 100% HP / MP then abort meditation if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") or Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "{maxHP}") and Memory.Value is("{processName}", "{currentMPMemoryAddress}", "4", "{maxMP}") begin Window.Send press keys("{windowName}", "yes", "0", "{MeditateKey}") Macro.Pause("1000") Window.Send press keys("{windowName}", "yes", "0", "{LootKey}") Function.Abort() end end end function function("Perform healing if required") // If we specified a key for the spell "Iron heart" (or another healing spell) if Variable.Is not empty("HealingKey") begin Function.Execute("Calculate current HP percentage") if Variable.Is less than (Math)("currentHPpercentage", "{UseHealingSpellAtHPPercentage}") begin Macro.Pause("250") Window.Send press keys("{windowName}", "yes", "0", "{HealingKey}") Macro.Pause("{HealingSpellCastTime}") end end function function("Release corpse, heal and fly back if dead") if Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "0") begin Variable.Increment (Math)("deathCount") // Move the "You are dead" box to coordinate 0,0 Memory.Set value("{processName}", "{deathDialogLocationXMemoryAddress}", "4", "0") Memory.Set value("{processName}", "{deathDialogLocationYMemoryAddress}", "4", "0") Macro.Pause("1000") // Click "Release corpse" Window.Send mouse click("{windowName}", "yes", "0", "125", "71", "left") Macro.Pause("10000") if Variable.Is equal to("deathCount", "{StopMacroIfDeadTimes}") begin Variable.Evaluate (Text)("The bot was aborted because you died {deathCount} times", "output") Window.Display message box("{output}", "no") Macro.Abort() end Function.Execute("Use potions") Function.Execute("Meditate if required") Macro.Pause("1000") Function.Execute("Init buffs") Function.Execute with timeout("Ensure within specified hunting ground", "300000") end function function("Get target") begin loop() if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin // If we already have a target, abort Function.Abort() end Window.Send press keys("{windowName}", "yes", "0", "{TargetKey}") Macro.Pause("250") Function.Execute("Use potions") end function function("Get loot") begin Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "locationHash") Macro.Pause("200") // If we are being attacked, dont waste any time picking up drops if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin loop() begin loop("8") Window.Send press keys("{windowName}", "yes", "0", "{LootKey}") Macro.Pause("200") end Function.Execute("Use potions") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") or Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin // Abort if we finished picking up drops (stopped moving), or if we are under attack. Function.Abort() end Variable.Set("locationHash", "{newLocationHash}") end end function function("Kill target") if Variable.Is not empty("PreAttackKey") and Random.Maybe("{PreAttackPercentage}") begin Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "locationHash") Window.Send press keys("{windowName}", "yes", "0", "{PreAttackKey}") Macro.Pause("750") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is not equal to("locationHash", "{newLocationHash}") begin loop("7") // If we had to move to get close enough to our target, wait a bit while casting the PreAttack spell Variable.Set("locationHash", "{newLocationHash}") Macro.Pause("750") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") begin Macro.Break from loop() end end end begin loop() Window.Send press keys("{windowName}", "yes", "0", "{AttackKey}") Macro.Pause("40") Function.Execute("Use potions") Macro.Pause("40") // If our target is dead or we died ourselves, stop attacking if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "0") or Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "0") begin Variable.Increment (Math)("killCount") // Quickly press esc to avoid wasting MP on a monster that is already dead. Window.Send press keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("100") Function.Abort() end end function function("Ensure within specified hunting ground") // If we are attacked, abort to be able to defend ourselves before flying anywhere if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin Function.Execute("Get desired location") Function.Execute("Get player location") Variable.Evaluate (Math)("{x} - {desiredX}", "rangeX") if Variable.Is less than (Math)("rangeX", "0") begin Variable.Multiply (Math)("rangeX", "-1") end Variable.Evaluate (Math)("{y} - {desiredY}", "rangeY") if Variable.Is less than (Math)("rangeY", "0") begin Variable.Multiply (Math)("rangeY", "-1") end if Variable.Is less than (Math)("rangeX", "{desiredRange}") and Variable.Is less than (Math)("rangeY", "{desiredRange}") begin // If we are already within the specified range of our prefered hunting ground, dont go anywhere Function.Abort() end Variable.Evaluate (Text)("{desiredX} {desiredY}", "location") Window.Get size("{windowName}", "yes", "width", "unused") Variable.Subtract (Math)("width", "35") // If we are able to fly, activate wings, to help avoiding getting stuck if Variable.Is not empty("FlyKey") begin Window.Send press keys("{windowName}", "yes", "0", "{FlyKey}") end Macro.Pause("50") // Open the Path dialog Window.Send mouse click("{windowName}", "yes", "0", "{width}", "110", "left") Macro.Pause("750") Window.Send mouse click("{windowName}", "yes", "0", "293", "381", "left") Macro.Pause("250") Window.Send press keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("250") Window.Send mouse click("{windowName}", "yes", "0", "270", "40", "left") Macro.Pause("250") begin loop("25") // Delete whatever has already been entered Window.Send press keys("{windowName}", "yes", "0", "{<backspace>}") Macro.Pause("5") end Window.Send press keys("{windowName}", "yes", "0", "{location}") Macro.Pause("50") Window.Send press keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("200") Window.Send press keys("{windowName}", "yes", "0", "{location}") Macro.Pause("50") Window.Send press keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("200") Window.Send mouse double click("{windowName}", "yes", "0", "250", "60", "left") Macro.Pause("250") // Make sure the Auto-Path-Height box is located at coordinate 0,0 Memory.Set value("{processName}", "{topMostDialogLocationXMemoryAddress}", "4", "0") Memory.Set value("{processName}", "{topMostDialogLocationYMemoryAddress}", "4", "0") // Enable "Reach Destination" Memory.Set value("{processName}", "{reachDestinationCheckBoxMemoryAddress}", "1", "1") Macro.Pause("25") Window.Send mouse click("{windowName}", "yes", "0", "145", "43", "left") Macro.Pause("150") begin loop("15") // Delete whatever "Height" previously entered Window.Send press keys("{windowName}", "yes", "0", "{<backspace>}") Macro.Pause("5") end Window.Send press keys("{windowName}", "yes", "0", "{desiredHeight}") Macro.Pause("50") Window.Send mouse click("{windowName}", "yes", "0", "108", "106", "left") Variable.Set("locationHash", "0") begin loop() // Wait for our character to stop moving, meaning we reached our destination Macro.Pause("2500") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") begin // if the location "hash" is unchanged, meaning we reached our destination, close the Path window Window.Send mouse click("{windowName}", "yes", "0", "108", "106", "left") Macro.Pause("250") Window.Send press keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("250") Function.Abort() end Variable.Set("locationHash", "{newLocationHash}") end end function function("Get desired location") // If this is the first run, we will load the hunting ground paths in to memory if Variable.Does not exist("paths") begin File.Read text("{LevelPath}", "paths") if Variable.Does not exist("paths") begin Variable.Evaluate (Text)("A level path file was not found at {LevelPath}, the macro will now quit (for help please visit http://www.blueeye-macro.com)", "errorOutput") Window.Display message box("{errorOutput}", "no") Macro.Abort() end Variable.Extract partial text (Regex)("paths", "(?s)-{25,}(.*)", "1", "paths") if Variable.Is not match (Regex)("paths", ":1:(?: [0-9]+){4}") begin Variable.Evaluate (Text)("A level path file was found, but it does not contain a leveling path for at least level 1. The macro will now quit, for help please visit http://www.blueeye-macro.com)", "errorOutput") Window.Display message box("{errorOutput}", "no") Macro.Abort() end end begin // Find the area coordinate that applies to our current level (or go with the nearest level path lower than our current level) Memory.Get value("{processName}", "{currentLevelMemoryAddress}", "4", "lvl") begin loop() Variable.Evaluate (Text)(":{lvl}: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)", "pattern") if Variable.Is match (Regex)("paths", "{pattern}") begin Macro.Break from loop() end Variable.Decrement (Math)("lvl") if Variable.Is less than (Math)("lvl", "0") begin Window.Display message box("Failed determining the leveling path for your level", "no") Macro.Abort() end end Variable.Extract partial text (Regex)("paths", "{pattern}", "1", "desiredX") Variable.Extract partial text (Regex)("paths", "{pattern}", "2", "desiredY") Variable.Extract partial text (Regex)("paths", "{pattern}", "3", "desiredHeight") Variable.Extract partial text (Regex)("paths", "{pattern}", "4", "desiredRange") end function function("Get player location") begin // Get our current location, with all decimals Memory.Get value("{processName}", "{currentLocationXMemoryAddress}", "float", "x") Variable.Evaluate (Math)("401+({x}/10)", "x") Memory.Get value("{processName}", "{currentLocationYMemoryAddress}", "float", "y") Variable.Evaluate (Math)("551+({y}/10)", "y") Memory.Get value("{processName}", "{currentLocationHeightMemoryAddress}", "float", "z") Variable.Divide (Math)("z", "10") end function currently the code looks like this ... but with a new error.
Attachments: |
Capturar.PNG [ 39.24 KiB | Viewed 3103 times ]
|
[quote] begin // // For help using/configuring this bot, please refer to http://www.blueeye-macro.com/viewtopic.php?f=269&t=885 // // Note: Make sure to ALWAYS set the location of the "Coordinates Assistant" to the top left corner before starting the macro! // The location of the dialog will be remembered the next time you start the game, so you just need to do this once // // USER CONFIGURATION START // // Key bindings: Set your key bindings in the lower left corner variables // Example: To set a keybinding to the F1-Key, enter: {<F1>} // Example: To set a keybinding to the numeric 1-key, enter: 1 // // The filepath to your leveling paths file e.g. c:\leveling path.txt (See/share examples of this file at http://www.blueeye-macro.com) Variable.Set("LevelPath", "c:\Perfect World Path.txt") // If you die this many times, the macro will automatically abort Variable.Set("StopMacroIfDeadTimes", "10") // Only run the macro for the following amount of minutes (How long does your armor and weapon durability last? (if you care)) Variable.Set("WarpToTownAndStopMacroAfterMinutes", "120") // How often (in %) should a a single pre-attack spell be cast, before finishing off the monster with your primary attack (Good for a slowing spell) Variable.Set("PreAttackPercentage", "90") // How often (in %) should a human-like pause be inserted between monsters? (Makes you appear less bot-like) Variable.Set("HumanPausePercentage", "5") // At which percentage of your full HP / MP should meditation begin (Set HP to 0 if you dont want to use meditation for HP regen (if you have healing spell)) Variable.Set("MeditateAtHPPercentage", "40") Variable.Set("MeditateAtMPPercentage", "30") // Between each monster, use healing spell if your HP gets bellow this percentage Variable.Set("UseHealingSpellAtHPPercentage", "85") // If you have a healing spell, how long does it take to cast? (in ms. 1000 ms = 1 sec. 1500 ms = 1,5 sec etc.) Variable.Set("HealingSpellCastTime", "1000") // During fights, at which HP / MP percentage should potions be used Variable.Set("UseHealthPotionAtHPPercentage", "35") Variable.Set("UseManaPotionAtMPPercentage", "70") // // USER CONFIGURATION END // // Static configuration Variable.Set("processName", "elementclient") Variable.Set("windowName", "Element Client") // Store memory addresses / window name in variables, to make it easier to update if the memory addresses change with a game update Variable.Set("maxHPMemoryAddress", "elementclient.exe+65BFCC,20,4b4") Variable.Set("maxMPMemoryAddress", "elementclient.exe+65BFCC,20,4b8") Variable.Set("currentHPMemoryAddress", "elementclient.exe+65BFCC,20,474") Variable.Set("currentMPMemoryAddress", "elementclient.exe+65BFCC,20,478") Variable.Set("currentLevelMemoryAddress", "elementclient.exe+65BFCC,20,46c") Variable.Set("currentLocationXMemoryAddress", "elementclient.exe+65bfcc,20,384,3c") Variable.Set("currentLocationYMemoryAddress", "elementclient.exe+65bfcc,20,384,44") Variable.Set("currentLocationHeightMemoryAddress", "elementclient.exe+65bfcc,20,384,40") Variable.Set("hasTargetMemoryAddress", "elementclient.exe+65BFCC,20,1088,38") Variable.Set("topMostDialogLocationXMemoryAddress", "elementclient.exe+0065BFCC,4,8,70,98") Variable.Set("topMostDialogLocationYMemoryAddress", "elementclient.exe+0065BFCC,4,8,70,9c") Variable.Set("deathDialogLocationXMemoryAddress", "elementclient.exe+0065BFCC,4,8,4a0,98") Variable.Set("deathDialogLocationYMemoryAddress", "elementclient.exe+0065BFCC,4,8,4a0,9c") Variable.Set("reachDestinationCheckBoxMemoryAddress", "elementclient.exe+65BFE4,270,2bc,1f0,119") Variable.Set("windowActiveMemoryAddress", "elementclient.exe+65B90C,48c") // Adjust variables Variable.Set("deathCount", "0") Variable.Set("killCount", "0") Variable.Add (Math)("HealingSpellCastTime", "750") // Convert minutes into milliseconds Variable.Multiply (Math)("WarpToTownAndStopMacroAfterMinutes", "60000") // Make sure the required key bindings have been set Function.Execute("Check keybindings") // Make sure the window doesnt freeze when it looses focus (to support playing with the game minimized and without focus) Memory.Freeze value("{processName}", "{windowActiveMemoryAddress}", "4", "1") // Make sure to reset targets when starting the bot by pressing escape Window.Send press keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("750") if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Window.Display message box("Please make sure you dont have an npc targeted when starting the Macro! the Macro will now exit", "no") Macro.Abort() end // Activate our buffs before starting, and start the stop watches, keeping track of the buff durations Function.Execute("Init buffs") begin loop() Function.Execute("Output status") Function.Execute("Use potions") Function.Execute("Ensure buffs are still active") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute with timeout("Ensure within specified hunting ground", "300000") Function.Execute("Output status") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute("Perform healing if required") Function.Execute("Output status") Function.Execute with timeout("Get target", "2500") if Function.Did not timeout("Get target") begin Function.Execute("Release corpse, heal and fly back if dead") Function.Execute with timeout("Kill target", "60000") Function.Execute("Perform healing if required") if Function.Did timeout("Kill target") begin // If the target does not die within 1 minute, the monster probably cant get to us, so it cant die, select a new target Window.Send press keys("{windowName}", "yes", "0", "{targetKey}") Macro.Pause("250") Function.Execute with timeout("Kill target", "60000") Function.Execute("Perform healing if required") end end Function.Execute with timeout("Get loot", "10000") Function.Execute("Output status") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute("Output status") Function.Execute("Meditate if required") Function.Execute("Simulate human pause") if Macro.Execution time has exceeded("{WarpToTownAndStopMacroAfterMinutes}") begin Window.Send press keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("1000") Window.Send press keys("{windowName}", "yes", "0", "{TownPortalKey}") Macro.Pause("500") Macro.Abort() end end end
function("Simulate human pause") if Random.Maybe("{HumanPausePercentage}") begin Variable.Set random number("pauseTimes", "5", "15") begin loop("{pauseTimes}") Macro.Pause("500") // If we are attacked, abort human pause to be able to defend ourselves first if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end end end function
function("Use potions") if Variable.Is not empty("HealthPotionKey") begin Function.Execute("Calculate current HP percentage") if Variable.Is less than (Math)("currentHPpercentage", "{UseHealthPotionAtHPPercentage}") begin Window.Send press keys("{windowName}", "yes", "0", "{HealthPotionKey}") end end if Variable.Is not empty("ManaPotionKey") begin Function.Execute("Calculate current MP percentage") if Variable.Is less than (Math)("currentMPpercentage", "{UseManaPotionAtMPPercentage}") begin Window.Send press keys("{windowName}", "yes", "0", "{ManaPotionKey}") end end function
function("Check keybindings") if Variable.Is empty("AttackKey") or Variable.Is empty("LootKey") or Variable.Is empty("MeditateKey") or Variable.Is empty("TownPortalKey") or Variable.Is empty("TargetKey") begin Window.Display message box("Please 'Right click' --> 'Edit Macro' and make sure to specify key bindings for at least: Target, Attack, Loot, Town portal and Meditation", "no") Macro.Abort() end function
function("Init buffs") if Variable.Is not empty("Buff1Key") and Variable.Is not empty("Buff1Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff1Key}") if Variable.Is less than (Math)("Buff1Duration", "1000") begin // Convert the duration from minutes to milliseconds Variable.Evaluate (Math)("({Buff1Duration}*60)*1000", "Buff1Duration") end Macro.Restart stopwatch("Buff1Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff2Key") and Variable.Is not empty("Buff2Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff2Key}") if Variable.Is less than (Math)("Buff2Duration", "1000") begin Variable.Evaluate (Math)("({Buff2Duration}*60)*1000", "Buff2Duration") end Macro.Restart stopwatch("Buff2Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff3Key") and Variable.Is not empty("Buff3Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff3Key}") if Variable.Is less than (Math)("Buff3Duration", "1000") begin Variable.Evaluate (Math)("({Buff3Duration}*60)*1000", "Buff3Duration") end Macro.Restart stopwatch("Buff3Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff4Key") and Variable.Is not empty("Buff4Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff4Key}") if Variable.Is less than (Math)("Buff4Duration", "1000") begin Variable.Evaluate (Math)("({Buff4Duration}*60)*1000", "Buff4Duration") end Macro.Restart stopwatch("Buff4Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff5Key") and Variable.Is not empty("Buff5Duration") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff5Key}") if Variable.Is less than (Math)("Buff5Duration", "1000") begin Variable.Evaluate (Math)("({Buff5Duration}*60)*1000", "Buff5Duration") end Macro.Restart stopwatch("Buff5Watch") Macro.Pause("2000") end function
function("Ensure buffs are still active") // If we are attacked, abort to be able to defend ourselves first if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end if Macro.Stopwatch exists("Buff1Watch") begin Macro.Read stopwatch("Buff1Watch", "buff1Time") if Variable.Is greater than (Math)("buff1Time", "{Buff1Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff1Key}") Macro.Restart stopwatch("Buff1Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff2Watch") begin Macro.Read stopwatch("Buff2Watch", "buff2Time") if Variable.Is greater than (Math)("buff2Time", "{Buff2Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff2Key}") Macro.Restart stopwatch("Buff2Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff3Watch") begin Macro.Read stopwatch("Buff3Watch", "buff3Time") if Variable.Is greater than (Math)("buff3Time", "{Buff3Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff3Key}") Macro.Restart stopwatch("Buff3Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff4Watch") begin Macro.Read stopwatch("Buff4Watch", "buff4Time") if Variable.Is greater than (Math)("buff4Time", "{Buff4Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff4Key}") Macro.Restart stopwatch("Buff4Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff5Watch") begin Macro.Read stopwatch("Buff5Watch", "buff5Time") if Variable.Is greater than (Math)("buff5Time", "{Buff5Duration}") begin Window.Send press keys("{windowName}", "yes", "0", "{Buff5Key}") Macro.Restart stopwatch("Buff5Watch") Macro.Pause("2000") end end function
function("Output status") begin Memory.Get value("{processName}", "{currentLevelMemoryAddress}", "4", "outputLvl") Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "outputHP") Memory.Get value("{processName}", "{currentMPMemoryAddress}", "4", "outputMP") Variable.Evaluate (Text)("Level: {outputLvl}, Kills: {killCount}, Deaths: {deathCount}, HP: {outputHP}, MP: {outputMP}", "statusOutput") Macro.Report progress("{statusOutput}") end function
function("Calculate current HP percentage") begin Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "currentHP") Memory.Get value("{processName}", "{maxHPMemoryAddress}", "4", "maxHP") Variable.Evaluate (Math)("({currentHP}/{maxHP})*100", "currentHPpercentage") end function
function("Calculate current MP percentage") begin Memory.Get value("{processName}", "{currentMPMemoryAddress}", "4", "currentMP") Memory.Get value("{processName}", "{maxMPMemoryAddress}", "4", "maxMP") Variable.Evaluate (Math)("({currentMP}/{maxMP})*100", "currentMPpercentage") end function
function("Meditate if required") // If we are attacked, abort to be able to defend ourselves if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin Function.Execute("Calculate current HP percentage") Function.Execute("Calculate current MP percentage") end if Variable.Is less than (Math)("currentHPpercentage", "{MeditateAtHPPercentage}") or Variable.Is less than (Math)("currentMPpercentage", "{MeditateAtMPPercentage}") begin Window.Send press keys("{windowName}", "yes", "0", "{MeditateKey}") begin loop() Macro.Pause("750") Function.Execute("Output status") Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "hpCheckCurrent") // If we are attacked, or at 100% HP / MP then abort meditation if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") or Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "{maxHP}") and Memory.Value is("{processName}", "{currentMPMemoryAddress}", "4", "{maxMP}") begin Window.Send press keys("{windowName}", "yes", "0", "{MeditateKey}") Macro.Pause("1000") Window.Send press keys("{windowName}", "yes", "0", "{LootKey}") Function.Abort() end end end function
function("Perform healing if required") // If we specified a key for the spell "Iron heart" (or another healing spell) if Variable.Is not empty("HealingKey") begin Function.Execute("Calculate current HP percentage") if Variable.Is less than (Math)("currentHPpercentage", "{UseHealingSpellAtHPPercentage}") begin Macro.Pause("250") Window.Send press keys("{windowName}", "yes", "0", "{HealingKey}") Macro.Pause("{HealingSpellCastTime}") end end function
function("Release corpse, heal and fly back if dead") if Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "0") begin Variable.Increment (Math)("deathCount") // Move the "You are dead" box to coordinate 0,0 Memory.Set value("{processName}", "{deathDialogLocationXMemoryAddress}", "4", "0") Memory.Set value("{processName}", "{deathDialogLocationYMemoryAddress}", "4", "0") Macro.Pause("1000") // Click "Release corpse" Window.Send mouse click("{windowName}", "yes", "0", "125", "71", "left") Macro.Pause("10000") if Variable.Is equal to("deathCount", "{StopMacroIfDeadTimes}") begin Variable.Evaluate (Text)("The bot was aborted because you died {deathCount} times", "output") Window.Display message box("{output}", "no") Macro.Abort() end Function.Execute("Use potions") Function.Execute("Meditate if required") Macro.Pause("1000") Function.Execute("Init buffs") Function.Execute with timeout("Ensure within specified hunting ground", "300000") end function
function("Get target") begin loop() if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin // If we already have a target, abort Function.Abort() end Window.Send press keys("{windowName}", "yes", "0", "{TargetKey}") Macro.Pause("250") Function.Execute("Use potions") end function
function("Get loot") begin Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "locationHash") Macro.Pause("200") // If we are being attacked, dont waste any time picking up drops if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin loop() begin loop("8") Window.Send press keys("{windowName}", "yes", "0", "{LootKey}") Macro.Pause("200") end Function.Execute("Use potions") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") or Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin // Abort if we finished picking up drops (stopped moving), or if we are under attack. Function.Abort() end Variable.Set("locationHash", "{newLocationHash}") end end function
function("Kill target") if Variable.Is not empty("PreAttackKey") and Random.Maybe("{PreAttackPercentage}") begin Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "locationHash") Window.Send press keys("{windowName}", "yes", "0", "{PreAttackKey}") Macro.Pause("750") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is not equal to("locationHash", "{newLocationHash}") begin loop("7") // If we had to move to get close enough to our target, wait a bit while casting the PreAttack spell Variable.Set("locationHash", "{newLocationHash}") Macro.Pause("750") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") begin Macro.Break from loop() end end end begin loop() Window.Send press keys("{windowName}", "yes", "0", "{AttackKey}") Macro.Pause("40") Function.Execute("Use potions") Macro.Pause("40") // If our target is dead or we died ourselves, stop attacking if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "0") or Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "0") begin Variable.Increment (Math)("killCount") // Quickly press esc to avoid wasting MP on a monster that is already dead. Window.Send press keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("100") Function.Abort() end end function
function("Ensure within specified hunting ground") // If we are attacked, abort to be able to defend ourselves before flying anywhere if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin Function.Execute("Get desired location") Function.Execute("Get player location") Variable.Evaluate (Math)("{x} - {desiredX}", "rangeX") if Variable.Is less than (Math)("rangeX", "0") begin Variable.Multiply (Math)("rangeX", "-1") end Variable.Evaluate (Math)("{y} - {desiredY}", "rangeY") if Variable.Is less than (Math)("rangeY", "0") begin Variable.Multiply (Math)("rangeY", "-1") end if Variable.Is less than (Math)("rangeX", "{desiredRange}") and Variable.Is less than (Math)("rangeY", "{desiredRange}") begin // If we are already within the specified range of our prefered hunting ground, dont go anywhere Function.Abort() end Variable.Evaluate (Text)("{desiredX} {desiredY}", "location") Window.Get size("{windowName}", "yes", "width", "unused") Variable.Subtract (Math)("width", "35") // If we are able to fly, activate wings, to help avoiding getting stuck if Variable.Is not empty("FlyKey") begin Window.Send press keys("{windowName}", "yes", "0", "{FlyKey}") end Macro.Pause("50") // Open the Path dialog Window.Send mouse click("{windowName}", "yes", "0", "{width}", "110", "left") Macro.Pause("750") Window.Send mouse click("{windowName}", "yes", "0", "293", "381", "left") Macro.Pause("250") Window.Send press keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("250") Window.Send mouse click("{windowName}", "yes", "0", "270", "40", "left") Macro.Pause("250") begin loop("25") // Delete whatever has already been entered Window.Send press keys("{windowName}", "yes", "0", "{<backspace>}") Macro.Pause("5") end Window.Send press keys("{windowName}", "yes", "0", "{location}") Macro.Pause("50") Window.Send press keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("200") Window.Send press keys("{windowName}", "yes", "0", "{location}") Macro.Pause("50") Window.Send press keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("200") Window.Send mouse double click("{windowName}", "yes", "0", "250", "60", "left") Macro.Pause("250") // Make sure the Auto-Path-Height box is located at coordinate 0,0 Memory.Set value("{processName}", "{topMostDialogLocationXMemoryAddress}", "4", "0") Memory.Set value("{processName}", "{topMostDialogLocationYMemoryAddress}", "4", "0") // Enable "Reach Destination" Memory.Set value("{processName}", "{reachDestinationCheckBoxMemoryAddress}", "1", "1") Macro.Pause("25") Window.Send mouse click("{windowName}", "yes", "0", "145", "43", "left") Macro.Pause("150") begin loop("15") // Delete whatever "Height" previously entered Window.Send press keys("{windowName}", "yes", "0", "{<backspace>}") Macro.Pause("5") end Window.Send press keys("{windowName}", "yes", "0", "{desiredHeight}") Macro.Pause("50") Window.Send mouse click("{windowName}", "yes", "0", "108", "106", "left") Variable.Set("locationHash", "0") begin loop() // Wait for our character to stop moving, meaning we reached our destination Macro.Pause("2500") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") begin // if the location "hash" is unchanged, meaning we reached our destination, close the Path window Window.Send mouse click("{windowName}", "yes", "0", "108", "106", "left") Macro.Pause("250") Window.Send press keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("250") Function.Abort() end Variable.Set("locationHash", "{newLocationHash}") end end function
function("Get desired location") // If this is the first run, we will load the hunting ground paths in to memory if Variable.Does not exist("paths") begin File.Read text("{LevelPath}", "paths") if Variable.Does not exist("paths") begin Variable.Evaluate (Text)("A level path file was not found at {LevelPath}, the macro will now quit (for help please visit http://www.blueeye-macro.com)", "errorOutput") Window.Display message box("{errorOutput}", "no") Macro.Abort() end Variable.Extract partial text (Regex)("paths", "(?s)-{25,}(.*)", "1", "paths") if Variable.Is not match (Regex)("paths", ":1:(?: [0-9]+){4}") begin Variable.Evaluate (Text)("A level path file was found, but it does not contain a leveling path for at least level 1. The macro will now quit, for help please visit http://www.blueeye-macro.com)", "errorOutput") Window.Display message box("{errorOutput}", "no") Macro.Abort() end end begin // Find the area coordinate that applies to our current level (or go with the nearest level path lower than our current level) Memory.Get value("{processName}", "{currentLevelMemoryAddress}", "4", "lvl") begin loop() Variable.Evaluate (Text)(":{lvl}: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)", "pattern") if Variable.Is match (Regex)("paths", "{pattern}") begin Macro.Break from loop() end Variable.Decrement (Math)("lvl") if Variable.Is less than (Math)("lvl", "0") begin Window.Display message box("Failed determining the leveling path for your level", "no") Macro.Abort() end end Variable.Extract partial text (Regex)("paths", "{pattern}", "1", "desiredX") Variable.Extract partial text (Regex)("paths", "{pattern}", "2", "desiredY") Variable.Extract partial text (Regex)("paths", "{pattern}", "3", "desiredHeight") Variable.Extract partial text (Regex)("paths", "{pattern}", "4", "desiredRange") end function
function("Get player location") begin // Get our current location, with all decimals Memory.Get value("{processName}", "{currentLocationXMemoryAddress}", "float", "x") Variable.Evaluate (Math)("401+({x}/10)", "x") Memory.Get value("{processName}", "{currentLocationYMemoryAddress}", "float", "y") Variable.Evaluate (Math)("551+({y}/10)", "y") Memory.Get value("{processName}", "{currentLocationHeightMemoryAddress}", "float", "z") Variable.Divide (Math)("z", "10") end function [/quote]
currently the code looks like this ... but with a new error.
|
|
|
|
Posted: Sun Dec 27, 2020 8:10 am |
|
|
|
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
Syrifina wrote: It looks like you posted the pop-up error message above the function that BEM colored red (get player location), but the error message states where the error actually is...in the function "simulate human pause"
It looks like you didn't copy/paste correctly. In the image you can see it says:
Randomizer.Maybe("{HumanPausePercentage}")" <---see that last little quotation mark; it's not supposed to be there.
It should read:
Randomizer.Maybe("{HumanPausePercentage}")
It should parse if you make that adjustment. Additionally, you haven't filled in any of the variables, but maybe you're getting to that. Randomizer.Maybe("{HumanPausePercentage}") these quotes don't have "< I was watching at Randomizer.Maybe commands do not exist in version 2.4 I believe it is Random.Maybe the other tests I didn't do because I still couldn't save: X
[quote="Syrifina"]It looks like you posted the pop-up error message above the function that BEM colored red (get player location), but the error message states where the error actually is...in the function "simulate human pause"
It looks like you didn't copy/paste correctly. In the image you can see it says:
Randomizer.Maybe("{HumanPausePercentage}")" <---see that last little quotation mark; it's not supposed to be there.
It should read:
Randomizer.Maybe("{HumanPausePercentage}")
It should parse if you make that adjustment. Additionally, you haven't filled in any of the variables, but maybe you're getting to that.[/quote]
Randomizer.Maybe("{HumanPausePercentage}") these quotes don't have "<
I was watching at Randomizer.Maybe commands do not exist in version 2.4 I believe it is Random.Maybe
the other tests I didn't do because I still couldn't save: X
|
|
|
|
Posted: Sun Dec 27, 2020 8:04 am |
|
|
|
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
It looks like you posted the pop-up error message above the function that BEM colored red (get player location), but the error message states where the error actually is...in the function "simulate human pause"
It looks like you didn't copy/paste correctly. In the image you can see it says:
Randomizer.Maybe("{HumanPausePercentage}")" <---see that last little quotation mark; it's not supposed to be there.
It should read:
Randomizer.Maybe("{HumanPausePercentage}")
It should parse if you make that adjustment. Additionally, you haven't filled in any of the variables, but maybe you're getting to that.
It looks like you posted the pop-up error message above the function that BEM colored red (get player location), but the error message states where the error actually is...in the function "simulate human pause"
It looks like you didn't copy/paste correctly. In the image you can see it says:
Randomizer.Maybe("{HumanPausePercentage}")" <---see that last little quotation mark; it's not supposed to be there.
It should read:
Randomizer.Maybe("{HumanPausePercentage}")
It should parse if you make that adjustment. Additionally, you haven't filled in any of the variables, but maybe you're getting to that.
|
|
|
|
Posted: Sun Dec 27, 2020 7:36 am |
|
|
|
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
Gigus wrote: Here is my first attempt at a full blown game bot. The bot is for the game Perfect World, which is a free MMORPG with more than 50 million players world wide. The bot will Hunt, track down monsters, kill them, automatically pick up drops and cash. It will keep your character safe by healing, activating buffs, meditating to regen HP / MP and even if you should die, (which I didn't during my 4 days non-stop testing) the bot will automatically revive, heal it self, and fly back to the desired hunting ground, and continue where it left off. If your HP or MP gets low during a fight, it will automatically use HP/MP potions, if you set the tress-hold percentages higher than those for meditation, it will use potions instead of meditating, to save time, level faster, but you will need to spent more money on potions. If a monster attacks you while you are meditating, meditation will immediately be aborted, and the bot will start defending itself. Also the bot will automatically travel from place to place as it levels up, to ensure you are always leveling at the best spot. The different coordinates are stored inside a txt file which contains the leveling path. For my testing I created the following leveling path file: Code: Syntax: :Level: X-Coordinate Y-Coordinate Z-Coodinate(height) Range
Level = From which level should the provided coordinates apply. X-Coordinate = The X coordinate of the desired hunting ground. Y-Coordinate = The Y coordinate of the desired hunting ground. Z-Coordinate = The height at which your character should fly at, when flying towards this location. Range = How far away from these coordinates should your character be allowed to run before returning to the desired location.
Example: :1: 150 150 25 5 :3: 250 250 35 5 This will make any level 1 character remain within a range of 5 of the coordinates 150/150 and will remain a flying height of 25 while flying, once reaching level 2, your character will remain at the level 1 hunting grounds since no path for level 2's was provided. As soon as your character reaches level 3, it will automatically fly to 250/250 in a flying height of 35, and once there, remain within a range of 5
Enter your leveling paths below this line (do not remove this line). -------------------------------------------------------------------- :1: 356 452 28 5 :3: 352 439 28 5 :7: 390 479 30 6 :9: 350 322 32 6 :11: 316 543 58 8 :18: 389 566 60 6 :21: 392 592 60 6 :26: 455 630 60 6
You can download my leveling path file here: Attachment: The attachment Perfect World Path.txt is no longer available The macro will load this txt file in to memory, and use it to determine where to go hunting at which levels. Everything the macro needs to know while running is read directly from memory, meaning it does not matter at what resolution your game is running. All inputs to the game, is done by manipulating memory / sending messages directly to the window, this means the window does not have to be focused while it is playing, you can use your computer for other stuff while the bot plays the game. However, Do not minimize the game! If you do - the dialog to fly to new coordinates will appear in the wrong spot, and instead of entering the coordinates in the coordinates window, you will be shouting them out loud in the chat, so make sure the game is not minimized, which does not mean it has to be visible on the screen, you can drag it to the side, place another window on top of it etc.To use the macro, all you need to do is load it in to Blue Eye Macro, Right click the macro and select Edit. Now specify your key bindings and available buffs in the lower left corner (variables) if your character does not have a healing spell, or any of the 5 available buffs, just leave the keys empty, and Blue Eye will automatically ignore the spells that require these keys. Also make sure to go through the settings in the top of the macro, to specify the file path to your leveling path file, as well as other general settings for the macro. Before starting the macro for the first time, make sure to Manually open the "Coordinates Assistant" at move the window to the top left corner of the screen, you can then close the dialog again, and start the macro. The location of the dialog will automatically be remembered by the game, and wont change when you re-launch the game, so you will only need to do this once. Attachment: The attachment coordinatesAssistant.png is no longer available Required variables are:- LevelPath (the location of your leveling path txt file, e.g. c:\Perfect World leveling path.txt)
- AttackKey (the keyboard shortcut for attacking, e.g. {<f2>})
- LootKey (the keyboard shortcut for picking up loot, e.g. {<f4>})
- MeditateKey (the keyboard shortcut for meditation, e.g. {<f5>})
All the memory addresses have been found using Cheat Engine, and all of them are saved as variables in the top of the macro, this makes it easier to "upgrade" the macro to use new memory addresses, in case they change with a future update of the game client. The latest version of the macro can be downloaded directly from the repository. Here is the complete (and massive) code for it Code:Code: begin // // For help using/configuring this bot, please refer to http://www.blueeye-macro.com/viewtopic.php?f=269&t=885 // // Note: Make sure to ALWAYS set the location of the "Coordinates Assistant" to the top left corner before starting the macro! // The location of the dialog will be remembered the next time you start the game, so you just need to do this once // // USER CONFIGURATION START // // Key bindings: Set your key bindings in the lower left corner variables // Example: To set a keybinding to the F1-Key, enter: {<F1>} // Example: To set a keybinding to the numeric 1-key, enter: 1 // // The filepath to your leveling paths file e.g. c:\leveling path.txt (See/share examples of this file at http://www.blueeye-macro.com) Variable.Set("LevelPath", "c:\Perfect World Path.txt") // If you die this many times, the macro will automatically abort Variable.Set("StopMacroIfDeadTimes", "3") // Only run the macro for the following amount of minutes (How long does your armor and weapon durability last? (if you care)) Variable.Set("WarpToTownAndStopMacroAfterMinutes", "120") // How often (in %) should a a single pre-attack spell be cast, before finishing off the monster with your primary attack (Good for a slowing spell) Variable.Set("PreAttackPercentage", "90") // How often (in %) should a human-like pause be inserted between monsters? (Makes you appear less bot-like) Variable.Set("HumanPausePercentage", "5") // At which percentage of your full HP / MP should meditation begin (Set HP to 0 if you dont want to use meditation for HP regen (if you have healing spell)) Variable.Set("MeditateAtHPPercentage", "40") Variable.Set("MeditateAtMPPercentage", "30") // Between each monster, use healing spell if your HP gets bellow this percentage Variable.Set("UseHealingSpellAtHPPercentage", "85") // If you have a healing spell, how long does it take to cast? (in ms. 1000 ms = 1 sec. 1500 ms = 1,5 sec etc.) Variable.Set("HealingSpellCastTime", "1000") // During fights, at which HP / MP percentage should potions be used Variable.Set("UseHealthPotionAtHPPercentage", "35") Variable.Set("UseManaPotionAtMPPercentage", "70") // // USER CONFIGURATION END // // Static configuration Variable.Set("processName", "elementclient") Variable.Set("windowName", "Element Client") // Store memory addresses / window name in variables, to make it easier to update if the memory addresses change with a game update Variable.Set("maxHPMemoryAddress", "elementclient.exe+65BFCC,20,4b4") Variable.Set("maxMPMemoryAddress", "elementclient.exe+65BFCC,20,4b8") Variable.Set("currentHPMemoryAddress", "elementclient.exe+65BFCC,20,474") Variable.Set("currentMPMemoryAddress", "elementclient.exe+65BFCC,20,478") Variable.Set("currentLevelMemoryAddress", "elementclient.exe+65BFCC,20,46c") Variable.Set("currentLocationXMemoryAddress", "elementclient.exe+65bfcc,20,384,3c") Variable.Set("currentLocationYMemoryAddress", "elementclient.exe+65bfcc,20,384,44") Variable.Set("currentLocationHeightMemoryAddress", "elementclient.exe+65bfcc,20,384,40") Variable.Set("hasTargetMemoryAddress", "elementclient.exe+65BFCC,20,1088,38") Variable.Set("topMostDialogLocationXMemoryAddress", "elementclient.exe+0065BFCC,4,8,70,98") Variable.Set("topMostDialogLocationYMemoryAddress", "elementclient.exe+0065BFCC,4,8,70,9c") Variable.Set("deathDialogLocationXMemoryAddress", "elementclient.exe+0065BFCC,4,8,4a0,98") Variable.Set("deathDialogLocationYMemoryAddress", "elementclient.exe+0065BFCC,4,8,4a0,9c") Variable.Set("reachDestinationCheckBoxMemoryAddress", "elementclient.exe+65BFE4,270,2bc,1f0,119") Variable.Set("windowActiveMemoryAddress", "elementclient.exe+65B90C,48c") // Adjust variables Variable.Set("deathCount", "0") Variable.Set("killCount", "0") Variable.Add (Math)("HealingSpellCastTime", "750") // Convert minutes into milliseconds Variable.Multiply (Math)("WarpToTownAndStopMacroAfterMinutes", "60000") // Make sure the required key bindings have been set Function.Execute("Check keybindings") // Make sure the window doesnt freeze when it looses focus (to support playing with the game minimized and without focus) Memory.Freeze value("{processName}", "{windowActiveMemoryAddress}", "4", "1") // Make sure to reset targets when starting the bot by pressing escape Window.Send keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("750") if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Window.Display message box("Please make sure you dont have an npc targeted when starting the Macro! the Macro will now exit", "no") Macro.Abort() end // Activate our buffs before starting, and start the stop watches, keeping track of the buff durations Function.Execute("Init buffs") begin loop() Function.Execute("Output status") Function.Execute("Use potions") Function.Execute("Ensure buffs are still active") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute with timeout("Ensure within specified hunting ground", "300000") Function.Execute("Output status") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute("Perform healing if required") Function.Execute("Output status") Function.Execute with timeout("Get target", "2500") if Function.Did not timeout("Get target") begin Function.Execute("Release corpse, heal and fly back if dead") Function.Execute with timeout("Kill target", "60000") Function.Execute("Perform healing if required") if Function.Did timeout("Kill target") begin // If the target does not die within 1 minute, the monster probably cant get to us, so it cant die, select a new target Window.Send keys("{windowName}", "yes", "0", "{targetKey}") Macro.Pause("250") Function.Execute with timeout("Kill target", "60000") Function.Execute("Perform healing if required") end end Function.Execute with timeout("Get loot", "10000") Function.Execute("Output status") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute("Output status") Function.Execute("Meditate if required") Function.Execute("Simulate human pause") if Macro.Execution time has exceeded("{WarpToTownAndStopMacroAfterMinutes}") begin Window.Send keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("1000") Window.Send keys("{windowName}", "yes", "0", "{TownPortalKey}") Macro.Pause("500") Macro.Abort() end end end
function("Simulate human pause") if Randomizer.Maybe("{HumanPausePercentage}") begin Variable.Set random number("pauseTimes", "5", "15") begin loop("{pauseTimes}") Macro.Pause("500") // If we are attacked, abort human pause to be able to defend ourselves first if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end end end function
function("Use potions") if Variable.Is not empty("HealthPotionKey") begin Function.Execute("Calculate current HP percentage") if Variable.Is less than (Math)("currentHPpercentage", "{UseHealthPotionAtHPPercentage}") begin Window.Send keys("{windowName}", "yes", "0", "{HealthPotionKey}") end end if Variable.Is not empty("ManaPotionKey") begin Function.Execute("Calculate current MP percentage") if Variable.Is less than (Math)("currentMPpercentage", "{UseManaPotionAtMPPercentage}") begin Window.Send keys("{windowName}", "yes", "0", "{ManaPotionKey}") end end function
function("Check keybindings") if Variable.Is empty("AttackKey") or Variable.Is empty("LootKey") or Variable.Is empty("MeditateKey") or Variable.Is empty("TownPortalKey") or Variable.Is empty("TargetKey") begin Window.Display message box("Please 'Right click' --> 'Edit Macro' and make sure to specify key bindings for at least: Target, Attack, Loot, Town portal and Meditation", "no") Macro.Abort() end function
function("Init buffs") if Variable.Is not empty("Buff1Key") and Variable.Is not empty("Buff1Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff1Key}") if Variable.Is less than (Math)("Buff1Duration", "1000") begin // Convert the duration from minutes to milliseconds Variable.Evaluate (Math)("({Buff1Duration}*60)*1000", "Buff1Duration") end Macro.Restart stopwatch("Buff1Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff2Key") and Variable.Is not empty("Buff2Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff2Key}") if Variable.Is less than (Math)("Buff2Duration", "1000") begin Variable.Evaluate (Math)("({Buff2Duration}*60)*1000", "Buff2Duration") end Macro.Restart stopwatch("Buff2Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff3Key") and Variable.Is not empty("Buff3Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff3Key}") if Variable.Is less than (Math)("Buff3Duration", "1000") begin Variable.Evaluate (Math)("({Buff3Duration}*60)*1000", "Buff3Duration") end Macro.Restart stopwatch("Buff3Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff4Key") and Variable.Is not empty("Buff4Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff4Key}") if Variable.Is less than (Math)("Buff4Duration", "1000") begin Variable.Evaluate (Math)("({Buff4Duration}*60)*1000", "Buff4Duration") end Macro.Restart stopwatch("Buff4Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff5Key") and Variable.Is not empty("Buff5Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff5Key}") if Variable.Is less than (Math)("Buff5Duration", "1000") begin Variable.Evaluate (Math)("({Buff5Duration}*60)*1000", "Buff5Duration") end Macro.Restart stopwatch("Buff5Watch") Macro.Pause("2000") end function
function("Ensure buffs are still active") // If we are attacked, abort to be able to defend ourselves first if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end if Macro.Stopwatch exists("Buff1Watch") begin Macro.Read stopwatch("Buff1Watch", "buff1Time") if Variable.Is greater than (Math)("buff1Time", "{Buff1Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff1Key}") Macro.Restart stopwatch("Buff1Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff2Watch") begin Macro.Read stopwatch("Buff2Watch", "buff2Time") if Variable.Is greater than (Math)("buff2Time", "{Buff2Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff2Key}") Macro.Restart stopwatch("Buff2Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff3Watch") begin Macro.Read stopwatch("Buff3Watch", "buff3Time") if Variable.Is greater than (Math)("buff3Time", "{Buff3Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff3Key}") Macro.Restart stopwatch("Buff3Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff4Watch") begin Macro.Read stopwatch("Buff4Watch", "buff4Time") if Variable.Is greater than (Math)("buff4Time", "{Buff4Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff4Key}") Macro.Restart stopwatch("Buff4Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff5Watch") begin Macro.Read stopwatch("Buff5Watch", "buff5Time") if Variable.Is greater than (Math)("buff5Time", "{Buff5Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff5Key}") Macro.Restart stopwatch("Buff5Watch") Macro.Pause("2000") end end function
function("Output status") begin Memory.Get value("{processName}", "{currentLevelMemoryAddress}", "4", "outputLvl") Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "outputHP") Memory.Get value("{processName}", "{currentMPMemoryAddress}", "4", "outputMP") Variable.Evaluate (Text)("Level: {outputLvl}, Kills: {killCount}, Deaths: {deathCount}, HP: {outputHP}, MP: {outputMP}", "statusOutput") Macro.Report progress("{statusOutput}") end function
function("Calculate current HP percentage") begin Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "currentHP") Memory.Get value("{processName}", "{maxHPMemoryAddress}", "4", "maxHP") Variable.Evaluate (Math)("({currentHP}/{maxHP})*100", "currentHPpercentage") end function
function("Calculate current MP percentage") begin Memory.Get value("{processName}", "{currentMPMemoryAddress}", "4", "currentMP") Memory.Get value("{processName}", "{maxMPMemoryAddress}", "4", "maxMP") Variable.Evaluate (Math)("({currentMP}/{maxMP})*100", "currentMPpercentage") end function
function("Meditate if required") // If we are attacked, abort to be able to defend ourselves if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin Function.Execute("Calculate current HP percentage") Function.Execute("Calculate current MP percentage") end if Variable.Is less than (Math)("currentHPpercentage", "{MeditateAtHPPercentage}") or Variable.Is less than (Math)("currentMPpercentage", "{MeditateAtMPPercentage}") begin Window.Send keys("{windowName}", "yes", "0", "{MeditateKey}") begin loop() Macro.Pause("750") Function.Execute("Output status") Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "hpCheckCurrent") // If we are attacked, or at 100% HP / MP then abort meditation if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") or Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "{maxHP}") and Memory.Value is("{processName}", "{currentMPMemoryAddress}", "4", "{maxMP}") begin Window.Send keys("{windowName}", "yes", "0", "{MeditateKey}") Macro.Pause("1000") Window.Send keys("{windowName}", "yes", "0", "{LootKey}") Function.Abort() end end end function
function("Perform healing if required") // If we specified a key for the spell "Iron heart" (or another healing spell) if Variable.Is not empty("HealingKey") begin Function.Execute("Calculate current HP percentage") if Variable.Is less than (Math)("currentHPpercentage", "{UseHealingSpellAtHPPercentage}") begin Macro.Pause("250") Window.Send keys("{windowName}", "yes", "0", "{HealingKey}") Macro.Pause("{HealingSpellCastTime}") end end function
function("Release corpse, heal and fly back if dead") if Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "0") begin Variable.Increment (Math)("deathCount") // Move the "You are dead" box to coordinate 0,0 Memory.Set value("{processName}", "{deathDialogLocationXMemoryAddress}", "4", "0") Memory.Set value("{processName}", "{deathDialogLocationYMemoryAddress}", "4", "0") Macro.Pause("1000") // Click "Release corpse" Window.Send mouse click("{windowName}", "yes", "0", "125", "71", "left") Macro.Pause("10000") if Variable.Is equal to("deathCount", "{StopMacroIfDeadTimes}") begin Variable.Evaluate (Text)("The bot was aborted because you died {deathCount} times", "output") Window.Display message box("{output}", "no") Macro.Abort() end Function.Execute("Use potions") Function.Execute("Meditate if required") Macro.Pause("1000") Function.Execute("Init buffs") Function.Execute with timeout("Ensure within specified hunting ground", "300000") end function
function("Get target") begin loop() if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin // If we already have a target, abort Function.Abort() end Window.Send keys("{windowName}", "yes", "0", "{TargetKey}") Macro.Pause("250") Function.Execute("Use potions") end function
function("Get loot") begin Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "locationHash") Macro.Pause("200") // If we are being attacked, dont waste any time picking up drops if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin loop() begin loop("8") Window.Send keys("{windowName}", "yes", "0", "{LootKey}") Macro.Pause("200") end Function.Execute("Use potions") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") or Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin // Abort if we finished picking up drops (stopped moving), or if we are under attack. Function.Abort() end Variable.Set("locationHash", "{newLocationHash}") end end function
function("Kill target") if Variable.Is not empty("PreAttackKey") and Randomizer.Maybe("{PreAttackPercentage}") begin Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "locationHash") Window.Send keys("{windowName}", "yes", "0", "{PreAttackKey}") Macro.Pause("750") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is not equal to("locationHash", "{newLocationHash}") begin loop("7") // If we had to move to get close enough to our target, wait a bit while casting the PreAttack spell Variable.Set("locationHash", "{newLocationHash}") Macro.Pause("750") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") begin Macro.Break from loop() end end end begin loop() Window.Send keys("{windowName}", "yes", "0", "{AttackKey}") Macro.Pause("40") Function.Execute("Use potions") Macro.Pause("40") // If our target is dead or we died ourselves, stop attacking if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "0") or Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "0") begin Variable.Increment (Math)("killCount") // Quickly press esc to avoid wasting MP on a monster that is already dead. Window.Send keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("100") Function.Abort() end end function
function("Ensure within specified hunting ground") // If we are attacked, abort to be able to defend ourselves before flying anywhere if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin Function.Execute("Get desired location") Function.Execute("Get player location") Variable.Evaluate (Math)("{x} - {desiredX}", "rangeX") if Variable.Is less than (Math)("rangeX", "0") begin Variable.Multiply (Math)("rangeX", "-1") end Variable.Evaluate (Math)("{y} - {desiredY}", "rangeY") if Variable.Is less than (Math)("rangeY", "0") begin Variable.Multiply (Math)("rangeY", "-1") end if Variable.Is less than (Math)("rangeX", "{desiredRange}") and Variable.Is less than (Math)("rangeY", "{desiredRange}") begin // If we are already within the specified range of our prefered hunting ground, dont go anywhere Function.Abort() end Variable.Evaluate (Text)("{desiredX} {desiredY}", "location") Window.Get size("{windowName}", "yes", "width", "unused") Variable.Subtract (Math)("width", "35") // If we are able to fly, activate wings, to help avoiding getting stuck if Variable.Is not empty("FlyKey") begin Window.Send keys("{windowName}", "yes", "0", "{FlyKey}") end Macro.Pause("50") // Open the Path dialog Window.Send mouse click("{windowName}", "yes", "0", "{width}", "110", "left") Macro.Pause("750") Window.Send mouse click("{windowName}", "yes", "0", "293", "381", "left") Macro.Pause("250") Window.Send keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("250") Window.Send mouse click("{windowName}", "yes", "0", "270", "40", "left") Macro.Pause("250") begin loop("25") // Delete whatever has already been entered Window.Send keys("{windowName}", "yes", "0", "{<backspace>}") Macro.Pause("5") end Window.Send keys("{windowName}", "yes", "0", "{location}") Macro.Pause("50") Window.Send keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("200") Window.Send keys("{windowName}", "yes", "0", "{location}") Macro.Pause("50") Window.Send keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("200") Window.Send mouse double click("{windowName}", "yes", "0", "250", "60", "left") Macro.Pause("250") // Make sure the Auto-Path-Height box is located at coordinate 0,0 Memory.Set value("{processName}", "{topMostDialogLocationXMemoryAddress}", "4", "0") Memory.Set value("{processName}", "{topMostDialogLocationYMemoryAddress}", "4", "0") // Enable "Reach Destination" Memory.Set value("{processName}", "{reachDestinationCheckBoxMemoryAddress}", "1", "1") Macro.Pause("25") Window.Send mouse click("{windowName}", "yes", "0", "145", "43", "left") Macro.Pause("150") begin loop("15") // Delete whatever "Height" previously entered Window.Send keys("{windowName}", "yes", "0", "{<backspace>}") Macro.Pause("5") end Window.Send keys("{windowName}", "yes", "0", "{desiredHeight}") Macro.Pause("50") Window.Send mouse click("{windowName}", "yes", "0", "108", "106", "left") Variable.Set("locationHash", "0") begin loop() // Wait for our character to stop moving, meaning we reached our destination Macro.Pause("2500") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") begin // if the location "hash" is unchanged, meaning we reached our destination, close the Path window Window.Send mouse click("{windowName}", "yes", "0", "108", "106", "left") Macro.Pause("250") Window.Send keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("250") Function.Abort() end Variable.Set("locationHash", "{newLocationHash}") end end function
function("Get desired location") // If this is the first run, we will load the hunting ground paths in to memory if Variable.Does not exist("paths") begin File.Read text("{LevelPath}", "paths") if Variable.Does not exist("paths") begin Variable.Evaluate (Text)("A level path file was not found at {LevelPath}, the macro will now quit (for help please visit http://www.blueeye-macro.com)", "errorOutput") Window.Display message box("{errorOutput}", "no") Macro.Abort() end Variable.Extract partial text (Regex)("paths", "(?s)-{25,}(.*)", "1", "paths") if Variable.Is not match (Regex)("paths", ":1:(?: [0-9]+){4}") begin Variable.Evaluate (Text)("A level path file was found, but it does not contain a leveling path for at least level 1. The macro will now quit, for help please visit http://www.blueeye-macro.com)", "errorOutput") Window.Display message box("{errorOutput}", "no") Macro.Abort() end end begin // Find the area coordinate that applies to our current level (or go with the nearest level path lower than our current level) Memory.Get value("{processName}", "{currentLevelMemoryAddress}", "4", "lvl") begin loop() Variable.Evaluate (Text)(":{lvl}: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)", "pattern") if Variable.Is match (Regex)("paths", "{pattern}") begin Macro.Break from loop() end Variable.Decrement (Math)("lvl") if Variable.Is less than (Math)("lvl", "0") begin Window.Display message box("Failed determining the leveling path for your level", "no") Macro.Abort() end end Variable.Extract partial text (Regex)("paths", "{pattern}", "1", "desiredX") Variable.Extract partial text (Regex)("paths", "{pattern}", "2", "desiredY") Variable.Extract partial text (Regex)("paths", "{pattern}", "3", "desiredHeight") Variable.Extract partial text (Regex)("paths", "{pattern}", "4", "desiredRange") end function
function("Get player location") begin // Get our current location, with all decimals Memory.Get value("{processName}", "{currentLocationXMemoryAddress}", "float", "x") Variable.Evaluate (Math)("401+({x}/10)", "x") Memory.Get value("{processName}", "{currentLocationYMemoryAddress}", "float", "y") Variable.Evaluate (Math)("551+({y}/10)", "y") Memory.Get value("{processName}", "{currentLocationHeightMemoryAddress}", "float", "z") Variable.Divide (Math)("z", "10") end function
Download:Keep in mind the macro requires the predefined variables located in the lower left corner of the designer, so I suggest downloading the macro from the repository, instead of copy pasting the above code. I would very much appreciate any feedback / ideas for improvements from you guys. Testing:When I tested the bot, I went from level 1 to level 31 in a couple of days, leaving my computer on overnight. I should also mention this bot was created / tested using a character of the class "Cleric" (Winged Elf), but I believe the bot will work just fine with other classes as well, but this have not been tested. Warning:The use of any 3d party tool like Blue Eye Macro to play your character on any official Perfect World server, is likely to be considdered a violation of the games regulations. It is solely your responsibility to ensure no such regulations are violated - or use at your own risk. Credits:A big thanks to Martin for helping out with the tasks of locating base pointers and development of the macro. wouldn't there be a possible update? : S is giving error
Attachments: |
Capturar.PNG [ 53.22 KiB | Viewed 3106 times ]
|
[quote="Gigus"]Here is my first attempt at a full blown game bot.
The bot is for the game Perfect World, which is a free MMORPG with more than 50 million players world wide.
The bot will Hunt, track down monsters, kill them, automatically pick up drops and cash. It will keep your character safe by healing, activating buffs, meditating to regen HP / MP and even if you should die, (which I didn't during my 4 days non-stop testing) the bot will automatically revive, heal it self, and fly back to the desired hunting ground, and continue where it left off.
If your HP or MP gets low during a fight, it will automatically use HP/MP potions, if you set the tress-hold percentages higher than those for meditation, it will use potions instead of meditating, to save time, level faster, but you will need to spent more money on potions.
If a monster attacks you while you are meditating, meditation will immediately be aborted, and the bot will start defending itself.
Also the bot will automatically travel from place to place as it levels up, to ensure you are always leveling at the best spot.
The different coordinates are stored inside a txt file which contains the leveling path.
For my testing I created the following leveling path file: [code] Syntax: :Level: X-Coordinate Y-Coordinate Z-Coodinate(height) Range
Level = From which level should the provided coordinates apply. X-Coordinate = The X coordinate of the desired hunting ground. Y-Coordinate = The Y coordinate of the desired hunting ground. Z-Coordinate = The height at which your character should fly at, when flying towards this location. Range = How far away from these coordinates should your character be allowed to run before returning to the desired location.
Example: :1: 150 150 25 5 :3: 250 250 35 5 This will make any level 1 character remain within a range of 5 of the coordinates 150/150 and will remain a flying height of 25 while flying, once reaching level 2, your character will remain at the level 1 hunting grounds since no path for level 2's was provided. As soon as your character reaches level 3, it will automatically fly to 250/250 in a flying height of 35, and once there, remain within a range of 5
Enter your leveling paths below this line (do not remove this line). -------------------------------------------------------------------- :1: 356 452 28 5 :3: 352 439 28 5 :7: 390 479 30 6 :9: 350 322 32 6 :11: 316 543 58 8 :18: 389 566 60 6 :21: 392 592 60 6 :26: 455 630 60 6 [/code] You can download my leveling path file here: [attachment=2]Perfect World Path.txt[/attachment]
The macro will load this txt file in to memory, and use it to determine where to go hunting at which levels.
Everything the macro needs to know while running is read directly from memory, meaning it does not matter at what resolution your game is running. All inputs to the game, is done by manipulating memory / sending messages directly to the window, this means the window does not have to be focused while it is playing, you can use your computer for other stuff while the bot plays the game.
[b]However, [color=#BF0000]Do not minimize the game![/color] If you do - the dialog to fly to new coordinates will appear in the wrong spot, and instead of entering the coordinates in the coordinates window, you will be shouting them out loud in the chat, so make sure the game is not minimized, which does not mean it has to be visible on the screen, you can drag it to the side, place another window on top of it etc.[/b]
To use the macro, all you need to do is load it in to Blue Eye Macro, Right click the macro and select Edit. Now specify your key bindings and available buffs in the lower left corner (variables) if your character does not have a healing spell, or any of the 5 available buffs, just leave the keys empty, and Blue Eye will automatically ignore the spells that require these keys.
Also make sure to go through the settings in the top of the macro, to specify the file path to your leveling path file, as well as other general settings for the macro.
Before starting the macro for the first time, make sure to Manually open the "Coordinates Assistant" at move the window to the top left corner of the screen, you can then close the dialog again, and start the macro. The location of the dialog will automatically be remembered by the game, and wont change when you re-launch the game, so you will only need to do this once. [attachment=1]coordinatesAssistant.png[/attachment]
[b]Required variables are:[/b] [list] [*]LevelPath (the location of your leveling path txt file, e.g. c:\Perfect World leveling path.txt) [*]AttackKey (the keyboard shortcut for attacking, e.g. {<f2>}) [*]LootKey (the keyboard shortcut for picking up loot, e.g. {<f4>}) [*]MeditateKey (the keyboard shortcut for meditation, e.g. {<f5>})[/list]
All the memory addresses have been found using Cheat Engine, and all of them are saved as variables in the top of the macro, this makes it easier to "upgrade" the macro to use new memory addresses, in case they change with a future update of the game client.
The latest version of the macro can be downloaded directly from the repository.
Here is the complete (and massive) code for it [b]Code:[/b] [code] begin // // For help using/configuring this bot, please refer to http://www.blueeye-macro.com/viewtopic.php?f=269&t=885 // // Note: Make sure to ALWAYS set the location of the "Coordinates Assistant" to the top left corner before starting the macro! // The location of the dialog will be remembered the next time you start the game, so you just need to do this once // // USER CONFIGURATION START // // Key bindings: Set your key bindings in the lower left corner variables // Example: To set a keybinding to the F1-Key, enter: {<F1>} // Example: To set a keybinding to the numeric 1-key, enter: 1 // // The filepath to your leveling paths file e.g. c:\leveling path.txt (See/share examples of this file at http://www.blueeye-macro.com) Variable.Set("LevelPath", "c:\Perfect World Path.txt") // If you die this many times, the macro will automatically abort Variable.Set("StopMacroIfDeadTimes", "3") // Only run the macro for the following amount of minutes (How long does your armor and weapon durability last? (if you care)) Variable.Set("WarpToTownAndStopMacroAfterMinutes", "120") // How often (in %) should a a single pre-attack spell be cast, before finishing off the monster with your primary attack (Good for a slowing spell) Variable.Set("PreAttackPercentage", "90") // How often (in %) should a human-like pause be inserted between monsters? (Makes you appear less bot-like) Variable.Set("HumanPausePercentage", "5") // At which percentage of your full HP / MP should meditation begin (Set HP to 0 if you dont want to use meditation for HP regen (if you have healing spell)) Variable.Set("MeditateAtHPPercentage", "40") Variable.Set("MeditateAtMPPercentage", "30") // Between each monster, use healing spell if your HP gets bellow this percentage Variable.Set("UseHealingSpellAtHPPercentage", "85") // If you have a healing spell, how long does it take to cast? (in ms. 1000 ms = 1 sec. 1500 ms = 1,5 sec etc.) Variable.Set("HealingSpellCastTime", "1000") // During fights, at which HP / MP percentage should potions be used Variable.Set("UseHealthPotionAtHPPercentage", "35") Variable.Set("UseManaPotionAtMPPercentage", "70") // // USER CONFIGURATION END // // Static configuration Variable.Set("processName", "elementclient") Variable.Set("windowName", "Element Client") // Store memory addresses / window name in variables, to make it easier to update if the memory addresses change with a game update Variable.Set("maxHPMemoryAddress", "elementclient.exe+65BFCC,20,4b4") Variable.Set("maxMPMemoryAddress", "elementclient.exe+65BFCC,20,4b8") Variable.Set("currentHPMemoryAddress", "elementclient.exe+65BFCC,20,474") Variable.Set("currentMPMemoryAddress", "elementclient.exe+65BFCC,20,478") Variable.Set("currentLevelMemoryAddress", "elementclient.exe+65BFCC,20,46c") Variable.Set("currentLocationXMemoryAddress", "elementclient.exe+65bfcc,20,384,3c") Variable.Set("currentLocationYMemoryAddress", "elementclient.exe+65bfcc,20,384,44") Variable.Set("currentLocationHeightMemoryAddress", "elementclient.exe+65bfcc,20,384,40") Variable.Set("hasTargetMemoryAddress", "elementclient.exe+65BFCC,20,1088,38") Variable.Set("topMostDialogLocationXMemoryAddress", "elementclient.exe+0065BFCC,4,8,70,98") Variable.Set("topMostDialogLocationYMemoryAddress", "elementclient.exe+0065BFCC,4,8,70,9c") Variable.Set("deathDialogLocationXMemoryAddress", "elementclient.exe+0065BFCC,4,8,4a0,98") Variable.Set("deathDialogLocationYMemoryAddress", "elementclient.exe+0065BFCC,4,8,4a0,9c") Variable.Set("reachDestinationCheckBoxMemoryAddress", "elementclient.exe+65BFE4,270,2bc,1f0,119") Variable.Set("windowActiveMemoryAddress", "elementclient.exe+65B90C,48c") // Adjust variables Variable.Set("deathCount", "0") Variable.Set("killCount", "0") Variable.Add (Math)("HealingSpellCastTime", "750") // Convert minutes into milliseconds Variable.Multiply (Math)("WarpToTownAndStopMacroAfterMinutes", "60000") // Make sure the required key bindings have been set Function.Execute("Check keybindings") // Make sure the window doesnt freeze when it looses focus (to support playing with the game minimized and without focus) Memory.Freeze value("{processName}", "{windowActiveMemoryAddress}", "4", "1") // Make sure to reset targets when starting the bot by pressing escape Window.Send keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("750") if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Window.Display message box("Please make sure you dont have an npc targeted when starting the Macro! the Macro will now exit", "no") Macro.Abort() end // Activate our buffs before starting, and start the stop watches, keeping track of the buff durations Function.Execute("Init buffs") begin loop() Function.Execute("Output status") Function.Execute("Use potions") Function.Execute("Ensure buffs are still active") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute with timeout("Ensure within specified hunting ground", "300000") Function.Execute("Output status") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute("Perform healing if required") Function.Execute("Output status") Function.Execute with timeout("Get target", "2500") if Function.Did not timeout("Get target") begin Function.Execute("Release corpse, heal and fly back if dead") Function.Execute with timeout("Kill target", "60000") Function.Execute("Perform healing if required") if Function.Did timeout("Kill target") begin // If the target does not die within 1 minute, the monster probably cant get to us, so it cant die, select a new target Window.Send keys("{windowName}", "yes", "0", "{targetKey}") Macro.Pause("250") Function.Execute with timeout("Kill target", "60000") Function.Execute("Perform healing if required") end end Function.Execute with timeout("Get loot", "10000") Function.Execute("Output status") Function.Execute("Release corpse, heal and fly back if dead") Function.Execute("Output status") Function.Execute("Meditate if required") Function.Execute("Simulate human pause") if Macro.Execution time has exceeded("{WarpToTownAndStopMacroAfterMinutes}") begin Window.Send keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("1000") Window.Send keys("{windowName}", "yes", "0", "{TownPortalKey}") Macro.Pause("500") Macro.Abort() end end end
function("Simulate human pause") if Randomizer.Maybe("{HumanPausePercentage}") begin Variable.Set random number("pauseTimes", "5", "15") begin loop("{pauseTimes}") Macro.Pause("500") // If we are attacked, abort human pause to be able to defend ourselves first if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end end end function
function("Use potions") if Variable.Is not empty("HealthPotionKey") begin Function.Execute("Calculate current HP percentage") if Variable.Is less than (Math)("currentHPpercentage", "{UseHealthPotionAtHPPercentage}") begin Window.Send keys("{windowName}", "yes", "0", "{HealthPotionKey}") end end if Variable.Is not empty("ManaPotionKey") begin Function.Execute("Calculate current MP percentage") if Variable.Is less than (Math)("currentMPpercentage", "{UseManaPotionAtMPPercentage}") begin Window.Send keys("{windowName}", "yes", "0", "{ManaPotionKey}") end end function
function("Check keybindings") if Variable.Is empty("AttackKey") or Variable.Is empty("LootKey") or Variable.Is empty("MeditateKey") or Variable.Is empty("TownPortalKey") or Variable.Is empty("TargetKey") begin Window.Display message box("Please 'Right click' --> 'Edit Macro' and make sure to specify key bindings for at least: Target, Attack, Loot, Town portal and Meditation", "no") Macro.Abort() end function
function("Init buffs") if Variable.Is not empty("Buff1Key") and Variable.Is not empty("Buff1Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff1Key}") if Variable.Is less than (Math)("Buff1Duration", "1000") begin // Convert the duration from minutes to milliseconds Variable.Evaluate (Math)("({Buff1Duration}*60)*1000", "Buff1Duration") end Macro.Restart stopwatch("Buff1Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff2Key") and Variable.Is not empty("Buff2Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff2Key}") if Variable.Is less than (Math)("Buff2Duration", "1000") begin Variable.Evaluate (Math)("({Buff2Duration}*60)*1000", "Buff2Duration") end Macro.Restart stopwatch("Buff2Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff3Key") and Variable.Is not empty("Buff3Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff3Key}") if Variable.Is less than (Math)("Buff3Duration", "1000") begin Variable.Evaluate (Math)("({Buff3Duration}*60)*1000", "Buff3Duration") end Macro.Restart stopwatch("Buff3Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff4Key") and Variable.Is not empty("Buff4Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff4Key}") if Variable.Is less than (Math)("Buff4Duration", "1000") begin Variable.Evaluate (Math)("({Buff4Duration}*60)*1000", "Buff4Duration") end Macro.Restart stopwatch("Buff4Watch") Macro.Pause("2000") end if Variable.Is not empty("Buff5Key") and Variable.Is not empty("Buff5Duration") begin Window.Send keys("{windowName}", "yes", "0", "{Buff5Key}") if Variable.Is less than (Math)("Buff5Duration", "1000") begin Variable.Evaluate (Math)("({Buff5Duration}*60)*1000", "Buff5Duration") end Macro.Restart stopwatch("Buff5Watch") Macro.Pause("2000") end function
function("Ensure buffs are still active") // If we are attacked, abort to be able to defend ourselves first if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end if Macro.Stopwatch exists("Buff1Watch") begin Macro.Read stopwatch("Buff1Watch", "buff1Time") if Variable.Is greater than (Math)("buff1Time", "{Buff1Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff1Key}") Macro.Restart stopwatch("Buff1Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff2Watch") begin Macro.Read stopwatch("Buff2Watch", "buff2Time") if Variable.Is greater than (Math)("buff2Time", "{Buff2Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff2Key}") Macro.Restart stopwatch("Buff2Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff3Watch") begin Macro.Read stopwatch("Buff3Watch", "buff3Time") if Variable.Is greater than (Math)("buff3Time", "{Buff3Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff3Key}") Macro.Restart stopwatch("Buff3Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff4Watch") begin Macro.Read stopwatch("Buff4Watch", "buff4Time") if Variable.Is greater than (Math)("buff4Time", "{Buff4Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff4Key}") Macro.Restart stopwatch("Buff4Watch") Macro.Pause("2000") end end if Macro.Stopwatch exists("Buff5Watch") begin Macro.Read stopwatch("Buff5Watch", "buff5Time") if Variable.Is greater than (Math)("buff5Time", "{Buff5Duration}") begin Window.Send keys("{windowName}", "yes", "0", "{Buff5Key}") Macro.Restart stopwatch("Buff5Watch") Macro.Pause("2000") end end function
function("Output status") begin Memory.Get value("{processName}", "{currentLevelMemoryAddress}", "4", "outputLvl") Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "outputHP") Memory.Get value("{processName}", "{currentMPMemoryAddress}", "4", "outputMP") Variable.Evaluate (Text)("Level: {outputLvl}, Kills: {killCount}, Deaths: {deathCount}, HP: {outputHP}, MP: {outputMP}", "statusOutput") Macro.Report progress("{statusOutput}") end function
function("Calculate current HP percentage") begin Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "currentHP") Memory.Get value("{processName}", "{maxHPMemoryAddress}", "4", "maxHP") Variable.Evaluate (Math)("({currentHP}/{maxHP})*100", "currentHPpercentage") end function
function("Calculate current MP percentage") begin Memory.Get value("{processName}", "{currentMPMemoryAddress}", "4", "currentMP") Memory.Get value("{processName}", "{maxMPMemoryAddress}", "4", "maxMP") Variable.Evaluate (Math)("({currentMP}/{maxMP})*100", "currentMPpercentage") end function
function("Meditate if required") // If we are attacked, abort to be able to defend ourselves if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin Function.Execute("Calculate current HP percentage") Function.Execute("Calculate current MP percentage") end if Variable.Is less than (Math)("currentHPpercentage", "{MeditateAtHPPercentage}") or Variable.Is less than (Math)("currentMPpercentage", "{MeditateAtMPPercentage}") begin Window.Send keys("{windowName}", "yes", "0", "{MeditateKey}") begin loop() Macro.Pause("750") Function.Execute("Output status") Memory.Get value("{processName}", "{currentHPMemoryAddress}", "4", "hpCheckCurrent") // If we are attacked, or at 100% HP / MP then abort meditation if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") or Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "{maxHP}") and Memory.Value is("{processName}", "{currentMPMemoryAddress}", "4", "{maxMP}") begin Window.Send keys("{windowName}", "yes", "0", "{MeditateKey}") Macro.Pause("1000") Window.Send keys("{windowName}", "yes", "0", "{LootKey}") Function.Abort() end end end function
function("Perform healing if required") // If we specified a key for the spell "Iron heart" (or another healing spell) if Variable.Is not empty("HealingKey") begin Function.Execute("Calculate current HP percentage") if Variable.Is less than (Math)("currentHPpercentage", "{UseHealingSpellAtHPPercentage}") begin Macro.Pause("250") Window.Send keys("{windowName}", "yes", "0", "{HealingKey}") Macro.Pause("{HealingSpellCastTime}") end end function
function("Release corpse, heal and fly back if dead") if Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "0") begin Variable.Increment (Math)("deathCount") // Move the "You are dead" box to coordinate 0,0 Memory.Set value("{processName}", "{deathDialogLocationXMemoryAddress}", "4", "0") Memory.Set value("{processName}", "{deathDialogLocationYMemoryAddress}", "4", "0") Macro.Pause("1000") // Click "Release corpse" Window.Send mouse click("{windowName}", "yes", "0", "125", "71", "left") Macro.Pause("10000") if Variable.Is equal to("deathCount", "{StopMacroIfDeadTimes}") begin Variable.Evaluate (Text)("The bot was aborted because you died {deathCount} times", "output") Window.Display message box("{output}", "no") Macro.Abort() end Function.Execute("Use potions") Function.Execute("Meditate if required") Macro.Pause("1000") Function.Execute("Init buffs") Function.Execute with timeout("Ensure within specified hunting ground", "300000") end function
function("Get target") begin loop() if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin // If we already have a target, abort Function.Abort() end Window.Send keys("{windowName}", "yes", "0", "{TargetKey}") Macro.Pause("250") Function.Execute("Use potions") end function
function("Get loot") begin Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "locationHash") Macro.Pause("200") // If we are being attacked, dont waste any time picking up drops if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin loop() begin loop("8") Window.Send keys("{windowName}", "yes", "0", "{LootKey}") Macro.Pause("200") end Function.Execute("Use potions") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") or Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin // Abort if we finished picking up drops (stopped moving), or if we are under attack. Function.Abort() end Variable.Set("locationHash", "{newLocationHash}") end end function
function("Kill target") if Variable.Is not empty("PreAttackKey") and Randomizer.Maybe("{PreAttackPercentage}") begin Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "locationHash") Window.Send keys("{windowName}", "yes", "0", "{PreAttackKey}") Macro.Pause("750") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is not equal to("locationHash", "{newLocationHash}") begin loop("7") // If we had to move to get close enough to our target, wait a bit while casting the PreAttack spell Variable.Set("locationHash", "{newLocationHash}") Macro.Pause("750") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") begin Macro.Break from loop() end end end begin loop() Window.Send keys("{windowName}", "yes", "0", "{AttackKey}") Macro.Pause("40") Function.Execute("Use potions") Macro.Pause("40") // If our target is dead or we died ourselves, stop attacking if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "0") or Memory.Value is("{processName}", "{currentHPMemoryAddress}", "4", "0") begin Variable.Increment (Math)("killCount") // Quickly press esc to avoid wasting MP on a monster that is already dead. Window.Send keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("100") Function.Abort() end end function
function("Ensure within specified hunting ground") // If we are attacked, abort to be able to defend ourselves before flying anywhere if Memory.Value is("{processName}", "{hasTargetMemoryAddress}", "1", "1") begin Function.Abort() end begin Function.Execute("Get desired location") Function.Execute("Get player location") Variable.Evaluate (Math)("{x} - {desiredX}", "rangeX") if Variable.Is less than (Math)("rangeX", "0") begin Variable.Multiply (Math)("rangeX", "-1") end Variable.Evaluate (Math)("{y} - {desiredY}", "rangeY") if Variable.Is less than (Math)("rangeY", "0") begin Variable.Multiply (Math)("rangeY", "-1") end if Variable.Is less than (Math)("rangeX", "{desiredRange}") and Variable.Is less than (Math)("rangeY", "{desiredRange}") begin // If we are already within the specified range of our prefered hunting ground, dont go anywhere Function.Abort() end Variable.Evaluate (Text)("{desiredX} {desiredY}", "location") Window.Get size("{windowName}", "yes", "width", "unused") Variable.Subtract (Math)("width", "35") // If we are able to fly, activate wings, to help avoiding getting stuck if Variable.Is not empty("FlyKey") begin Window.Send keys("{windowName}", "yes", "0", "{FlyKey}") end Macro.Pause("50") // Open the Path dialog Window.Send mouse click("{windowName}", "yes", "0", "{width}", "110", "left") Macro.Pause("750") Window.Send mouse click("{windowName}", "yes", "0", "293", "381", "left") Macro.Pause("250") Window.Send keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("250") Window.Send mouse click("{windowName}", "yes", "0", "270", "40", "left") Macro.Pause("250") begin loop("25") // Delete whatever has already been entered Window.Send keys("{windowName}", "yes", "0", "{<backspace>}") Macro.Pause("5") end Window.Send keys("{windowName}", "yes", "0", "{location}") Macro.Pause("50") Window.Send keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("200") Window.Send keys("{windowName}", "yes", "0", "{location}") Macro.Pause("50") Window.Send keys("{windowName}", "yes", "0", "{<enter>}") Macro.Pause("200") Window.Send mouse double click("{windowName}", "yes", "0", "250", "60", "left") Macro.Pause("250") // Make sure the Auto-Path-Height box is located at coordinate 0,0 Memory.Set value("{processName}", "{topMostDialogLocationXMemoryAddress}", "4", "0") Memory.Set value("{processName}", "{topMostDialogLocationYMemoryAddress}", "4", "0") // Enable "Reach Destination" Memory.Set value("{processName}", "{reachDestinationCheckBoxMemoryAddress}", "1", "1") Macro.Pause("25") Window.Send mouse click("{windowName}", "yes", "0", "145", "43", "left") Macro.Pause("150") begin loop("15") // Delete whatever "Height" previously entered Window.Send keys("{windowName}", "yes", "0", "{<backspace>}") Macro.Pause("5") end Window.Send keys("{windowName}", "yes", "0", "{desiredHeight}") Macro.Pause("50") Window.Send mouse click("{windowName}", "yes", "0", "108", "106", "left") Variable.Set("locationHash", "0") begin loop() // Wait for our character to stop moving, meaning we reached our destination Macro.Pause("2500") Function.Execute("Get player location") Variable.Evaluate (Text)("{x}{y}{z}", "newLocationHash") if Variable.Is equal to("locationHash", "{newLocationHash}") begin // if the location "hash" is unchanged, meaning we reached our destination, close the Path window Window.Send mouse click("{windowName}", "yes", "0", "108", "106", "left") Macro.Pause("250") Window.Send keys("{windowName}", "yes", "0", "{<esc>}") Macro.Pause("250") Function.Abort() end Variable.Set("locationHash", "{newLocationHash}") end end function
function("Get desired location") // If this is the first run, we will load the hunting ground paths in to memory if Variable.Does not exist("paths") begin File.Read text("{LevelPath}", "paths") if Variable.Does not exist("paths") begin Variable.Evaluate (Text)("A level path file was not found at {LevelPath}, the macro will now quit (for help please visit http://www.blueeye-macro.com)", "errorOutput") Window.Display message box("{errorOutput}", "no") Macro.Abort() end Variable.Extract partial text (Regex)("paths", "(?s)-{25,}(.*)", "1", "paths") if Variable.Is not match (Regex)("paths", ":1:(?: [0-9]+){4}") begin Variable.Evaluate (Text)("A level path file was found, but it does not contain a leveling path for at least level 1. The macro will now quit, for help please visit http://www.blueeye-macro.com)", "errorOutput") Window.Display message box("{errorOutput}", "no") Macro.Abort() end end begin // Find the area coordinate that applies to our current level (or go with the nearest level path lower than our current level) Memory.Get value("{processName}", "{currentLevelMemoryAddress}", "4", "lvl") begin loop() Variable.Evaluate (Text)(":{lvl}: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)", "pattern") if Variable.Is match (Regex)("paths", "{pattern}") begin Macro.Break from loop() end Variable.Decrement (Math)("lvl") if Variable.Is less than (Math)("lvl", "0") begin Window.Display message box("Failed determining the leveling path for your level", "no") Macro.Abort() end end Variable.Extract partial text (Regex)("paths", "{pattern}", "1", "desiredX") Variable.Extract partial text (Regex)("paths", "{pattern}", "2", "desiredY") Variable.Extract partial text (Regex)("paths", "{pattern}", "3", "desiredHeight") Variable.Extract partial text (Regex)("paths", "{pattern}", "4", "desiredRange") end function
function("Get player location") begin // Get our current location, with all decimals Memory.Get value("{processName}", "{currentLocationXMemoryAddress}", "float", "x") Variable.Evaluate (Math)("401+({x}/10)", "x") Memory.Get value("{processName}", "{currentLocationYMemoryAddress}", "float", "y") Variable.Evaluate (Math)("551+({y}/10)", "y") Memory.Get value("{processName}", "{currentLocationHeightMemoryAddress}", "float", "z") Variable.Divide (Math)("z", "10") end function [/code]
[b]Download:[/b] Keep in mind the macro requires the predefined variables located in the lower left corner of the designer, so I suggest downloading the macro from the repository, instead of copy pasting the above code.
I would very much appreciate any feedback / ideas for improvements from you guys.
[b]Testing:[/b] When I tested the bot, I went from level 1 to level 31 in a couple of days, leaving my computer on overnight. I should also mention this bot was created / tested using a character of the class "Cleric" (Winged Elf), but I believe the bot will work just fine with other classes as well, but this have not been tested.
[b]Warning:[/b] The use of any 3d party tool like Blue Eye Macro to play your character on any official Perfect World server, is likely to be considdered a violation of the games regulations. It is solely your responsibility to ensure no such regulations are violated - or use at your own risk.
[b]Credits:[/b] A big thanks to Martin for helping out with the tasks of locating base pointers and development of the macro.[/quote]
wouldn't there be a possible update? : S is giving error
|
|
|
|
Posted: Sun Dec 27, 2020 6:14 am |
|
|
|
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
I love this game, but all my macros to date have been tiny little aiming fails :p I'm going to check this out as soon as I can for sure c:
I love this game, but all my macros to date have been tiny little aiming fails :p I'm going to check this out as soon as I can for sure c:
|
|
|
|
Posted: Mon Mar 28, 2016 2:34 am |
|
|
|
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
|
|
|
Posted: Tue Oct 08, 2013 4:28 am |
|
|
|
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
Ok, I will try to find out if it's the path to the Element client that has been changed. xD
(edit) and yes sir it has changed. this is the new target path to the patcher: "C:\Perfect World Entertainment\Perfect World International\patcher"
It might vary depending on what machine people are running on, just for anyone else who is wondering.
Ok, I will try to find out if it's the path to the Element client that has been changed. xD
(edit) and yes sir it has changed. this is the new target path to the patcher: "C:\Perfect World Entertainment\Perfect World International\patcher"
It might vary depending on what machine people are running on, just for anyone else who is wondering.
|
|
|
|
Posted: Thu May 02, 2013 9:42 pm |
|
|
|
|
|
Post subject: |
Re: Perfect Bot v1.3 |
|
|
Useless Person wrote: Here is what I gathered from the memory pointer test:
Executing: Window.Send press keys(Window ID/Title: Element Client, Exact match: yes, Child: 0, Keys: {<esc>}) Error: The window could not be found Executing: Memory.Set value(Process/Window name: elementclient, Memory Address: elementclient.exe+0065BFCC,4,8,4a0,98, Length: 4, Value: 0) Error: Could not write the value: 0 to a process named elementclient at the following address: 152 Executing: Memory.Set value(Process/Window name: elementclient, Memory Address: elementclient.exe+0065BFCC,4,8,4a0,9c, Length: 4, Value: 0) Error: Could not write the value: 0 to a process named elementclient at the following address: 156 Executing: Window.Send mouse click(Window ID/Title: Element Client, Exact match: yes, Child: 0, X Coordinate: 125, Y Coordinate: 71, Mouse Button: left) Error: The window could not be found Executing: Variable.Evaluate (Math)(Expression: ({currentHP}/{maxHP})*100, To variable: currentHPpercentage) Error: The following expression could not be evaluated: ({currentHP}/{maxHP})*100 (parsed as: (0/0)*100) Executing: Variable.Evaluate (Math)(Expression: ({currentMP}/{maxMP})*100, To variable: currentMPpercentage) Error: The following expression could not be evaluated: ({currentMP}/{maxMP})*100 (parsed as: (0/0)*100) Checking if: Variable.Is less than (Math)(Variable name: currentHPpercentage, Value: 40) Error: A variable called currentHPpercentage, does not exist Checking if: Variable.Is less than (Math)(Variable name: currentMPpercentage, Value: 30) Error: A variable called currentMPpercentage, does not exist Executing: File.Read text(Path: c:\Perfect World Path.txt, Variable name: paths) Error: Reading text from the following file failed c:\Perfect World Path.txt
I'm still wondering why it's not reading the Pathing file. Could this be what's causing the bot to not work? Do we need to put in the actual current amount of HP and MP of our characters? I will have to try running this on a new character later tonight. It looks like the game is not running actually. Cant find the window, and cant find the process - unless the name of the windows and the process has been changed since I did the bot (quite a while ago).
[quote="Useless Person"]Here is what I gathered from the memory pointer test:
Executing: Window.Send press keys(Window ID/Title: Element Client, Exact match: yes, Child: 0, Keys: {<esc>}) Error: The window could not be found Executing: Memory.Set value(Process/Window name: elementclient, Memory Address: elementclient.exe+0065BFCC,4,8,4a0,98, Length: 4, Value: 0) Error: Could not write the value: 0 to a process named elementclient at the following address: 152 Executing: Memory.Set value(Process/Window name: elementclient, Memory Address: elementclient.exe+0065BFCC,4,8,4a0,9c, Length: 4, Value: 0) Error: Could not write the value: 0 to a process named elementclient at the following address: 156 Executing: Window.Send mouse click(Window ID/Title: Element Client, Exact match: yes, Child: 0, X Coordinate: 125, Y Coordinate: 71, Mouse Button: left) Error: The window could not be found Executing: Variable.Evaluate (Math)(Expression: ({currentHP}/{maxHP})*100, To variable: currentHPpercentage) Error: The following expression could not be evaluated: ({currentHP}/{maxHP})*100 (parsed as: (0/0)*100) Executing: Variable.Evaluate (Math)(Expression: ({currentMP}/{maxMP})*100, To variable: currentMPpercentage) Error: The following expression could not be evaluated: ({currentMP}/{maxMP})*100 (parsed as: (0/0)*100) Checking if: Variable.Is less than (Math)(Variable name: currentHPpercentage, Value: 40) Error: A variable called currentHPpercentage, does not exist Checking if: Variable.Is less than (Math)(Variable name: currentMPpercentage, Value: 30) Error: A variable called currentMPpercentage, does not exist Executing: File.Read text(Path: c:\Perfect World Path.txt, Variable name: paths) Error: Reading text from the following file failed c:\Perfect World Path.txt
I'm still wondering why it's not reading the Pathing file. Could this be what's causing the bot to not work? Do we need to put in the actual current amount of HP and MP of our characters? I will have to try running this on a new character later tonight.[/quote]
It looks like the game is not running actually. Cant find the window, and cant find the process - unless the name of the windows and the process has been changed since I did the bot (quite a while ago).
|
|
|
|
Posted: Thu May 02, 2013 9:20 am |
|
|
|
|