Данный скрипт в текущей редакции применим исключительно для uorpg.com (ввиду особенностей воскрешения, help > stuck, починки предметов).
Принцип работы:
1. Прилетаем к дому или предварительно воскрешаемся;
2. Выгружаем все ресурсы и камни;
3. Перезаряжаем рунбуку скролами из сундука;
4. Берём кирку из сундука;
5. Чиним кирку (необходимы логи и инготы, из которых сделана кирка, tinker tools);
6. Берём invisibility potion из сундука для hiding>recall домой в случае 'is attacking you';
7. Выбираем случайным образом шахту, в которую полетим (в промежутке [RunebookCaveButtonBegin, RunebookCaveButtonEnd]);
8. Летим в шахту;
9. Находим тайлы для копки вокруг себя в заданном радиусе SeekRange;
10. Копаем до максимального веса или пока не выкопаем все тайлы и переходим к пункту 1;
11. В случае смерти летим на рынок, воскрешаемся, подходим к сфере телепорта, перемещаемся, переходим к пункту 1.
Надеюсь комментариев в самом скрипте будет достаточно для адаптации под ваших персонажей.
п.с. Дописывание скрипта остаётся на ваши усмотрение и возможности.
Code: Select all
Program mining;
const
///////////////////////
// Should be updated //
///////////////////////
SeekRange = 7; // Search radius for mining tiles
ToolsContainer = $40277DF1; // ID of a container that contains tools (tinker tools, invisibility potions)
ResourceContainer = $40277DD7; // ID of a container that contains resources (drop ores, get ingots and logs for repairing)
xTileResourceContainer = 3145; // X tile near resource container
yTileResourceContainer = 457; // Y tile near resource container
Runebook = $401D3EF8; // ID of a runebook that is used for recalling to caves and home
RunebookCaveButtonBegin = 1; // Caves runes index starts from
RunebookCaveButtonEnd = 9; // Caves runes index ends to
RunebookHomeButton = 10; // Home rune index
PickaxeColor = $043A; // Pickaxe color ($043A - is Lava), also used to take ingots for repairing
////////////////////////////////
// Probably should be updated //
////////////////////////////////
TakePickaxeCount = 1; // How many pickaxes should be taken to cave
TakeInvisibilityCount = 1; // How many invisibilities should be taken to cave
Pickaxe = $0E86; // Pickaxe type
TinkerTools = $1EBC; // Tinker tools type
Recall = $1F4C; // Recall scroll type
Log = $1BDD; // Log type
Ingot = $1BEF; // Ingot type
Invis = $0F0C; // Invisibility potion type
InvisColor = $0945; // Invisibility potion color
MinIngotsForRepair = 5; // How many ingots to take for repair per try
MinLogsForRepair = 5; // How many logs to take for repair per try
xTileResurrect = 3819; // X tile near resurection ankh
yTileResurrect = 1284; // Y tile near resurection ankh
TeleportStone = $40146004; // ID of a teleport stone (sphere) at market
xTileTeleportStone = 3841; // X tile near teleport stone (sphere)
yTileTeleportStone = 1283; // Y tile near teleport stone (sphere)
RecallMinMana = 20; // How many mana required for a recall using runebook
LagMs = 10000; // Delay in ms for checklag
GumpDelay = 2000; // Delay in ms for gump opening (help / stuck / move to market)
StoneTeleportDelay = 7000; // Delay in ms for teleporting using teleport stone (sphere)
RunebookTeleportDelay = 10000; // Delay in ms for recalling using runebook
type
MinTile = record
x, y, z, Tile : Word;
end;
var
MinTiles_Array : Array of MinTile;
CaveButton, MineResult, i : Integer;
function Abs(Num : Integer) : Integer;
begin
if Num < 0 then begin
result := Num * (-1);
end
else begin
result := Num;
end;
end;
// Procedure is used for opening container
procedure OpenContainer(Container: Cardinal);
begin
CheckLag(LagMs);
UseObject(Container);
wait(1000);
end;
// Function is used for counting pickaxes in the container
function GetPickaxeCount(container: Cardinal) : Integer;
begin
Disarm();
wait(500);
CheckLag(LagMs);
FindTypeEx(Pickaxe, PickaxeColor, container, false);
result := FindFullQuantity;
end;
// Function is used for counting invisibility potions in the container
function GetInvisibilityCount(container: Cardinal) : Integer;
begin
CheckLag(LagMs);
FindTypeEx(Invis, InvisColor, container, false);
result := FindFullQuantity;
end;
// Procedure is used for taking invisibilities from the container to a backpack
procedure GetInvisibility;
var
Invisibilities : Cardinal;
InvisibilitiesCount : Integer;
begin
OpenContainer(ToolsContainer);
CheckLag(LagMs);
Invisibilities := FindTypeEx(Invis, InvisColor, ToolsContainer, false);
InvisibilitiesCount := FindFullQuantity;
AddToSystemJournal('Found ' + IntToStr(InvisibilitiesCount) + ' invisibilities in tools container.');
if InvisibilitiesCount = 0 then begin
AddToSystemJournal('No invisibilities. Disconnect.');
Disconnect;
end else begin
MoveItem(Invisibilities, 1, Backpack, 0, 0, 0);
wait(1000);
CheckLag(LagMs);
end;
end;
// Procedure is used for taking pickaxes from the container to a backpack
procedure GetPickaxe;
var
Pickaxes : Cardinal;
PickaxesCount : Integer;
begin
OpenContainer(ToolsContainer);
CheckLag(LagMs);
Pickaxes := FindType(Pickaxe, ToolsContainer);
PickaxesCount := FindFullQuantity;
AddToSystemJournal('Found ' + IntToStr(PickaxesCount) + ' pickaxes in tools container.');
if PickaxesCount = 0 then begin
AddToSystemJournal('No pickaxes. Disconnect.');
Disconnect;
end else begin
MoveItem(Pickaxes, 0, Backpack, 0, 0, 0);
wait(1000);
CheckLag(LagMs);
end;
end;
// Procedure is used for recharging runebook with a recall scrolls in container
procedure RechargeRunebook;
var
Scrolls : Cardinal;
ScrollsCount : Integer;
begin
OpenContainer(ToolsContainer);
CheckLag(LagMs);
Scrolls := FindType(Recall, ToolsContainer);
ScrollsCount := FindFullQuantity;
AddToSystemJournal('Found ' + IntToStr(ScrollsCount) + ' recall scrolls in tools container.');
if ScrollsCount = 0 then begin
AddToSystemJournal('No recall scrolls. Disconnect.');
Disconnect;
end else begin
MoveItem(Scrolls, 0, Runebook, 0, 0, 0);
wait(2500);
CheckLag(LagMs);
end;
end;
// Procedure is used for meditating before recall
procedure CheckMana(MinMana : Integer);
begin
while Mana < MinMana do begin
UseSkill('Meditation');
wait(5000);
end;
end;
// Function is used for meditating before recall
function RunebookRecall(RunebookButton : Integer) : Boolean;
begin
CheckMana(RecallMinMana);
AddToSystemJournal('Recall to ' + IntToStr(RunebookButton) + ' is in progress.');
UOSay('.recall ' + IntToStr(RunebookButton));
wait(RunebookTeleportDelay);
result := true;
end;
// Procedure is used for moving to teleport stone at market
procedure MoveToTeleportStone;
begin
CheckLag(LagMs);
NewMoveXY(xTileTeleportStone, yTileTeleportStone, true, 0, true);
end;
// Procedure is used for teleporting to minoc using teleport stone
procedure TeleportToMinoc;
var
AGInfo : TGumpInfo;
MinocButton : Integer;
begin
MinocButton := 13;
CheckLag(LagMs);
UseObject(TeleportStone);
wait(GumpDelay);
GetGumpInfo(GetGumpsCount-1, AGInfo);
NumGumpButton(GetGumpsCount-1, AGInfo.GumpButtons[MinocButton].return_value);
wait(StoneTeleportDelay);
end;
// Procedure is used for moving to the world from the market
procedure MoveToWorld;
begin
while (Abs(GetX(Self) - xTileTeleportStone) < 50) or (Abs(GetY(Self) - yTileTeleportStone) < 50) do begin
CheckLag(LagMs);
MoveToTeleportStone;
TeleportToMinoc;
end;
end;
// Procedure is used for teleporting to the market using help / stuck / move to altair menu
procedure TeleportToMarket;
var
AGInfo : TGumpInfo;
StuckButton, ConfirmButton, StuckDelay : Integer;
begin
StuckButton := 8;
ConfirmButton := 0;
while (Abs(GetX(Self) - xTileResurrect) > 50) or (Abs(GetY(Self) - yTileResurrect) > 50) do begin
if Dead then begin
StuckDelay := 5000;
end
else begin
StuckDelay := 150000;
end;
CheckLag(LagMs);
HelpRequest;
wait(GumpDelay);
GetGumpInfo(GetGumpsCount-1, AGInfo);
NumGumpButton(GetGumpsCount-1, AGInfo.GumpButtons[StuckButton].return_value);
CheckLag(LagMs);
wait(GumpDelay);
GetGumpInfo(GetGumpsCount-1, AGInfo);
NumGumpButton(GetGumpsCount-1, AGInfo.GumpButtons[ConfirmButton].return_value);
CheckLag(LagMs);
wait(StuckDelay);
end;
end;
// Procedure is used for moving to the resurrect ankh
procedure MoveToAnkh;
begin
CheckLag(LagMs);
NewMoveXY(xTileResurrect, yTileResurrect, true, 0, true);
end;
// Procedure is used for resurrecting
procedure Resurrect;
begin
if Dead then begin
AddToSystemJournal('! Resurrecting...');
TeleportToMarket;
MoveToAnkh;
end;
end;
// Procedure is used for (resurect if needs) and recall to home
procedure MoveToHome;
begin
while (Abs(GetX(Self) - xTileResourceContainer) > 2) or (Abs(GetY(Self) - yTileResourceContainer) > 2) do begin
CheckLag(LagMs);
if Dead then begin
Resurrect;
MoveToWorld;
end;
RunebookRecall(RunebookHomeButton);
end;
end;
// Function is used for weight control
function CheckMaxWeight : Boolean;
begin
Result := Weight >= MaxWeight - 15;
end;
// Procedure is used for dropping resources to the resource container (ores & stones, ingots and logs for repair)
procedure DropResources;
var
ItemTypes : array of Word;
i : Integer;
begin
ItemTypes := [
$19B7, // ores
$19B8, // ores
$19B9, // ores
$19BA, // ores
$0F25, // amber
$0F2D, // tourmaline
$0F15, // citrine
$0F16, // amethyst
$0F19, // saphire
Log, // Logs for repair
Ingot // Ingots for repair
];
for i := 0 to Length(ItemTypes) - 1 do begin
while FindType(ItemTypes[i], Backpack) > 0 do begin
AddToSystemJournal('Drop ' + GetCliloc(FindItem) + ' to container.');
MoveItem(FindItem,0,ResourceContainer,0,0,0);
Wait(2500);
end;
end;
end;
// Procedure is used for dropping any tools we used to tools container
procedure DropTools;
var
ItemTypes : array of Word;
i : Integer;
begin
ItemTypes := [
TinkerTools // Tinker tools for repair
];
for i := 0 to Length(ItemTypes) - 1 do begin
while FindType(ItemTypes[i], Backpack) > 0 do begin
AddToSystemJournal('Drop ' + GetCliloc(FindItem) + ' to container.');
MoveItem(FindItem,0,ToolsContainer,0,0,0);
Wait(2500);
end;
end;
end;
// Procedure is used for searching mine tiles depends on SeekRange
procedure GetTilesToMine;
var
x, y, i : Integer;
TileInfo : TStaticCell;
begin
SetLength(MinTiles_Array, 0);
for x := (-1 * SeekRange) to SeekRange do
for y := (-1 * SeekRange) to SeekRange do
begin
TileInfo := ReadStaticsXY(GetX(self)+x, GetY(self)+y, WorldNum);
if TileInfo.StaticCount > 0 then
for i := Low(TileInfo.Statics) to High(TileInfo.Statics) do
if (TileInfo.Statics[i].Tile >= 1339) and (TileInfo.Statics[i].Tile <= 1359) and (TileInfo.Statics[i].z = GetZ(self)) then
begin
SetLength(MinTiles_Array, Length(MinTiles_Array) + 1);
MinTiles_Array[High(MinTiles_Array)].Tile := TileInfo.Statics[i].Tile;
MinTiles_Array[High(MinTiles_Array)].x := TileInfo.Statics[i].x;
MinTiles_Array[High(MinTiles_Array)].y := TileInfo.Statics[i].y;
MinTiles_Array[High(MinTiles_Array)].z := TileInfo.Statics[i].z;
end;
end;
AddToSystemJournal('Found ' + IntToStr(Length(MinTiles_Array)) + ' tiles for mining.');
end;
// Function is used for mining the particular mine spot
// 1 - pickaxe not found
// 2 - attacking you
function MinTileSpot(Idx : Integer) : Integer;
var
i, k : Integer;
msgFizzle, msgEnd, msgUseless, msgAttack : String;
cTime : TDateTime;
begin
msgFizzle := 'You put |You loosen |не получилось ';
msgEnd := 'is nothing| too far| mining in rock| cannot mine| no line| reach| not to mine|Try mining|слишком далеко|прекратили';
msgUseless := 'the Iron Ore|the Copper Ore|the Bronze Ore';
msgAttack := 'is attacking you';
result := 0;
if Dist(GetX(self), GetY(self), MinTiles_Array[Idx].x, MinTiles_Array[Idx].y) > 1 then
NewMoveXY(MinTiles_Array[Idx].x, MinTiles_Array[Idx].y, true, 1, true);
for k := 0 to 4 do
begin
if (ObjAtLayerEx(RhandLayer,self) = 0) then begin
if FindType(Pickaxe, Backpack) = 0 then begin
AddToSystemJournal('There are no pickaxes in a backpack.');
result := 1;
exit;
end;
end;
if WarMode then SetWarMode(False);
if UseType(Pickaxe, $FFFF) = 0 then
UseType(Pickaxe, $FFFF);
CheckLag(LagMs);
if not WaitForTarget(10000) then
begin
AddToSystemJournal('There is no target for a long time (probably we lose a pickaxe).');
result := 1;
exit;
end
else
begin
cTime := Now;
TargetToTile(MinTiles_Array[Idx].Tile, MinTiles_Array[Idx].x, MinTiles_Array[Idx].y, MinTiles_Array[Idx].z);
for i := 0 to 100 do
begin
Wait(100);
CheckLag(LagMs);
if (InJournalBetweenTimes(msgAttack, cTime, Now) <> -1) then begin result := 2; exit; end;
if (InJournalBetweenTimes(msgEnd, cTime, Now) <> -1) then exit;
if (InJournalBetweenTimes(msgUseless, cTime, Now) <> -1) then exit;
if (InJournalBetweenTimes(msgFizzle, cTime, Now) <> -1) then break;
end;
end;
end;
end;
// Procedure is used for hiding
procedure CheckHide;
var
i : Integer;
begin
while not Hidden do
begin
UseSkill('Hiding');
for i := 0 to 10 do
begin
Wait(500);
CheckLag(LagMs);
if Hidden then break;
end;
end;
end;
// Procedure is used for drinking invisibility potion
procedure DrinkInvisibility;
begin
AddToSystemJournal('Drinking invisibility.');
CheckLag(LagMs);
UseObject(FindTypeEx(Invis, InvisColor, Backpack, true));
end;
// Function is used for checking a condition do we need to take more pickaxes
function NeedMorePickaxe : Boolean;
begin
result := GetPickaxeCount(Backpack) < TakePickaxeCount;
end;
// Function is used for checking a condition do we need to take more invisibility potions
function NeedMoreInvisibility : Boolean;
begin
result := GetInvisibilityCount(Backpack) < TakeInvisibilityCount;
end;
// Procedure is used for taking ingots from the container (required for repair)
procedure GetIngots;
var
Ingots : Cardinal;
IngotsCount : Integer;
begin
OpenContainer(ResourceContainer);
Ingots := FindTypeEx(Ingot, PickaxeColor, ResourceContainer, false);
IngotsCount := FindFullQuantity;
AddToSystemJournal('Found ' + IntToStr(IngotsCount) + ' Ingots in resource container.');
if(IngotsCount <= MinIngotsForRepair) then begin
AddToSystemJournal('Not enought Ingots for repair were found. Disconnect.');
Disconnect;
end;
AddToSystemJournal('Get ' + IntToStr(MinIngotsForRepair) + ' Ingots for repair.');
CheckLag(LagMs);
MoveItem(Ingots, MinIngotsForRepair, Backpack, 0, 0, 0);
wait(1000);
end;
// Procedure is used for taking logs from the container (required for repair)
procedure GetLogs;
var
Logs : Cardinal;
LogsCount : Integer;
begin
OpenContainer(ResourceContainer);
Logs := FindType(Log, ResourceContainer);
LogsCount := FindFullQuantity;
AddToSystemJournal('Found ' + IntToStr(LogsCount) + ' logs in resource container.');
if(LogsCount <= MinLogsForRepair) then begin
AddToSystemJournal('Not enought logs for repair were found. Disconnect.');
Disconnect;
end;
AddToSystemJournal('Get ' + IntToStr(MinLogsForRepair) + ' logs for repair.');
CheckLag(LagMs);
MoveItem(Logs, MinLogsForRepair, Backpack, 0, 0, 0);
wait(1000);
end;
// Procedure is used for taking tinker tools from the container (required for repair)
procedure GetTinkerTools;
var
Tools : Cardinal;
ToolsCount : Integer;
begin
OpenContainer(ToolsContainer);
Tools := FindType(TinkerTools, ToolsContainer);
ToolsCount := FindFullQuantity;
AddToSystemJournal('Found ' + IntToStr(ToolsCount) + ' tinker tools in tools container.');
if ToolsCount <= 0 then begin
AddToSystemJournal('Tinker tools was not found. Disconnect.');
Disconnect;
end;
CheckLag(LagMs);
MoveItem(Tools, 1, Backpack, 0, 0, 0);
wait(1000);
end;
// Procedure is used for repairing pickaxes in a backpack
procedure RepairPickaxes;
var
i : Integer;
cTime : TDateTime;
msgSuccess, msgFailed : String;
begin
msgSuccess := 'успешно починили|эта вещь не нуждается';
msgFailed := 'недостаточно ресурсов';
GetTinkerTools;
repeat
GetIngots;
GetLogs;
AddToSystemJournal('Repairing pickaxe...');
if WarMode then SetWarMode(False);
UseObject(FindType(TinkerTools, Backpack));
CheckLag(LagMs);
cTime := Now;
TargetToObject(FindTypeEx(Pickaxe, PickaxeColor, Backpack, false));
for i := 0 to 100 do begin
Wait(100);
CheckLag(LagMs);
if (InJournalBetweenTimes(msgSuccess, cTime, Now) <> -1) then break;
if (InJournalBetweenTimes(msgFailed, cTime, Now) <> -1) then break;
end;
until (InJournalBetweenTimes(msgSuccess, cTime, Now) <> -1);
DropResources;
DropTools;
end;
// Procedure is used for an initial initialization
procedure Init;
begin
UOSay('.runebook_add');
CheckLag(LagMs);
WaitForTarget(10000);
TargetToObject(Runebook);
end;
begin
Init;
repeat
MoveToHome;
CheckHide;
DropResources;
RechargeRunebook;
while NeedMoreInvisibility do GetInvisibility;
while NeedMorePickaxe do GetPickaxe;
RepairPickaxes;
CheckMana(MaxMana);
CaveButton := RandomRange(RunebookCaveButtonBegin, RunebookCaveButtonEnd);
RunebookRecall(CaveButton);
GetTilesToMine;
for i := Low(MinTiles_Array) to High(MinTiles_Array) do begin
MineResult := MinTileSpot(i);
if MineResult = 1 then break;
if MineResult = 2 then begin
DrinkInvisibility;
break;
end;
if CheckMaxWeight() then break;
if Dead then break;
end;
until false;
end.