Forum in READ ONLY mode! All questions and discussions on Discord official server, invite link: https://discord.gg/VxsGzJ7

Automining (Caves, Runebook, Repair, Resurr) для UORPG.com

Only working scripts
Post Reply
Scripts Writer
Novice
Novice
Posts: 130
Joined: 06.05.2008 18:03

Automining (Caves, Runebook, Repair, Resurr) для UORPG.com

Post by Scripts Writer »

Добрый день.

Данный скрипт в текущей редакции применим исключительно для 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.
Проще научить человека ловить рыбу, чем постоянно ею его кормить. (с) Destruction
GeeZeR
Apprentice
Apprentice
Posts: 226
Joined: 28.01.2012 19:48

Re: Automining (Caves, Runebook, Repair, Resurr) для UORPG.c

Post by GeeZeR »

все бы так код писали, мир стал бы лучше )
Stealth 8.10.2 | Клиент: 7.0.13.4
User avatar
Vizit0r
Developer
Developer
Posts: 3958
Joined: 24.03.2005 17:05
Contact:

Re: Automining (Caves, Runebook, Repair, Resurr) для UORPG.c

Post by Vizit0r »

не вчитывался, но проверок много, форматирование правильное - значит все хорошо :)

Взгляд зацепился только за мусорные begin-end в конструкциях типа

Code: Select all

        if Dead then begin
            StuckDelay := 5000;
        end
        else begin
            StuckDelay := 150000;
        end;
но это мелочи
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
Scripts Writer
Novice
Novice
Posts: 130
Joined: 06.05.2008 18:03

Re: Automining (Caves, Runebook, Repair, Resurr) для UORPG.c

Post by Scripts Writer »

Vizit0r wrote:не вчитывался, но проверок много, форматирование правильное - значит все хорошо :)

Взгляд зацепился только за мусорные begin-end в конструкциях типа

Code: Select all

        if Dead then begin
            StuckDelay := 5000;
        end
        else begin
            StuckDelay := 150000;
        end;
но это мелочи
Перестраховывался :) Жаль нельзя StuckDelay := Dead ? 5000 : 150000;
Проще научить человека ловить рыбу, чем постоянно ею его кормить. (с) Destruction
KocTuk
Posts: 2
Joined: 06.12.2017 13:54

Re: Automining (Caves, Runebook, Repair, Resurr) для UORPG.c

Post by KocTuk »

Макрос работает замечательно, вот только просьба:
1 Можно сделать так что бы он выкидывал Iron руду
2 что бы при выкапывание Айрона переходил к следующему тайлу.
Спасибо.
KocTuk
Posts: 2
Joined: 06.12.2017 13:54

Re: Automining (Caves, Runebook, Repair, Resurr) для UORPG.c

Post by KocTuk »

Персонаж не воскрешается после смерти,сервер UORPG.
если персонажа убивают, он не воскрешается,но если остановить скрипт и запустить снова, то воскрешается,в чем может быть дело ?
Vijokonta
Posts: 1
Joined: 04.05.2018 17:21

Re: Automining (Caves, Runebook, Repair, Resurr) для UORPG.c

Post by Vijokonta »

Макрос работает хорошо но есть 1на проблема, все скролы(рекола) что есть в сундуке бросает непонятно куда и они ищезают а книга рун не пополняется, каждые примерно 4 чяса приходится в ручную попонять книгу, в чем может быть проблема и куда макрос бросает скролы что они пропадают?
Post Reply