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

Работа с мул-файлами (библиотека функций StealthMUL)

Archive messages
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Работа с мул-файлами (библиотека функций StealthMUL)

Post by Edred »

Автор библиотеки Ruff.

Скачать последнюю версию библиотеки можно здесь

Для использования библиотеки необходимо положить ее в папку с стелсом а в скрипте импортировать необходимые функции.

Библиотека экспортирует следущие функции:

Code: Select all

function InitMUL(path:PChar):integer; 
- Инициализация библиотеки. path - путь к клиенту

Code: Select all

function GetLayerCount(x, y:word; facet:byte; var LayerCount:byte):boolean;


- Возвращает число доступных слоев в данной координате в аргумент LayerCount.
почва всегда слой 0. Остальные слои - статика. Например если это банк, то слои будут почва и крыша (если банк одноэтажный) или если дерево - то ствол и крона (листья)

Code: Select all

function GetTileData(x, y:word; facet:byte; layer:byte; var TileType:word; var z:shortint):boolean; 
- Возвращает тип тайла в указанной координате в указанном слое. А так же z координату этого тайла.
Для нулевого слоя будет возвращена графика тайла почвы (группа 1), для остальных - статического объекта (группа 2).

Code: Select all

function GetTileDetailsA(buf:PChar;bc:integer;grp:byte;tile:word) : integer; 
- Информация о объекте. Информация записывается в текстовый буфер buf с объемом bc байт.
grp - группа запрашиваемого объекта: 1 - тайлы,2 - объекты, 3 - анимация (неписи, плееры).
tile - тип объекта (то что обычно передается в инжу и стелс в функцию FindType)

Code: Select all

function GetTileDetailsR(var TileData:TTileData;grp:byte;tile:word) : integer; 
- тож самое но информация записывается в структуру TileData. описание типа TTileData:

Code: Select all

    TTileData = record 
      Handle  :LongWord; 
      Tag     :LongWord; 
      Flags   :LongWord; 
      Graphic :word; 
      Weight  :byte; 
      Quality :byte; 
      Quantity:byte; 
      ExtraID :word; 
      Hue     :byte; 
      Height  :byte; 
      Name    :Array[0..19] of Char; 
    end;


где:
Handle - внутренний индекс в муле (тиледата)
Tag - хз
Flags - флаги (в сыром виде, надо побитово разложить для актуальных флагов)
Graphic - тип (objecttype для объектов и тайлтайп для тайлов)
Weight - вес
Quality - качество
Quantity - кол-во
ExtraID - индекс доп ресурса (textureid для тайлов, animid для объектов)
Hue - цвет
Height - высота (вместимость контейнера)
Name - имя объекта/тайла

Code: Select all

function GetTileFlags(grp:byte;tile:word) : cardinal; 
- возвращает флаги указаного тайла.

Code: Select all

function ShowRadar():integer; 
- Создает окно радара и показывает его. По умолчанию показывается вся карта. Необходимо установить область видимости с помощью

Code: Select all

procedure SetRadarArea(l,t,w,h:integer); 
- Устанавливает область видимости радара. l,t,w,h - Левая граница,Верхняя граница,Ширина области,Высота области соответственно.

Для того чтобы отследить объекты на радаре, необходимо их добавить с помощью

Code: Select all

procedure AddObjects(a:array of TObjCell;n:integer); 
- Добавляет объекты в кеш радара. Глубина кеша - 255. При переполнении начинают замещатся самые старые объекты в кеше (которые давно не обновлялись). При добавлении идет проверка ID объектов, и если они уже есть то просто обновляются.
а - массив объектов типа

Code: Select all

  TObjCell = Record 
    OID:cardinal; 
    GID:word; 
    Quantity,x,y:word; 
    z,grp:byte; 
    tm:TDateTime; 
  end;


где OID - ID объекта, GID - тип (графика) объекта, Quantity - для не статики (монстров, НПС, плееров) - цвет Notority (злобность), grp - группа объекта (см выше), tm - используется внутри библиотеки (временной штамп последней модификации, при добавлении игнорируется).

Code: Select all

procedure HideRadar(); 
- Скрывает окно радара.


Пример объявления библиотеки в скрипте:

Code: Select all

type 
  TTileData = record 
    Handle  :LongWord; 
    Tag     :LongWord; 
    Flags   :LongWord; 
    Graphic :word; 
    Weight  :byte; 
    Quality :byte; 
    Quantity:byte; 
    ExtraID :word; 
    Hue     :byte; 
    Height  :byte; 
    Name    :Array[0..19] of Char; 
  end;

  TObjCell = Record 
    OID:cardinal; 
    GID:word; 
    Quantity,x,y:word; 
    z,grp:byte; 
    tm:TDateTime; 
  end;

function InitMUL(path:PChar):integer; external '[email protected]'; 
function GetLayerCount(x, y:word; facet:byte; var LayerCount:byte):boolean; external '[email protected]'; 
function GetTileDetailsR(TileData:TTileData;grp:byte;tile:word) : integer; external '[email protected]'; 
function GetTileDetailsA(buf:PChar;bc:integer;grp:byte;tile:word) : integer; external '[email protected]'; 
function GetTileData(x, y:word; facet:byte; layer:byte; var TileType:word; var z:shortint):boolean; external '[email protected]'; 
function ShowRadar() : integer; external '[email protected]'; 
procedure SetRadarArea(t,l,w,h:integer); external '[email protected]'; 
procedure AddObjects(objs : Array of TObjCell;objnum:integer); external '[email protected]'; 
procedure HideRadar(); external '[email protected]'; 



Пример использования библиотеки :

Code: Select all

function MessageBox(hWnd: Longint; lpText, lpCaption: PChar; uType: Longint): Longint; external '[email protected] stdcall'; 

{$Include 'flow.inc'} 
{$Include 'misc.inc'} 
{$Include 'move.inc'} 
{$Include 'path.inc'} 

type 
  TTileData = record 
    Handle  :LongWord; 
    Tag     :LongWord; 
    Flags   :LongWord; 
    Graphic :word; 
    Weight  :byte; 
    Quality :byte; 
    Quantity:byte; 
    ExtraID :word; 
    Hue     :byte; 
    Height  :byte; 
    Name    :Array[0..19] of Char; 
  end;

function InitMUL(path:PChar):integer; external '[email protected]'; 
function GetLayerCount(x, y:word; facet:byte; var LayerCount:byte):boolean; external '[email protected]'; 
function GetTileDetailsR(TileData:TTileData;grp:byte;tile:word) : integer; external '[email protected]'; 
function GetTileDetailsA(buf:PChar;bc:integer;grp:byte;tile:word) : integer; external '[email protected]'; 
function GetTileData(x, y:word; facet:byte; layer:byte; var TileType:word; var z:shortint):boolean; external '[email protected]'; 
procedure SetRadarArea(t,l,w,h:integer); external '[email protected]'; 
procedure AddObjects(objs : Array of TObjCell;objnum:integer); external '[email protected]'; 

procedure error(func:string;err:integer); 
begin 
   MessageBox(0, func+': Error: '+IntToStr(err), 'ERROR!', 0); 
end; 

procedure msg(txt:string;num:integer); 
begin 
   MessageBox(0, txt+': '+IntToStr(num), 'Message!', 0); 
end; 

function CheckStep(x,y:word): boolean; 
var 
   ret,i:integer; 
   found:boolean; 
   Flags:cardinal; 
   tile:word; 
   LayerCount:byte; 
   z:shortint; 
begin 
   // If we cant do anything, assume we can step. 
   result := true; 
   // How much layers do we have here? 
   if not GetLayerCount(x,y,0,LayerCount) then 
      exit; 
   if LayerCount > 0 then // Something Static out there 
   begin 
      dlog('Complex tile test'); 
      i := 1; 
      found := false; 
      // Let's find our layer (near our z) 
      repeat 
         if not GetTileData(x,y,0,i,tile,z) then 
            exit 
         else 
            if abs(getZ(self) - z) < 10 then 
            begin 
               found:=true; 
               // Get Static Tile details (group 2) 
               Flags := GetTileFlags(2,tile); 
               // Check if the tile has Impassable flag 
               if (Flags AND $00000040 > 0) then 
                  result := false; 
            end; 
         i := i + 1; 
         dlog('Static at layer '+IntToStr(i)+' has '+IntToStr(z)+' altitude. We are at '+IntToStr(getz(self))); 
      until ((i>= LayerCount)); 
      if not found then 
      begin 
         // Get Land Tile details (group 1) 
         Flags := GetTileFlags(1,tile); 
         // Check if the tile has Impassable flag 
         if (Flags AND $00000040 > 0) then 
            result := false; 
      end; 
   end 
   else // We have pure ground 
   begin 
      dlog('Field tile test'); 
      // Get Land Tile details 
      Flags := GetTileFlags(1,tile); 
      // Check if the tile has Impassable flag 
      if (Flags AND $00000040 > 0) then 
         result := false; 
   end; 
end; 

procedure UpdateObject(oid:cardinal); 
var 
   o:Array[0..1] of TObjCell; 
begin 
   o[0].OID := oid; 
   o[0].GID := GetType(oid); 
   o[0].x := GetX(oid); 
   o[0].y := GetY(oid); 
   o[0].z := GetZ(oid); 
   o[0].grp := 3; 
   o[0].Quantity := $FFFF; 
   AddObjects(o,1); 
end; 

procedure Radar(); 
begin 
   UpdateObject(self); 
   if ShowRadar() then 
      SetRadarArea(GetX(self)-150,GetY(self)-150,300,300); 
end; 

procedure checklib(); 
var 
   ret:integer; 
   x,y:word; 
   lc:byte; 
begin 
   ret := InitMUL('C:\\Program Files\\Dragon World\\Ultima Online\\'); 
   if ret < 0 then 
   begin 
      error('Init',ret); 
      exit; 
   end; 
   Radar(); 
   x := getX(self); 
   y := getY(self)+1; 
   if checkstep(x,y) then 
      Raw_Move(2,true); 
   UpdateObject(self); 
end; 

BEGIN 
   checklib(); 
END.
Last edited by Edred on 21.03.2008 21:41, edited 1 time in total.
grundick
Developer
Developer
Posts: 272
Joined: 31.01.2008 21:16

Post by grundick »

Мне кажется ты опспешил выкладывать...
Acronym
Novice
Novice
Posts: 114
Joined: 10.05.2005 18:42
Location: Odessa, NDW
Contact:

Post by Acronym »

grundick wrote:Мне кажется ты опспешил выкладывать...
Ну так или иначе это уже имело место быть на форуме.
aka Trickster [YGG]
current version: 1.0 [RC3]
grundick
Developer
Developer
Posts: 272
Joined: 31.01.2008 21:16

Post by grundick »

Да, но этот чекстеп не рабоает.Точнее он на каждом тайле пишет пассабл...
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Какой чекстеп? Дважды просмотрел список функций и процедур, никакого чекстепа не нашел. Откуда ты его взял?

А, ты имеешь в виду пример скрипта? Ну дык, я думаю, ошибка именно в скрипте, а не в используемых функциях библиотеки.

Функции библиотеки тестились, насколько я понимаю. А вот ходилку Руф так и не дописал еще, поэтому скрипт с функцией наверняка не тестился.

Не используй просто эту функцию. А функции получения типа тайла по координатам (для мининга, ламбера, фишинга) использовать наверняка можно успешно.
AlexM2008
Neophyte
Neophyte
Posts: 16
Joined: 23.05.2008 12:07
Contact:

Post by AlexM2008 »

Edred wrote:А функции получения типа тайла по координатам (для мининга, ламбера, фишинга) использовать наверняка можно успешно.
Если можно подробнее с этого места.

Code: Select all

private Tree[] SearchTrees()
{
ArrayList trees_list = new ArrayList();
Tree[] trees_array;

for (int x = player.X - 50; x < player.X + 50; x++) 
// 50 вправо по оси X
{
 for (int y = player.Y - 100; y < player.Y + 100; y++) 
//квадрат поиска деревьев 100 вверх и 100 вниз по оси Y
 {
  Ultima.HuedTile[] hTiles = Ultima.Map.Felucca.Tiles.GetStaticTiles(x, y);

  for ( int i = 0; i < hTiles.Length; i++ )
  {
  switch (hTiles[i].ID-0x4000)
  {
   case 0x0cca:
   case 0x0ccb:
     . . . . . . 
   case 0x0d84:
   case 0x0d85:
   case 0x0d86:
    Tree tree = new Tree();
    tree.x = x;
    tree.y = y;
    tree.z = (byte)hTiles[i].Z;
    tree.id = hTiles[i].ID - 0x4000;
    trees_list.Add(tree);
    break;
   default:
    break;
    }
   }
  }
 }
  curr_time = DateTime.Now;
  Tracer.TraceDebug("Count start date/time: {0}", curr_time);
  Tracer.TraceDebug("\n {0} Trees added for LumberJacking\n", trees_list.Count);
  trees_array = (Tree[])trees_list.ToArray(typeof(Tree));
  return (Tree[])trees_list.ToArray(typeof(Tree)); 
 }

AlexM2008
Neophyte
Neophyte
Posts: 16
Joined: 23.05.2008 12:07
Contact:

Post by AlexM2008 »

Edred wrote:А вот ходилку Руф так и не дописал еще, поэтому скрипт с функцией наверняка не тестился.
А ходить можно вот так

Code: Select all

Tree[] trees = SearchTrees();
			
foreach(Tree tree in trees)
{
 for(int tx = -1; tx <= 1; tx++)
 {
  for(int ty = -1; ty <= 1; ty++)
  {
   if(tx == 0 && ty == 0)
    continue;
   if(Move(tree.x + tx, tree.y + ty, false))
   {					
    connection.World.Player.WarModeSet(0);
    UseType(dagger); //Использование даггера для получения простого лога
    bool is_logs = true; 
    DCut(tree); //Использование даггера для получения простого лога
    UseType(axe);
    while(is_logs)
    {
      . . .
      is_logs = Chop(tree);
     }
     goto end;
     }
    CheckAttack();
   }
v26RuS
Novice
Novice
Posts: 61
Joined: 18.05.2008 16:07
Location: DRW
Contact:

Post by v26RuS »

Попытался скачать библиотеку, но к сожелению ссылка недоступна... если у кого есть она выложите куданитьбудь для скачивания... Буду признателен
Невозможное возможнО!
Acronym
Novice
Novice
Posts: 114
Joined: 10.05.2005 18:42
Location: Odessa, NDW
Contact:

Post by Acronym »

v26RuS wrote:Попытался скачать библиотеку, но к сожелению ссылка недоступна... если у кого есть она выложите куданитьбудь для скачивания... Буду признателен
Вообще то качается. На всякий случай:
http://ifolder.ru/7302809
aka Trickster [YGG]
current version: 1.0 [RC3]
v26RuS
Novice
Novice
Posts: 61
Joined: 18.05.2008 16:07
Location: DRW
Contact:

Post by v26RuS »

Незнаю меня перегидывает вот сюда http://1sthost.org/blog3/
А за то что залил спасибо буду разбераться)
Невозможное возможнО!
ParadoX
Apprentice
Apprentice
Posts: 256
Joined: 17.03.2005 16:06

Post by ParadoX »

благодарю, этот Ruff или конспиратор, или уныл совсем, связатся с ним нельзя, так как я почти уверен что это было без исходников...

но блин какая моя радость что там есть

прямо находка..

огромное спасибо

однако..

//function GetLayerCount(x, y:word; facet:byte; var LayerCount:byte):boolean; export;
//function GetTileData(x, y:word; facet:byte; layer:byte; var TileType:word; var z:shortint):boolean; export;

закоменчены и нигде не описаны
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Исходники этого хозяйства есть на SVN. У Руфа временные проблемы с невозможностью поставить на рабочий комп дельфи (он в европе, фирма жестко контролирует чтобы не было нелицензионного софта на компах). Проблемы эти уже с конца прошлого года и когда он сможет их решить - неизвестно.
DismalZ
Neophyte
Neophyte
Posts: 13
Joined: 09.10.2008 16:10

Post by DismalZ »

Функции GetTileData и GetLayerCount вроде исправно работают. Только GetTileData выдает тип тайла смещенный на -1 значение. например тип дерева 3294, а он выдает 3293. Хотелоь бы узнать, кому-нибудь удалось заставить GetTileDetailsR выдавать информацию о тайле или объекте? и как пользоваться GetTileDetailsA?
Alexej
Novice
Novice
Posts: 79
Joined: 06.06.2008 11:55
Contact:

Post by Alexej »

GetTileData - работает исправно, попробуй поиграться со слоями (0,1,2,3)
(у мня шахтеры с нею работают отлично, правда пыаются копать даже за стенами шахты :) )
GetLayerCount - значения выдает, а как их другим чем проверить - непридумал, да и особой цели небыло...

остальные функции вообще не осилил... дето чтото непонятно... но ковырялся долго... долго намаялся и с радаром - так и не засветился и непонятно как должен работать...
вообщем рыбака на НД (СД) так и не получилось заставить рыбачить :(
DismalZ
Neophyte
Neophyte
Posts: 13
Joined: 09.10.2008 16:10

Post by DismalZ »

Для тех кто пытается разобраться с этой библиотекой, могу добавить, что она читает файлы только из версии UO Mondain's Legacy. Но, например, на оскоме эта версия безбожно глючит. Я использовал Samurai Empire, но файлы от нее не подходят. Так что будте внимательны =)
Post Reply