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

Спарринг двух чаров на одном скрипте

Only working scripts
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Спарринг двух чаров на одном скрипте

Post by Edred »

Вот, все отладил. Чары друг друга не убивают :)

ВНИМАНИЕ: В этом скрипте нет подхилов чара! Для этого надо запустить параллельно данному скрипту скрипт на непрерывный подхил чара (каждому чару, естественно):
http://stealth.od.ua/forum/viewtopic.php?t=577

Code: Select all

Program SparringUP;
// Спарринг двух воинов. Пауза для подхилла если здоровье меньше 
// максимального минус заданная величина. Проверка сериала чара,
// скомандовавшего останов или рестарт боя (от приколистов).
// Добор бинтов с пола в радиусе двух клеток (бинты положить или
// между чарами, или у каждого за спиной.
// Один скрипт для обоих чаров. Скрипт сам разберется, кто первый, а
// кто второй :)
// Не забудьте обоим чарам в параллель запустить скрипт SparringHeal!
// Вам также потребуется любой чар в пределах видимости, для временного
// сброса флага атаки. Желательно, чтобы этот чар не стоял на соседней
// клетке, иначе ему достанется :)
//
// v.1.01b (c) Edred
//
// todo: ввести лечение спирит спиком, если закончились бинты

{$Include 'all.inc'}

const
Warrior1 = $0004D053;		// Первый чар
Warrior2 = $0004ACFB;		// Второй чар (порядок не важен)
Delta = 30;
// Чар, на которого сбрасывать временно атаку
FarAttack = $0005288D;		// 

var
War1Flag : boolean;			// true - готов к бою, false - нет
War2Flag : boolean;			// аналогично
CurWarrior : integer;		// какой чар использует скрипт (1 или 2)
EnemyWarrior : integer;		// соответственно - противник
ctime : TDateTime;

	procedure CheckWarrior;
		// Сверяет сериал чара с заданными и определяет, какой чар
		// (1 или 2) использует этот скрипт. Устанавливает соотв. флаг
		begin
			waitconnection(3000);
			if Self = Warrior1 then
			begin
				CurWarrior := 1;
				EnemyWarrior := 2;
				War1Flag := true;
			end
			else
			begin
				CurWarrior := 2;
				EnemyWarrior := 1;
				War2Flag := true;
			end;
		end;

	procedure AttackEnemy(var f:integer);
	begin
		if f = 1 then attack(Warrior1);
		if f = 2 then attack(Warrior2);
	end;

	function CheckPeaceFlag(var f:integer; var ctime:TDateTime):boolean;
	var i:integer;
	begin
		result := false;
		if f = 1 then
		begin
			i := InJournalBetweenTimes('Stop', ctime, Now);
			if (i<>-1) and (LineId = Warrior1) then result := true;
		end
		else begin
			i := InJournalBetweenTimes('Stop', ctime, Now);
			if (i<>-1) and (LineId = Warrior2) then result := true;
		end;
	end;

	function CheckWarFlag(var f:integer; var ctime:TDateTime):boolean;
	var i:integer;
	begin
		result := false;
		if f = 1 then
		begin
			i := InJournalBetweenTimes('Start', ctime, Now);
			if (i<>-1) and (LineId = Warrior1) then result := true;
		end
		else begin
			i := InJournalBetweenTimes('Start', ctime, Now);
			if (i<>-1) and (LineId = Warrior2) then result := true;
		end;
	end;

	procedure ChangeWarFlag(var f:integer);
	begin
		if f = 1 then
		begin
			// для первого чара
			if War1Flag then begin
				// отменим бой
				UOSay( 'Stop' ); War1Flag := false; SetWarMode(false); end
			else begin
				// готовы к бою
				UOSay( 'Start' ); War1Flag := true; attack(FarAttack);
			end;
		end
		else begin
			// для второго чара
			if War2Flag then begin
				// отменим бой
				UOSay( 'Stop' ); War2Flag := false; SetWarMode(false); end
			else begin
				// готовы к бою
				UOSay( 'Start' ); War2Flag := true; attack(FarAttack);
			end;
		end;
	end;

Begin
	CheckWarrior;
	while not Dead do
	begin
		if not WarMode then SetWarMode(true);
		ctime := Now;
		AttackEnemy(EnemyWarrior);
		addtosystemjournal('проверка 0')
		repeat
			wait(100);
			checksave;
		until CheckPeaceFlag(EnemyWarrior, ctime) or (Life <= (MaxLife - Delta));
		ChangeWarFlag(CurWarrior);
		// Иногда сразу не срабатывает сброс вара, пока сделаем так:
		wait(100)
		SetWarMode(false)
		wait(100)
		SetWarMode(false)
		repeat
			wait(100);
			checksave;
		until HP = MaxHP;
		ctime := Now;
		ChangeWarFlag(CurWarrior);
		repeat
			wait(100);
			checksave;
		until CheckWarFlag(EnemyWarrior, ctime) or (Life < MaxLife);
	end;
End.
Далее планирую добавить:
1. В подхилл - мытье бинтов
2. В спарринг - лечение спирит спиком и медитацией, если бинты кончились
3. В спарринг - оружие, армы, щиты. Добор по разрушению из контейнера (один на обоих чаров)
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Новая версия. Значительно упростил код по старым функциям, добавил кучу нового. Теперь подхил идет прямо в этом скрипте, отдельный запускать в параллель не надо.

Примечание: на версии 96 у вас не будет работать проверка сериала чара, скомандовавшего Start или Stop. Поэтому в скрипт надо после произнесения соответствующих фраз добавить команду ClearJournal;

Все остальное - в комментариях в начале скрипта.

Code: Select all

Program SparringUP;
// Спарринг двух воинов с автонадеванием на себя арма, взятием щитов
// и оружия, хилом с бинтов и мытьем бинтов в тазике. Все материалы
// берутся из сундука или мешка.
// Автопоиск партнера по спаррингу, вывод его имени в системный
// журнал для визуального контроля. Контейнеры и мойка бинтов
// ищутся вокруг чара по типу.
// Команды на останов и продолжения атаки. При получении соответствующего
// сообщения, скрипт проверит сериал чара, сказавшего команду и
// будет использовать только команды партнера по спаррингу (это
// от приколистов и для того, чтобы в одном доме можно было ставить
// несколько пар чаров на один скрипт).
// Если в сундуке кончатся бинты - скрипт выдаст сообщение и будет ждать,
// пока вы их не подложите на пол или в сундук. Если кончится оружие -
// чары будут драться на кулаках. Если нет армов и щитов - значит будут
// драться голые.
// Настройка скрипта: проверьте только типы, все остальное скрипт сделает
// сам.
// Вам также потребуется любой чар в пределах видимости, для временного
// сброса флага атаки. Желательно, чтобы этот чар не стоял на соседней
// клетке, иначе ему достанется :) Сериал этого чара необходимо ввести
// в скрипт.
//
// Вам нет необходимости делать копии этого скрипта для каждого чара!
// Один скрипт на всех чаров.
//
// 1.02 - вводим щиты, брать их
// 1.03 - автопоиск партнера по спаррингу в радиусе 1 клетки. Ищет как
//        мужиков, так и баб. Вывод в системный журнал имени найденного
//        противника для визуальной проверки игрока. Автоодевание армора:
//        chain туники, ног, шеи. Естественно, при необходимости добор из
//        сундука.
// 1.04 - Вводим подхил чаров в этот скрипт с мытьем бинтов. Стелс, как
//        оказалось, очень не любит параллельно запущенных скриптов.
//        Подхил идет во время боя и после останова до полного здоровья.
//        Мойка для бинтов ищется вокруг чаров по типу.
//
// v.1.04b (c) Edred
//
// todo: ввести лечение спирит спиком, если закончились бинты
//

{$Include 'all.inc'}

const
EnemyType1 = $0190;			// типы чаров разных полов
EnemyType2 = $0191;
// Чар, на которого сбрасывать временно атаку
FarAttack = $00042AB5;		// Servus
Delta = 30;					// Разница в здоровье с максимумом для останова
SundukType = $0E76;			// Тип контейнера с щитами и оружием
ShieldType1 = $1B74;		// Щит, тип 1 (Kite)
ShieldType2 = $1B75;		// Щит, тип 2 (Kite)
TunicType1 = $13BF;			// чайн туника, тип 1
TunicType2 = $13C4;			// чайн туника, тип 2
LeggsType1 = $13BE;			// чайн ноги, всего один тип
CoifType1 = $13C0;			// чайн шея, тип 1
CoifType2 = $13BB;			// чайн шея, тип 2
DaggerType = $0F51;			// Даггер
WaterType = $B42;			// тип тазика с водой
Bint=$0E21;					// Бинты
BlBint=$0E20;				// Кровавые бинты

var
Sunduk : cardinal;
WaterID : cardinal;
EnemyWarrior : cardinal;	// сериал противника
ctime : TDateTime;
stime : TDateTime;
WaterFlag : boolean;		// Мыть бинты или нет
i : integer;
k : integer;

	function OpenSunduk : Boolean;
		begin
			WaitConnection(3000);
			CheckSave;
			Sunduk := FindType(SundukType, Ground);
			if Sunduk = 0 then
			begin
				AddToSystemJournal('Warning: Сундук не найден!');
				Result := false;
			end
			else 
			begin
				Result := true;
				UseObject(Sunduk);
				wait(2000);
			end;
		end;

	procedure CheckWeapon;
		// Если сундук открыт, проверяем на слоях, есть ли оружие и щиты.
		// если чего-то нет - ищем в сундуке и надеваем подходящее.
		// если ничего нет - фиг с ним, кулаки тоже оружие :)
		// 1.03 - добавляем чайн тунику, ноги, шею.
		// 1.04 - добавляем проверку количества бинтов и их мытье
		begin
			waitconnection(3000);
			if OpenSunduk then
			begin
				// Проверим щит
				if (ObjAtLayer(LhandLayer) = 0) then
				// ни фига в руках нету
				begin
					// Переоткроем сундук, вдруг мы после дисконнекта
					if OpenSunduk then
					begin
						if (findtype(ShieldType1,Sunduk) = 0) then findtype(ShieldType2,Sunduk);
						if (FindCount > 0) then
						// нашли щит
						begin
							Equip(LhandLayer,finditem);
							wait(1000);
						end;
					end;
				end;
				// Проверим оружие
				if (ObjAtLayer(RhandLayer) = 0) then
				// ни фига в руках нету
				begin
					// Переоткроем сундук, вдруг мы после дисконнекта
					if OpenSunduk then
					begin
						findtype(DaggerType, Sunduk);
						if (FindCount > 0) then
						// нашли щит
						begin
							Equip(RhandLayer,finditem);
							wait(1000);
						end;
					end;
				end;
				// Проверим тунику
				if (ObjAtLayer(TorsoLayer) = 0) then
				// ни фига нету
				begin
					// Переоткроем сундук, вдруг мы после дисконнекта
					if OpenSunduk then
					begin
						if findtype(TunicType1, Sunduk) = 0 then findtype(TunicType2, Sunduk);
						if (FindCount > 0) then
						// нашли тунику
						begin
							Equip(TorsoLayer,finditem);
							wait(1000);
						end;
					end;
				end;
				// Проверим ноги
				if (ObjAtLayer(PantsLayer) = 0) then
				// ни фига нету
				begin
					// Переоткроем сундук, вдруг мы после дисконнекта
					if OpenSunduk then
					begin
						findtype(LeggsType1, Sunduk)
						if (FindCount > 0) then
						// нашли тунику
						begin
							Equip(PantsLayer,finditem);
							wait(1000);
						end;
					end;
				end;
				// Проверим шею
				if (ObjAtLayer(HatLayer) = 0) then
				// ни фига нету
				begin
					// Переоткроем сундук, вдруг мы после дисконнекта
					if OpenSunduk then
					begin
						if findtype(CoifType1, Sunduk) = 0 then findtype(CoifType2, Sunduk);
						if (FindCount > 0) then
						// нашли тунику
						begin
							Equip(HatLayer,finditem);
							wait(1000);
						end;
					end;
				end;
				// теперь разберемся с грязными бинтами
				if (Count(BlBint)>=0) and WaterFlag then
				begin
					repeat
						findtype(BlBint,backpack);
						if (FindCount > 0) then
						begin
							checksave;
							useobject(FindItem);
							waitfortarget(5000);
							if TargetPresent then TargetToObject(WaterID);
							wait(1000);
						end;
					until (FindCount=0);
				end;
				if not WaterFlag then
				begin
					FindType(BlBint, Backpack);
					while (FindCount > 0) do
					begin
						Drop(finditem,0,0,0,0);
						wait(1000);
						FindType(BlBint, Backpack);
					end;
				end;
				if (Count(Bint) < 20) then
				begin
					FindType(Bint, Sunduk);
					if (FindCount > 0) then
					begin
						Grab(finditem,20);
						wait(1000);
					end
					else
					begin
						addtosystemjournal('Не нашел бинтов! Подложите в сундук!');
						repeat
							wait(500)
							FindType(Bint, Ground);
						until (FindCount > 0);
						Grab(finditem,20);
						wait(1000);
					end;
				end;
			end;
		end;

	procedure FullHealChar;
		begin
			// лечение чара до максимума
			while (HP < MaxHP) do
			begin
				if count(Bint) = 0 then
				begin
					if OpenSunduk then
					begin
						FindType(Bint, Sunduk);
						if (FindCount > 0) then
						begin
							Grab(finditem,20);
							wait(1000);
						end
						else
						begin
							addtosystemjournal('Не нашел бинтов! Подложите в сундук!');
							repeat
								wait(500)
								FindType(Bint, Sunduk);
							until (FindCount > 0);
							Grab(finditem,20);
							wait(1000);
						end;
					end
					else
					begin
						addtosystemjournal('Не нашел бинтов! Подложите на пол!');
						repeat
							wait(500)
							FindType(Bint, ground);
						until (FindCount > 0);
						Grab(finditem,20);
						wait(1000);
					end;
				end;
				FindType(Bint, Backpack);
				if TargetPresent then CancelTarget;
				stime := Now;
				UseObject(FindItem);
				WaitForTarget(5000);
				If TargetPresent then TargetToObject(Self);
				k := 0;
				repeat
					wait(100);
					k := k + 1;
				until (InJournalBetweenTimes('You put the bloody bandage|failed.', stime, Now)<>-1) or (k > 300);
			end;
		end;


Begin
	FindDistance:=1;
	waitconnection(3000);
	// ищем врагов вокруг
	if FindType(EnemyType1, Ground) = 0 then FindType(EnemyType2, Ground);
	EnemyWarrior := finditem;
	if EnemyWarrior = 0 then
	begin
		// не нашли врагов :(
		AddToSystemJournal('Error: Enemy not found');
	    Exit;
    end
	else
	begin
		// Ага! Вот он, гадина!
		ClickOnObject(EnemyWarrior);
		wait(2000)
		checksave;
		// Дадим сообщение о том, кого будем бить!
		AddToSystemJournal('Enemy found: ' + GetName(EnemyWarrior));
	end;
	// Откроем сундук и вооружимся
	CheckWeapon;
	// Разберемся с водой для мытья бинтов
	WaterFlag := true;
	WaterID := FindType(WaterType, Ground);
	if WaterID = 0 then WaterFlag := false;
	// Теперь скажем старт и будем ждать ответа или начала атаки
	attack(FarAttack);
	UOSay( 'Start' );
	ctime := Now;
	repeat
		wait(100);
		i := InJournalBetweenTimes('Start', ctime, Now);
	until (i<>-1) and (LineId = EnemyWarrior) or (Life < MaxLife);
	// можно входить в цикл
	while not Dead do
	begin
		if not WarMode then SetWarMode(true);
		attack(EnemyWarrior);
		ctime := Now;
		k := 0;
		repeat
			wait(100);
			k := k + 1;
			if (k = 50) and (count(Bint) > 0) and (Life < MaxLife) then
			// подхил чара во время боя
			begin
				FindType(Bint, Backpack);
				if TargetPresent then CancelTarget;
				UseObject(FindItem);
				WaitForTarget(5000);
				If TargetPresent then TargetToObject(Self);
				k := 0;
			end;
			i := InJournalBetweenTimes('Stop', ctime, Now);
		until (i<>-1) and (LineId = EnemyWarrior) or (Life <= (MaxLife - Delta));
		UOSay( 'Stop' );
		SetWarMode(false);
		// Иногда сразу не срабатывает сброс вара, пока сделаем так:
		wait(100)
		SetWarMode(false)
		wait(100)
		SetWarMode(false)
		FullHealChar;
		CheckWeapon;
		ctime := Now;
		UOSay( 'Start' );
		attack(FarAttack);
		repeat
			wait(100);
			i := InJournalBetweenTimes('Start', ctime, Now);
		until (i<>-1) and (LineId = EnemyWarrior) or (Life < MaxLife);
	end;
End.
Dr.Assassin
Neophyte
Neophyte
Posts: 14
Joined: 14.03.2005 12:46
Location: Ukraine
Contact:

Post by Dr.Assassin »

Edred, помню ты писал - что нужно проверять
ID чара который говорит START

Но я решил эту проблемку иначе, я просто проверяю
WarMode того чара - который думаю атачить:

Code: Select all

 if   (IsWarMode(enemy[1]))
 and(not isDead(enemy[1]))
 and(GetDistance(enemy[1])<2)
 then begin 
            attack(enemy[1]);
            ataked:=true; 
        end
тоесть, если чар плохо себя чуствует - то он просто
сбрасывает WarMode - и его атачить больше не будут
(естественно нужно ещё позаботиться об этом,
но это уже не принципиальный вопрос)
May The Force Be With You!
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Dr.Assassin wrote:Edred, помню ты писал - что нужно проверять
ID чара который говорит START
Дык ты посмотри на мой скрипт внимательно - там сериал проверяется. То есть кто сказал старт, кто сказал стоп. Но теперь надо переделать скрипт на глобальные переменные, так проще и меньше флуда.
Dr.Assassin
Neophyte
Neophyte
Posts: 14
Joined: 14.03.2005 12:46
Location: Ukraine
Contact:

Post by Dr.Assassin »

Дык ты посмотри на мой скрипт внимательно - там сериал проверяется.
я не об этом!
я о том что незачем вообще использовать этот "Старт" :D

А глобальные переменные, ты прав - это несомненно круче!! :wink:
May The Force Be With You!
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Dr.Assassin wrote:я не об этом!
я о том что незачем вообще использовать этот "Старт" :D
Использовать нужно. УО по-дурацки устроена - ты отменяешь вар на обоих чарах, но разница в срабатывании может быть в 100 мс... А это много. За это время чар, уже отключивший вар, может словить плюху от чара, не успевшего это еще сделать и автоматически войти в вар и ответить. Ответить чару, который уже успел сбросить вар... Дальше по кругу.
hotel_zadat_odin_vopros
Posts: 5
Joined: 05.11.2006 7:46

любимые актерские пары

Post by hotel_zadat_odin_vopros »

Хвала Великим Починильщикам а что было-то если не секрет? Наука о контактах
Last edited by hotel_zadat_odin_vopros on 26.12.2009 23:24, edited 2 times in total.
CFA
Developer
Developer
Posts: 492
Joined: 20.04.2006 6:03
Contact:

Post by CFA »

hotel_zadat_odin_vopros wrote:у меня при спарринге баба vs мужик , баба нашла мужика, а мужик нашел сам себя :lol: решилось это изменением приоритета пола в поиске врага, но тогда мужик находит бабу, а баба находит себя, тоже косяк, пришлось разбить на два скрипта, для баб и для мужиков
проще перед поиском было поставить ignore(self)
Macks
Apprentice
Apprentice
Posts: 250
Joined: 27.02.2006 22:23
Location: АоП - Age Of Power

Post by Macks »

Edred wrote:
Dr.Assassin wrote:я не об этом!
я о том что незачем вообще использовать этот "Старт" :D
Использовать нужно. УО по-дурацки устроена - ты отменяешь вар на обоих чарах, но разница в срабатывании может быть в 100 мс... А это много. За это время чар, уже отключивший вар, может словить плюху от чара, не успевшего это еще сделать и автоматически войти в вар и ответить. Ответить чару, который уже успел сбросить вар... Дальше по кругу.
Нужно отходить на шаг в сторону противоположную от противника, ходилка же есть...
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Когда этот скрипт писался, хождения в стелсе еще не было. У меня есть в планах его усовершенствовать. Когда-нибудь.
Macks
Apprentice
Apprentice
Posts: 250
Joined: 27.02.2006 22:23
Location: АоП - Age Of Power

Post by Macks »

Edred wrote:Когда этот скрипт писался, хождения в стелсе еще не было. У меня есть в планах его усовершенствовать. Когда-нибудь.
Просим, просим, маэстро.
Macks
Apprentice
Apprentice
Posts: 250
Joined: 27.02.2006 22:23
Location: АоП - Age Of Power

Post by Macks »

После реконекта стоят втыкают, флаг атаки не сохраняется :(
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Новая версия. Полный автомат. Написана с учетом всех возможностей последней версии (1.00 RC1). Тестим.

Вот картинка с примером как лучше ставить чаров и раскладывать шмотки для них... ;)

Image

Code: Select all

Program SparringUP;
{
 Новая версия спарринга двух воинов. Делает:
 1. автоопределение партнера по спаррингу (имя выводится в системный
    журнал при запуске скрипта для визуального контроля)
 2. автонахождение мешка под ногами с армами, оружием, бинтами
 3. автонахождение корыта с водой для мытья бинтов рядом с чаром
 4. автоопределение направления, в котором стоит партнер по спаррингу
    и, соответственно, вычисление точки для отхода (противоположное
    направление, расстояние в 1 клетку)
 5. автоопределение видов арма и на какие слои одевать, автоматическое
    одевание арма, автоматическая проверка арма, 
    одетого на чара и одевание из мешка по мере разрушения.
 6. автоматическое взятие в руки оружия, типы оружия занесены в массив
    (по скиллам, порядок прокачки скиллов задается в скрипте)
 7. Автоматическое переключение на прокачку следующего боевого после того,
    как текущий вырастет до заданной величины (по умолчанию - 100.0)
 8. Автоматический подхил чара во время сражения, переключение режимов
    war/peace через глобальные переменные, отход чаров назад в случае
    критического уменьшения здоровья, команды на начало/останов боя через
    глобальные переменные, автодобор бинтов и мытье их в корыте.
 9. В случае отсутствия какого-либо ресурса скрипт приостанавливает свое действие,
    отведя чара назад на один шаг (для безопасности), выдает в системный журнал
    соответствующее сообщение и ожидает пока вы не добавите в его мешок
    необходимые ресурсы.
 10.Контроль за реконнектом, при необходимости переоткрытие мешка с ресурсами.
 11.v.2.01 - дополнительный контроль. Теперь чары контролируют дополнительно
    здоровье противника, если оно меньше 30% - отход на безопасные позиции.

 Настройка скрипта: проверьте только типы, все остальное скрипт сделает
 сам. Не забудьте правильно заполнить массивы в функции IniMyArm - вам надо
 изменять только типы на соответствующих слоях. Слои перечислены все, если
 на каком-то слое ничего не надевается - там стоит $0000. Второй массив содержит
 названия скиллов, макс размеры, типы оружия (скрипт сам будет перезаписывать нужную
 строку в первом массиве по мере необходимости). Скиллы идут в том порядке, в каком
 вы хотите их контролировать и качать.

 Оружие в соответствии со скиллами находится в отдельном массиве. Двуручное
 оружие не предусмотрено, все оружие надевается в правую руку.

 Вам нет необходимости делать копии этого скрипта для каждого чара!
 Один скрипт на всех чаров.
}

// v.2.01b (c) Edred

{$Include 'all.inc'}

const
EnemyType1 = $0190;			// типы чаров разных полов
EnemyType2 = $0191;
MyWait = 500;				// пауза на перемещение и одевание
SundukType = $0E76;			// Тип контейнера с армами, оружием, бинтами
WaterType = $B42;			// тип тазика с водой
Delta = 60;					// Разница в здоровье с максимумом для останова
Bint=$0E21;					// Бинты
BlBint=$0E20;				// Кровавые бинты
HowMinBandages = 20;		// Если меньше - вымыть и, если надо, добрать
HowGetBandages = 100;		// и взять вот столько

type ArmLayers = Record
	typlayer : Byte;
	typarm : Cardinal;
	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, 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[1].typlayer := LhandLayer;
		MyArm[1].typarm := $1B76;
		MyArm[2].typlayer := ShoesLayer;
		MyArm[2].typarm := $0000;
		MyArm[3].typlayer := PantsLayer;
		MyArm[3].typarm := $1411;
		MyArm[4].typlayer := ShirtLayer;
		MyArm[4].typarm := $0000;
		MyArm[5].typlayer := HatLayer;
		MyArm[5].typarm := $1412;
		MyArm[6].typlayer := GlovesLayer;
		MyArm[6].typarm := $1414;
		MyArm[7].typlayer := RingLayer;
		MyArm[7].typarm := $0000;
		MyArm[8].typlayer := NeckLayer;
		MyArm[8].typarm := $1413;
		MyArm[9].typlayer := WaistLayer;
		MyArm[9].typarm := $0000;
		MyArm[10].typlayer := TorsoLayer;
		MyArm[10].typarm := $1415;
		MyArm[11].typlayer := BraceLayer;
		MyArm[11].typarm := $0000;
		MyArm[12].typlayer := TorsoHLayer;
		MyArm[12].typarm := $0000;
		MyArm[13].typlayer := EarLayer;
		MyArm[13].typarm := $0000;
		MyArm[14].typlayer := BraceLayer;
		MyArm[14].typarm := $0000;
		MyArm[15].typlayer := ArmsLayer;
		MyArm[15].typarm := $1410;
		MyArm[16].typlayer := CloakLayer;
		MyArm[16].typarm := $0000;
		MyArm[17].typlayer := RobeLayer;
		MyArm[17].typarm := $0000;
		MyArm[18].typlayer := EggsLayer;
		MyArm[18].typarm := $0000;
		MyArm[19].typlayer := LegsLayer;
		MyArm[19].typarm := $0000;
		// Скиллы, макс величины, оружие (для перезаписи в пред. массиве
		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 - просто открываем наш мешок (в переменной CurBag)
	// если f - false - проверяем, был ли реконнект чара после последнего
	// открывания контейнера, если был - переоткрываем контейнер и записываем
	// новое значение в переменную LastContOpen, если не был - ничего не делаем
	begin
		waitconnection(3000);
		if (f = true) or (LastContOpen < ConnectedTime) then
		begin
			UseObject(CurBag);
			wait(MyWait * 2);
			checksave;
			LastContOpen := Now;
			addtosystemjournal('Контейнер открыт в ' + DateTimeToStr(Now));
		end;
	end;

	procedure CheckArm;
	// проверка в цикле есть ли на соответствующих слоях нужные типы, если
	// чего-то нет - возьмем это из мешка и оденем на этот слой.
	VAR i : integer;
		tmpid : cardinal;
	begin
		for i := 0 to 19 do
		begin
			if MyArm[i].typarm = $0000 then continue;
			if GetType(ObjAtLayer(MyArm[i].typlayer)) = MyArm[i].typarm then continue;
			// На соответствующем слое либо ничего не надето, либо одето что-то другое
			if ObjAtLayer(MyArm[i].typlayer) <> 0 then
			begin
				while not UnEquip(MyArm[i].typlayer) do wait(500);
			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 клетки от чара)
	// Возвращает false если что-то не найдено.
	begin
		// мешок с добром
		Result := False;
		WaitConnection(3000);
		Finddistance := 1;
		if FindType(SundukType, Ground) = 0 then
		begin
			AddToSystemJournal('Error: Сундук или мешок не найден!');
			exit;
		end;
		CurBag := 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);
		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
		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
	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
				if TargetPresent then CancelTarget;
				if UseType(Bint,$FFFF) <> 0 then
				begin
					WaitForTarget(5000);
					If TargetPresent then TargetToObject(Self);
					k := 0;
				end;
			end;
		until (Life <= (MaxLife - Delta)) OR (GetGlobal('stealth',EnemyFlagWar) = '0') OR (EnemyHPControl < 30.0);
		SetGlobal('stealth',MyFlagWar,'0');
		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;
		GotoXY(WarX,WarY,0,false);
		SetGlobal('stealth',MyFlagWar,'1');
		waitconnection(3000);
		repeat
			wait(100);
		until (Life < MaxLife) OR (GetGlobal('stealth',EnemyFlagWar) = '1');
	end;
End.
Destruction
Neophyte
Neophyte
Posts: 17
Joined: 03.09.2006 11:05
Contact:

Post by Destruction »

Как насчёт поставить в спарринг 3-4 чара, чтобы например кому-то по-быстрому вкачать парринг -)

Пример такого - мой спарринг на форуме йоко, стелс ещё не выучил, как разберусь - обязательно сам напишу все скрипты -)

Это просто, идея на будущее -)
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

На том шарде, на котором я счас играю, в этом просто нет необходимости. Парринг и тактика вкачиваются быстро параллельно с парой боевых.
Post Reply