Macro_FTW
2009-06-15 23:48:00
Hello. Welcome to my thread. :E
Attached is my first script ever; it's a F2P power cutter that can run just about anywhere. Please note: It's not the best script here by far. XD
Mainly what I'm looking for is feedback on my semantics, code, etc. if you would be so kind as to look through it and tell me what you thought I did that was good/bad in the coding of it.
Glitches, warnings, instructions, and fixes are in the function header.
Features:
And that's about it. If you want to bugtest it, go ahead. Like said above, I've not had the opportunity to bug test it much. :/
All feedback is welcome. Thanks for taking interest in my script! :D
~Macro_FTW
Attached is my first script ever; it's a F2P power cutter that can run just about anywhere. Please note: It's not the best script here by far. XD
Mainly what I'm looking for is feedback on my semantics, code, etc. if you would be so kind as to look through it and tell me what you thought I did that was good/bad in the coding of it.
Glitches, warnings, instructions, and fixes are in the function header.
Features:
- Multiplayer
- Any F2P tree, anywhere
- Members trees easy to add [just a few manual add-ins. Promise. ;)]
- Antiban
- Antirandoms
- LOTS of failsafes. o.o
- Dynamic Direction Selection for running away (the first 3 words were a combination of alliteration and conosance! XD)
- Axe detection. Detects if your axe is wielded or in your inventory, and if it's actually there
{-=-==-===-====-=====-======-=======-======-=====-====-===-==-=-)
@Author: Macro_FTW
@Script: Powercutter
@Instructions:
1. Set players in SetUpPlayers
2. Set repeatLoads in constants section.
3. Select the RS applet
4. Press 'run'
5. Watch it
My first script. Not meant to be really complicated/sophisticated. Highly limited
bugtesting, because I had but one account to use... Said account has 2 WC. XD
My auto army's various files were lost many a format ago. :/
Tested:
DeclarePlayers
SetUpNicknames
SetColorsAndTreeStrings
AutoRespond
RandomTalk
AntiBan
GetAllBlackChatBoxText
IsUpTextMultiCustom2
WaitUntilStartedChopping
WaitUntilTreeDown
ChopTree
ChopUntilFull
DropAllLogs
ProgReport
ProgressReport
SetUp
HasAxe
SetUpPlayer
MainLoop
...Everything else [which isn't much XD] is untested.
**NOTE** Due to my lack of autoing accounts, I have *not* tested the Willow, Yew,
or Oak colors. Sorry. XD
Known glitches include:
Sometimes loses the target tree if there are 2 of the same tree close together.
Takes quite a while to search for new trees.
Rarely misses with the WaitUntilDown function. Reclicks on the same/a close
tree if that happens.
And my fix for all of those glitches?
Time failsafes! Rawr! XD
**Credits**:
I did use Torrent Of Flame's tutorial to make parts of this, because
I couldn't remember half of the methods I had to use to Set up SRL, etc.
Kudos and thanks to him/her. :D
Also, thanks to Dusk412's TPA tutorial. It helped quite a bit. :D
Enjoy anyway. :P
(-=-==-===-====-=====-======-=======-======-=====-====-===-==-=-}
Program FirstPowerCutter;
{.include SRL\SRL.Scar}
{.include SRL\SRL\Skill\WoodCutting.scar}
var
TColors: array[0..5] of Integer;
TStrings: TStringArray;
FunnyText, FunnyResponse, RandomSayings, ReqResponse: array of String;
nLoads, LastInteractionTime, LastRespondTime, MaxTime: Integer;
{==============================================================)
Constants
(==============================================================}
const repeatLoads = False; //After that character is done with
//all of its loads, do you want it to Chop again
//after the script runs through the list of cutters? ]
const escapeDir = 'D'; //CASE SENSITIVE. N for north, S for south, E for east
//W for west, D for dynamic. D runs to the least npcs
const lSkill = 'woodcutting'; //Skill to use the lamp on.
{==============================================================)
Options:
'tree': Regular tree
'oak': Oak tree
'willow': Willow tree
'yew': Yew tree
Does not support members-only trees.
(==============================================================}
procedure DeclarePlayers;
begin
HowManyPlayers := 1; //Number of players used
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0; //The player whom you wish to start with
Players[0].Name := '';
Players[0].Pass := '';
Players[0].Nick := ''; //Optional.
Players[0].Active := True;
Players[0].Integers[0] := 5; //Loads to do before log out
Players[0].Strings[0] := 'tree'; //Tree to cut, all lower case. Options above.
end;
{==============================================================)
If a nickname was not input for a Player, this auto-generates
one. The exact nickname generated is char[1..4] in the string.
Ex.
Name: Macro FTW
Generated nickname: acro
(==============================================================}
procedure SetUpNicknames;
var
TotalPlayers, i: Integer;
TempStr: String;
begin
TotalPlayers := GetArrayLength(Players) - 1;
for i:=0 to TotalPlayers do
begin
//If no nickname has been declared...
if(Players[i].Nick='')then
begin
writeln(Players[i].Name+' needs a nickname.');
TempStr := Players[i].Name;
if(Length(Players[i].Name)>=5)then
begin
TempStr := Left(TempStr, 5);
TempStr := Right(TempStr, 4);
end;
Players[i].Nick := TempStr;
writeln(Players[i].Nick+' was assigned.');
end;
end;
end;
{==============================================================)
Sets up the tree Colors and name strings, based on the
user input of which trees they want to Chop. :P
(==============================================================}
procedure SetColorsAndTreeStrings;
var
i: Integer;
begin
SetArrayLength(TStrings, 3);
case Lowercase(Players[CurrentPlayer].Strings[0]) of
'oak':
begin
TStrings[0] := 'Oak';
TStrings[1] := 'ak';
TStrings[2] := 'Oa';
TColors[0] := 5346696;
TColors[1] := 4228729;
TColors[2] := 3496531;
TColors[3] := 3107164;
TColors[4] := 2252883;
MaxTime := 45000;
end;
'willow':
begin
TStrings[0] := 'Willow';
TStrings[1] := 'ill';
TStrings[2] := 'ow';
TColors[0] := 3165781;
TColors[1] := 7644567;
TColors[2] := 2635310;
TColors[3] := 3167052;
TColors[4] := 3561567;
MaxTime := 50000;
end;
'yew':
begin
TStrings[0] := 'Yew';
TStrings[1] := 'Ye';
TStrings[2] := 'ew';
TColors[0] := 5346183;
TColors[1] := 2252368;
TColors[2] := 4354956;
TColors[3] := 1126954;
TColors[4] := 3959425;
MaxTime := 60000;
end;
'tree':
begin
TStrings[0] := 'Tree';
TStrings[1] := 'ree';
TStrings[2] := 'Tre';
TColors[0] := 5606529;
TColors[1] := 4091236;
TColors[2] := 2836803;
TColors[3] := 4954508;
TColors[4] := 2839628;
MaxTime := 15000;
end;
else
begin
writeln('Invalid tree. Terminating script...');
TerminateScript;
end;
end;
while(i>Length(TStrings))do
begin
if(TStrings[i]='')then
TStrings[i]:='_#_';
inc(i);
end;
end;
{==============================================================)
Basic AutoRespond, an extention of antiban.
Responds to:
Trade requests
Assistance requests
Things in the "FunnyText" const
(==============================================================}
procedure AutoRespond;
var
flg: Boolean;
i, a: Integer;
Msg: String;
begin
//If we haven't responded to chat in more than 2 mins...
if(GetTimeRunning>LastRespondTime+120000)then
begin
//Going through every message in the chat box...
for i:=1 to 8 do
begin
Msg := Lowercase(GetChatBoxText(i, clBlue));
//If there is player text on that line...
if(not(Msg=''))then
begin
for a:=0 to Length(FunnyText)-1 do
begin
//If it Finds any word in FunnyText in the message...
if(not(Pos(FunnyText[a], Msg)=0))then
begin
//Send a Random message in FunnyResponse with misgakes
TypeSend(AddMistakes(FunnyResponse[Random(Length(FunnyResponse))], 25));
flg := True;
Break;
end;
end;
end;
if(flg)then
begin
flg := False;
LastInteractionTime := GetTimeRunning;
Break;
end;
end;
end;
//If we haven't responded to trade/assist requests in more than 5 mins...
if(GetTimeRunning>LastInteractionTime+300000)then
begin
for i:=1 to 8 do
begin
Msg := getChatBoxText(i, clPurple);
if(not(Msg=''))then
begin
flg := True;
TypeSend(AddMistakes(reqResponse[Random(Length(reqResponse))], 25));
end;
if(flg)then
begin
flg := False;
LastInteractionTime := GetTimeRunning;
Break;
end;
end;
end;
end;
{==============================================================)
antiban extention; says a Random phrase 10% of the time called.
(==============================================================}
procedure RandomTalk;
begin
if(Random(10)=1)then
begin
TypeSend(AddMistakes(RandomSayings[Random(Length(RandomSayings))], 25));
end;
end;
{==============================================================)
Simple, Random antiban. Returns mouse to original position after
each antiban loop.
(==============================================================}
procedure AntiBan;
var
x, y: Integer;
begin
GetMousePos(x, y);
if not LoggedIn then Exit;
case Random(40) of
1: RandomMovement;
2: RandomRClick;
3: HoverSkill(LampSkill, False);
4: BoredHuman;
5: RandomTalk;
else Wait(1000+random(1500));
end;
end;
{==============================================================)
Gets all the black [game] chat in the chat box and returns it
in a TStringArray.
(==============================================================}
function GetAllBlackChatBoxText: TStringArray;
var
i: Integer;
begin
SetArrayLength(Result, 8);
for i:=1 to 8 do
begin
Result[i-1] := GetChatBoxText(i, clBlack);
end;
end;
{==============================================================)
Finds the cardinal direction with the least NPCs.
(==============================================================}
function FindEscapeDir: char;
var
n, s, e, w: Integer;
WinNS, WinEW, WinAll: Char;
begin
//Gets how many NPC dots are N/S/E/W of the character
n := Length(GetMinimapDotsIn('npc', MMx1, MMy1, MMx2, MMCy));
s := Length(GetMinimapDotsIn('npc', MMx1, MMCy, MMx2, MMy2));
e := Length(GetMinimapDotsIn('npc', MMx1, MMy1, MMCx, MMy2));
w := Length(GetMinimapDotsIn('npc', MMCx, MMy1, MMx2, MMy2));
//Figures out if n or s has less npcs
if(n<=s)then
begin
WinNS := 'N';
end else
begin
WinNS := 'S';
end;
//Figures out if e or w has less npcs
if(e<=w)then
begin
WinEW := 'E';
end else
begin
WinEW := 'W';
end;
//Figures out if WinEW or WinNS has less npcs
if(WinNS<=WinEW)then
begin
WinAll := WinNS;
end else
begin
WinAll := WinEW;
end;
//Result = the place with the least NPCs
Result := WinAll;
end;
{==============================================================)
Finds and handles Random events.
(==============================================================}
procedure HandleRandoms;
var
dir: Char;
begin
if(FindFight)then
begin
if(escapeDir='D')then
begin
dir := FindEscapeDir;
end else
begin
dir := escapeDir;
end;
RunAway(dir, True, 1, 2000);
end;
FindLamp(lSkill);
FindNormalRandoms;
end;
{*******************************************************************************
function IsUpTextMultiCustom(Text: TStringArray): Boolean;
By: Starblaster100 / Nielsie95 / Freddy1990
Description: Checks for the occurance of any of the strings in the array.
Use: IsUpTextMultiCustom(['Att', 'ttac', 'ack', 'monst', 'ster'])
[[EDITED by Macro_FTW: Wasn't working because the default value for Boolean was
'true' for me, So, I just added a line in.]]
*******************************************************************************}
function IsUpTextMultiCustom2(Text: TStringArray): Boolean;
var
TheText: string;
i, n: Integer;
begin
Result := False;
TheText := rs_GetUpText;
n := High(Text);
for i := 0 to n do
if (Pos(Text[i], TheText) <> 0) then
begin
Result := True;
Exit;
end;
end;
{==============================================================)
Waits until we start chopping the tree. Uses the chatbox to accomplish
this. Looks for a non-'you swing your axe at the tree' line, and
fixates on it. As soon as that changes, it reads the bottom chat
line. Based on that, it returns a number.
Parameters:
x, y: the point at which we clicked the tree
Color: the color at that point
tol: the tolerance for that color
Returns:
0 if it successfully executed
1 if an acceptable error occured ["I can't reach that!" appeared
or 30 seconds expired.]
2 if an unacceptable error occured [Something that disallows the
function to work entirely.]
(==============================================================}
function WaitUntilStartedChopping(var x, y: Integer; color, tol: Integer): Integer;
var
ChatStrings: TStringArray;
StringAtNCI: String;
i, NonChopIndex, Errors, tx, ty, ErrorsMain, StartTime: Integer;
begin
StartTime := GetTimeRunning;
if(not LoggedIn)then
begin
Result := 2;
Exit;
end;
writeln('WaitUntilStartedChopping Started.');
NonChopIndex := -1;
ErrorsMain := 0;
//Searching for lines that aren't "you swing your axe at the tree."
repeat
ChatStrings := GetAllBlackChatBoxText;
for i:=0 to 7 do
begin
if(ChatStrings[i]='')then
ChatStrings[i] := ' your hatchet ';
if(pos('your hatchet', ChatStrings[i])=0)then
begin
NonChopIndex := i;
StringAtNCI := ChatStrings[i];
Break;
end;
end;
//If we couldn't find any text but "You swing your axe at the tree..."
if(NonChopIndex=-1)then
begin
tx := x;
ty := y;
Errors := 0;
//Attempt to Examine something to add variety to the chat box.
repeat
if(FindObjTPA(tx, ty, color, tol, -1, 20, 20, 5, TStrings))then
begin
if(ChooseOptionMultiEx(['Examine', 'Exa', 'mine', 'amin'], 'action', ClickLeft))then
begin
Break;
end else
begin
writeln('Couldn''t find examine text. Trying again.');
Inc(Errors);
end;
end else
begin
writeln('Couldn''t find tree TPA. Trying again.');
Inc(Errors);
end;
//If it can't find Examine or the tree after 5 tries, it stops.
until(Errors>=5);
if(Errors>=5)then
begin
Result := 2;
Exit;
end;
end;
Inc(ErrorsMain);
until(not(NonChopIndex=-1) or (ErrorsMain>5));
if(ErrorsMain>5)then
begin
Result := 2;
Exit;
end;
//At this point, there has to be a NonChopIndex of not 0.
Result := 0;
repeat
wait(100);
SetArrayLength(ChatStrings, 8);
ChatStrings := GetAllBlackChatBoxText;
FindObjTPA(x, y, color, tol, -1, 20, 20, 5, TStrings);
//If that string has moved...
if(not(ChatStrings[NonChopIndex]=StringAtNCI))then
begin
if(pos('your hatchet', ChatStrings[Length(ChatStrings)-1])>0)then
begin
Result := -1;
writeln('Tree found. Chopping.');
end else
begin
Result := -2;
writeln('Exiting WUSC. NonFatal Error.');
end;
end;
//Until the result is negative, or 30 seconds have elapsed...
until((Result<0) or (((StartTime/1000)+30)<(GetTimeRunning/1000)));
if(Result=-1)then
begin
Result := 0;
end else
begin
Result := 1;
end;
end;
{==============================================================)
Waits until the tree falls down or inventory is full.
(==============================================================}
procedure WaitUntilTreeDown(x, y: Integer);
var
StartTime, Errors: Integer;
tempBool: Boolean;
begin
writeln('Waiting until it is down...');
StartTime := GetTimeRunning;
//If "Tree" isn't the up text
if(not(IsUpTextMultiCustom(TStrings)))then
begin
//Wait if we are chopping. If not, 10 seconds never killed anyone. XD
wait(10000);
Exit;
end;
AntiBan;
tempBool := true;
writeln('Antiban done.');
Errors := 0;
MMouse(x, y, 5, 5);
while (IsUpTextMultiCustom2(['Chop', 'hop', 'Cho']) and (StartTime+MaxTime>GetTimeRunning)) do
begin
wait(500+random(1500));
end;
writeln('Tree down.');
end;
{==============================================================)
Attempts to Find a tree. Returns True if Found and Chopped,
False otherwise.
Tries 4 times to Find a tree, the first time using the beginning
(current) camera angle, the second using the beginning angle
+ 90, etc.
(==============================================================}
function ChopTree: Boolean;
var
Found: Boolean;
Iterator, Iterator2, StartDir, TColorsLength, x, y, ColorAt: Integer;
begin
Found := false;
if(not LoggedIn)then
begin
writeln('Not logged in detected. Exiting ChopTree...');
Result := False;
Exit;
end;
writeln('Attempting to chop tree...');
Iterator := 0;
StartDir := floor(rs_getCompassAngleDegrees);
writeln('Compass is at '+inttostr(StartDir)+'.');
TColorsLength := Length(TColors);
writeln('debug I.');
//Looking for the tree...
while(not(Found) and (Iterator < 4)) do
begin
writeln('debug II.');
MakeCompass((Iterator * 90 + StartDir) mod 360);
//Looking for each Color...
x := MSCx;
y := MSCy;
Iterator2 := 0;
writeln('Looking for tree at '+inttostr(Iterator*90)+' degrees.');
while(not(Found) and (Iterator2<TColorsLength)) do
begin
//Did we Find it?
writeln('Looking for tree. Attempt: '+inttostr(Iterator2)+'.');
Found := FindObjTPA(x, y, TColors[Iterator2], 50, -1, 20, 20, 5, TStrings);
Inc(Iterator2);
end;
Inc(Iterator);
end;
//If we Found it...
if(Found)then
begin
writeln('Tree Found.');
//No right-click support at the moment.
ColorAt := GetColor(x, y);
Mouse(x, y, 3, 3, True);
//If we were able to successfully follow the Color until we end up at
//the tree, Chopping...
if(WaitUntilStartedChopping(x, y, ColorAt, 50)=0)then
begin
WaitUntilTreeDown(x, y);
end else
begin
Result := False;
end;
end;
writeln('debug III');
Result := Found;
end;
{==============================================================)
Chops logs until the inventory is full. Returns True if the
inventory is full; False if there was an error.
(==============================================================}
function ChopUntilFull: Boolean;
var
repeats: Integer;
begin
writeln('Chopping begun...');
if(not LoggedIn)then
begin
writeln('Not logged in. Exiting ChopUntilFull.');
Result := False;
Exit;
end;
repeat
Result := ChopTree;
if(not Result)then
begin
writeln('Cannot Find tree. Waiting 10 seconds. '+inttostr(repeats+1)+'/5.');
Inc(repeats);
Wait(10000+Random(5000));
end else
begin
Wait(500+Random(1500));
repeats := 0;
end;
until((not LoggedIn) or (InvFull) or (repeats>=5));
if(InvFull)then
begin
Result := True;
Inc(Players[CurrentPlayer].Integers[1]);
end else
Result := False;
end;
{==============================================================)
Drops all logs in the inventory.
(==============================================================}
procedure DropAllLogs;
var
limit, i: Integer;
begin
limit := 0
if(not Players[CurrentPlayer].Booleans[0])then
Inc(limit);
for i:=1+limit to 28 do
DropItem(i);
end;
{==============================================================)
Prints out the playerNum player's Progress report.
(==============================================================}
procedure ProgReport(playerNum: Integer);
begin
writeln('Player: '+Players[playerNum].Name);
writeln('Done '+intToStr(Players[playerNum].Integers[1])+' loads so far.');
writeln('We''ve been running for '+timeRunning+'.');
end;
{==============================================================)
Prints out the current player's Progress report.
(==============================================================}
procedure ProgressReport;
begin
ProgReport(CurrentPlayer);
end;
{==============================================================)
Program initilization function.
(==============================================================}
procedure SetUp;
begin
writeln('Beginning Setup...');
clearDebug;
SetUpSRL;
declarePlayers;
SetUpNicknames;
SetArrayLength(TStrings, 3);
//AutoResponding string arrays.
FunnyText := ['lol', 'haha', 'rofl', 'lmao', 'ha'];
FunnyResponse := ['XD', 'Haha!', 'Lol', 'Wow...'];
RandomSayings := ['...', 'I''m a lumberjack and I''m O.K. I sleep all night...', 'Bored... >.<'];
reqResponse := ['Nty', 'No, thanks.', 'Nah.', 'I''m good.', 'No, thanks though.', 'Hm... Nty.'];
writeln('Setup complete.');
disguise('Microsoft Word');
end;
{==============================================================)
Player initilization/switch function.
(==============================================================}
procedure GoToNextPlayer(active: Boolean);
begin
ProgressReport;
nLoads := 0;
nextPlayer(active);
end;
{==============================================================)
Ensures the player has their axe.
(==============================================================}
function HasAxe: Boolean;
begin
//Is the axe in the inventory?
GameTab(4);
if(ExistsItem(1))then
begin
MMouseItem(1);
wait(1000+random(1500));
if(isUpTextMultiCustom(['hatchet', 'hatc', 'het', 'tche']))then
begin
Result := True;
Exit;
end;
end;
//Is the axe in the weapon slot?
GameTab(5);
MouseBox(573, 293, 600, 319, 3); //MouseEquippedItem didn't work for me.
wait(1000+random(1500));
Result := IsUpTextMultiCustom(['hatchet', 'hatc', 'het', 'tche']);
end;
{==============================================================)
Sets up the player when they are logged in, checks to ensure
they have all the necessary equipment.
(==============================================================}
function SetUpPlayer: Boolean;
begin
SetColorsAndTreeStrings;
SetAngle(True);
SetRun(True);
gameTab(4);
SetChat('all', 0);
SetChat('on', 1);
SetChat('friends', 2);
SetChat('on', 3);
SetChat('on', 4);
SetChat('on', 5);
Result := HasAxe;
DropAllLogs;
end;
{==============================================================)
The main loop of the Program.
(==============================================================}
procedure MainLoop;
begin
//If we're not logged in...
if(not LoggedIn)then
begin
writeln('Not logged in detected. Going to next player.');
GoToNextPlayer(False);
Exit;
end;
gameTab(4);
//If we have a full inventory...
if(ChopUntilFull)then
begin
writeln('Inventory is full. Dropping logs.');
Inc(nLoads);
DropAllLogs;
//If we've successfully completed all the loads we've been told to...
if(nLoads = Players[CurrentPlayer].Integers[0])then
begin
writeln('All loads are finished for this character. Switching...');
GoToNextPlayer(repeatLoads);
Exit;
end;
end else
begin
GoToNextPlayer(False);
Exit;
end;
end;
begin
SetUp;
ActivateClient;
wait(500);
repeat
writeln('Attempting to log player in...');
logInPlayer;
writeln('Player logged in. Setting up...');
if(not(SetUpPlayer))then
begin
writeln('Failed to Set up player '+intToStr(CurrentPlayer)+'. Going to next one.');
GoToNextPlayer(False);
end else
begin
Wait(300);
writeln('Player '+intToStr(CurrentPlayer)+' successfully Set up. Beginning main loop...');
MainLoop;
end;
until(AllPlayersInactive);
end.And that's about it. If you want to bugtest it, go ahead. Like said above, I've not had the opportunity to bug test it much. :/
All feedback is welcome. Thanks for taking interest in my script! :D
~Macro_FTW