Перейти к содержанию

Скрипт для добычи руды (Mining script)

Материал из Wiki Legnes

Скрипт для Legnes/Orion Assist. Вариант с возвратом (Recall) по руне в банке. Отстреливает "слабых" стражей (Ore Guardian) из лука с примитивным отбеганием, использует магию Рассеивание (Dispel) на призванных стражем существ.

Автор скрипта: Hotride

// В ToolsBag должны лежать расходники:
// Реги на реколл и диспел, свитки диспела, бинты, стрелы для лука, кирки
// Руны в пещеры должны лежать в банке

// Использовать фильтр руды, 0 - не использовать, 1 - использовать
var UseOreNameFilter = 1;

// Названия руды для игнорирования жилы (не продолжать копать)
var IgnoreOreNames = 'Iron ore|Железная руда';

// Использовать хайд, 0 - не использовать, 1 - использовать
var UseHidding = 0;

// Выгружать руду с переплавкой, 0 - не плавить, 1 - плавить
var UnloadWithSmelt = 1;

// Звук при появлении элементаля
var SoundForGuard = 'C:/a.wav';

// Количество повтора звука
var SoundRepeatCount = 5;

// Серийник сундука, в котором находятся мешки (может быть пустым)
var TopChest = '0x401EFC28';

// Серийник мешка с инструментами, регами и едой
var ToolsBag = '0x402D405A';

// Серийник мешка для руды
var OresBag = '0x401C01A2';

// Типы еды
var FoodType = '0x09B7|0x09F2|0x097B';

// Серийник оружия, который использовать при появлении гварда
var UseWeaponForGuard = 'guard_weapon';

// Серийник руны домой
var RuneHome = '0x40325C4C';

// Серийники рун в пещеры
var RunesToCave =
[
	// Trinsic secret cave
	'0x40299CC3',
	// Trinsic cave
	'0x40299CBB',
	// Hytloth 1
	'0x402D1461',
	// Hytloth 2
	'0x402D145A',
	// Cave 3
	'0x40299CB6'
];

// Точки обкопки в пещерах
var CaveSpots =
[
	// Trinsic secret cave
	[
		[ 1662, 2935 ],
		[ 1661, 2934 ],
		[ 1659, 2932 ],
		[ 1655, 2932 ],
		[ 1655, 2927 ],
		[ 1653, 2926 ],
		[ 1653, 2922 ],
		[ 1652, 2917 ],
		[ 1650, 2915 ],
		[ 1649, 2912 ],
		[ 1648, 2908 ],
		[ 1647, 2903 ],
		[ 1647, 2898 ],
		[ 1648, 2894 ],
	],
	// Trinsic cave
	[
		[ 1490, 2852 ],
		[ 1494, 2852 ],
		[ 1491, 2847 ],
		[ 1495, 2848 ],
		[ 1495, 2843 ],
		[ 1494, 2839 ],
		[ 1495, 2834 ],
		[ 1491, 2834 ],
		[ 1489, 2837 ],
		[ 1484, 2837 ],
		[ 1481, 2840 ],
		[ 1478, 2842 ],
		[ 1488, 2834 ],
		[ 1492, 2829 ],
		[ 1488, 2825 ],
		[ 1489, 2821 ],
		[ 1492, 2824 ],
		[ 1496, 2828 ],
		[ 1498, 2830 ],
	],
	// Hytloth 1
	[
		[ 4605, 3821 ],
		[ 4602, 3819 ],
		[ 4600, 3815 ],
		[ 4598, 3813 ],
		[ 4600, 3811 ],
		[ 4604, 3813 ],
		[ 4605, 3816 ],
		[ 4609, 3817 ],
		[ 4612, 3817 ],
		[ 4610, 3820 ]
	],
	// Hytloth 2
	[
		[ 4552, 3172 ],
		[ 4551, 3175 ],
		[ 4548, 3175 ],
		[ 4547, 3172 ],
		[ 4547, 3167 ],
		[ 4551, 3167 ]
	],
	// Cave 3
	[
		[ 996, 1600 ],
		[ 998, 1600 ],
		[ 996, 1595 ],
		[ 996, 1590 ],
		[ 991, 1593 ],
		[ 989, 1589 ],
		[ 992, 1588 ],
		[ 990, 1584 ],
		[ 995, 1585 ],
		[ 994, 1580 ],
		[ 998, 1581 ],
		[ 996, 1576 ],
		[ 1000, 1576 ],
		[ 1003, 1579 ],
		[ 1003, 1584 ],
		[ 1000, 1586 ],
		[ 1004, 1589 ],
		[ 1001, 1591 ],
		[ 1001, 1596 ],
		[ 1005, 1594 ],
		[ 1008, 1595 ],
		[ 1010, 1592 ],
		[ 1008, 1589 ],
		[ 1007, 1586 ]
	]
];

// Не трогать!!!
var FakeId = 0;

function UsePickaxe(_private)
{
	if (!Orion.UseType('0x0E85', 'any', self, false))
	{
		if (!Orion.UseType('0x0E85'))
		{
			Orion.Print('0x0021', 'Your tool is gone!');
			return false;
		}
	}

	return true;
}

function WalkHangChecker(_private)
{
	var x = Player.X();
	var y = Player.Y();
	var count = 0;

	while (true)
	{
		if (x == Player.X() && y == Player.Y())
			count++;
		else
			count = 0;

		if (count >= 15)
		{
			Orion.StopWalking();
			count = 0;
		}

		x = Player.X();
		y = Player.Y();

		Orion.Wait(1000);
	}
}

function WalkToWrapper(x, y, distance, run)
{
	Orion.Exec('WalkHangChecker');
	Orion.Wait(20);
	// Потому что на пути следования могут быть динамические препятствия
	for (var i = 0; i < 3; i++)
	{
		if (Orion.WalkTo(x, y, 0, distance, 255, run))
		{
			Orion.Terminate('WalkHangChecker');
			Orion.Wait(20);
			return true;
			}
	}

	Orion.Terminate('WalkHangChecker');
	Orion.Wait(20);
	return false;
}

function RecallTo(rune)
{
	var x = Player.X();
	var y = Player.Y();
	var successCount = 0;

	while (x == Player.X() && y == Player.Y() && successCount < 5)
	{
		Orion.WarMode(0);
		Orion.Wait(100);
		Orion.ClearJournal();
		var timeout = Orion.Now() + 10000;
		var mr = Orion.Count('mr');
		Orion.Cast('32', rune);

		while (mr == Orion.Count('mr') && timeout > Orion.Now())
			Orion.Wait(100);

		if (Orion.InJournal('The spell fizzles', 'my|sys') == null)
			successCount++;

		var msgUses = Orion.InJournal('uses left', 'my|sys');
	
		if (msgUses != null)
		{
			for (var i = 0; i < 10; i++)
			{
				if (Orion.Contains(msgUses.Text(), 'has ' + i + ' uses left'))
				{
					MarkRune(rune);
					break;
				}
			}

			break;
		}
	}
	
	if (Player.Mana('%') < 99)
	{
		Orion.WarMode(false);
		Orion.Exec('AutoMeditation', true);
	}
}

function MarkRune(rune)
{
	while (true)
	{
		if (Player.Mana('%') < 40)
		{
			while (Player.Mana('%') < 100)
			{
				Orion.UseSkill('46');
				Orion.Wait(500);
			}
		}

		Orion.WarMode(0);
		Orion.Wait(100);
		Orion.ClearJournal();
		var timeout = Orion.Now() + 10000;
		var mr = Orion.Count('mr');
		Orion.Cast('45', rune);

		while (mr == Orion.Count('mr') && timeout > Orion.Now())
			Orion.Wait(100);

		if (Orion.InJournal('The spell fizzles', 'my|sys') == null)
			break;
	}
}

function Restock(graphic, count)
{
	var val = Orion.Count(graphic);
	
	while (val < count)
	{
		if (!Orion.MoveItemType(graphic, 'any', ToolsBag, count - val))
			break;

		Orion.Wait(400);
		val = Orion.Count(graphic);
	}
}

function CheckOverweight(forced, runeCave)
{
	if (forced || Player.Weight('%') >= 97)
	{
		var oldX = Player.X();
		var oldY = Player.Y();

		if (!forced)
			Orion.Print('0x0021', 'Weight limit reached!!!');

		RecallTo(RuneHome);

		if (UnloadWithSmelt)
		{
			while (Orion.UseType('0x19B7|0x19BA|0x19B8|0x19B9'))
				Orion.Wait(100);
		}

		if (TopChest != '')
			Orion.UseObject(TopChest);

		Orion.UseObject(ToolsBag);
		Orion.UseObject(OresBag);
		Orion.Wait(200);

		UnloadIngots();
		UnloadOres();

		// Bloody bandages
		if (Orion.MoveItemType('0x0E20', '0', backpack, 0, ToolsBag))
			Orion.Wait(400);

		if (Orion.Count(FoodType, '0') > 0 || Orion.MoveItemType(FoodType, '0', ToolsBag, 1))
		{
			Orion.UseType(FoodType, '0');
			Orion.Wait(100);
		}

		Restock('0x0E85', 4); // Pickaxe
		Restock('0x0F3F', 100); // Arrows
		Restock('0x1F55', 20); // Dispel scrolls
		//Restock('0x1F62', 10); // Mass dispel scrolls
		Restock('bandage', 100);
		Restock('mr', 50);
		Restock('bp', 20);
		Restock('bm', 20);
		Restock('ga', 30);
		Restock('sa', 30);

		if (Orion.Count('0x0E85') == 0)
		{
			Orion.Print('0x0021', 'No pickaxes!!!');
			Orion.PauseScript();
		}
		else if (Orion.Count('0x0F3F') < 30)
		{
			Orion.Print('0x0021', 'No arrows!!!');
			Orion.PauseScript();
		}
		else if (Orion.Count('mr') < 5 || Orion.Count('bp') < 5 || Orion.Count('bm') < 5)
		{
			Orion.Print('0x0021', 'No reagents to recalls!!!');
			Orion.PauseScript();
		}

		if (runeCave != '')
			RecallTo(runeCave);

		if (!forced)
			WalkToWrapper(oldX, oldY, 0,  (UseHidding == 0 || !Player.Hidden()));
	}
}

function PlayGuardAlarm(_private)
{
	for (var i = 0; i < SoundRepeatCount; i++)
	{
		Orion.PlayWav(SoundForGuard);
		Orion.Wait(1000);
	}
}

function DispelSummons(guard)
{
	var summon = null;

	if (guard != null && guard.Color() == '0x0000')
		summon = guard;
	else
	{
		var summons = Orion.FindTypeEx('0x000E|0x000F|0x0009|0x023E', '0', ground, 'mobile|near', 10);

		if (summons.length > 0)
			summon = summons[0];
	}

	if (summon != null)
	{
		while (summon.Exists() && Player.Hits('%') >= 50 && Player.Mana() >= 20)
		{
			var timeout = Orion.Now() + 6000;
			var type = '0x1F55';
			var count = Orion.Count(type);

			if (count > 0)
			{
				Orion.WaitTargetObject(summon.Serial());
				Orion.UseType(type);
			}
			else
			{
				type = 'mr';
				count = Orion.Count(type);

				if (count > 0 && Orion.Count('ga') > 0 && Orion.Count('sa') > 0)
					Orion.Cast('41', summon.Serial());
				else
					return false;
			}

			while (count == Orion.Count(type) && timeout > Orion.Now())
				Orion.Wait(100);

			Orion.Wait(100);
		}

		return !summon.Exists();
	}

	return true;
}

function GetDirectionToFlee(target, mirrored, inversedXY)
{
	var targetX = target.X();
	var targetY = target.Y();
	var x = Player.X();
	var y = Player.Y();

	if (mirrored)
	{
		targetX = Player.X();
		targetY = Player.Y();
		x = target.X();
		y = target.Y();
	}

	if (inversedXY)
	{
		var temp = targetX;
		targetX = targetY;
		targetY = temp;

		temp = x;
		x = y;
		y = temp;
	}

	if (x == targetX)
	{
		if (y < targetY)
			return 0;
		else //if (y >= targetY)
			return 4;
	}
	else if (y == targetY)
	{
		if (x < targetX)
			return 6;
		else //if (x > targetX)
			return 2;
	}
	else
	{
		if (x > targetX)
		{
			if (y < targetY)
				return 1;
			else //if (y > targetY)
				return 3;
		}
		else //if (x < targetX)
		{
			if (y > targetY)
				return 5;
			else //if (y < targetY)
				return 7;
		}
	}

	return 0;
}

function Flee(target, direction, distance)
{
	switch (direction)
	{
		case 0:
			return Orion.WalkTo(target.X(), target.Y() - distance, 0, 0, 255, true);
		case 1:
			return Orion.WalkTo(target.X() + distance, target.Y() - distance, 0, 0, 255, true);
		case 2:
			return Orion.WalkTo(target.X() + distance, target.Y(), 0, 0, 255, true);
		case 3:
			return Orion.WalkTo(target.X() + distance, target.Y() + distance, 0, 0, 255, true);
		case 4:
			return Orion.WalkTo(target.X(), target.Y() + distance, 0, 0, 255, true);
		case 5:
			return Orion.WalkTo(target.X() - distance, target.Y() + distance, 0, 0, 255, true);
		case 6:
			return Orion.WalkTo(target.X() - distance, target.Y(), 0, 0, 255, true);
		case 7:
			return Orion.WalkTo(target.X() - distance, target.Y() - distance, 0, 0, 255, true);
		default:
			break;
	}

	return false;
}

function CheckGuards(_private)
{
	var guards = Orion.FindTypeEx('0x000E', 'any', ground, 'mobile|near', 10);

	if (guards.length > 0)
	{
		var oldX = Player.X();
		var oldY = Player.Y();

		if (UseWeaponForGuard != '')
			Orion.UseObject(UseWeaponForGuard);

		var guard = guards[0];

		if (Orion.Contains('0x07D1|0x0253|0x052D|0x0455|0x0486|0x0487', guard.Color()))
		{
			Orion.Exec('PlayGuardAlarm');

			if (!Player.Hidden())
			{
				Orion.WarMode(false);
				Orion.Wait(100);
				Orion.UseSkill('21');
			}

			Orion.PauseScript();
		}

		Orion.WarMode(true);
		Orion.Ignore(guard.Serial());

		while (guard.Exists() && Player.Hits('%') >= 50)
		{
			if (guard.Distance() > 6)
			{
				Orion.WalkTo(guard.X(), guard.Y(), 0, 4, 255, true);
			}
			else
			{
				var distance = 4;

				if (guard.Distance() < distance)
				{
					var direction = GetDirectionToFlee(guard, false, false);

					if (!Flee(guard, direction, distance))
					{
						direction = GetDirectionToFlee(guard, false, true);

						if (!Flee(guard, direction, distance))
						{
							direction = GetDirectionToFlee(guard, true, true);

							if (!Flee(guard, direction, distance))
							{
								direction = GetDirectionToFlee(guard, true, false);
								Flee(guard, direction, distance);
							}
						}
					}
				}
			}

			Orion.Attack(guard.Serial());
			Orion.Wait(500);
			
			if (!DispelSummons(guard))
				break;
		}

		if (guard.Exists())
		{
			Orion.Exec('PlayGuardAlarm');
			Orion.PauseScript();
		}
		else
		{
			DispelSummons(null);

			// Blade spirits
			while (Player.Hits('%') >= 50)
			{
				var summons = Orion.FindTypeEx('0x023E', 'any', ground, 'mobile|near', 10);

				if (summons.length == 0)
					break;

				guard = summons[0];
				Orion.Ignore(guard.Serial());

				while (guard.Exists() && Player.Hits('%') >= 50)
				{
					Orion.Attack(guard.Serial());
					Orion.Wait(500);
				}
			}
		}

		if (Player.Mana('%') < 99)
		{
			Orion.WarMode(false);
			Orion.Exec('AutoMeditation', true);
		}

		var corpses = Orion.FindTypeEx('0x2006', 'any', ground, '', 10);

		if (corpses.length > 0)
		{
			for (var c = 0; c < corpses.length; c++)
			{
				var corpse = corpses[c];
				WalkToWrapper(corpse.X(), corpse.Y(), 1, true);
				Orion.Wait(1000);
				Orion.UseObject(corpse.Serial());
				Orion.Ignore(corpse.Serial());
				Orion.Wait(2500);
			}
		}
		else
		{
			Orion.Print('0x0021', 'Corpse not found!');
			Orion.Exec('PlayGuardAlarm');
			Orion.PauseScript();
		}

		Orion.WarMode(false);
		WalkToWrapper(oldX, oldY, 0,  (UseHidding == 0 || !Player.Hidden()));
	}
}

function AutoMeditation(_private)
{
	while (Player.Hits('%') > 50 && Player.Mana('%') < 99)
	{
		Orion.UseSkill('46');
		Orion.Wait(500);
	}
}

function MiningDig(runeCave)
{
	var text = 'в свой рюкзак|in your pack|Вы расшатываете несколько камней, но не можете найти|You loosen some rocks but fail to find|Это слишком далеко|That is too far away|Цель находится вне прямой видимости|Target is not in line of sight|Здесь нет руды, которую можно было бы добывать|There is no ore here to mine';

	for (var x = -2; x <= 2; x++)
	{
		for (var y = -2; y <= 2; y++)
		{
			var tryingCount = 0;

			while (true)
			{
				if (Player.Hits('%') < 50)
				{
					Orion.Exec('PlayGuardAlarm');
					Orion.PauseScript();
				}

				CheckGuards(0);
				DispelSummons(null);

				var hits = Player.Hits('%');
				var needHeal = (hits > 50 && hits < 99 &&  Orion.Count('bandage') > 0);

				if (needHeal)
				{
					Orion.PauseScript('AutoMeditation');

					while (needHeal)
					{
						Orion.BandageSelf();
						Orion.Wait(2000);
						hits = Player.Hits('%');
						needHeal = (hits > 50 && hits < 99 &&  Orion.Count('bandage') > 0);
					}

					Orion.ResumeScript('AutoMeditation');
				}

				while (Orion.ScriptRunning('AutoMeditation'))
					Orion.Wait(500);

				while (UseHidding && !Player.Hidden())
				{
					Orion.WarMode(false);
					Orion.Wait(100);
					Orion.UseSkill('21');
					Orion.WaitJournal('Вы хорошо спрятались|You have hidden yourself well|Кажется, ты не можешь здесь спрятаться|t seem to hide here', Orion.Now(), Orion.Now() + 3000);
				}

				CheckOverweight(false, runeCave);

				if (!Orion.ValidateTargetTileRelative('mine', x, y, 0))
					break;

				var now = Orion.Now();
				Orion.WaitTargetTileRelative('mine', x, y, 0);

				if (!UsePickaxe(0))
				{
					CheckOverweight(true, runeCave);

					Orion.WaitTargetTileRelative('mine', x, y, 0);
					UsePickaxe(0);
				}

				var msg = Orion.WaitJournal(text, now, now + 5000, 'my|sys');
				
				if (msg != null)
				{
					if (msg.FindTextID() > 3)
						break;

					tryingCount++;

					if (tryingCount >= 10)
						break;

					if (UseOreNameFilter && Orion.Contains(msg.Text(), IgnoreOreNames))
						break;
				}

				Orion.WarMode(false);
				Orion.Wait(50);
			}
		}
	}
}

function Mining()
{
	for (var cave = 0; cave < CaveSpots.length; cave++)
	{
		RecallTo(RunesToCave[cave]);
		var spot = CaveSpots[cave];

		//for (var c = 0; c < 2; c++) // Потому что на первом проходе, почему-то, бывают пропуски тайлов и недокопы
		{
			for (var i = 0; i < spot.length; i++)
			{
				WalkToWrapper(spot[i][0], spot[i][1], 0,  (UseHidding == 0 || !Player.Hidden()));
				MiningDig(RunesToCave[cave]);
			}
		}

		if (Player.Weight('%') >= 65)
			CheckOverweight(true, '');
	}

	Orion.Print(0x0044, 'Caves cycle done, restarting in ' + SoundRepeatCount + ' seconds...');
	PlayGuardAlarm(0);
	Orion.Wait(5000);

	// Exec а не while (true) чтобы перезагружались константы (если ломается лук или какие-то правки кода)
	// Чтоб вручную не ловить конец цикла/стопать на полпути и не перезапускать заново
	Orion.Exec('Mining');
	Orion.Wait(500);
}

function UnloadIngots()
{
	while (Orion.MoveItemType('0x1BEF|0x1BF2|0x1BE3|0x1BE9|0x1BF5|0x0F02', 'any', backpack, 0, OresBag))
		Orion.Wait(400);
}

function UnloadOres()
{
	while (Orion.MoveItemType('0x19B7|0x19BA|0x19B8|0x19B9|gp', 'any', backpack, 0, OresBag))
		Orion.Wait(400);
}

function SmeltIronOres()
{
	while (true)
	{
		var list = Orion.FindTypeEx('0x19B7|0x19BA|0x19B8|0x19B9', '0');

		for (var i = 0; i < list.length; i++)
		{
			if (list[i].Count() == 1)
			{
				Orion.UseObject(list[i].Serial());
				Orion.Wait(100);
			}
			else
			{
				Orion.MoveItem(list[i].Serial(), 1, backpack, 50, 50);
				Orion.Wait(400);
			}
		}

		if (list.length == 0)
			return;
	}
}

function TestHarvestingZones(rune)
{
	Orion.ClearFakeMapObjects();

	if (rune < 0 || rune >= CaveSpots.length)
	{
		Orion.Print('0x0021', 'Invalid rune index: ' + rune);
		return;
	}

	FakeId = 1;
	var spots = CaveSpots[rune];

	for (var spot = 0; spot < spots.length; spot++)
	{
		TestHarvestingZone(spots[spot][0], spots[spot][1], 2);
	}
}

function TestHarvestingZone(centerX, centerY, distance)
{
	for (var x = -distance; x <= distance; x++)
	{
		for (var y = -distance; y <= distance; y++)
		{
			Orion.AddFakeMapObject(FakeId++, '0x051A', '0x0044', centerX + x, centerY + y, Player.Z());
		}
	}
}