Code: Select all
Program SparringUP;
{
 Новая версия спарринга двух воинов. Делает:
 1. автоопределение партнера по спаррингу (имя выводится в системный
    журнал при запуске скрипта для визуального контроля)
 2. автонахождение мешка под ногами с армами, оружием, бинтами
 3. автонахождение корыта с водой для мытья бинтов рядом с чаром
 4. автоопределение направления, в котором стоит партнер по спаррингу
    и, соответственно, вычисление точки для отхода (противоположное
    направление, расстояние в 1 клетку)
 5. автоопределение видов арма и на какие слои одевать, автоматическое
    одевание арма, автоматическая проверка арма, 
    одетого на чара и одевание из мешка по мере разрушения.
 6. автоматическое взятие в руки оружия, типы оружия занесены в массив
    (по скиллам, порядок прокачки скиллов задается в скрипте)
 7. Автоматическое переключение на прокачку следующего боевого после того,
    как текущий вырастет до заданной величины (по умолчанию - 100.0)
 8. Автоматический подхил чара во время сражения, переключение режимов
    war/peace через глобальные переменные, отход чаров назад в случае
    критического уменьшения здоровья, команды на начало/останов боя через
    глобальные переменные, автодобор бинтов и мытье их в корыте.
 9. В случае отсутствия какого-либо ресурса скрипт приостанавливает свое действие,
    отведя чара назад на один шаг (для безопасности), выдает в системный журнал
    соответствующее сообщение и ожидает пока вы не добавите в его мешок
    необходимые ресурсы.
10. Контроль за реконнектом, при необходимости переоткрытие мешка с ресурсами.
 Настройка скрипта: проверьте только типы, все остальное скрипт сделает
 сам. Не забудьте правильно заполнить массивы в функции IniMyArm - вам надо
 изменять только типы на соответствующих слоях. Слои перечислены все, если
 на каком-то слое ничего не надевается - там стоит $0000. Второй массив содержит
 названия скиллов, макс размеры, типы оружия (скрипт сам будет перезаписывать нужную
 строку в первом массиве по мере необходимости). Скиллы идут в том порядке, в каком
 вы хотите их контролировать и качать.
 Оружие в соответствии со скиллами находится в отдельном массиве. Двуручное
 оружие не предусмотрено, все оружие надевается в правую руку.
 Вам нет необходимости делать копии этого скрипта для каждого чара!
 Один скрипт на всех чаров.
 v.2.02b (c) Edred
   1.02 - вводим щиты, брать их
   1.03 - автопоиск партнера по спаррингу в радиусе 1 клетки. Ищет как
          мужиков, так и баб. Вывод в системный журнал имени найденного
          противника для визуальной проверки игрока. Автоодевание армора:
          chain туники, ног, шеи. Естественно, при необходимости добор из
          сундука.
   1.04 - Вводим подхил чаров в этот скрипт с мытьем бинтов. Стелс, как
          оказалось, очень не любит параллельно запущенных скриптов.
          Подхил идет во время боя и после останова до полного здоровья.
          Мойка для бинтов ищется вокруг чаров по типу.
   1.05 - Мелкая правка. Все равно не всегда останавливаются чары!
   2.00 - Новый алгоритм работы, смотри описание в начале скрипта
   2.01 - дополнительный контроль. Теперь чары контролируют дополнительно
          здоровье противника, если оно меньше 30% - отход на безопасные позиции.
   2.02 - Во время лечения чара в безопасной позиции теперь проверяется армор-класс
          чара. Если он меньше заданной величины - при проверке арма и оружия по слоям
          проверяется армслором износ всех вещей. Если он меньше опять же заданной
          (индивидуально для каждого типа, в массиве по слоям) величины - вещь снимается
          и сбрасывается в спецмешок для складывания битых армов (один мешок на обоих чаров),
          а чар одевает новую вещь на этот слой.
}
{$Include 'all.inc'}
const
EnemyType1 = $0190;			// типы чаров разных полов
EnemyType2 = $0191;
MyWait = 500;				// пауза на перемещение и одевание
SundukType = $0E76;			// Тип контейнера с армами, оружием, бинтами
WaterType = $B42;			// тип тазика с водой
Delta = 60;					// Разница в здоровье с максимумом для останова
Bint=$0E21;					// Бинты
BlBint=$0E20;				// Кровавые бинты
HowMinBandages = 20;		// Если меньше - вымыть и, если надо, добрать
HowGetBandages = 100;		// и взять вот столько
MinArmorClass = 50;			// Если меньше - будет проверяться битость армов
ArmorTrashType = $0E79;		// тип мешка, куда скидывать битые армы. Тип должен
							// отличаться от типа мешков с ресурсами! Мешок
							// должен лежать в доступности обоим чарам!
type ArmLayers = Record
	typlayer : Byte;		// Слой
	typarm : Cardinal;		// Тип вещи
	minarm : integer;		// минимальный допустимый уровень битости
	end;
type DefineSkill = Record
	NamSkill : String;
	MaxValue : Double;
	TypWeapon : Cardinal;
	end;
var
MyArm : array [0..19] of ArmLayers;
MySkill : array [0..2] of DefineSkill;
EnemyWarrior, CurBag, ArmorTrash, WaterID : Cardinal;
SafeX, SafeY, WarX, WarY, k : Integer;
LastContOpen : TDateTime;
MyFlagWar,EnemyFlagWar, CurSkill : String;
OldSkill : Double;
	procedure IniMyArm;
	begin
		// Армы и оружие по слоям
		MyArm[0].typlayer := RhandLayer;
		MyArm[0].typarm := $13E3;
		MyArm[0].minarm := 1;
		MyArm[1].typlayer := LhandLayer;
		MyArm[1].typarm := $1B76;
		MyArm[1].minarm := 10;
		MyArm[2].typlayer := ShoesLayer;
		MyArm[2].typarm := $0000;
		MyArm[2].minarm := 20;
		MyArm[3].typlayer := PantsLayer;
		MyArm[3].typarm := $1411;
		MyArm[3].minarm := 20;
		MyArm[4].typlayer := ShirtLayer;
		MyArm[4].typarm := $0000;
		MyArm[4].minarm := 20;
		MyArm[5].typlayer := HatLayer;
		MyArm[5].typarm := $1412;
		MyArm[5].minarm := 20;
		MyArm[6].typlayer := GlovesLayer;
		MyArm[6].typarm := $1414;
		MyArm[6].minarm := 20;
		MyArm[7].typlayer := RingLayer;
		MyArm[7].typarm := $0000;
		MyArm[7].minarm := 20;
		MyArm[8].typlayer := NeckLayer;
		MyArm[8].typarm := $1413;
		MyArm[8].minarm := 20;
		MyArm[9].typlayer := WaistLayer;
		MyArm[9].typarm := $0000;
		MyArm[9].minarm := 20;
		MyArm[10].typlayer := TorsoLayer;
		MyArm[10].typarm := $1415;
		MyArm[10].minarm := 20;
		MyArm[11].typlayer := BraceLayer;
		MyArm[11].typarm := $0000;
		MyArm[11].minarm := 20;
		MyArm[12].typlayer := TorsoHLayer;
		MyArm[12].typarm := $0000;
		MyArm[12].minarm := 20;
		MyArm[13].typlayer := EarLayer;
		MyArm[13].typarm := $0000;
		MyArm[13].minarm := 20;
		MyArm[14].typlayer := BraceLayer;
		MyArm[14].typarm := $0000;
		MyArm[14].minarm := 20;
		MyArm[15].typlayer := ArmsLayer;
		MyArm[15].typarm := $1410;
		MyArm[15].minarm := 20;
		MyArm[16].typlayer := CloakLayer;
		MyArm[16].typarm := $0000;
		MyArm[16].minarm := 20;
		MyArm[17].typlayer := RobeLayer;
		MyArm[17].typarm := $0000;
		MyArm[17].minarm := 20;
		MyArm[18].typlayer := EggsLayer;
		MyArm[18].typarm := $0000;
		MyArm[18].minarm := 20;
		MyArm[19].typlayer := LegsLayer;
		MyArm[19].typarm := $0000;
		MyArm[19].minarm := 20;
		// Скиллы, макс величины, оружие (для перезаписи в пред. массиве
		MySkill[0].NamSkill := 'Mace Fighting';
		MySkill[0].MaxValue := 100.0;
		MySkill[0].TypWeapon := $13E3;		// Smith's Hammer
		MySkill[1].NamSkill := 'Fencing';
		MySkill[1].MaxValue := 100.0;
		MySkill[1].TypWeapon := $0F51;		// Dagger
		MySkill[2].NamSkill := 'Swordsmanship';
		MySkill[2].MaxValue := 100.0;
		MySkill[2].TypWeapon := $13F6;		// Butcher's Knife
	end;
	function AutoFindEnemy : Cardinal;
	// функция поиска чаров рядом для определения партнера по спаррингу
	// Возвращает сериал партнера по спаррингу.
	begin
		Finddistance := 1;
		Ignore(self);
		if FindType(EnemyType1, Ground) = 0 then FindType(EnemyType2, Ground);
		if finditem = 0 then
		begin
			// не нашли врагов :(
			AddToSystemJournal('Error: Партнер по спаррингу не найден!');
			Result := $00000000;
		    Exit;
	    end
		else
		begin
			// Ага! Вот он, гадина!
			AddToSystemJournal('Enemy found: ' + GetName(finditem));
			Result := finditem;
		end;
	end;
	procedure OpenContainer(f : boolean);
	// если f - true - просто открываем наш мешок и мешок для битого
	// если f - false - проверяем, был ли реконнект чара после последнего
	// открывания контейнера, если был - переоткрываем контейнер и записываем
	// новое значение в переменную LastContOpen, если не был - ничего не делаем
	begin
		waitconnection(3000);
		if (f = true) or (LastContOpen < ConnectedTime) then
		begin
			UseObject(CurBag);
			wait(MyWait * 2);
			checksave;
			UseObject(ArmorTrash);
			wait(MyWait * 2);
			checksave;
			LastContOpen := Now;
			addtosystemjournal('Контейнеры открыт в ' + DateTimeToStr(Now));
		end;
	end;
	function testCurArm(tlayer : byte; tmin : integer) : boolean;
	{ Тестируем вещь на указанном слое армслором.
	  ловим в журнале ответ, парсим его, вычленяем величину. Если она меньше
	  переданного значения - возвращаем true, иначе - false
	  Вот образцы строк:
	  Defense [56].This item is in full repair.
	  Defense [8].This item is badly damaged.
	  Defense [0].This item is about to fall apart.It looks quite fragile.
	  Defense [48].This item is a bit worn.
	
	  В журнале будет ловиться строка содержащая 'Defense'. Из нее вычленяться
	  число в квадратных скобках. Если на вашем шарде армслор выдает другие строки,
	  вам придется переписать эту функцию.
	}
	var tmpid : Cardinal;
		tmptime : TDateTime;
		r, p : Integer;
		tmpstr : String;
	begin
		Result :=false;
		tmpid := ObjAtLayer(tlayer);
		if TargetPresent then CancelTarget;
		tmptime := Now;
		UseSkill('Arms Lore');
		WaitForTarget(5000);
		If TargetPresent then TargetToObject(tmpid);
		r := 0;
		repeat
			wait(100);
			r := r + 1;
			p := InJournalBetweenTimes('Defense', tmptime, Now);
		until (p <> -1) or (r > 300);
		if p <> -1 then
		begin
			tmpstr := Journal(p);
			r := Pos('[',tmpstr);
			p := Pos(']',tmpstr);
			if StrToInt(Copy(tmpstr,r+1,p-r-1)) < tmin then Result := True;
		end else Addtosystemjournal('Warning: Армслор не работает. Проверьте правильность тестирования');
	end;
	procedure CheckArm;
	// проверка в цикле есть ли на соответствующих слоях нужные типы, если
	// чего-то нет - возьмем это из мешка и оденем на этот слой.
	VAR i : integer;
		tmpid : cardinal;
		testarm : boolean;
	begin
		if Armor < MinArmorClass then testarm := true else testarm := false;
		for i := 0 to 19 do
		begin
			if MyArm[i].typarm = $0000 then continue;
			if GetType(ObjAtLayer(MyArm[i].typlayer)) = MyArm[i].typarm then
			begin
				if not testarm then continue;
				// требуется проверка текущей части арма на битость
				if i = 0 then continue;
				if not testCurArm(MyArm[i].typlayer,MyArm[i].minarm) then continue;
			end;
			// На соответствующем слое либо ничего не надето, либо одето что-то другое
			if (ObjAtLayer(MyArm[i].typlayer) <> 0) then
			begin
				tmpid := ObjAtLayer(MyArm[i].typlayer);
				while not UnEquip(MyArm[i].typlayer) do wait(500);
				// тут надо сделать сброс снятой вещи в пак для битых армов
				OpenContainer(false);
				MoveItem(tmpid,1,ArmorTrash,0,0,0);
				wait(MyWait);
				checksave;
			end;
			// теперь на слое точно ничего не надето
			waitconnection(3000);
			OpenContainer(false);
			if Findtype(MyArm[i].typarm,CurBag) = 0 then
			begin
				AddToSystemJournal('Не могу найти в мешке что надеть на слой ' + inttostr(MyArm[i].typlayer));
				AddToSystemJournal('Добавьте в мешок вещь типа $' + inttohex(MyArm[i].typarm,4));
				repeat
					wait(MyWait * 4);
					waitconnection(3000);
					Findtype(MyArm[i].typarm,CurBag);
				until finditem <> 0;
			end;
			tmpid := finditem;
			while Count(MyArm[i].typarm) = 0 do
			begin
				waitconnection(3000);
				OpenContainer(false);
				Grab(tmpid,1);
				wait(MyWait);
				checksave;
			end;
			while ObjAtLayer(MyArm[i].typlayer) <> tmpid do
			begin
				waitconnection(3000);
				Equip(MyArm[i].typlayer,tmpid);
				wait(MyWait);
				checksave;
			end;
		end;
	end;
	function FindEnvironment : Boolean;
	// Находит под ногами у чара или сзади него мешок с добром (радиус = 1 клетка от чара)
	// Находит корыто с водой для мытья бинтов (радиус = 2 клетки от чара)
	// Находит мешок для битых армов (радиус = 3 клетки от чара)
	// Возвращает false если что-то не найдено.
	begin
		// мешок с добром
		Result := False;
		WaitConnection(3000);
		Finddistance := 1;
		if FindType(SundukType, Ground) = 0 then
		begin
			AddToSystemJournal('Error: Сундук или мешок не найден!');
			exit;
		end;
		CurBag := finditem;
		// мешок для битых армов
		Finddistance := 3;
		if FindType(ArmorTrashType, Ground) = 0 then
		begin
			AddToSystemJournal('Error: Сундук или мешок для битых армов не найден!');
			exit;
		end;
		ArmorTrash := finditem;
		LastContOpen := Now;
		OpenContainer(true);
		// корыто с водой
		Finddistance := 2;
		WaterID := FindType(WaterType, Ground);
		if WaterID = 0 then
		begin
			AddToSystemJournal('Error: Корыто с водой не найдено!');
			exit;
		end;
		Result := True;
	end;
	function CreateSafePoints : boolean;
	// Определяет координаты, где стоит чар и где стоит враг. Вычисляет направление
	// и определяет координаты точки отхода. Записывает их в SafeX и SafeY.
	// Текущие координаты - в WarX, WarY.
	var tmpx, tmpy : cardinal;
	begin
		Result := false;
		WarX := GetX(self);
		WarY := GetY(self);
		tmpx := GetX(EnemyWarrior);
		tmpy := GetY(EnemyWarrior);
		if (WarX <> tmpx) AND (WarY <> tmpY) then
		begin
			AddToSystemJournal('Error: Неправильная установка чаров!');
			AddToSystemJournal('Чары должны стоять по одной из осей,');
			AddToSystemJournal('Поставьте чаров либо по направлению 1-9 (на цифровой клавиатуре),');
			AddToSystemJournal('либо по направлению 3-7.');
			exit;
		end;
		if WarY = tmpy then
		begin
			SafeY := WarY;
			if WarX < tmpx then SafeX := WarX - 1;
			if WarX > tmpx then SafeX := WarX + 1;
			if WarX = tmpx then
			begin
				AddToSystemJournal('Error: Чары стоят в одной точке!');
				exit;
			end;
		end;
		if WarX = tmpx then
		begin
			SafeX := WarX;
			if WarY < tmpy then SafeY := WarY - 1;
			if WarY > tmpy then SafeY := WarY + 1;
		end;
		Result := true;
	end;
	procedure CheckBandages;
	// моет грязные бинты (если есть), добирает из мешка чистые (если мало)
	VAR tmpid : cardinal;
		i : integer;
	begin
		WaitConnection(3000);
		if Count(Bint) >= HowMinBandages then exit;
		// проверим грязные и помоем
		findtype(BlBint,backpack);
		while (FindCount > 0) do
		begin
			WaitConnection(3000);
			checksave;
			useobject(FindItem);
			waitfortarget(5000);
			if TargetPresent then TargetToObject(WaterID);
			wait(MyWait * 2);
			findtype(BlBint,backpack);
		end;
		WaitConnection(3000);
		if Count(Bint) >= HowMinBandages then exit;
		// бинты вымыты и их все равно меньше минимума
		OpenContainer(false);
		if  FindType(Bint, CurBag) = 0 then
		begin
			AddToSystemjournal('Warning: Кончились бинты, подложите в мешок');
				repeat
					wait(MyWait * 4);
					waitconnection(3000);
					Findtype(Bint, CurBag);
				until finditem <> 0;
		end;
		i := HowGetBandages;
		tmpid := finditem;
		if GetQuantity(tmpid) < HowGetBandages then i := GetQuantity(tmpid);
		OpenContainer(false);
		Grab(tmpid, i);
		wait(MyWait * 2);
		checksave;
	end;
	
	procedure FullHealChar;
	// лечение чара до максимума
	var stime : TDateTime;
		i : integer;
	begin
		while (HP < MaxHP) do
		begin
			CheckBandages;
			if TargetPresent then CancelTarget;
			stime := Now;
			if UseType(Bint,$FFFF) = 0 then break;
			WaitForTarget(5000);
			If TargetPresent then TargetToObject(Self);
			i := 0;
			repeat
				wait(100);
				i := i + 1;
			until (InJournalBetweenTimes('You put the bloody bandage|failed.', stime, Now)<>-1) or (i > 300);
			waitconnection(3000);
		end;
	end;
	procedure GotoXY(x,y,prec : integer; runflag : boolean);
	// x,y - координаты, в которые идем
	// prec - точность подхода
	// runflag - бежать или идти
	// v. 1.04 (с) Edred, скрипт портирован с инжекта
	// оригинальная версия Yoko с доработкой AGRS и Edred.
	var ld, ldc, dx, dy, mx, my : Integer;
	begin
		ld := 0; ldc := 0;
		while true do
		begin
			dx := GetX(self) - x; if dx < 0 then dx := 0 - dx;
			dy := GetY(self) - y; if dy < 0 then dy := 0 - dy;
			if dy > dx then dx := dy;
			if dx <= prec then exit;
			mx := GetX(self); my := GetY(self);
			dx := mx - x; if dx < 0 then dx := 0 - dx;
			dy := my - y; if dy < 0 then dy := 0 - dy;
			if dy > dx then dx := dy;
			if dx <= prec then exit;
			if ld = dx then begin
				ldc := ldc + 1;
				if ldc > 100 then begin addtosystemjournal( 'GotoXY: Cannot reach location!' ); exit; end;
			end
			else ld := dx;
			waitconnection(5000);
			if mx = x then begin
				if my = y then exit;
				// North
				if my > y then begin Raw_Move(0,runflag); continue; end;
				// South
				Raw_Move(4,runflag); continue;
			end;
			if mx < x then begin
				// Northeast
				if my > y then begin Raw_Move(1,runflag); continue; end;
				// East
				if my = y then begin Raw_Move(2,runflag); continue; end;
				// Southeast
				Raw_Move(3,runflag); continue;
			end;
			// Southwest
			if my < y then begin Raw_Move(5,runflag); continue; end;
			// West
			if my = y then begin Raw_Move(6,runflag); continue; end;
			// Nortwest
			Raw_Move(7,runflag); continue;
		end;
	end;
	function SkillControl : boolean;
	// Переключает какой скилл качать и перезаписывает в оружие.
	// Возвращает false если необходим выход из скрипта (все вкачано).
	var i : integer;
	begin
		waitconnection(3000);
		Result := true;
		for i := 0 to 2 do
		begin
			if GetSkillValue(MySkill[i].NamSkill) < MySkill[i].MaxValue then break;
		end;
		if GetSkillValue(MySkill[i].NamSkill) < MySkill[i].MaxValue then
		begin
			MyArm[0].typarm := MySkill[i].TypWeapon;
			CurSkill := MySkill[i].NamSkill;
		end
		else
		begin
			// Все три скилла по 100.0
			Result := false;
			exit;
		end;
	end;
	function EnemyHPControl : Double;
	begin
		Result := 100 * GetHP(EnemyWarrior) / GetMaxHP(EnemyWarrior);
	end;
Begin
	waitconnection(3000);
	SetGlobal('stealth',MyFlagWar,'0');
	EnemyWarrior := AutoFindEnemy;
	if EnemyWarrior = $00000000 then exit;
	if not FindEnvironment then exit;
	if not CreateSafePoints then exit;
	IniMyArm;
	if not SkillControl then exit;
	OldSkill := GetSkillValue(CurSkill);
	FullHealChar;
	CheckArm;
	CheckBandages;
	MyFlagWar := GetName(self) + 'War';
	EnemyFlagWar := GetName(EnemyWarrior) + 'War';
	SetGlobal('stealth',MyFlagWar,'1');
	waitconnection(3000);
	repeat
		wait(100);
	until (Life < MaxLife) OR (GetGlobal('stealth',EnemyFlagWar) = '1');
	// оба чара готовы к началу спарринга
	while not Dead do
	begin
		if not WarMode then SetWarMode(true);
		attack(EnemyWarrior);
		k := 0;
		repeat
			wait(100);
			k := k + 1;
			if (k = 50) and (count(Bint) > 0) and (Life < MaxLife) then
			// подхил чара во время боя
			begin
				waitconnection(3000);
				if TargetPresent then CancelTarget;
				if UseType(Bint,$FFFF) <> 0 then
				begin
					WaitForTarget(5000);
					If TargetPresent then TargetToObject(Self);
					k := 0;
				end;
			end;
			waitconnection(3000);
		until (Life <= (MaxLife - Delta)) OR (GetGlobal('stealth',EnemyFlagWar) = '0') OR (EnemyHPControl < 30.0);
		SetGlobal('stealth',MyFlagWar,'0');
		waitconnection(3000);
		GotoXY(SafeX,SafeY,0,false);
		SetWarMode(false);
		FullHealChar;
		if GetSkillValue(CurSkill) > OldSkill then
		begin
			AddToSystemJournal('Скилл ' + CurSkill + ' вырос. Теперь он равен ' + FloatToStr(GetSkillValue(CurSkill)));
			OldSkill := GetSkillValue(CurSkill);
			if not SkillControl then exit;
		end;
		CheckArm;
		waitconnection(3000);
		GotoXY(WarX,WarY,0,false);
		SetGlobal('stealth',MyFlagWar,'1');
		waitconnection(3000);
		repeat
			wait(100);
		until (Life < MaxLife) OR (GetGlobal('stealth',EnemyFlagWar) = '1');
	end;
End.
 очень заинтересовался этим клиентом,но вот  проблема с написанием и даже исправлением скриптов(даже на инже)
 очень заинтересовался этим клиентом,но вот  проблема с написанием и даже исправлением скриптов(даже на инже)  не мог  бы помочь этот  скриптик немного подправить?там немного , прото убрать корыто с водой чтобы бинты не мыли и чтоб  во время драчки анатомию юзали
 не мог  бы помочь этот  скриптик немного подправить?там немного , прото убрать корыто с водой чтобы бинты не мыли и чтоб  во время драчки анатомию юзали 



