ideas:

Need some help with that macro you're working on or aren't quite sure how to get your macro to do something? Ask here!

Moderator: MacroQuest Developers

takenote
orc pawn
orc pawn
Posts: 11
Joined: Sat Jan 31, 2004 1:04 am

ideas:

Post by takenote » Sat Jan 31, 2004 2:11 pm

Idea:

what if we were to set up a macro learning center?
i am a noobie when it comes to writing macros/scripts. would love to see a "school" of macroing listed in the posts... for example ...
noobie: how to make macros to press hot keys in game (simple stuff like that)
i like the snippets but how would i add them to a current macro?
how do i edit a current macro?


.... i learned what i know from useing "xylobot" but it seems that the macro/scripting here is differant

second idea:

in the macr depository set up areas for the classes ..ie. mage ,warror, rogue/warror.bard/druid/ranger... so that if i am looking for a macro for my druid i wouldent have to sort through 10,000 posts to find one



....what do you think??

ml2517
a grimling bloodguard
a grimling bloodguard
Posts: 1216
Joined: Wed Nov 12, 2003 1:12 am

Post by ml2517 » Sat Jan 31, 2004 2:14 pm

I came here from Xylobot also. Everything you need to learn how to make macros is already here. It just takes a bit of effort on your part. Read, read more.. and then when you think you know what you are doing, read some more.

takenote
orc pawn
orc pawn
Posts: 11
Joined: Sat Jan 31, 2004 1:04 am

Post by takenote » Sat Jan 31, 2004 2:33 pm

was hopeing to get a little better organization (sp) in the macro lib. i dont mind reading but i have spent 3 hrs trying to find a macro that would help my warr auto assist (player 1) attack the mob with taunt,kick,bash. then follow p-1. the problem i faced with xylobot is that the (dumb) warr wouldent step up to the mob close enough to hit it.

i have two comps that i run 3 accounts off of and at the moment i am pl'ing two toons with a third. will MQ let me run macros on both accounts that i run on one pc?


also.. have you noticed that the macro descriptions are a little weak? would be nice to see a list of what can and cant be changed while running macro (var )??

bob_the_builder
a hill giant
a hill giant
Posts: 275
Joined: Tue Jul 22, 2003 1:22 pm

Post by bob_the_builder » Sat Jan 31, 2004 5:23 pm

trying to find a macro that would help my warr auto assist (player 1) attack the mob with taunt,kick,bash. then follow
Check the Depot, there is genbot and stick
Both will do what you need, might have to add a follow master after mob is dead for the stick.mac

Bob

Preocts
a snow griffon
a snow griffon
Posts: 312
Joined: Thu Jan 29, 2004 1:02 pm

Humble Opinions

Post by Preocts » Sat Jan 31, 2004 6:57 pm

Being new to the forums but a long time programmer I'll tread lightly on this subject lest I offend someone too much.
also.. have you noticed that the macro descriptions are a little weak? would be nice to see a list of what can and cant be changed while running macro (var )??
It has been my longtime understanding of scripts and macros that the authors intentionally leave things vauge. From IRC to Macroquesting EQ, when you want to learn how to program the tools and knowledge pool are there but you must be willing to search.
Macroquest breaks the rules. Plain and simple. From the EULA on up. If it were simple, Sony would crack down so fast that our heads would spin.

The code posted here is for both examples and direct application. Yet that does not mean the code posted here is to help the majority customize their MQ to suit their needs.
There is a reason that MQ is released in source code only and needs the user to compile it. That is not your average, "I took a Intro To Computers class" skill. The macros are similarly written. There is enough information there to guide the programmer. You simply need the drive to understand it.

You complied MQ and installed it, I assume. Don't stop now. Explore, expand, and experiment. The forums are here to help you learn, but only if you are willing to help yourself learn.

have two comps that i run 3 accounts off of and at the moment i am pl'ing two toons with a third. will MQ let me run macros on both accounts that i run on one pc?
Have you tried? I'd be interested in the results. Been planning on experimenting with that concept myself, just been working too hard on another project right now.

::ponders:: Sometimes I reread my work and wonder: "Just how many people was I trying to upset anyway?" :twisted:

User avatar
SimpleMynd_01
a lesser mummy
a lesser mummy
Posts: 71
Joined: Thu May 08, 2003 3:16 pm

2 EQs on 1 comp

Post by SimpleMynd_01 » Sat Jan 31, 2004 7:31 pm

I run two characters on one machine and MacroQuest works just fine on both of them.

-SimpleMynd

takenote
orc pawn
orc pawn
Posts: 11
Joined: Sat Jan 31, 2004 1:04 am

2 accounts one pc

Post by takenote » Sat Jan 31, 2004 7:36 pm

tryed the 2 accounts on one pc with MQ running map workd great still working on the scripts
would be great if i can get scripts running on both

User avatar
wilso132
Contributing Member
Contributing Member
Posts: 106
Joined: Thu Oct 17, 2002 11:53 am

Post by wilso132 » Sat Jan 31, 2004 11:05 pm

The best way to learn is just to sit down a do some code, no matter how simple it may be. If you really want to learn, make a script that finds all orc pawns, walk to them, kill them, then loot any orc picks they may have.


That's how you learn, you read the manual and figure out how do to it by DOING it, not by being taught. The best way to learn any language (in my opinion) is just to teach yourself, otherwise you really won't learn it at all.

takenote
orc pawn
orc pawn
Posts: 11
Joined: Sat Jan 31, 2004 1:04 am

Post by takenote » Sat Jan 31, 2004 11:54 pm

wilso132 wrote:The best way to learn is just to sit down a do some code, no matter how simple it may be. .
but you see the macro scripting is not the same here as "xylobot" you see here is a script from them

// Script: twister.xys
// Description: Twister (with control channel)
// Written By: oracleofdelphi
// Modified By: Maelstrom
// Last Updated: August 30, 2003

//[ REMEMBER TO SET ['Auto pause on user input for 1 second' TO FALSE IN YOUR XYLOBOT ADVANCED SETTINGS!!! ]

//[ ALSO ['Use Xylobot "Fast" Keys' TO FALSE IN YOUR XYLOBOT ADVANCED SETTINGS!!! ]

//[ ALSO [In 'Options' in Xylobot you must select your character's logfile in the 'Log File' box. ]
//[ [It will be something like 'C:\Program Files\Sony\EverQuest Trilogy\eqlog_CharacterName_33.txt' ]
//[ [** If you use the AutoSearchLogFile setting it should be able to find your latest logfile and ]
//[ [** start reading it without having to set it from the Xylobot GUI. ]

// NOTE: The old /cast functionality is still in the code but avoid at all costs, it will probably interfere too much primarily
// if you have circle mode engaged. Altmode works alot better.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////// Control Channel Commands///////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// h Help Menu //
//----------------------------------------------------------------------------------------------------------------------------//
// . Pause/Unpause Song Twisting //
//----------------------------------------------------------------------------------------------------------------------------//
// , Pause/Unpause Circle Run Mode //
//----------------------------------------------------------------------------------------------------------------------------//
// @ Abort and exit script //
//----------------------------------------------------------------------------------------------------------------------------//
// ! Reports current settings //
//----------------------------------------------------------------------------------------------------------------------------//
// + Increases circle size to be run //
//----------------------------------------------------------------------------------------------------------------------------//
// - Decreases circle size to be run //
//----------------------------------------------------------------------------------------------------------------------------//
// # Toggles auto selos refresh on/off //
//----------------------------------------------------------------------------------------------------------------------------//
// $ Toggles auto insta-cast-item refresh on/off //
//----------------------------------------------------------------------------------------------------------------------------//
// ^ Toggles auto noninsta-cast-item refresh on/off //
//----------------------------------------------------------------------------------------------------------------------------//
// * Toggles auto correct on/off //
//----------------------------------------------------------------------------------------------------------------------------//
// a Triggers auto correct on demand //
//----------------------------------------------------------------------------------------------------------------------------//
// t Toggles auto targeting on/off //
//----------------------------------------------------------------------------------------------------------------------------//
// sg=x Sets the selos spell gem number to use when auto selos is engaged, where x is the spell gem number //
//----------------------------------------------------------------------------------------------------------------------------//
// b=xxx Sets buffer size to be added to the spell time constant, where xxx is a numeric value in milliseconds //
//----------------------------------------------------------------------------------------------------------------------------//
// w=xxx Sets time to wait between songs, where xxx is a numeric value in milliseconds //
//----------------------------------------------------------------------------------------------------------------------------//
// xxxxx You can enter in a string of numbers that represent the twist order of songs, where xxxxx are numbers. //
// The numbers correspond to the spell gem numbers. This string can be fairly long such as 3456345634563456345634568 //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//======================================================================
// The following settings can only be set in the script
//======================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const AutoSearchLogFile = true; // If set to true this will search for the logfile of your currently logged on character. If you have an older OS such as Windows 98 this might not work. If it doesn't work for you, simply choose your correct logfile in the Xylobot application and set AutoSearchLogFile to false.
// If this is taking too long and/or you do not switch characters that often simply set your log file in Xylobot and change this to false.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var Channel : string = 'marksbard1'; // Chat channel to be used for control channel commands -- Change this to a unique channel name
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var ChannelPass : string = 'hannah'; // Chat channel password -- Change this to a unique password
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const AutoJoinChannel = true; // Turn off/on Auto-Joining to the channel. (Turn this to false if you use /autojoin within EQ already for that channel and prefer to use that.)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const DebugMode = false; // Turn off/on Debug mode
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const AltSingMode = true; // Toggle between traditional /cast spellgem mode and alt spell gem mode. true = alt mode -- false = /cast mode
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const AutoSeloRefreshTime = 120000; // Sets how long between refreshing selos in milliseconds, if using auto-selo refresh in circle mode.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const AutoCorrectRefreshTime = 30000; // Sets how long between auto-running you back to your starting location in milliseconds if using auto-correct refresh in circle mode.
// NOTE: If you are within MaxDistance locs from your starting point Auto Correct will not trigger and will wait until the next refresh time.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
// These entries are restarted immediately upon being seen if the casting timer hasn't completed.
const Fail1 = 'You haven''t recovered yet';
const Fail2 = 'You miss a note';
const Fail3 = 'Your song ends.';
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
// These entries are restarted after a pause (The pause is set via the NoSpam constant) so as not to spam your text window.
const NoSpam = 100; // Time to wait in milliseconds to retry these songs. I'd suggest leaving this about here.
const FailNS1 = 'You can''t cast spells while stunned!';
const FailNS2 = 'You are stunned!';
const FailNS3 = 'Your target is out of range'; // If in Circle and Twisting mode and this entry is encountered the system will restart the song after a brief pause.
const FailNS4 = 'You cannot see your target.'; // If in Circle and Twisting mode and this entry is encountered the system will restart the song after a brief pause.
const FailNS5 = 'You must first select a target for this spell!'; // If AutoTargetMode, Circle and Twisting modes are on and this entry is encountered the system will try to use F8 to target a mob.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
// These entries are for songs that are critical to have completed properly.
const Repeat1 = 'Your target resisted the Tuyen`s Chant of the Plague spell.';
const Repeat2 = 'Your target resisted the Tuyen`s Chant of Ice spell.';
const Repeat3 = 'Your target resisted the Tuyen`s Chant of Fire spell.';
const Repeat4 = 'Your target resisted the Tuyen`s Chant of Venom spell.';
const Repeat5 = 'Your feet move faster.'; // This specific entry is only used to make sure that while in auto-selo refresh mode your selos actually gets refreshed.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const Fatal1 = '] LOADING, PLEASE WAIT...'; // This entry is for determining if you zoned or died. Will autopause the script if encountered.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const StopSongString = '/st<CR>'; // String used for doing a /stopsong
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const ChatString = '/chat #'; // String used for sending a /chat message to a channel
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const CastString = '/cas '; // String used for /casting a spell gem
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const CastTime = 3010; // Sets the standard time it takes to sing songs
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var ObjectNumSides : integer = 12; // 8 sides seems to work well for me. You can experiment though.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const InstaCastKey = 10; // Default key to hit for InstaCastItem -- The correct way to do this is to reserve one hotkey on every hotkey
// page and place a hotkey for the insta-cast item in question in that hotbox. Then go into your keyboard
// mappings in EQ and set up an alternate key mapping for that hotkey number and set it to something like the * or / on your numeric pad.
// This way when you switch hotpages there is no fear of it triggering the wrong thing. Also this is
// done so that it hopefully doesn't interrupt your typing etc.

// ** You can find Key code mappings in the Xylobot forums.** 181 is the key code for the Num Keypad "/" key.
// NOTE: You apparently can't use ctrl+key or alt+key mappings for triggering hotkeys. You must use a single key.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const InstaCastItemRefreshTime = 12; // Sets how long between refreshing your Insta-cast item in milliseconds, if using UseAutoInstaCast refresh in singing mode.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const InstaCastTime = 5; // This is the casting time on your instacast item -- Yes some items appear to be instacast and aren't, if you come accross an item
// like this use this setting to compensate. If it truly is an instacast item try taking the entry down to 1.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const NonInstaCastKey = 55; // Default key to hit for NonInstaCastItem -- The correct way to do this is to reserve one hotkey on every hotkey
// page and place a hotkey for the noninsta-cast item in question in that hotbox. Then go into your keyboard
// mappings in EQ and set up an alternate key mapping for that hotkey number and set it to something like the * or / on your numeric pad.
// This way when you switch hotpages there is no fear of it triggering the wrong thing. Also this is
// done so that it hopefully doesn't interrupt your typing etc.

// ** You can find Key code mappings in the Xylobot forums.** 55 is the key code for the Num Keypad "*" key.
// NOTE: You apparently can't use ctrl+key or alt+key mappings for triggering hotkeys. You must use a single key.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const NonInstaCastTime = 4300; // This is the casting time in milliseconds on your non-instacast item. If you get some spell spam your number probably isn't high enough, add a few 100 to it at a time to see if it helps.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
const NonInstaCastItemRefreshTime = 60000; // Sets how long between refreshing your Non-insta-cast item in milliseconds, if using UseAutoNonInstaCast refresh in singing mode.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var MaxDistanceB4AutoCorrect : integer = 100;// Sets the maximum distance you can wander from your circle mode starting point. If you are outside of the MaxDistanceB4AutoCorrect range in X or Y Location from where you started Circle Mode and AutoCorrect is called,
// either via the AutoCorrectRefresh or manually triggered with the "a" key sent to your command channel,
// you will be sent back to your starting location and then singing and circle mode will resume. If you are going to be running a large circle you should increase this number some.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

//====================================================================================================================================
// The following settings can be set in the script as well as in game -- When set here they are your defaults.
//=====================================================================================================================================
var AutoTargetMode : boolean = True; // Default for AutoTargeting of Mobs while in Circle and Twisting mode. This should only be used when using single target DoTs. There is no need to use this setting with AoE because you don't have to pick a target. This simply uses F8 to try to target a mob in the area.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var Buffer : integer = 200; // Default buffer to add to the const CastTime
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var Wait : integer = 100; // Default wait time between songs
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var Melody : string = '1234'; // Default starting songs.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var UseAutoSeloRefresh : boolean = true; // Turn off/on Auto-Selos refresh (Only does this while in circle run mode.)
// * ONLY use this with the 2min 30sec selos
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var SeloRefreshGem : string = '8'; // Default spell gem for Auto-Selos refresh
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var UseAutoInstaCast : boolean = false; // Turn off/on insta-cast item refresh (Only does this while in singing mode.)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var UseAutoNonInstaCast : boolean = false; // Turn off/on noninsta-cast item refresh (Only does this while in singing mode.)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var UseAutoCorrect : boolean = true; // Turn off/on auto-correct (Only does this while in circle mode.) This runs you back to your starting loc every so often based on your AutoCorrectRefreshTime setting above.
// Keep in mind that while AutoCorrect is running it might interrupt typing when it has to issue its /loc commands to get its information.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
var RadiusSize : integer = 500; // The larger the number the larger the circle. You must use increments of 500.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

// ------------------
// Includes
{$I 'keyisdown.h'}
// ------------------

//======================================================================
// Code starts here, change at your own risk
//======================================================================

//======================================================================
// Variables
//======================================================================

type
TLocPoint = record
x, y, z : float;
end;

var AbortScript : boolean = false;
var ActualStopTurnTime : integer;
var ActualStopPauseTime : integer;
var AddStraights : float;
var AddTurns : float;
var Answer : string;
var AutoCorrectStr : string;
var AutoCorrectTimer : integer;
var AutoICIStr : string;
var AutoNICIStr : string;
var AutoSeloStr : string;
var AutoTargetStr : string;
var CalCLogText : string;
var CalGotLoc : boolean;
var CalLOCSTR : string;
var CalCLogMarker : integer;
var CalOrigMarker : integer;
var CalNumTry : integer;
var CalPauseFor : integer;
var CalCounter : integer;
var Circle : boolean = false;
var CircObject : float;
var Circumference : float;
var CurrentlyCorrecting : boolean = false;
var CurrentAngle : float;
var CurrentLocation : TLocPoint;
var DoingCalibration : boolean;
var DoneMelody : boolean = false;
var eqTargetCurrent : string;
var FailSongArea : boolean = false;
var HalfInsideAngle : float;
var HighMarkDegrees : float;
var HighMarkms : float;
var HoldButtonTimeDown : integer;
var i : integer;
var InstaClickCastTimer : integer;
var InstaClickTimer : integer = 1;
var LengthOfLine : integer;
var LogMarker : integer;
var LogText : string;
var LowMarkDegrees : float;
var LowMarkms : float;
var NonInstaClickCastTimer : integer;
var NonInstaClickTimer : integer = 1;
var NoSpamTimer : integer;
var PauseTwisting : boolean = false;
var Radius : integer;
var RadiusSizeMod : integer;
var RepeatSong : boolean = false;
var RepeatSongArea : boolean = false;
var SaveCircleMode : boolean = False;
var SaveMelody : string;
var SavePausedMode : boolean = True;
var SaveSong : integer;
var SeloStartTime : integer = 1;
var SingStartTime : integer;
var SingWaitTime : integer;
var Song : integer = 1;
var SongSlot : integer;
var StartedAtLocX : float;
var StartedAtLocY : float;
var StartPauseTimeFlag : boolean = false;
var StartTurnTimeFlag : boolean = false;
var StartWaitTime : integer;
var StepInterval : integer;
var StopPauseTime : integer;
var StopPauseTimeFlag : boolean = false;
var StopPauseTimeMod : integer = 0;
var StopSong : boolean;
var StopTurnTime : integer;
var StopTurnTimeFlag : boolean = false;
var StopTurnTimeMod : integer = 0;
var StraightSpeed : float;
var TargetAngle : float;
var Temp : string;
var TempLogText : string;
var TempStep : string;
var TimesCorrected : integer;
var TotalRepsStraight : integer;
var TotalRepsTurn : integer;
var TurnSpeed : array [1..16] of array [1..2] of float;
var TriggerSelo : boolean = false;
var TSS : array [1..16] of array [1..2] of float;
var WedgePauseTime : float;
var WedgeTurnTime : integer;
var Xlocation : float;
var Ylocation : float;
var ZonedOrDied : boolean = false;

procedure AutoCorrectProc; forward;
procedure CalcTargetAngle(x, y: float); forward;
procedure CalibrateLogFileSpeed; forward;
procedure ChannelCheck; forward;
procedure CircleProc; forward;
procedure Command(TempLogText:string); forward;
procedure ConfigCircle; forward;
procedure DoCalibration; forward;
procedure GetAngle; forward;
procedure GetLocation; forward;
procedure RunToLoc(x, y: float; Careful: boolean); forward;
procedure SendLine(Line : string); forward;
procedure Sing; forward;
procedure TargetNearestNPC; forward;
procedure TurnToTarget; forward;


SendKeys('/'); SendKeys('c'); SendKeys('l'); SendKeys('e'); SendKeys('a'); SendKeys('r'); SendKeys('<CR>');


if (AutoSearchLogFile) then begin
SendLine('/log<CR>');
SendLine('/log<CR>');
SetLogFile(GetCurrentLogFile);
end;

// --------------------------------------------------
// Determines if logging is turned on in EQ and turns it on if necessary. If it still can't read the log it aborts the script.
CalLOCSTR := 'Your location is';
CalCLogMarker := SetLogMarker;
CalOrigMarker := CalCLogMarker;
SendLine('/loc<CR>');
Pause(200);
CalCLogMarker := CalOrigMarker;
CalCLogText := GetNewLogText(CalCLogMarker);
CalGotLoc := HasToken(CalCLogText, CalLOCSTR);

if (NOT CalGotLoc) then begin
SendLine('/log<CR>');
CalCLogMarker := SetLogMarker;
CalOrigMarker := CalCLogMarker;
SendLine('/loc<CR>');
Pause(200);
CalCLogMarker := CalOrigMarker;
CalCLogText := GetNewLogText(CalCLogMarker);
CalGotLoc := HasToken(CalCLogText, CalLOCSTR);
end;
if (NOT CalGotLoc) then Debug('Unable to access your logfile! Ensure it is set properly in Xylobot.');
if (NOT CalGotLoc) then exit;
// --------------------------------------------------



// Joins your chat channel if you have AutoJoinChannel set to true
if (AutoJoinChannel) then begin
SendLine('/join ' + Channel + ':' + ChannelPass + '<CR>');
end;

var IniFile : TIniFile = TIniFile.Create(GetXylobotDirectory + 'calibrate.txt');
if NOT IniFile.SectionExists('RunSpeed') then begin
IniFile.Free;
Debug('---------------------------------------------------------------------------------------------------');
Debug('calibrate.txt not found. The script needs to run a calibration for your system. ');
Debug('Please type YES on the dialogue box that appears to continue or NO to exit and run it later. ');
Debug(' ');
Debug('If you choose to continue with the calibration ***make sure that your Selos is up and running and ');
Debug('and that you have your drum and everything equipped ***. Also, ensure that you are in an open area');
Debug('with no obstructions. ');
Debug(' ');
Debug('Please Do Not touch your mouse or keyboard during the calibration. It will take about 5 minutes. ');
Debug(' ');
Debug('*At the beginning of the test you will notice alot of spam from the /help command in EQ, dont worry');
Debug('about it. It is designed to give the script some indication of how fast your logfile read speed is.');
Debug(' ');
Debug('If for some reason you need to re-calibrate, just delete the calibrate.txt file in the root of your');
Debug('Xylobot directory. ');
Debug(' ');
Debug('Close this dialigue box when done reading. ');
Debug('---------------------------------------------------------------------------------------------------');
Pause(25000);
InputQuery('Continue? Type YES or NO then Enter to continue.', Answer);
if NOT (UpperCase(Answer)='YES') then Debug('You will not be able to run this script without calibrating. Exiting.');
if NOT (UpperCase(Answer)='YES') then Exit;
DoCalibration;
Debug('Calibration complete please restart the script.');
Exit;
end;
IniFile.Free;

// Grabbing your default straight and turn time settings from the calibrate.txt file.
// NOTE: If your speed changes for any reason (you get a new drum, run speed AAxp etc..) you must delete the calibrate.txt file from the root of your Xylobot directory and re-run this script for the settings to be precise.

var IniFile2 : TIniFile = TIniFile.Create(GetXylobotDirectory + 'calibrate.txt');

var RunSpeed : float = IniFile2.ReadFloat('RunSpeed', 'RunSpeed', 0);
if (RunSpeed=0) then IniFile2.Free;
if (RunSpeed=0) then exit;
var RunSpeedSave : float = RunSpeed;


var LogSpeed : integer = IniFile2.ReadInteger('LogFileSpeed', 'LogSpeed', 0);
if (LogSpeed=0) then IniFile2.Free;
if (LogSpeed=0) then exit;


var Stepit : integer = 50;
for i:=1 to 16 do begin
TurnSpeed [1]:= IniFile2.ReadFloat('TurnSpeed', 'TurnSpeed' + IntToStr(stepit), 0);
TurnSpeed [2]:= Stepit;
TSS [1]:= TurnSpeed [1];
TurnSpeed [1]:=((TurnSpeed [1]/1000)*TurnSpeed [2]); // Convert from average degrees per second to degrees per millisecond
if (Stepit<1000) and (Stepit>499) then Stepit:=Stepit+100;
if (Stepit<500) and (Stepit>99) then Stepit:=Stepit+50;
if (Stepit<100) then Stepit:=Stepit+25;
end;
IniFile2.Free;

ConfigCircle;

Channel:=lowercase(Channel);
if (DebugMode) then Debug('Script started');
if (DebugMode) then Debug('Selected logfile: '+GetLogFile);
if (DebugMode) then Debug('Selected channel: '+Channel);
SendLine(ChatString+Channel+' O<CR>');

if (UseAutoSeloRefresh) then AutoSeloStr:='ON' else AutoSeloStr:='OFF';
if (UseAutoInstaCast) then AutoICIStr:='ON' else AutoICIStr:='OFF';
if (UseAutoNonInstaCast) then AutoNICIStr:='ON' else AutoNICIStr:='OFF';
if (UseAutoCorrect) then AutoCorrectStr:='ON' else AutoCorrectStr:='OFF';
if (AutoTargetMode) then AutoTargetStr:='ON' else AutoTargetStr:='OFF';

PauseTwisting:=true;
LogMarker:=SetLogMarker;

// Main Loop

if (NOT AbortScript) then begin
repeat
if (Radius<>RadiusSize) then ConfigCircle;
CircleProc;
ChannelCheck;
if (ZonedOrDied) and (NOT PauseTwisting) then Command('You tell '+Channel+', ''.''');
if (Circle) and (ZonedOrDied) then Command('You tell '+Channel+', '',''');
ZonedOrDied:=false;
if (Circle) and (UseAutoSeloRefresh) and (GetTickCount-SeloStartTime>(AutoSeloRefreshTime-20000)) then begin
SeloStartTime:=GetTickCount;
TriggerSelo:=true;
SaveMelody:=Melody;
SaveSong:=Song;
Melody:=SeloRefreshGem;
DoneMelody:=true;
Song:=1;
SendLine(StopSongString);
Sing;
Melody:=SaveMelody;
Song:=SaveSong;
TriggerSelo:=false;
if (DebugMode) then Debug('Redo Selo');
end;
if (UseAutoCorrect) and (Circle) then begin
if (GetTickCount-AutoCorrectTimer>AutoCorrectRefreshTime) then begin
AutoCorrectTimer:=GetTickCount;
AutoCorrectProc;
end;
end;
if (NOT PauseTwisting) then Sing;
until (AbortScript);
end;

// End Main loop

SendLine(ChatString+Channel+' X<CR>');
KeyDown(208); KeyUp(208); KeyDown(200); KeyUp(200); KeyDown(205); KeyUp(205); KeyDown(203); KeyUp(203);

if (AutoJoinChannel) then begin
SendLine('/leave ' + Channel + '<CR>');
end;

// Exit

// -------------------------------- Procedures --------------------------------------------

// Procedure for triggering the AutoCorrect routine.

procedure AutoCorrectProc;
begin
if (Circle) then begin
GetLocation;
if (Abs(StartedAtLocX-(XLocation))>MaxDistanceB4AutoCorrect) or (Abs(StartedAtLocY-(YLocation))>MaxDistanceB4AutoCorrect) then begin

CurrentlyCorrecting:=true;
Command('You tell '+Channel+', '',''');
SavePausedMode:=true;

If (NOT PauseTwisting) then begin
SavePausedMode:=PauseTwisting;
Command('You tell '+Channel+', ''.''');
end;
KeyDown(205); KeyUp(205); KeyDown(203); KeyUp(203);
TimesCorrected:=TimesCorrected+1;
//debug('Times Corrected: ' + IntToStr(TimesCorrected));
RunToLoc(StartedAtLocX, StartedAtLocY, False);
If (NOT SavePausedMode) then begin
Command('You tell '+Channel+', ''.''');
end;
Command('You tell '+Channel+', '',''');
CurrentlyCorrecting:=false;
end;
end;
end;

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

// Procedure for reading the log file

procedure ChannelCheck;
begin
if (SetLogMarker<>LogMarker) then begin
LogText:=GetNewLogText(LogMarker);
TempLogText:=LogText;
LogMarker:=SetLogMarker;
if (DebugMode) then Debug(LogMarker);
if (DebugMode) then Debug(SetLogMarker);
if (HasToken(LogText, Fatal1)) then begin
ZonedOrDied:=true; StopSong:=true; DoneMelody:=true;
end;
if (HasToken(LogText, 'You tell '+Channel)) then Command(LogText);
if (FailSongArea) then begin
if ((HasToken(LogText, FailNS1)) or (HasToken(LogText, FailNS2))) then begin
if (DebugMode) then Debug('Fail No Spam area');
NoSpamTimer:=GetTickCount;
Repeat
CircleProc;
Until (GetTickCount-NoSpamTimer>NoSpam);
StopSong:=true;
end;

if (Circle) then begin
if ((HasToken(LogText, FailNS3)) or (HasToken(LogText, FailNS4))) then begin
if (DebugMode) then Debug('Fail No Spam area while in Circle Mode');
NoSpamTimer:=GetTickCount;
Repeat
CircleProc;
Until (GetTickCount-NoSpamTimer>NoSpam);
StopSong:=true;
end;
end;

if (Circle) and (AutoTargetMode) and (HasToken(LogText, FailNS5)) then begin
if (DebugMode) then Debug('Target closest NPC');
CircleProc;
TargetNearestNPC;
StopSong:=true;
end;

if ((HasToken(LogText, Fail1)) or (HasToken(LogText, Fail2)) or (HasToken(LogText, Fail3))) then begin
if (DebugMode) then Debug('Fail Normal area');
StopSong:=true;
end;
end;
if (RepeatSongArea) then begin
if ((HasToken(LogText, Repeat1)) or (HasToken(LogText, Repeat2)) or (HasToken(LogText, Repeat3)) or (HasToken(LogText, Repeat4))) then begin
if (DebugMode) then Debug('Repeat Song');
RepeatSong:=true; StopSong:=true;
end;
if (Circle) and (UseAutoSeloRefresh) and (TriggerSelo) then begin
if (NOT (HasToken(LogText, Repeat5))) then begin
if (DebugMode) then Debug('Repeat Song');
RepeatSong:=true; StopSong:=true;
end;
end;
end;
LogText:='';
end;
end;

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

// Procedure for running in a circle

procedure CircleProc;
begin
if (Circle) then begin
if (StopPauseTimeFlag) and (GetTickCount-StopPauseTime<((WedgePauseTime+StopPauseTimeMod)-20)) then Pause(20);
if (StopTurnTimeFlag) and (GetTickCount-StopTurnTime<((WedgeTurnTime+StopTurnTimeMod)-20)) then Pause(20);
if (StopPauseTimeFlag) and (GetTickCount-StopPauseTime>(WedgePauseTime+StopPauseTimeMod)) then begin
ActualStopPauseTime:=(GetTickCount-StopPauseTime);
if (ActualStopPauseTime>WedgePauseTime) then StopPauseTimeMod:=(StopPauseTimeMod-1);
if (ActualStopPauseTime<WedgePauseTime) then StopPauseTimeMod:=(StopPauseTimeMod+1);
StopPauseTimeFlag:=False;
StartTurnTimeFlag:=True;
if NOT KeyIsDown('<UP>') then begin
KeyUp(200); KeyDown(200);
end;
//Debug('WedgePauseTime=' + IntToStr(WedgePauseTime) + ' Actually Took=' + IntToStr(ActualStopPauseTime) + ' Modifier is:' + IntToStr(StopPauseTimeMod));
//Debug('----------------------------------------------');
end;
if (StopTurnTimeFlag) and (GetTickCount-StopTurnTime>(WedgeTurnTime+StopTurnTimeMod)) then begin
ActualStopTurnTime:=(GetTickCount-StopTurnTime);
if (ActualStopTurnTime>WedgeTurnTime) then StopTurnTimeMod:=(StopTurnTimeMod-1);
if (ActualStopTurnTime<WedgeTurnTime) then StopTurnTimeMod:=(StopTurnTimeMod+1);
StopTurnTimeFlag:=False;
StartPauseTimeFlag:=True;
KeyDown(205); KeyUp(205);
if NOT KeyIsDown('<UP>') then begin
KeyUp(200); KeyDown(200);
end;
//Debug('WedgeTurnTime=' + IntToStr(WedgeTurnTime) + ' Actually Took=' + IntToStr(ActualStopTurnTime) + ' Modifier is:' + IntToStr(StopTurnTimeMod));
//Debug('----------------------------------------------');
end;
if (StartPauseTimeFlag) then begin
StartPauseTimeFlag:=False;
StopPauseTimeFlag:=True;
if NOT KeyIsDown('<UP>') then begin
KeyUp(200); KeyDown(200);
end;
StopPauseTime:=GetTickCount;
end;
if (StartTurnTimeFlag) then begin
StartTurnTimeFlag:=False;
StopTurnTimeFlag:=True;
KeyUp(205); KeyDown(205);
if NOT KeyIsDown('<UP>') then begin
KeyUp(200); KeyDown(200);
end;
StopTurnTime:=GetTickCount;
end;
end;
end;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

procedure ConfigCircle;
begin
Radius:=RadiusSize;
StopPauseTimeMod:=0;
StopTurnTimeMod:=0;

// Figure out how much straight run time we should pause for based on the size of your circle and the number of sides of your
// run pattern. (if you picked 8 sides you'd have an octagon that is rounded off on the edges.)
StraightSpeed:=RunSpeed;
Circumference:=(2*PI)*Radius;
HalfInsideAngle:=(90-(180/ObjectNumSides));
CircObject:=((((((Radius*((Cos(HalfInsideAngle/(180/PI)))/Sin(HalfInsideAngle/(180/PI)))*2))*ObjectNumSides)-Circumference)/2)+Circumference);
WedgePauseTime:=trunc((CircObject/ObjectNumSides)*(StraightSpeed/1000)); // We have our straight/pause time in milliseconds here.

// Figure out your turn speeds based on the information we gathered from the calibrate.txt file.
i:=16;
repeat
if (TurnSpeed [1]>(360/ObjectNumSides)) then begin
if NOT (i=1) then begin
if ((TurnSpeed [i-1] [1])<(TurnSpeed [1])) or ((TurnSpeed [i-1] [1])=(TurnSpeed [1])) then begin
HighMarkDegrees:=TurnSpeed [i] [1]; HighMarkms:=TurnSpeed [i] [2];
//Debug(FloatToStr(HighMarkDegrees));
end;
end;
end;
i:=i-1;
until (i=0);
i:=1;
repeat
if (TurnSpeed [i] [1]<(360/ObjectNumSides)) then begin
if NOT (i=16) then begin
if ((TurnSpeed [i+1] [1])>(TurnSpeed [i] [1])) or ((TurnSpeed [i+1] [1])=(TurnSpeed [i] [1])) then begin
LowMarkDegrees:=TurnSpeed [i] [1]; LowMarkms:=TurnSpeed [i] [2];
end;
end;
end;
i:=i+1;
until (i=17);
var GetTurn : array [1..3] of array [1..2] of float;
GetTurn [1] [1]:=LowMarkDegrees; GetTurn [1] [2]:= LowMarkms;
GetTurn [2] [1]:=HighMarkDegrees; GetTurn [2] [2]:= HighMarkms;
repeat
GetTurn [3] [1]:=(((GetTurn[2] [1]-GetTurn [1] [1])/2)+GetTurn [1] [1]); // Value in degrees
GetTurn [3] [2]:=(((GetTurn[2] [2]-GetTurn [1] [2])/2)+GetTurn [1] [2]); // Value in ms
if (GetTurn [3] [1]>(360/ObjectNumSides)) then begin
GetTurn [2] [1]:=GetTurn [3] [1];
GetTurn [2] [2]:=GetTurn [3] [2];
end else begin
GetTurn [1] [1]:=GetTurn [3] [1];
GetTurn [1] [2]:=GetTurn [3] [2];
end;
until (trunc(GetTurn [3] [1]))=(trunc(360/ObjectNumSides));
if (trunc(GetTurn [3] [1]))=(trunc(360/ObjectNumSides)) then begin
WedgeTurnTime:=trunc(GetTurn [3] [2]); // We have our turn time in milliseconds here.
end;
end;

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

// Procedure that looks for channel input.

procedure Command(TempLogText:string);
begin
TempLogText:=TextAfterToken(TempLogText, Channel + ':');
TempLogText:=TextAfterToken(TempLogText, ', ''');
TempLogText:=TextBeforeToken(TempLogText, '''');
TempLogText:=Trim(TempLogText);
if (DebugMode) then Debug('Command recognised: '+TempLogText);

// Stops and restarts the playing of songs.
if TempLogText='.' then begin
if (DebugMode) then Debug('Pause toggled.');
if (PauseTwisting) then PauseTwisting:=false else PauseTwisting:=true;
if (PauseTwisting) then DoneMelody:=true;
if (PauseTwisting) then StopSong:=true;
if (PauseTwisting) then SendLine(StopSongString);
if (NOT PauseTwisting) then begin
SendLine(StopSongString);
Song:=1;
end;
TempLogText:='';
end;

// Stops and restarts you running in circles.
if TempLogText=',' then begin
if (DebugMode) then Debug('Circle toggled.');
if (Circle) then Circle:=false else Circle:=true;
if (Circle) then begin
if (NOT CurrentlyCorrecting) then begin
GetLocation;
StartedAtLocX:=XLocation;
StartedAtLocY:=YLocation;
end;
StopPauseTimeMod:=0;
StopTurnTimeMod:=0;
StartPauseTimeFlag:=True;
AutoCorrectTimer:=GetTickCount;
if NOT KeyIsDown('<UP>') then begin
KeyUp(200); KeyDown(200);
end;
CircleProc;
end;
if (NOT Circle) then begin
StartPauseTimeFlag:=false;
StartTurnTimeFlag:=false;
StopPauseTimeFlag:=false;
StopTurnTimeFlag:=false;
KeyDown(208); KeyUp(208); KeyDown(200); KeyUp(200); KeyDown(205); KeyUp(205); KeyDown(203); KeyUp(203);
end;
TempLogText:='';
end;

// Aborts you out of the script entirely
if TempLogText='@' then begin
if (DebugMode) then Debug('Abort attempt.');
AbortScript:=true;
TempLogText:='';
end;

// Toggles Auto-Selo Refresh on/off
if TempLogText='#' then begin
if (DebugMode) then Debug('Auto-Selo toggled.');
if (UseAutoSeloRefresh) then UseAutoSeloRefresh:=false else UseAutoSeloRefresh:=true;
if (UseAutoSeloRefresh) then AutoSeloStr:='ON' else AutoSeloStr:='OFF';
TempLogText:='';
end;

// Toggles Auto Insta-Cast Refresh on/off
if TempLogText='$' then begin
if (DebugMode) then Debug('Auto-InstaCast toggled.');
if (UseAutoInstaCast) then UseAutoInstaCast:=false else UseAutoInstaCast:=true;
if (UseAutoInstaCast) then AutoICIStr:='ON' else AutoICIStr:='OFF';
TempLogText:='';
end;

// Toggles Auto NonInsta-Cast Refresh on/off
if TempLogText='^' then begin
if (DebugMode) then Debug('Auto NonInsta-Cast toggled.');
if (UseAutoNonInstaCast) then UseAutoNonInstaCast:=false else UseAutoNonInstaCast:=true;
if (UseAutoNonInstaCast) then AutoNICIStr:='ON' else AutoNICIStr:='OFF';
TempLogText:='';
end;

// Toggles Auto Correct Refresh Timer on/off
if TempLogText='*' then begin
if (DebugMode) then Debug('Auto Correct toggled.');
if (UseAutoCorrect) then UseAutoCorrect:=false else UseAutoCorrect:=true;
if (UseAutoCorrect) then AutoCorrectStr:='ON' else AutoCorrectStr:='OFF';
TempLogText:='';
end;

// Trigger Auto Correct Immediately
if TempLogText='a' then begin
if (DebugMode) then Debug('Auto Correct toggled.');
AutoCorrectProc;
TempLogText:='';
end;


// Toggles Auto Targeting on/off
if TempLogText='t' then begin
if (DebugMode) then Debug('Auto Target toggled.');
if (AutoTargetMode) then AutoTargetMode:=false else AutoTargetMode:=true;
if (AutoTargetMode) then AutoTargetStr:='ON' else AutoTargetStr:='OFF';
TempLogText:='';
end;


// Sets the Selo song gem number on the fly
if (HasToken(TempLogText, 'sg=')) then begin
if (DebugMode) then Debug('Selo gem number setting.');
TempLogText:=TextAfterToken(TempLogText, 'sg=');
SeloRefreshGem:=TempLogText;
TempLogText:='';
end;

// Sets the buffer size on the fly.
if (HasToken(TempLogText, 'b=')) then begin
if (DebugMode) then Debug('Buffer setting.');
TempLogText:=TextAfterToken(TempLogText, 'b=');
Buffer:=StrToInt(TempLogText);
TempLogText:='';
end;

// Increases the circle size.
if TempLogText='+' then begin
if (DebugMode) then Debug('Make a larger circle.');
RadiusSizeMod:=RadiusSize+500;
RadiusSize:=RadiusSizeMod;
if (RadiusSize>50000) then RadiusSize:=50000;
TempLogText:='';
end;

// Decreases the circle size.
if TempLogText='-' then begin
if (DebugMode) then Debug('Make a smaller circle.');
RadiusSizeMod:=RadiusSize-500;
RadiusSize:=RadiusSizeMod;
if (RadiusSize<500) then RadiusSize:=500;
TempLogText:='';
end;

// Sets the wait time on the fly.
if (HasToken(TempLogText, 'w=')) then begin
if (DebugMode) then Debug('Wait setting.');
TempLogText:=TextAfterToken(TempLogText, 'w=');
Wait:=StrToInt(TempLogText);
TempLogText:='';
end;

// Reports what your currect changable settings are.
if TempLogText='!' then begin
if (DebugMode) then Debug('Report request.');
Debug('+- Melody='+Melody+' | Buffer='+IntToStr(Buffer)+' | Wait='+IntToStr(Wait)+' | CircSz='+IntToStr(RadiusSize/500)+' | SeloRfrsh='+AutoSeloStr+' | InstaRfrsh='+AutoICIStr+' | NonInstaRfrsh='+AutoNICIStr+' | AutoCorrectRfrsh='+AutoCorrectStr+' | AutoTgt='+AutoTargetStr+' | SeloGem='+SeloRefreshGem+' -+');
LogMarker:=SetLogMarker;
TempLogText:='';
end;

// Help Menu
if TempLogText='h' then begin
if (DebugMode) then Debug('Help Menu.');
Debug('+------------------------------------------------------------------+');
Debug('| . ~~~~~~~~ Pause/Unpause Song Twisting ');
Debug('| b=xxx ~~~~ Buffer size in milliseconds where xxx is the number ');
Debug('| w=xxx ~~~~ Wait time in milliseconds where xxx is the number ');
Debug('| xxxxx ~~~~ Twist order where x is the spell gem number ');
Debug('| , ~~~~~~~~ Pause/Unpause Circle Run Mode ');
Debug('| + ~~~~~~~~ Increase Circle Size ');
Debug('| - ~~~~~~~~ Decrease Circle Size ');
Debug('| sg=x ~~~~~ Sets what spell gem to use for AutoSelo Refresh ');
Debug('| # ~~~~~~~~ Turn Auto Selo Refresh ON/OFF ');
Debug('| $ ~~~~~~~~ Turn Auto Insta-Cast Item Refresh ON/OFF ');
Debug('| ^ ~~~~~~~~ Turn Auto NonInsta-Cast Item Refresh ON/OFF ');
Debug('| * ~~~~~~~~ Turn Auto Correct Refresh ON/OFF ');
Debug('| a ~~~~~~~~ Triggers Auto Correct on demand ');
Debug('| t ~~~~~~~~ Turn Auto Target ON/OFF ');
Debug('| @ ~~~~~~~~ Abort Script ');
Debug('| ! ~~~~~~~~ Setting Report ');
Debug('+------------------------------------------------------------------+');
TempLogText:='';
end;

// Sets the Melody.
if ((TempLogText<>'') and (uppercase(TempLogText)=lowercase(TempLogText))) then begin
if (DebugMode) then Debug('Melody setting.');
Melody:=TempLogText;
end;
end;

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------


// SendLine Procedure - Fixes the SendKeys problem.

procedure SendLine(Line : string);

begin
Temp:=Copy(Line, 2, Length(Line)-1);
SendKeys('<CR>');
SendKeys(Copy(Line, 1, 1));
if HasToken(Temp, '<CR>') then begin
LengthOfLine:=Length(TextBeforeToken(Temp, '<CR>'));
for i:=1 to LengthOfLine do begin
SendKeys(Copy(TextBeforeToken(Temp, '<CR>'), i, 1));
end;
SendKeys('<CR>');
if TextAfterToken(Temp, '<CR>')<>'' then begin

LengthOfLine:=Length(TextAfterToken(Temp, '<CR>'));
for i:=1 to LengthOfLine do begin
SendKeys(Copy(TextAfterToken(Temp, '<CR>'), i, 1));
end;
end;
end;
end;

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

// Procedure that twists the songs.

procedure Sing;
begin
if (NOT AbortScript) then begin
DoneMelody:=false;
repeat
CircleProc;
SongSlot:=StrToInt(Copy(Melody, Song, 1));
SingStartTime:=GetTickCount;
StopSong:=false;
RepeatSong:=false;
if (DebugMode) then Debug('Sing: '+IntToStr(SongSlot)+'.');

if (AltSingMode) then begin
KeyDown(56); KeyDown(SongSlot+1); KeyUp(SongSlot+1); KeyUp(56);
end else begin
SendLine(CastString+IntToStr(SongSlot)+'<CR>');
end;
CircleProc;
ChannelCheck;
repeat
if (GetTickCount-SingStartTime>CastTime+Buffer) then StopSong:=true;
if (StopSong) then begin
CircleProc;
if ((AltSingMode) and (NOT AbortScript)) then begin
KeyDown(56); KeyDown(SongSlot+1); KeyUp(SongSlot+1); KeyUp(56);
end else begin
SendLine(StopSongString);
end;
CircleProc;
if (DebugMode) then Debug('Stop song.');
SingWaitTime:=GetTickCount;
repeat
CircleProc;
until (GetTickCount-SingWaitTime>Wait);

RepeatSongArea:=true;
ChannelCheck;
RepeatSongArea:=false;

if (NOT RepeatSong) then begin
Song:=Song+1;
if (Song>Length(Melody)) then begin
Song:=1; DoneMelody:=true;
end;
end;
CircleProc;
end else begin
FailSongArea:=true;
CircleProc;
ChannelCheck;
FailSongArea:=false;
end;
until (StopSong);
if (NOT PauseTwisting) then begin
if (UseAutoInstaCast) then begin
If (GetTickCount-InstaClickTimer>InstaCastItemRefreshTime) then begin
InstaClickTimer:=GetTickCount;
KeyDown(InstaCastKey);
KeyUp(InstaCastKey);
InstaClickCastTimer:=GetTickCount;
Repeat
CircleProc;
Until (GetTickCount-InstaClickCastTimer>(InstaCastTime));
end;
end;
ChannelCheck;
if (UseAutoNonInstaCast) then begin
If (GetTickCount-NonInstaClickTimer>NonInstaCastItemRefreshTime) then begin
NonInstaClickTimer:=GetTickCount;
KeyDown(NonInstaCastKey);
KeyUp(NonInstaCastKey);
NonInstaClickCastTimer:=GetTickCount;
Repeat
CircleProc;
Until (GetTickCount-NonInstaClickCastTimer>(NonInstaCastTime));
end;
end;
ChannelCheck;
end;
until ((DoneMelody) or (AbortScript));
end;
end;


//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

// Target Nearest NPC and check con

procedure TargetNearestNPC;

begin
KeyDown(66); KeyUp(66);
end;


//--------------------------------------------------------------------------------------------------

procedure GetLocation;
var
CLogText : string;
GotLoc : boolean;
LOCSTR : string;
CLogMarker : integer;
OrigMarker : integer;
NumTry : integer;
XStr, YStr, ZStr : string;
begin
LOCSTR := 'Your location is';
CLogMarker := SetLogMarker;
OrigMarker := CLogMarker;
NumTry := 0;
repeat
NumTry := NumTry + 1;
SendLine('/loc<CR>');
WaitForMouse;
Pause((30 + LogSpeed));
CLogMarker := OrigMarker;
CLogText := GetNewLogText(CLogMarker);
GotLoc := HasToken(CLogText, LOCSTR);
if not GotLoc then begin
Pause((30 + LogSpeed));
end;
until GotLoc or (NumTry = 500);
if not GotLoc then exit;
// We want to get the *last* loc in the log
while HasToken(CLogText, LOCSTR) do
CLogText := TextAfterToken(CLogText, LOCSTR);
CLogText := TextBeforeToken(CLogText, #13#10);
XStr := Trim(TextBeforeToken(CLogText, ','));
CLogText := TextAfterToken(CLogText, ',');
YStr := Trim(TextBeforeToken(CLogText, ','));
CLogText := TextAfterToken(CLogText, ',');
ZStr := Trim(CLogText);
CurrentLocation.x := StrToFloat(XStr);
CurrentLocation.y := StrToFloat(YStr);
CurrentLocation.z := StrToFloat(ZStr);
XLocation:=CurrentLocation.x;
YLocation:=CurrentLocation.y;
//Debug('Loc = ' + FloatToStr(CurrentLocation.x) + ' ' + FloatToStr(CurrentLocation.y));
end;

//--------------------------------------------------------------------------------------------------

function CalculateAngle(dx, dy, dis: float): float;
begin
Result := ArcSin(Abs(dx) / dis);
//Debug('dx =' + FloatToStr(dx) + ' dy =' + FloatToStr(dy));
if (dx >= 0) and (dy < 0) then Result := PI - Result;
if (dx < 0) and (dy < 0) then Result := PI + Result;
if (dx < 0) and (dy >= 0) then Result := 2 * PI - Result;
Result := Result * (180 / PI);
//Debug('Result =' + FloatToStr(Result));
end;

//--------------------------------------------------------------------------------------------------

procedure GetAngle;
var
StartX, StartY : float;
EndX, EndY : float;
dx, dy, dis : float;
ang : float;
begin
GetLocation;
StartX := CurrentLocation.X;
StartY := CurrentLocation.Y;
KeyDown(200); // 200 = up arrow, so run forward
if (NOT DoingCalibration) then Pause(20);
if (DoingCalibration) then Pause(HoldButtonTimeDown);
if (DoingCalibration) then KeyUp(200);
WaitForMouse;
GetLocation;
EndX := CurrentLocation.X;
EndY := CurrentLocation.Y;
dx := EndX - StartX;
dy := EndY - StartY;
dis := Sqrt(dx * dx + dy * dy);
//Debug('dis = ' + FloatToStr(ang));
ang := CalculateAngle(dx, dy, dis);
CurrentAngle := ang;
//Debug('Angle = ' + FloatToStr(ang) + ' degrees');
// Now return to our starting point
if (DoingCalibration) then begin
KeyDown(208); // 208 = down arrow, so run backwards
Pause(Trunc(Round(HoldButtonTimeDown * 1.1))); // Backwards is slower?
KeyUp(208);
WaitForMouse;
end;
end;

//--------------------------------------------------------------------------------------------------

function Calibrate_Run_Speed(HoldButtonTimeDown: integer): float;
var
StartX, StartY : float;
EndX, EndY : float;
dx, dy, dis : float;
LocPerSec : float;
begin
//Debug('Calibrating Run for HoldButtonTimeDown = ' + IntToStr(HoldButtonTimeDown) + ' ms');
GetLocation;
StartX := CurrentLocation.X;
StartY := CurrentLocation.Y;
KeyDown(200); // 200 = up arrow, so run forward
Pause(HoldButtonTimeDown);
KeyUp(200);
WaitForMouse;
GetLocation;
EndX := CurrentLocation.X;
EndY := CurrentLocation.Y;
dx := EndX - StartX;
dy := EndY - StartY;
dis := Sqrt(dx * dx + dy * dy);
LocPerSec := dis / ((HoldButtonTimeDown + 0.0) / 1000.0);
//Debug('LocPerSec = ' + FloatToStr(LocPerSec));
AddStraights:=AddStraights+LocPerSec;
Result := LocPerSec;
// Now return to our starting point
KeyDown(208); // 208 = down arrow, so run backwards
Pause(Trunc(Round(HoldButtonTimeDown * 1.2))); // Backwards is slower?
KeyUp(208);
WaitForMouse;
end;

//--------------------------------------------------------------------------------------------------

procedure CalibrateLogFileSpeed;
begin
CalLOCSTR := 'Your location is';
CalCLogMarker := SetLogMarker;
CalOrigMarker := CalCLogMarker;
CalPauseFor:=1;
CalNumTry := 0;
CalCounter:=0;
SendLine('/clear<CR>');
repeat
repeat
CalNumTry := CalNumTry + 1;
SendLine('/loc<CR>');
WaitForMouse;
Pause(CalPauseFor);
CalCLogMarker := CalOrigMarker;
CalCLogText := GetNewLogText(CalCLogMarker);
CalGotLoc := HasToken(CalCLogText, CalLOCSTR);
if not CalGotLoc then begin
CalPauseFor:=CalPauseFor + 1;
Pause(CalPauseFor);
end;
until CalGotLoc or (CalNumTry = 500);
CalCounter:=Calcounter + 1;
CalOrigMarker:=SetLogMarker;
SendLine('/help<CR>');
until (CalCounter = 100);
//Debug('It takes about ' + IntToStr(CalPauseFor) + ' Milliseconds to read your log file reliably.');
end;

//--------------------------------------------------------------------------------------------------

function AngleDif(Ang1, Ang2: float): float;
begin
while Ang1 < 0 do Ang1 := Ang1 + 360;
while Ang2 < 0 do Ang2 := Ang2 + 360;
while Ang1 >= 360 do Ang1 := Ang1 - 360;
while Ang2 >= 360 do Ang2 := Ang2 - 360;
Result := Ang1 - Ang2;
while Result < 0 do Result := Result + 360;
while Result >= 360 do Result := Result - 360;
end;

//--------------------------------------------------------------------------------------------------

function Calibrate_Turn_Speed(HoldButtonTimeDown: integer): float;
var
StartAng, EndAng : float;
AngPerSec : float;
angdif : float;
begin
//Debug('Calibrating Turn for HoldButtonTimeDown = ' + IntToStr(HoldButtonTimeDown) + ' ms');
GetAngle;
StartAng := CurrentAngle;
KeyDown(203); // 203 = left arrow, so turn left
Pause(HoldButtonTimeDown);
KeyUp(203);
WaitForMouse;
GetAngle;
EndAng := CurrentAngle;
angdif := AngleDif(EndAng, StartAng);
if angdif >= 180 then angdif := (360 - angdif);
AngPerSec := angdif / ((HoldButtonTimeDown + 0.0) / 1000.0);
// if AngPerSec < 0 then AngPerSec := 360 + AngPerSec;
//Debug('AngPerSec = ' + FloatToStr(AngPerSec));
AddTurns:=AddTurns+AngPerSec;
Result := AngPerSec;
// Now return to our starting point
KeyDown(205); // 205 = right arrow, so turn back
Pause(HoldButtonTimeDown);
KeyUp(205);
WaitForMouse;
end;

//--------------------------------------------------------------------------------------------------

procedure DoCalibration;
begin
SendLine('/clear<CR>');
DoingCalibration:=true;
HoldButtonTimeDown := 200;
var IniFile : TIniFile = TIniFile.Create(GetXylobotDirectory + 'calibrate.txt');
IniFile.EraseSection('RunSpeed');
IniFile.EraseSection('TurnSpeed');
IniFile.EraseSection('LogFileSpeed');

CalibrateLogFileSpeed;
IniFile.WriteInteger('LogFileSpeed', 'LogSpeed' , CalPauseFor);

TotalRepsStraight:=0;
repeat
Calibrate_Run_Speed(2000);
TotalRepsStraight:=TotalRepsStraight+1;
until (TotalRepsStraight=10);
AddStraights:=AddStraights/TotalRepsStraight;
IniFile.WriteFloat('RunSpeed', 'RunSpeed', AddStraights);
StepInterval:=25;
repeat
if (StepInterval<1000) and (StepInterval>499) then StepInterval:=StepInterval+100;
if (StepInterval<500) and (StepInterval>99) then StepInterval:=StepInterval+50;
if (StepInterval<100) then StepInterval:=StepInterval+25;
TotalRepsTurn:=0;
AddTurns:=0;
repeat
Calibrate_Turn_Speed(StepInterval);
TotalRepsTurn:=TotalRepsTurn+1;
until (TotalRepsTurn=5);
AddTurns:=AddTurns/TotalRepsTurn;
TempStep:=('TurnSpeed' + IntToStr(StepInterval));
IniFile.WriteFloat('TurnSpeed', TempStep, AddTurns);
until (StepInterval=1000);
IniFile.UpdateFile;
IniFile.Free;
end;

//--------------------------------------------------------------------------------------------------

function ApproxRunDown(Dis,RSS: float): integer;
var
sec : float;
begin
sec := Dis / RSS;
Result := Round(sec * 1000);
if Result < 500 then begin
sec := Dis / RSS;
Result := Round(sec * 1000);

takenote
orc pawn
orc pawn
Posts: 11
Joined: Sat Jan 31, 2004 1:04 am

cont...

Post by takenote » Sun Feb 01, 2004 12:05 am

if you only hear french youd never learn the language.. only mimic it i dont want to be spoon fed just show me the kitchen...in xylobot one could make a macro on the fly(type [..."recording "...type your macro...]] "stoped recording' ) then you could go in and see what it was doing...you could see what the apple was not just hear the word"apple "sorry i dont speek french) im running MQ more for the map then anything elce but i would like to have my bot follow and taunt,kick,bash(all of which i have on hot keys....not to sound like im flaming but i have a real life and only soo much time to spend in research...

User avatar
wilso132
Contributing Member
Contributing Member
Posts: 106
Joined: Thu Oct 17, 2002 11:53 am

Re: cont...

Post by wilso132 » Sun Feb 01, 2004 12:59 am

takenote wrote:if you only hear french youd never learn the language.. only mimic it i dont want to be spoon fed just show me the kitchen...in xylobot one could make a macro on the fly(type [..."recording "...type your macro...]] "stoped recording' ) then you could go in and see what it was doing...you could see what the apple was not just hear the word"apple "sorry i dont speek french) im running MQ more for the map then anything elce but i would like to have my bot follow and taunt,kick,bash(all of which i have on hot keys....not to sound like im flaming but i have a real life and only soo much time to spend in research...

Since when was the manual written in french? Along with all the walkthroughs and macros (which you can see a result of)? I taught myself to code, so obviously I'm slightly bias.

ml2517
a grimling bloodguard
a grimling bloodguard
Posts: 1216
Joined: Wed Nov 12, 2003 1:12 am

Post by ml2517 » Sun Feb 01, 2004 1:12 am

takenote.. thanks for posting my bard Xylobot script here. ml2517=Maelstrom :D

takenote
orc pawn
orc pawn
Posts: 11
Joined: Sat Jan 31, 2004 1:04 am

Post by takenote » Mon Feb 02, 2004 6:16 am

ml2517 wrote:takenote.. thanks for posting my bard Xylobot script here. ml2517=Maelstrom :D

maelstrom, i thought it was a great example of how a script should be written. it ran the first time was vary clear as to what it could and couldent do and was devided into parts, so if i want to change some thing about it to make it work differant i dont have to tear it compleatly apart.
i use it often when running xylobot.
Why cant more people write scripts like this?!?


i am still haveing problems making scripts run in MQ i keep getting "cant parce bla bla blaaa"

takenote
orc pawn
orc pawn
Posts: 11
Joined: Sat Jan 31, 2004 1:04 am

Re: cont...

Post by takenote » Mon Feb 02, 2004 6:42 am

wilso132 wrote:

Since when was the manual written in french? Along with all the walkthroughs and macros (which you can see a result of)? I taught myself to code, so obviously I'm slightly bias.

like i said befor (or at least tryed to imply) i dont speek script... delfi...exc. an i dont have the time to read 10,000 posts just to find some one who makes sence with their scripting !
i use MQ to play everquest not the other way around ,playing everquest so i can use MQ. and yes the manual might as well be in french, as i havent gotten any macros (with the exception of one) to work. if i pick up a french to english dictionary it would give me an english word then the french and how to pronounce it. being that i cant get the scripts to work how can i learn how to make one?? throwing a bunch of words on a page doent teach on to speek the language.

my poin in the start of all this was hopeing for some organization in the script listings and the subjects read through them some time and ask your self if they realy answer the question "what is this person trying for ... an example under macro help one subject is " i need some help..." help with what tieing his shoe??/

ok enough ranting im starting to sound like "bad karma"

Mckorr
Developer
Developer
Posts: 2326
Joined: Fri Oct 18, 2002 1:16 pm
Location: Texas

Post by Mckorr » Mon Feb 02, 2004 3:05 pm

Must.... not.... flame....

Okay, MQ has a learning curve. If you don't have time to learn it, you're better off not using it. If all you want to do is cut-and-paste scripts, go back to Xylobot.

Macros here include as much or as little documentation and comments as the authors care to put in. There is a basic assumption that you have read the readme file, the help file, and have at least attempted to write your own simple macros so you get a feel for how things are put together. There is also the assumption that you are willing to spend the time necessary to comprehend what a script is doing (or in some cases not doing) before asking for help.

Xylobot is a commercial product. MacroQuest is open source. That means that all development here, source or macros, are done on a volunteer basis. While we DO accept donations to keep things running, no one is getting paid for their work.

To do what you ask, to properly maintain and organize hundreds of macros, would require a very dedicated dev who did nothing else. In other words, customer support. I'm certainly not gonna do it, and I'm the closest thing to "board police" you are likely to see here.

My recommendation? Go back to the beginning and start where most of us did. Read all the documents in the Release directory (after you compile MQ), and then write a simple fishing macro. Flesh it out, add to it, let it crash on you. Figure out where you went wrong. Count your curly braces and try again.

Next, go find something more complicated in the forums (and that does NOT mean GenBot!) Copy it over and try it. Make some changes, do it again.

If you don't have time for all this you need to go elsewhere. No one here has time to hold your hand through the learning process, and no dev has time to clean up the boards so you can script-kiddie your way to fame and fortune. Especially not with a major patch heading our way in a week.