Register for your free account! | Forgot your password?

You last visited: Today at 05:25

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



[Release] Muddy's D2NT

Discussion on [Release] Muddy's D2NT within the Diablo 2 Programming forum part of the Diablo 2 category.

Reply
 
Old 04/02/2011, 17:44   #1066
 
elite*gold: 0
Join Date: Apr 2010
Posts: 27
Received Thanks: 10
Könnte es vielleicht damit zusammenhängen, dass die Dame auf Hell grundsätzlich Feuer- und Kälteimmun ist?

Dass der normale Angriff dann in die Hose geht ist verständlich, man könnte es eventuell über die selbst definierte Immunität lösen. Allerdings bin ich unsicher, ob das mit der derzeit veröffentlichten Version so möglich ist, ich meine ich habe es für meine neuen Ladder Sorcs etwas angepasst.

Lg
Muddy
__________________

Eigentlich hätte ich für Gräfin kill ja den Merc aber wenn die Soso nicht angreift und sofort die Fehlermeldung kommt ist halt auch schlecht!
Trotzdem Danke ^^
gery68 is offline  
Old 04/02/2011, 17:51   #1067
 
elite*gold: 0
Join Date: Aug 2009
Posts: 435
Received Thanks: 159
jut wenn du sagst dass is schlampig, dann guck ich mir das heute oder morgen mal etwas genauer an^^
aber das sind ja nicht meines scripts sondern von njom :P
mal sehen was sich machen lässt.

wo hast du denn jetzt schon das equip her mit der dame auf hell mauso und ähnliches zu machen? ich hab ja selbst bei den chests noch einiges an chickens
DeathFromHeaven is offline  
Old 04/03/2011, 00:38   #1068
 
Shrimps in Bierteig's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 394
Received Thanks: 75
Ich hatte selbes problem Death, dan hat mir Muddy zu Redvex geraten, bzw. das fastmod plugin für redvex. Das macht schon vieles aus mit 200fhr/200fbr/200Fcr usw^^ vorallem kann der bot dan viel besser ausweichen . Und natürlich ein Söldner der weng dmg macht und was aushält. Dan brauchste auch kein so tolles gear für hell. Aber wen das immer noch ned reicht, geh halt erst in alp, andy und meph farmen. ^^ Ne nacht oder zwei lang, dan solltest das gear zam haben.
Shrimps in Bierteig is offline  
Old 04/03/2011, 00:52   #1069
 
elite*gold: 0
Join Date: Aug 2009
Posts: 435
Received Thanks: 159
hmm doof nur, dass ich Fastmod schon nutze :P
und joa hab schon ein paar nächte auf alp andi meph und gräfin gefarmt... naja so tolles is nicht gedroppt
naja egal morgen ein bisschen von Hand MFen und lvln dann geht das schon^^
DeathFromHeaven is offline  
Old 04/03/2011, 01:01   #1070
Administrator
 
Muddy Waters's Avatar
 
elite*gold: 41364
Join Date: Jan 2010
Posts: 22,727
Received Thanks: 12,653
Also ich hatte einen Spirit Monarch und ein Spirit Schwert vom Durchspielen, ausserdem noch jede Menge Mist.

Ausserdem hatte mein merc eine non eth Insight CA.

Damit habe ich dann mit Mausoleum und Pit angefangen und das dann mit dem Finden weiterer Items etwas ausgedehnt.
Mittlerweile bin ich soweit, dass ich sage, es wird.

Man muss eben mit den kleinen Dingen anfangen und sich dann langsam weiter steigern.

Gerade am Anfang, wenn die Chickenrate eher hoch ist, sollte man aber in jedem Fall darauf achten, dass die Mindestdauer pro Spiel im Entry point (GameMinLength) hoch genug gewählt ist, um Realm Downs zu vermeiden.

Lg
Muddy
Muddy Waters is offline  
Old 04/03/2011, 02:24   #1071
 
elite*gold: 0
Join Date: Aug 2009
Posts: 435
Received Thanks: 159
hehe ja darauf achte ich schon^^

so hab mir mal ein wenig mf besorgt und jetzt wird die nacht zum MFen missbraucht :P

hoffen wir mal, dass es was wird^^
DeathFromHeaven is offline  
Old 04/03/2011, 06:55   #1072
 
elite*gold: 0
Join Date: Oct 2010
Posts: 2
Received Thanks: 0
Hab momentan auch ein wenig Probleme mit der Gräfin, blizzard/fb-sorc. Manuell cleare ich halt die adds mit FB und der merk kriegt die Alte recht fix tot. Aber irgendwie mag das net so richtig mit dem bot funktionieren

Hat wer ne Ahnung wie ich ihn überredet krieg oder ist ne blizzard+light-spec doch eher anzuraten? Überleg die eh, weil mir meines Wissens bisher sehr sehr wenig eis+blitz-immune begegnet sind...

edit: Habs noch net versucht und da ich eh grad hier poste: Kann ich bot-scripte aus anderen Installationen verwenden? In diesem Fall geht es mir vor allem um das crypta-script von Sternenlooper, weil das Gebiet bei dir fehlt

P.S: Gute Arbeit btw, danke.
hanshase99 is offline  
Old 04/03/2011, 10:31   #1073
 
Shrimps in Bierteig's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 394
Received Thanks: 75
Also zu der skillung kann ich dir sagen, ich hab vor reset immer mit Blitz/orb oder blitz/blizzard gespielt. Aber das lohnt sich erst wirklich, wen du auch gute items hast und einige +skills, da sonst dein dmg ziemlich gering ist. Würd daher für blitz/frost skillung erst später verwenden, find ich persönlich aber besser wie fb/orb.

Und ich persönlich würd dir nicht empfehlen scripte von nem anderem gemoddeten NT version einfach so rein zu nehmen. Da kann schnell was schief gehen. Und nimm einfach das Mausoleum script^^ is auch sehr n1 und eigentlich fast das selbe.
Shrimps in Bierteig is offline  
Old 04/03/2011, 12:29   #1074
 
elite*gold: 0
Join Date: Oct 2010
Posts: 105
Received Thanks: 11
Quote:
Originally Posted by hanshase99 View Post
edit: Habs noch net versucht und da ich eh grad hier poste: Kann ich bot-scripte aus anderen Installationen verwenden? In diesem Fall geht es mir vor allem um das crypta-script von Sternenlooper, weil das Gebiet bei dir fehlt

P.S: Gute Arbeit btw, danke.
ja das geht, habe ich mit einem fastdia script so gemacht. du musst allerdings etwas ändern:



beachte meinen post, wo ich nach einem fastdia script frage und lies dir muddys antwort durch, das sollte alles klären.
getgoodson is offline  
Thanks
1 User
Old 04/03/2011, 13:27   #1075
 
elite*gold: 0
Join Date: Mar 2011
Posts: 9
Received Thanks: 0
Hey mal ne frage zu den blauen/gelben items die er lootet um sie beim Vendor zu verkaufen. kann man das abstellen das er die lootet? mein inv ist eigentlich immer recht voll und wenn er dann 2 items lootet um die nur zu verkaufen geht er alle paar mob gruppen in die stadt und verkauft die, was natürlich das Mfn verlangsamt. habe bis jetzt nichts gefunden wo man das ausstellen kann.

ach und muddy falls du das liest, <3 das avoid feature.

hast du für die aktuelle eine neue pickit?(für die neue ladder) wenn ja könntest die vllt mal uppen?

mfg
koonak is offline  
Old 04/03/2011, 13:47   #1076
 
kal_el's Avatar
 
elite*gold: 0
Join Date: Jan 2009
Posts: 7,310
Received Thanks: 2,205
ich kriegte paar mal den snagit fehler...
deshalb die frage...
kommt der fehler wenn er das bestimmte item aufgehoben hat, oder bereits dann wenn er scant was rumliegt?
kal_el is offline  
Old 04/03/2011, 14:07   #1077
 
elite*gold: 0
Join Date: Apr 2010
Posts: 27
Received Thanks: 10
Ich vermisse irgendwie das Pindl Script ohne Nilla!!!!!!!!!!

mfg
Gery
gery68 is offline  
Old 04/03/2011, 14:24   #1078
Administrator
 
Muddy Waters's Avatar
 
elite*gold: 41364
Join Date: Jan 2010
Posts: 22,727
Received Thanks: 12,653
Quote:
Originally Posted by hanshase99 View Post
Hab momentan auch ein wenig Probleme mit der Gräfin, blizzard/fb-sorc. Manuell cleare ich halt die adds mit FB und der merk kriegt die Alte recht fix tot. Aber irgendwie mag das net so richtig mit dem bot funktionieren

Hat wer ne Ahnung wie ich ihn überredet krieg oder ist ne blizzard+light-spec doch eher anzuraten? Überleg die eh, weil mir meines Wissens bisher sehr sehr wenig eis+blitz-immune begegnet sind...

edit: Habs noch net versucht und da ich eh grad hier poste: Kann ich bot-scripte aus anderen Installationen verwenden? In diesem Fall geht es mir vor allem um das crypta-script von Sternenlooper, weil das Gebiet bei dir fehlt

P.S: Gute Arbeit btw, danke.
Ja, aber eventuell nicht mit der aktuell veröffentlichten Version.

Ich selber habe es bei mir so eingestellt, dass doppelt Immune einfach mit FB beschossen werden. Das eignet sich für Countess Runs ganz gut, weil die Wahrscheinlichkeit, dass die Diener dabei in die Schusslinie geraten hoch ist.

Meine Attack Config sieht dazu so aus:
Code:
	//------------------------------------------------------------------------------
	// Attack Configuration
	//------------------------------------------------------------------------------
	
	// Specify your attack skills below. NOTE: Constants for all skill ids can be found in "scripts\libs\common\MWSkills.ntl".
	NTConfig_AttackSkill[0] = MWS_METEOR;			// This skill is used once whenever attacking a new target. Set to 0 to deactivate.
	NTConfig_AttackSkill[1] = MWS_METEOR;			// Primary skill to bosses.
	NTConfig_AttackSkill[2] = MWS_FIRE_BALL;		// Primary untimed skill to boss. Set to 0 to deactivate.
	NTConfig_AttackSkill[3] = MWS_METEOR;			// Primary skill to others.
	NTConfig_AttackSkill[4] = MWS_FIRE_BALL;		// Primary untimed skill to others. Set to 0 to deactivate.
	NTConfig_AttackSkill[5] = MWS_BLIZZARD;			// Secondary skill in case monster is immune to primary skill. Set to 0 to deactivate.
	NTConfig_AttackSkill[6] = MWS_GLACIAL_SPIKE;	// Secondary untimed skill. Set to 0 to deactivate.
	NTConfig_AttackSkill[7] = MWS_ICE_BLAST;		// Alternative untimed skill which is used if the target is immune to your untimed skill - mostly useful for FB/FO/Meteor sorcs or other sorcs that are using the same untimed skills. Set to 0 to deactivate.

	// Set to true if you want to clear area after killing boss. NOTE: This only affects a few botscripts.
	NTConfig_ClearPosition = true;
	
	// Set to true to clear area when killing a boss and the position is crowded by monsters. NOTE: Setting this to true may cause NTA_KillMonster() to fail way more often.
	MWConfig_ClearBossPosition = false;
	
	// This is the number of attacks to be performed before the the character tries to move to another position. Set to 0 not to reposition.
	MWConfig_AttacksBeforeRepositioning = 50;

	// Define a time limit for your attacks for each type of monster.
	MWConfig_AttackTimeLimit[0] = 20;	// Maximum time in seconds to attack a normal monster
	MWConfig_AttackTimeLimit[1] = 120;	// Maximum time in seconds to attack a super unique monster
	MWConfig_AttackTimeLimit[2] = 30;	// Maximum time in seconds to attack a champion
	MWConfig_AttackTimeLimit[3] = 120;	// Maximum time in seconds to attack a bosse
	MWConfig_AttackTimeLimit[4] = 30;	// Maximum time in seconds to attack a minion
	
	// Define when a monster is considered immune by entering the index of one or more of your attack skills. As an example: [1, 3] means that a monster is considered immune if it is immune to both NTConfig_AttackSkill[1] and NTConfig_AttackSkill[3], whatever those may be.
	MWConfig_CheckImmunitySkills = [0, 5];
	
	// Select the behaviour of your character when encountering a monsters that is considered immune referring to the definition above.
	// 0: Don't do anything. (D2NT default)
	// 1: Get close to the monster, use static field if the monster is not immune to lightning.
	// 2: Skip the monster.
	// 3: Attack the monster using NTConfig_AttackSkill[8] and NTConfig_AttackSkill[9]
	NTConfig_BehaviourOnImmuneMonster = 3;
	
	NTConfig_AttackSkill[8] = MWS_METEOR;		// Skill to be used against user defined immunes.
	NTConfig_AttackSkill[9] = MWS_FIRE_BALL;	// Untimed Skill to be used against user defined immunes.
	
	// Always check if monsters are closing in and back off, in case they get too close. NOTE: You should at least have 105FCR in order to make this work smoothly.
	MWConfig_KeepDistanceToMonsters = true;
	// If you don't wish to evade monsters in a certain area, add it's areaid as an exception below. NOTE: All areaids can be found in "sdk\areas.txt".
	// MWConfig_EvasionExceptions.push(<areaid1>, <areaid2>, <areaidn>);
	
	// Check self safe in field (NOT in town). Set to 0 if you won't.
	// 0x01 : Potion
	// 0x02 : Poison
	// 0x04 : Amplify Damage
	// 0x08 : Weaken
	// 0x10 : Iron Maiden
	// 0x20 : Decrepify
	// 0x40 : Lower Resist
	NTConfig_CheckSelfSafe = 0;
	
	// Check merc's safe in field (NOT in town). Set to 0 if you won't.
	// 0x01 : Death
	// 0x02 : Poison
	// 0x04 : Amplify Damage
	// 0x08 : Weaken
	// 0x10 : Iron Maiden
	// 0x20 : Decrepify
	// 0x40 : Lower Resist
	NTConfig_CheckMercSafe = 0x01;

	// Cast Static Field until monster's HP lower below this percentage. Set to 100 not to use static field.
	NTConfig_CastStatic = 60;
	
	// Select the monsters you with to attack using static field. NOTE: If you do not add any monsters, static will be used against all monsters.
	MWConfig_StaticTargets.push(156); // Andariel
	MWConfig_StaticTargets.push(211); // Duriel
	MWConfig_StaticTargets.push(242); // Mephisto
	MWConfig_StaticTargets.push(243); // Diablo
	MWConfig_StaticTargets.push(544); // Baal
	MWConfig_StaticTargets.push(GetLocaleString(22500)); // Eldritch The Rectifier
	MWConfig_StaticTargets.push(GetLocaleString(22435)); // Shenk The Overseer
Du müsstest ausserdem aber auch noch deine NTAttack library anpassen, denke das einfachste wird sein, einfach die komplette library durch die folgende [code]-Box zu ersetzen:
Code:
/**
*	This file was modified by 				
*	Check the programming section for updates and further scripts
*	Last Update: 10:52 26.03.2011						
*/

const NTA_DAMAGE_NONE = 0;
const NTA_DAMAGE_PHYSICAL = 1;
const NTA_DAMAGE_MAGIC = 2;
const NTA_DAMAGE_FIRE = 3;
const NTA_DAMAGE_LIGHTNING = 4;
const NTA_DAMAGE_COLD = 5;
const NTA_DAMAGE_POISON = 6;

var _MWA_Attack_Slot = -1;

var _MWA_Merc_Weapon_Type = -1;

var _MWA_Corpse_Damage_Radius = -1.0;
var _MWA_Minion_Counts = new Array(-1, -1, -1);

var _NTA_SkillHand = new Array(10);
var _NTA_SkillDamage = new Array(10);
var _NTA_SkillRange = new Array(10);

var _MWA_SkipList = new Array();
var _MWA_Attack_Time = new Array();

var _MWA_Traps;

function NTA_Initialize()
{
	if(NTConfig_AttackSkill[1] == 0 || NTConfig_AttackSkill[3] == 0)
		NTA_DetectAttackPattern();
	
	for(var i = 0; i < NTConfig_AttackSkill.length; i++)
	{
		if(NTConfig_AttackSkill[i] > 0)
		{
			_NTA_SkillHand[i] = GetBaseStat("skills.txt", NTConfig_AttackSkill[i], 166) ? 2 : NTC_HAND_RIGHT;
			_NTA_SkillDamage[i] = NTA_GetDamageType(NTConfig_AttackSkill[i]);

			switch(NTConfig_AttackSkill[i])
			{
				case MWS_TORNADO:
					_NTA_SkillRange[i] = MWConfig_TornadoRange;
					break;
				case MWS_TWISTER:
					_NTA_SkillRange[i] = MWConfig_TwisterRange;
					break;
				case MWS_FROST_NOVA: //Frost Nova
				case MWS_NOVA: // Nova
				case MWS_HOLY_BOLT: // Holy Bolt
					_NTA_SkillRange[i] = 5;
					break;
				case MWS_FIRE_BLAST:
				case MWS_SHOCK_WEB:
				case MWS_FROZEN_ORB: // Frozen Orb
					_NTA_SkillRange[i] = 15;
					break;
				case MWS_CORPSE_EXPLOSION: // Corpse Explosion
					_NTA_SkillRange[i] = 25;
					break;
				case MWS_SMITE: // Smite
				case MWS_ZEAL: // Zeal
					_NTA_SkillHand[i] = NTC_HAND_LEFT; // Make sure those skills are casted without shift being hold
				case MWS_BLESSED_HAMMER: //Blessed Hammer
				case MWS_BERSERK: //Berserk
				case MWS_WAR_CRY: // War Cry
					_NTA_SkillRange[i] = 3;
					break;
				case MWS_WHIRLWIND: //Whirlwind
					_NTA_SkillRange[i] = 8;
					break;
				case MWS_INFERNO:
					_NTA_SkillRange[i] = 10;
					break;
				// Range definition for traps: [0]: range to place a trap [1]: range of the trap itself
				case MWS_CHARGED_BOLT_SENTRY:
				case MWS_WAKE_OF_FIRE:
				case MWS_WAKE_OF_INFERNO:
					_NTA_SkillRange[i] = [15, 10];
					break;
				case MWS_LIGHTNING_SENTRY:
				case MWS_DEATH_SENTRY:
					_NTA_SkillRange[i] = [15, 20];
					break;
				default:
					_NTA_SkillRange[i] = 20;
					break;
			}
		}
	}
}

function NTA_KillMonster(search)
{
	var _target, _attackcount, _attacksFailed;

	if(NTConfig_AttackSkill[1] < 1)
		return false;

	_target = NTC_FindUnit(NTC_UNIT_MONSTER, search, 5);

	if(!_target)
		return false;

	if(_target.IsAttackable())
	{
		_attackcount = 0;
		_attacksFailed = 0;
		
		if(MWConfig_ClearBossPosition && me.diff > 0 &&  MWA_FindNearbyMonsters(10, _target))
			NTA_ClearPosition(15, false, 0, false, false);

		while(_attackcount < 350 && NTA_IsValidMonster(_target))
		{
			if(MWConfig_ShowOverheadStatus)
				MWA_PrintAttackStatus(1, _target);
			
			if(NTA_Attack(_target, (_attackcount % 30) == 0) < 2)
				_attacksFailed++;

			_attackcount++;
			
			if(_attacksFailed > 2)
				break;
		}
	}
	
	if(MWConfig_PickItemsInstantly && (_target.hp <= 0 || _target.mode == 0 || _target.mode == 12))
		NTSI_PickItems();

	return (_target.hp <= 0 || _target.mode == 0 || _target.mode == 12);
}

function NTA_ClearPosition(range, pickitem, safelevel, openchests, usefinditem, spectype)
{
	var _orgx, _orgy;
	var _spectype = [0x0A, 0x0E, 0x01];
	var _skiplist;
	var _attackcount = 0;
	var _target;
	var _distance, _mingid, _mindistance;
	var _mingidPrio, _mindistPrio;
	var _result;
	var _outputType;

	if(NTConfig_AttackSkill[1] < 1 || NTConfig_AttackSkill[3] < 1)
		return false;

	switch(arguments.length)
	{
		case 0:
			range = 20;
		case 1:
			pickitem = false;
		case 2:
			safelevel = 2;
		case 3:
			if(NTConfig_CheckSelfSafe < 0x01 && NTConfig_CheckMercSafe < 0x01)
				safelevel = 0;
			openchests = true;
		case 4: 
			usefinditem = true;
		case 5:
			break;
		default:
			if(spectype > 0x01)
				_spectype = [spectype];
	}
	
	if(_spectype.length == 3 && (me.classid == NTC_CHAR_CLASS_NECROMANCER || me.classid == NTC_CHAR_CLASS_SORCERESS && MWConfig_KeepDistanceToMonsters))
		_spectype = [0x01];

	_orgx = me.x;
	_orgy = me.y;

	for(var i = 0; i < _spectype.length; i++)
	{
		_skiplist = new Array();

		while(_attackcount < (i+1)*100)
		{
			_mindistance = 1E6;
			_mindistPrio = 1E6;

			_target = NTC_FindUnit(NTC_UNIT_MONSTER);

			if(_target)
			{
				do
				{
					if(_skiplist.indexOf(_target.gid) < 0)
					{
						if(_target.IsAttackable() && (_target.spectype & _spectype[i]))
						{
							if(GetDistance(_orgx, _orgy, _target.x, _target.y) <= range && NTA_IsValidMonster(_target))
							{
								_distance = GetDistance(me, _target);

								if(_distance < _mindistance)
								{
									_mingid = _target.gid;
									_mindistance = _distance;
								}
								
								if(MWA_IsPriorityTarget(_target))
								{
									if(_distance < _mindistPrio)
									{
										_mingidPrio = _target.gid;
										_mindistPrio = _distance;
									}
								}
							}
						}
						else
							_skiplist.push(_target.gid);
					}
				} while(_target.GetNext());
			}

			if(_mindistance < 1E6)
			{
				if(_mindistPrio < 1E6)
				{
					_target = NTC_FindUnit(NTC_UNIT_MONSTER, _mingidPrio, 1);
					_outputType = 1;
				}
				else
				{				
					_target = NTC_FindUnit(NTC_UNIT_MONSTER, _mingid, 1);
					_outputType = 0;
				}

				if(_target)
				{
					if(MWConfig_ShowOverheadStatus)
						MWA_PrintAttackStatus(_outputType, _target);

					_result = NTA_Attack(_target, (_attackcount % 30) == 0);
					
					if(MWConfig_ShowOverheadStatus)
						MWA_PrintAttackStatus(_outputType, _target);

					switch(_result)
					{
					case 1:
						_skiplist.push(_mingid);
						break;
					case 2:
					case 3:
						if(MWConfig_PickItemsInstantly && (_target.hp <= 0 || _target.mode == 0 || _target.mode == 12))
							NTSI_PickItems();
						_attackcount++;
						break;
					default:
						return false;
					}
				}
			}
			else
				break;
		}
	}

	if(_attackcount > 2)
	{
		switch(me.classid)
		{
			case NTC_CHAR_CLASS_PALADIN:
				if(parseInt(me.hp * 100 / me.hpmax) < NTConfig_UseRedemptionHP || parseInt(me.mp * 100 / me.mpmax) < NTConfig_UseRedemptionMP)
				{
					if(NTC_PutSkill(MWS_REDEMPTION, NTC_HAND_RIGHT))
						NTC_PingDelay(1000);
				}
				break;
			case NTC_CHAR_CLASS_BARBARIAN:
				if(usefinditem && MWConfig_UseFindItem)
					MWL_FindItem(MWConfig_FindItemRange);
				break;
			case NTC_CHAR_CLASS_NECROMANCER:
				MWA_RaiseMinions();
				break;
		}
	}
	
	if(pickitem && _attackcount > 0)
		NTSI_PickItems();

	if(MWConfig_OpenAllNearbyChests && openchests)
		MWL_OpenNearbyChests(MWConfig_OpenChestsRange);
	
	if(MWConfig_ActivateNearbyShrines)
		MWL_ActivateNearbyShrines();

	switch(safelevel)
	{
		case 1:
			return NTTMGR_CheckSafe(0x00, NTConfig_CheckMercSafe&0x01);
		case 2:
			return NTTMGR_CheckSafe(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe);
	}

	if(MWConfig_IdentAfterPickup)
		MWL_IDItemsAfterPickup();

	return true;
}

function NTA_ClearLevel(pickitem, safelevel, spectype)
{
	var _room, _rooms;
	var _distance, _minindex, _mindistance;

	_room = GetRoom();

	if(!_room)
		return false;

	switch(arguments.length)
	{
		case 0:
			pickitem = true;
		case 1:
			safelevel = 2;
		case 2:
			if(NTConfig_CheckSelfSafe < 0x01 && NTConfig_CheckMercSafe < 0x01)
				safelevel = 0;
		default:
			spectype = 0x01;
	}

	_rooms = new Array();

	do
	{
		_rooms.push([parseInt(_room.x*5 + _room.xsize*5/2), parseInt(_room.y*5 + _room.ysize*5/2)]);
	} while(_room.GetNext());

	while(_rooms.length > 0)
	{
		_mindistance = 100000;

		for(var i = 0; i < _rooms.length; i++)
		{
			_distance = GetDistance(me.x, me.y, _rooms[i][0], _rooms[i][1]);

			if(_distance < _mindistance)
			{
				_minindex = i;
				_mindistance = _distance;
			}
		}

		if(NTM_MoveTo(me.areaid, _rooms[_minindex][0], _rooms[_minindex][1], 1))
		{
			if(!NTA_ClearRoom(pickitem, safelevel, spectype))
				return false;

			NTP_DoPrecast(false);
		}

		_rooms.splice(_minindex, 1);
	}

	return true;
}

function NTA_ClearRoom(pickitem, safelevel, spectype)
{
	var _room;
	var _spectype = [0x0A, 0x0E, 0x01];
	var _skiplist;
	var _attackcount = 0;
	var _target;
	var _distance, _mingid, _mindistance;
	var _mingidPrio, _mindistPrio;
	var _result;
	var _outputType;

	if(NTConfig_AttackSkill[1] < 1 || NTConfig_AttackSkill[3] < 1)
		return false;
		
	_room = me.GetRoom();

	if(!_room)
		return false;

	switch(arguments.length)
	{
		case 0:
			pickitem = false;
		case 1:
			safelevel = 0;
		case 2:
			if(NTConfig_CheckSelfSafe < 0x01 && NTConfig_CheckMercSafe < 0x01)
					safelevel = 0;
		default:
			if(spectype > 0x01)
				_spectype = [spectype];
	}
	
	if(_spectype.length == 3 && (me.classid == NTC_CHAR_CLASS_NECROMANCER || me.classid == NTC_CHAR_CLASS_SORCERESS && MWConfig_KeepDistanceToMonsters))
		_spectype = [0x01];

	for(var i = 0; i < _spectype.length; i++)
	{
		_skiplist = new Array();

		while(_attackcount < (i+1)*100)
		{
			_mindistance = 1E6;
			_mindistPrio = 1E6;

			_target = NTC_FindUnit(NTC_UNIT_MONSTER);

			if(_target)
			{
				do
				{
					if(_skiplist.indexOf(_target.gid) < 0)
					{
						if(_target.IsAttackable() && (_target.spectype & _spectype[i]))
						{
							if(_room.UnitInRoom(_target) && NTA_IsValidMonster(_target))
							{
								_distance = GetDistance(me, _target);

								if(_distance < _mindistance)
								{
									_mingid = _target.gid;
									_mindistance = _distance;
								}
								
								if(MWA_IsPriorityTarget(_target))
								{
									if(_distance < _mindistPrio)
									{
										_mingidPrio = _target.gid;
										_mindistPrio = _distance;
									}
								}
							}
						}
						else
							_skiplist.push(_target.gid);
					}
				} while(_target.GetNext());
			}

			if(_mindistance < 1E6)
			{
				if(_mindistPrio < 1E6)
				{
					_target = NTC_FindUnit(NTC_UNIT_MONSTER, _mingidPrio, 1);
					_outputType = 1;
				}
				else
				{				
					_target = NTC_FindUnit(NTC_UNIT_MONSTER, _mingid, 1);
					_outputType = 0;
				}

				if(_target)
				{
					if(MWConfig_ShowOverheadStatus)
						MWA_PrintAttackStatus(_outputType, _target);
					
					_result = NTA_Attack(_target, (_attackcount%30) == 0);
					
					if(MWConfig_ShowOverheadStatus)
						MWA_PrintAttackStatus(_outputType, _target);

					switch(_result)
					{
					case 1:
						_skiplist.push(_mingid);
						break;
					case 2:
					case 3:
						if(MWConfig_PickItemsInstantly && (_target.hp <= 0 || _target.mode == 0 || _target.mode == 12))
							NTSI_PickItems();
						_attackcount++;
						break;
					default:
						return false;
					}
				}
			}
			else
				break;
		}
	}

	if(_attackcount > 2)
	{
		switch(me.classid)
		{
			case NTC_CHAR_CLASS_PALADIN:
				if(parseInt(me.hp * 100 / me.hpmax) < NTConfig_UseRedemptionHP || parseInt(me.mp * 100 / me.mpmax) < NTConfig_UseRedemptionMP)
				{
					if(NTC_PutSkill(MWS_REDEMPTION, NTC_HAND_RIGHT))
						NTC_PingDelay(1000);
				}
				break;
			case NTC_CHAR_CLASS_BARBARIAN:
				if(MWConfig_UseFindItem)
					MWL_FindItem(MWConfig_FindItemRange);
				break;
			case NTC_CHAR_CLASS_NECROMANCER:
				MWA_RaiseMinions();
				break;
		}
	}

	if(pickitem && _attackcount > 0)
		NTSI_PickItems();
	
	if(MWConfig_OpenAllNearbyChests)
		MWL_OpenNearbyChests(_room);
		
	if(MWConfig_ActivateNearbyShrines)
		MWL_ActivateNearbyShrines();
			
	switch(safelevel)
	{
		case 1:
			return NTTMGR_CheckSafe(0x00, NTConfig_CheckMercSafe&0x01);
		case 2:
			return NTTMGR_CheckSafe(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe);
	}

	return true;
}

function NTA_IsValidMonster(monster)
{
	var _classid;

	if(monster.hp <= 0 && (monster.mode == 0 || monster.mode == 12 || monster.mode == 14))
		return false;
	
	_classid = monster.classid;

	if(((_classid >= 110 && _classid <= 113) || _classid == 608) && monster.mode == 8) // ignore flying scavengers
		return false;

	if(_classid == 68 && monster.mode == 14) // ignore burrowing maggots
		return false;

	if(_classid >= 258 && _classid <= 263) // ignore submerged WaterWatchers
		return false;

	if(monster.GetState(53) || monster.GetState(96)) // Conversion, Revive
		return false;
		
	if(!CheckCollision(me, monster, 0)) // Invalid map location
		return false;

	return true;
}

function NTA_GetDamageType(skillid, target, skillindex)
{
	if(target && MWA_IsUndead(target))
	{
		if(skillid == MWS_HOLY_BOLT || me.GetState(47) || !isNaN(skillindex) && _NTA_SkillDamage[skillindex] == NTA_DAMAGE_PHYSICAL && NTConfig_AttackSkill[skillindex + 1] == MWS_SANCTUARY)
			return NTA_DAMAGE_NONE;
	}
		
	if(skillid == MWS_CORPSE_EXPLOSION) // Corpse Explosion
		return NTA_DAMAGE_PHYSICAL;

	if(skillid == MWS_BLESSED_HAMMER) // Blessed Hammer
		return NTA_DAMAGE_MAGIC;

	switch(GetBaseStat("skills.txt", skillid, 233))
	{
		case "cold":
			return NTA_DAMAGE_COLD;
		case "fire":
			return NTA_DAMAGE_FIRE;
		case "ltng":
			return NTA_DAMAGE_LIGHTNING;
		case "mag":
			return NTA_DAMAGE_MAGIC;
		case "pois":
			return NTA_DAMAGE_POISON;
		case "stun":
			return NTA_DAMAGE_NONE;
		default:
			if(GetBaseStat("skills.txt", skillid, 178) || GetBaseStat("skills.txt", skillid, 182)) // aura or passive
				return NTA_DAMAGE_NONE;
	}

	return NTA_DAMAGE_PHYSICAL;
}

function NTA_GetResistance(enemy, type)
{
	switch(type)
	{
		case NTA_DAMAGE_PHYSICAL:
			if(MWA_IsUndead(enemy) && me.GetState(47))
				break;
			
			return enemy.GetStat(36);
		case NTA_DAMAGE_MAGIC:
			return enemy.GetStat(37);
		case NTA_DAMAGE_FIRE:
			return enemy.GetStat(39);
		case NTA_DAMAGE_LIGHTNING:
			return enemy.GetStat(41);
		case NTA_DAMAGE_COLD:
			return enemy.GetStat(43);
		case NTA_DAMAGE_POISON:
			return enemy.GetStat(45);
	}
	
	return 0;
}

function NTA_DetectAttackPattern()
{
	switch(me.classid)
	{
		case NTC_CHAR_CLASS_AMAZON:
			return NTA_AmazonAttackPatternInt();
		case NTC_CHAR_CLASS_SORCERESS:
			return NTA_SorceressAttackPatternInt();
		case NTC_CHAR_CLASS_NECROMANCER:
			return NTA_NecromancerAttackPatternInt();
		case NTC_CHAR_CLASS_PALADIN:
			return NTA_PaladinAttackPatternInt();
		case NTC_CHAR_CLASS_BARBARIAN:
			return NTA_BarbarianAttackPatternInt();
		case NTC_CHAR_CLASS_DRUID:
			return NTA_DruidAttackPatternInt();
		case NTC_CHAR_CLASS_ASSASSIN:
			return NTA_AssassinAttackPatternInt();
	}

	return false;
}

// Return value : 0 = Unrecoverable process, 1 = Unavailable attack, 2 = Onetime fail, 3 = Success
function NTA_Attack(target, firstorder)
{
	switch(me.classid)
	{
	case NTC_CHAR_CLASS_AMAZON:
		return NTA_AmazonAttackInt(target, firstorder);
	case NTC_CHAR_CLASS_SORCERESS:
		return NTA_SorceressAttackInt(target, firstorder);
	case NTC_CHAR_CLASS_NECROMANCER:
		return NTA_NecromancerAttackInt(target, firstorder);
	case NTC_CHAR_CLASS_PALADIN:
		return NTA_PaladinAttackInt(target, firstorder);
	case NTC_CHAR_CLASS_BARBARIAN:
		return NTA_BarbarianAttackInt(target, firstorder);
	case NTC_CHAR_CLASS_DRUID:
		return NTA_DruidAttackInt(target, firstorder);
	case NTC_CHAR_CLASS_ASSASSIN:
		return NTA_AssassinAttackInt(target, firstorder);
	}

	return 0;
}

// Internal function
function NTA_AmazonAttackPatternInt()
{
	return false;
}

function NTA_AmazonAttackInt(target, firstorder)
{
	return 1;
}

function NTA_AmazonCastSkillInt(index, target)
{
	return false;
}

function NTA_SorceressAttackPatternInt()
{
	var _maxindex, _maxskill;
	var _avgskilllevel = new Array();

	_avgskilllevel[0] = parseInt((me.GetSkill(59, false)+me.GetSkill(39, false)+me.GetSkill(45, false)+me.GetSkill(55, false))/4);
	_avgskilllevel[1] = parseInt((me.GetSkill(53, false)+me.GetSkill(38, false)+me.GetSkill(48, false)+me.GetSkill(49, false))/4);
	_avgskilllevel[2] = parseInt((me.GetSkill(47, false)+me.GetSkill(36, false)+me.GetSkill(56, false)+me.GetSkill(64, false))/4);
	_avgskilllevel[3] = parseInt((me.GetSkill(47, false)+me.GetSkill(36, false)+me.GetSkill(56, false))/3);

	_maxindex = -1;
	_maxskill = 0;

	for(var i = 0; i < _avgskilllevel.length; i++)
	{
		if(_avgskilllevel[i] > _maxskill)
		{
			_maxindex = i;
			_maxskill = _avgskilllevel[i];
		}
	}

	switch(_maxindex)
	{
	case 0: // Blizzard + Glacial Spike
		NTConfig_AttackSkill[1] = 59;
		NTConfig_AttackSkill[2] = 55;
		NTConfig_AttackSkill[3] = 59;
		NTConfig_AttackSkill[4] = 55;
		break;
	case 1: // Chain Lightning + Lightning
		NTConfig_AttackSkill[1] = 49;
		NTConfig_AttackSkill[3] = 53;
		break;
	case 2: // Fire Ball + Frozen Orb
		NTConfig_AttackSkill[0] = 64;
		NTConfig_AttackSkill[1] = 47;
		NTConfig_AttackSkill[3] = 47;
		NTConfig_AttackSkill[5] = 64;
		NTConfig_AttackSkill[6] = 55;
		break;
	case 3: // Fire Ball + Meteor
		NTConfig_AttackSkill[1] = 56;
		NTConfig_AttackSkill[2] = 47;
		NTConfig_AttackSkill[3] = 56;
		NTConfig_AttackSkill[4] = 47;
		break;
	}

	return (NTConfig_AttackSkill[1] && NTConfig_AttackSkill[3]);
}

function NTA_SorceressAttackInt(target, firstorder)
{
	var _primaryindex, _immuneTarget, _useStatic;
	
	_useStatic = false;
	
	if(NTTMGR_CheckCurse(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe))
	{
		if(!NTTMGR_VisitTown())
			return 0;
	}
	
	if(_MWA_SkipList.indexOf(target.gid) > -1)
	{
		Print("Return A");
		return 1;
	}
		
	if(MWConfig_AttacksBeforeRepositioning > 0 && _MWA_Attack_Time[3] % MWConfig_AttacksBeforeRepositioning == 0)
	{
		var _vec = MWA_GetEvasionVector(4, 2, target);
		
		if(_vec && !_vec.isZero())
			NTM_MoveTo(target.areaid, parseInt(target.x + _vec.x), parseInt(target.y + _vec.y), 0);
	}

	_immuneTarget = MWA_CheckMonsterImmunity(target);
		
	if(_immuneTarget && NTConfig_BehaviourOnImmuneMonster == 2 && !(target.spectype&0x02) && me.areaid != 131 || MWA_CheckAttackTimeLimit(target))
	{
		_MWA_SkipList.push(target.gid);
		Print("Return B");
		return 1;
	}
	
	if(_immuneTarget)
	{	
		if(NTConfig_BehaviourOnImmuneMonster == 3 && NTConfig_AttackSkill[8] > 0) // Attack the target using the selected skill
		{
			if(!NTA_SorceressCastSkillInt(8, target))
				return 2;

			return 3;
		}
		else if(NTConfig_BehaviourOnImmuneMonster == 1 && NTC_GetMerc())// Get close so the merc can attack the target
		{
			if(GetDistance(me, target) > 5)
				NTM_MoveTo(target.areaid, target.x + 2, target.y + 2);

			NTC_Delay(100);

			_useStatic = true;
		}
	}
		
	if(firstorder && NTConfig_AttackSkill[0] > 0 && MWA_CheckMonsterResistance(target, _NTA_SkillDamage[0]) && me.GetSkillStatus(NTConfig_AttackSkill[0]) != 8)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[0] || !CheckCollision(me, target, 4))
		{
			var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[0], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}

		if(!NTC_CastSkill(NTConfig_AttackSkill[0], _NTA_SkillHand[0], target))
			return 2;

		return 3;
	}
	
	if((_useStatic || MWA_UseStaticOnTarget(target)) && NTConfig_CastStatic < 100 && parseInt(target.hp * 100 / target.hpmax) > NTConfig_CastStatic && MWA_CheckMonsterResistance(target, NTA_DAMAGE_LIGHTNING))
	{
		var _staticlevel = NTC_GetSkillLevel(MWS_STATIC_FIELD);

		if(_staticlevel > 0)
		{
			var _staticrange;
			var _castx, _casty;

			_staticrange = Math.floor(( 5 + _staticlevel - 1) * 2 / 3);

			if(GetDistance(me, target) > _staticrange || !CheckCollision(me, target, 6))
			{
				var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _staticrange, 6);

				if(_pos)
					NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
			}

			if(target.x < me.x)
				_castx = me.x - 1;
			else if(target.x > me.x)
				_castx = me.x + 1;
			else
				_castx = me.x;

			if(target.y < me.y)
				_casty = me.y - 1;
			else if(target.y > me.y)
				_casty = me.y + 1;
			else
				_casty = me.y;

			if(!CheckCollision(target.areaid, _castx, _casty, 1))
			{
				_castx = me.x;
				_casty = me.y;
			}

			if(!NTC_CastSkill(MWS_STATIC_FIELD, NTC_HAND_RIGHT, _castx, _casty))
				return 2;

			return 3;
		}
	}
	
	if(_useStatic)
		return 3;

	_primaryindex = (target.spectype&0x0A) ? 1 : 3;

	if(MWA_CheckMonsterResistance(target, _NTA_SkillDamage[_primaryindex]))
	{
		if(!NTA_SorceressCastSkillInt(_primaryindex, target))
			return 2;

		return 3;
	}

	if(NTConfig_AttackSkill[5] > 0 && MWA_CheckMonsterResistance(target, _NTA_SkillDamage[5]))
	{
		if(!NTA_SorceressCastSkillInt(5, target))
			return 2;

		return 3;
	}
	Print("Return C");
	return 1;
}

function NTA_SorceressCastSkillInt(index, target, evade)
{
	var _maxDist, _pos;
	
	if(arguments.length < 3)
		evade = true;

	if(me.GetSkillStatus(NTConfig_AttackSkill[index]) != 8)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[index] || !CheckCollision(me, target, 4))
		{
			_pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
		
		return NTC_CastSkill(NTConfig_AttackSkill[index], _NTA_SkillHand[index], target);
	}

	switch(target.classid)
	{
		case 310: // Doom Knight (CS)
		case 362: // Venom Lord (CS)
		case 472: // Hell Temptress
		case 510: // Death Lord (Throne)
		case 558: // Venom Lord (Throne)
		case 571: // Minion of Desctrution (Throne)
		case 638: // Vile Witch
		case 691: // Undead Soul Killer (Throne)
			_maxDist = 5;
			break;
		default:
			_maxDist = 4;
			break;
	}

	if(evade && NTC_GetSkillLevel(MWS_TELEPORT) >= 1 && MWA_CalcDistToClosestMonster() <= _maxDist && MWConfig_KeepDistanceToMonsters && MWA_AreaCheckEvading(me.areaid))
		return MWA_MoveAwayFromMonster(target);

	if(NTConfig_AttackSkill[index + 1] > 0 && (index == 8 || MWA_CheckMonsterResistance(target, _NTA_SkillDamage[index + 1])))
	{
		if(GetDistance(me, target) > _NTA_SkillRange[index+1] || !CheckCollision(me, target, 4))
		{
			_pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index + 1], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
		
		return NTC_CastSkill(NTConfig_AttackSkill[index + 1], _NTA_SkillHand[index + 1], target);
	}
	else if(NTConfig_AttackSkill[7] > 0 && MWA_CheckMonsterResistance(target, _NTA_SkillDamage[7]))
	{
		if(GetDistance(me, target) > _NTA_SkillRange[7] || !CheckCollision(me, target, 4))
		{
			_pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[7], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
		
		return NTC_CastSkill(NTConfig_AttackSkill[7], _NTA_SkillHand[7], target);
	}

	for(var i = 0; i < 25; i++)
	{
		NTC_Delay(NTC_DELAY_FRAME);

		if(me.GetSkillStatus(NTConfig_AttackSkill[index]) != 8)
			break;
	}

	return false;
}

function NTA_NecromancerAttackPatternInt()
{
	return false;
}

function NTA_NecromancerAttackInt(target, firstorder)
{
	var _nextCorpse, _gid, _vec, _viciousFoe, _count, _pos;
	var i;
	
	if(NTTMGR_CheckCurse(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe))
	{
		if(!NTTMGR_VisitTown())
			return 0;
	}
	
	if(_MWA_SkipList.indexOf(target.gid) > -1)
		return 1;
	
	if(MWA_CheckAttackTimeLimit(target))
	{
		_MWA_SkipList.push(target.gid);

		return 1;
	}
	
	if(MWConfig_AttacksBeforeRepositioning > 0 && _MWA_Attack_Time[3] % MWConfig_AttacksBeforeRepositioning == 0)
	{
		_vec = MWA_GetEvasionVector(4, 2, target);
		
		if(!_vec && !_vec.isZero())
			NTM_MoveTo(target.areaid, parseInt(target.x + _vec.x), parseInt(target.y + _vec.y), 0);
	}

	_viciousFoe = MWA_IsHazardousMonster(target);
	
	// Define the maximum values once as they are mostly constant anyway
	if(_MWA_Corpse_Damage_Radius < 0 || _MWA_Minion_Counts[0] < 0 || _MWA_Minion_Counts[1] < 0 || _MWA_Minion_Counts[2] < 0)
	{
		// Define the Corpse or Poison Explosion Range Radius
		if(NTConfig_AttackSkill[3] == 74)
			_MWA_Corpse_Damage_Radius = MWA_CalcCorpseExplosionRadius();
		else
			_MWA_Corpse_Damage_Radius = 5; // TODO: Check poison exp range
		
		MWA_SetMinionCounts();
	}
	
	// Cast the initial attack unless it is a curse and the target is already cursed
	if(!_viciousFoe && firstorder && NTConfig_AttackSkill[0] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[0]) < 100 && me.GetSkillStatus(NTConfig_AttackSkill[0]) != 8 && !MWA_GetCurseState(NTConfig_AttackSkill[0], target))
	{
		if(GetDistance(me, target) > _NTA_SkillRange[0] || !CheckCollision(me, target, 4))
		{
			_pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[0], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}

		if(!NTC_CastSkill(NTConfig_AttackSkill[0], _NTA_SkillHand[0], target))
			return 2;
	}
	
	// The current target is vicious and we gotta use the selected skill in order to make it less dangerous
	if(_viciousFoe && !MWA_GetCurseState(NTConfig_AttackSkill[2], target))
	{
		if(GetDistance(me, target) > _NTA_SkillRange[2] || !CheckCollision(me, target, 4))
		{
			_pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[2], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}

		if(!NTA_NecromancerCastSkillInt(2, target))
			return 2;
			
		return 3;
	}
	// Use the standard curse unless the monster is already curse
	if(!_viciousFoe && !MWA_GetCurseState(NTConfig_AttackSkill[1], target))
	{
		if(GetDistance(me, target) > _NTA_SkillRange[1] || !CheckCollision(me, target, 4))
		{
			_pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[1], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}

		if(!NTA_NecromancerCastSkillInt(1, target))
			return 2;
			
		return 3;
	}

	// The target is vicious and some monsters are very close to the char --> Evade
	if(_viciousFoe && MWA_CalcDistToClosestMonster() < 3)
	{
		MWA_MoveAwayFromMonster(target);
		
		_vec = MWA_GetEvasionVector(3, 2);
		
		if(!_vec || _vec.isZero())
		{
			_vec = new vector(me.x - target.x, me.y - target.y);
			_vec.normalize();
		}
		
		_vec.setlength(3);
		
		NTC_Delay(100);
		ClickMap(NTC_CLICK_LDOWN, NTC_SHIFT_NONE, me.x + parseInt(_vec.x), me.y + parseInt(_vec.y));
		NTC_Delay(100);
		ClickMap(NTC_CLICK_LUP, NTC_SHIFT_NONE, null);
		NTC_Delay(100);
		
		return 3;
	}
		
	// Find the corpse closest to the target's current position
	_gid = MWA_GetClosestCorpseGID(target.x, target.y);
	
	// Instantiate the unit if a valid gid was found
	if(_gid > 0)
		_nextCorpse = NTC_FindUnit(NTC_UNIT_MONSTER, _gid);
	
	if(_nextCorpse)
	{
		// Use the corpse closest to the target in order to raise primary minions if you do not already have the desired amount of minions
		_count = MWC_GetMinionCount(NTConfig_AttackSkill[4]);
		
		if(_count < _MWA_Minion_Counts[0] - 1)
		{
			if(MWConfig_ShowOverheadStatus)
			{
				if(NTConfig_AttackSkill[4] == 95)
					MWC_PrintOverheadStatus("Reviving " + _corpse.name + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[0] + ")");
				else
					MWC_PrintOverheadStatus("Summoning " + MWC_GetMinionName(NTConfig_AttackSkill[4]) + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[0] + ")");
			}
			
			if(!NTA_NecromancerCastSkillInt(4, _nextCorpse))
				return 2;

			return 3;
		}
		
		// Use the corpse to attack the target using corpse or poison explosion
		if(GetDistance(target, _nextCorpse) <= _MWA_Corpse_Damage_Radius)
		{
			if(!NTA_NecromancerCastSkillInt(3, _nextCorpse))
				return 2;

			return 3;
		}
	}
	
	// The target is not too dangerous and the average target - minion distance is too high --> Move close to the target
	if(!_viciousFoe && MWA_CalcAverageMinionDistance(target) > 4.0)
	{
		_vec = new vector(me.x - target.x, me.y - target.y);
		
		if(_vec && !_vec.isZero())
		{
			_vec.normalize();
			
			NTM_MoveTo(target.areaid, target.x + parseInt(2 * _vec.x), target.y + parseInt(2 * _vec.y));
		}
	}
	
	// If the distance to our minions is rather short (stuck on our position?) or some enemy monsters are close --> Step aside
	if(MWA_CalcAverageMinionDistance() < 2.0 || MWA_CalcDistToClosestMonster() < 3)
	{
		_vec = MWA_GetEvasionVector(3, 2);
		
		if(!_vec || _vec.isZero())
			_vec = new vector(me.x - target.x, me.y - target.y);
		
		_vec.setlength(3);
		
		NTC_Delay(100);
		ClickMap(NTC_CLICK_LDOWN, NTC_SHIFT_NONE, me.x + parseInt(_vec.x), me.y + parseInt(_vec.y));
		NTC_Delay(100);
		ClickMap(NTC_CLICK_LUP, NTC_SHIFT_NONE, null);
		NTC_Delay(100);
		
		return 3;
	}
	
	// If the enemy is vicious or if our minions are already close to the target --> Wait and let the minions do their job
	if(_viciousFoe && MWA_CalcDistToClosestMonster() > 3 || MWA_CalcAverageMinionDistance(target) <= 4.0)
	{
		for(i = 0; i < 20; i++)
		{
			NTC_Delay(NTC_DELAY_FRAME);
			
			if(MWA_GetClosestCorpseGID(target.x, target.y, _MWA_Corpse_Damage_Radius) > 0 || !NTA_IsValidMonster(target))
				break;
		}
		
		return ((i >= 20) ? 3 : 2);
	}
	
	NTC_Delay(250);

	return NTA_NecromancerAttackInt(target, firstorder);
}

function NTA_NecromancerCastSkillInt(index, target)
{
	if(me.GetSkillStatus(NTConfig_AttackSkill[index]) != 8)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[index] || !CheckCollision(me, target, 4))
		{
			var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
		return NTC_CastSkill(NTConfig_AttackSkill[index], _NTA_SkillHand[index], target);
	}
			
	for(var i = 0; i < 25; i++)
	{
		NTC_Delay(NTC_DELAY_FRAME);

		if(me.GetSkillStatus(NTConfig_AttackSkill[index]) != 8)
			break;
	}
	
	return false;
}

function NTA_PaladinAttackPatternInt()
{
	var _maxindex, _maxskill;
	var _avgskilllevel = new Array();

	_avgskilllevel[0] = parseInt((me.GetSkill(112, false)+me.GetSkill(108, false)+me.GetSkill(115, false))/3);
	_avgskilllevel[1] = parseInt((me.GetSkill(106, false)+me.GetSkill(96, false))/2);
	_avgskilllevel[2] = parseInt((me.GetSkill(121, false)+me.GetSkill(101, false)+me.GetSkill(118, false))/3);

	_maxindex = -1;
	_maxskill = 0;

	for(var i = 0 ; i < _avgskilllevel.length ; i++)
	{
		if(_avgskilllevel[i] > _maxskill)
		{
			_maxindex = i;
			_maxskill = _avgskilllevel[i];
		}
	}

	switch(_maxindex)
	{
	case 0: // Blessed Hammer
		NTConfig_AttackSkill[1] = 112;
		NTConfig_AttackSkill[2] = 113;
		NTConfig_AttackSkill[3] = 112;
		NTConfig_AttackSkill[4] = 113;
		break;
	case 1: // Zeal
		NTConfig_AttackSkill[1] = 106;
		NTConfig_AttackSkill[2] = 122;
		NTConfig_AttackSkill[3] = 106;
		NTConfig_AttackSkill[4] = 122;
		break;
	case 2: // Fist of the Heavens
		NTConfig_AttackSkill[1] = 121;
		NTConfig_AttackSkill[2] = 123;
		NTConfig_AttackSkill[3] = 121;
		NTConfig_AttackSkill[4] = 123;
		break;
	}

	return (NTConfig_AttackSkill[1] && NTConfig_AttackSkill[3]);
}

function NTA_PaladinAttackInt(target, firstorder)
{
	var _primaryindex, _immuneTarget;

	if(NTTMGR_CheckCurse(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe))
	{
		if(!NTTMGR_VisitTown())
			return 0;
	}

	if(_MWA_SkipList.indexOf(target.gid) > -1)
		return 1;
		
	if(MWConfig_AttacksBeforeRepositioning > 0 && _MWA_Attack_Time[3] % MWConfig_AttacksBeforeRepositioning == 0)
	{
		var _vec = MWA_GetEvasionVector(4, 2, target);
		
		if(_vec && !_vec.isZero())
			NTM_MoveTo(target.areaid, parseInt(target.x + _vec.x), parseInt(target.y + _vec.y), 0);
	}
	
	_immuneTarget = MWA_CheckMonsterImmunity(target);
	
	if(_immuneTarget && NTConfig_BehaviourOnImmuneMonster == 2 && !(target.spectype&0x02) && me.areaid != 131 || MWA_CheckAttackTimeLimit(target)) // Skip the target
	{
		_MWA_SkipList.push(target.gid);

		return 1;
	}

	if(_immuneTarget)
	{	
		if(NTConfig_BehaviourOnImmuneMonster == 3 && NTConfig_AttackSkill[8] > 0) // Attack the target using the selected skill
		{
			if(!NTA_PaladinCastSkillInt(8, target))
				return 2;

			return 3;
		}
		else if(NTConfig_BehaviourOnImmuneMonster == 1 && MWA_FindNearbyMonsters(15, target) < 3 && NTC_GetMerc())// Get close so the merc can attack the target
		{
			if(GetDistance(me, target) > 5)
				NTM_MoveTo(target.areaid, target.x + 3, target.y + 3);

			NTC_Delay(100);

			return 2;
		}
	}
		
	if(firstorder && NTConfig_AttackSkill[0] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[0]) < 100)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[0] || !CheckCollision(me, target, 4))
		{
			var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[0], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}

		if(!NTC_CastSkill(NTConfig_AttackSkill[0], _NTA_SkillHand[0], target))
			return 2;

		return 3;
	}

	_primaryindex = (target.spectype&0x0A) ? 1 : 3;
	
	if(NTA_GetResistance(target, _NTA_SkillDamage[_primaryindex]) < 100 || MWA_IsUndead(target) && NTConfig_AttackSkill[_primaryindex + 1] == 119 && _NTA_SkillDamage[_primaryindex] == NTA_DAMAGE_PHYSICAL)
	{
		if(_NTA_SkillRange[_primaryindex] < 4 && !CheckCollision(target.areaid, target.x, target.y, 1))
			return 1;

		if(!NTA_PaladinCastSkillInt(_primaryindex, target))
			return 2;

		return 3;
	}

	if(NTConfig_AttackSkill[5] > 0 && NTA_GetResistance(target, NTA_GetDamageType(NTConfig_AttackSkill[5], target, 5)) < 100)
	{
		if(_NTA_SkillRange[5] < 4 && !CheckCollision(target.areaid, target.x, target.y, 1))
			return 1;
		
		if(!NTA_PaladinCastSkillInt(5, target))
			return 2;

		return 3;
	}

	return 1;
}

function NTA_PaladinCastSkillInt(index, target)
{
	if(NTConfig_AttackSkill[index] == MWS_BLESSED_HAMMER)
	{
		if(me.x-target.x < 1 || me.x-target.x > 2 || me.y-target.y < 1 || me.y-target.y > 2)
		{
			if(CheckCollision(target.areaid, target.x+2, target.y+2, 1))
			{
				switch(Random(0, 2))
				{
					case 0:
						NTM_MoveTo(target.areaid, target.x + 1, target.y, 0);
						break;
					case 1:
						NTM_MoveTo(target.areaid, target.x + 2, target.y - 1, 0);
						break;
					default:
						NTM_MoveTo(target.areaid, target.x + 2, target.y, 0);
				}
			}
			else if(me.x-target.x < -4 || me.x-target.x > 2 || me.y-target.y < 0 || me.y-target.y > 2)
				NTM_MoveTo(target.areaid, target.x-4, target.y, 0);
		}
	}
	else
	{
		if(GetDistance(me, target) > _NTA_SkillRange[index] || !CheckCollision(me, target, 4))
		{
			var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
	}
	
	if(target.classid == 704 && NTConfig_AttackSkill[7] > 0)
		NTC_PutSkill(NTConfig_AttackSkill[7], NTC_HAND_RIGHT);
	else if(NTConfig_AttackSkill[index + 1] > 0)
		NTC_PutSkill(NTConfig_AttackSkill[index + 1], NTC_HAND_RIGHT);

	return NTC_CastSkill(NTConfig_AttackSkill[index], _NTA_SkillHand[index], target);
}

function NTA_BarbarianAttackPatternInt()
{
	var _maxindex, _maxskill;
	var _avgskilllevel = new Array();

	_avgskilllevel[0] = me.GetSkill(MWS_WHIRLWIND, false);

	_maxindex = -1;
	_maxskill = 0;

	for(var i = 0 ; i < _avgskilllevel.length ; i++)
	{
		if(_avgskilllevel[i] > _maxskill)
		{
			_maxindex = i;
			_maxskill = _avgskilllevel[i];
		}
	}

	switch(_maxindex)
	{
	case 0: // Whirlwind
		NTConfig_AttackSkill[1] = MWS_WHIRLWIND;
		NTConfig_AttackSkill[3] = MWS_WHIRLWIND;
		NTConfig_AttackSkill[5] = MWS_BERSERK;
		break;
	}

	return (NTConfig_AttackSkill[1] && NTConfig_AttackSkill[3]);
}

function NTA_BarbarianAttackInt(target, firstorder)
{
	var _primaryindex, _immuneTarget;
		
	if(_MWA_Attack_Slot < 0)
	{
		_MWA_Attack_Slot = MWC_GetSlotID("attack");
		
		if(_MWA_Attack_Slot < 0)
			return 1;
	}
	
	NTC_SwapWeapons(_MWA_Attack_Slot);
	
	if(NTTMGR_CheckCurse(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe))
	{
		if(!NTTMGR_VisitTown())
			return 0;
	}
	
	if(_MWA_SkipList.indexOf(target.gid) > -1)
		return 1;
		
	if(MWConfig_AttacksBeforeRepositioning > 0 && _MWA_Attack_Time[3] % MWConfig_AttacksBeforeRepositioning == 0)
	{
		var _vec = MWA_GetEvasionVector(4, 2, target);
		
		if(_vec && !_vec.isZero())
			NTM_MoveTo(target.areaid, parseInt(target.x + _vec.x), parseInt(target.y + _vec.y), 0);
	}
		
	_immuneTarget = MWA_CheckMonsterImmunity(target);
		
	if(_immuneTarget && NTConfig_BehaviourOnImmuneMonster == 2 && !(target.spectype&0x02) && me.areaid != 131 || MWA_CheckAttackTimeLimit(target))
	{
		_MWA_SkipList.push(target.gid);
		
		return 1;
	}
	
	if(_immuneTarget)
	{	
		if(NTConfig_BehaviourOnImmuneMonster == 3 && NTConfig_AttackSkill[8] > 0) // Attack the target using the selected skill
		{
			if(!NTA_BarbarianCastSkillInt(8, target))
				return 2;

			return 3;
		}
		else if(NTConfig_BehaviourOnImmuneMonster == 1 && MWA_FindNearbyMonsters(15, target) < 3 && NTC_GetMerc())// Get close so the merc can attack the target
		{
			if(GetDistance(me, target) > 5)
				NTM_MoveTo(target.areaid, target.x + 2, target.y + 2);

			NTC_Delay(100);

			return 2;
		}
	}
	
	if(firstorder && NTConfig_AttackSkill[0] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[0]) < 100)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[0] || !CheckCollision(me, target, 4))
		{
			var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[0], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}

		if(!NTC_CastSkill(NTConfig_AttackSkill[0], _NTA_SkillHand[0], target))
			return 2;

		return 3;
	}

	_primaryindex = (target.spectype&0x0A) ? 1 : 3;

	if(NTA_GetResistance(target, _NTA_SkillDamage[_primaryindex]) < 100)
	{
		if((_NTA_SkillRange[_primaryindex] < 4 || NTConfig_AttackSkill[_primaryindex] == 151) && !CheckCollision(target.areaid, target.x, target.y, 1))
			return 1;

		if(!NTA_BarbarianCastSkillInt(_primaryindex, target))
			return 2;

		return 3;
	}

	if(NTConfig_AttackSkill[5] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[5]) < 100)
	{
		if((_NTA_SkillRange[5] < 4 || NTConfig_AttackSkill[5] == MWS_WHIRLWIND) && !CheckCollision(target.areaid, target.x, target.y, 1))
			return 1;

		if(!NTA_BarbarianCastSkillInt(5, target))
			return 2;

		return 3;
	}

	return 1;
}

function NTA_BarbarianCastSkillInt(index, target)
{
	if(NTConfig_AttackSkill[index] == MWS_WHIRLWIND)
	{
		var _cast, _vec;

		if(GetDistance(me, target) > _NTA_SkillRange[index] || !CheckCollision(me, target, 5))
		{
			var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index], 5);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
		
		_cast = new coord();
		_vec = new vector(target.x - me.x, target.y - me.y);
		
		if(!_vec)
			return false;
			
		_vec.setlength(4);
		_angles = new Array(30, -60, 90, -120, 150, -180);
			
		for(var i = 0; i < _angles.length; i++)
		{
			_cast.x = parseInt(target.x + _vec.x);
			_cast.y = parseInt(target.y + _vec.y);
			
			if(CheckCollision(me.areaid, _cast.x, _cast.y, 0))
				break;
				
			_vec.rotate(_angles[i]);
		}
		
		return NTC_CastSkill(NTConfig_AttackSkill[index], _NTA_SkillHand[index], _cast.x, _cast.y);
	}

	if(GetDistance(me, target) > _NTA_SkillRange[index] || !CheckCollision(me, target, 4))
	{
		var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index], 4);

		if(_pos)
			NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
	}

	return NTC_CastSkill(NTConfig_AttackSkill[index], _NTA_SkillHand[index], target);
}

function NTA_DruidAttackPatternInt()
{
	return false;
}

function NTA_DruidAttackInt(target, firstorder)
{
	var _primaryindex, _immuneTarget;

	if(NTTMGR_CheckCurse(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe))
	{
		if(!NTTMGR_VisitTown())
			return 0;
	}

	if(_MWA_SkipList.indexOf(target.gid) > -1)
		return 1;
		
	if(firstorder)
		NTP_DoPrecast(false);
		
	if(MWConfig_AttacksBeforeRepositioning > 0 && _MWA_Attack_Time[3] % MWConfig_AttacksBeforeRepositioning == 0)
	{
		var _vec = MWA_GetEvasionVector(4, 2, target);
		
		if(_vec && !_vec.isZero())
			NTM_MoveTo(target.areaid, parseInt(target.x + _vec.x), parseInt(target.y + _vec.y), 0);
	}
	
	_immuneTarget = MWA_CheckMonsterImmunity(target);
	
	if(_immuneTarget && NTConfig_BehaviourOnImmuneMonster == 2 && !(target.spectype&0x02) && me.areaid != 131 || MWA_CheckAttackTimeLimit(target)) // Skip the target
	{
		_MWA_SkipList.push(target.gid);

		return 1;
	}

	if(_immuneTarget)
	{	
		if(NTConfig_BehaviourOnImmuneMonster == 3 && NTConfig_AttackSkill[8] > 0) // Attack the target using the selected skill
		{
			if(!NTA_DruidCastSkillInt(8, target))
				return 2;

			return 3;
		}
		else if(NTConfig_BehaviourOnImmuneMonster == 1 && MWA_FindNearbyMonsters(15, target) < 3 && NTC_GetMerc())// Get close so the merc can attack the target
		{
			if(GetDistance(me, target) > 5)
				NTM_MoveTo(target.areaid, target.x + 3, target.y + 3);

			NTC_Delay(100);

			return 2;
		}
	}
		
	if(firstorder && NTConfig_AttackSkill[0] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[0]) < 100)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[0] || !CheckCollision(me, target, 4))
		{
			var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[0], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}

		if(!NTC_CastSkill(NTConfig_AttackSkill[0], _NTA_SkillHand[0], target))
			return 2;

		return 3;
	}

	_primaryindex = (target.spectype&0x0A) ? 1 : 3;
	
	if(NTA_GetResistance(target, _NTA_SkillDamage[_primaryindex]) < 100 || MWA_IsUndead(target) && NTConfig_AttackSkill[_primaryindex + 1] == 119 && _NTA_SkillDamage[_primaryindex] == NTA_DAMAGE_PHYSICAL)
	{
		if(_NTA_SkillRange[_primaryindex] < 4 && !CheckCollision(target.areaid, target.x, target.y, 1))
			return 1;

		if(!NTA_DruidCastSkillInt(_primaryindex, target))
			return 2;

		return 3;
	}

	if(NTConfig_AttackSkill[5] > 0 && NTA_GetResistance(target, NTA_GetDamageType(NTConfig_AttackSkill[5], target, 5)) < 100)
	{
		if(_NTA_SkillRange[5] < 4 && !CheckCollision(target.areaid, target.x, target.y, 1))
			return 1;
		
		if(!NTA_DruidCastSkillInt(5, target))
			return 2;

		return 3;
	}

	return 1;
}

function NTA_DruidCastSkillInt(index, target)
{
	var _pos;

	if(me.GetSkillStatus(NTConfig_AttackSkill[index]) != 8)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[index] || !CheckCollision(me, target, 4))
		{
			_pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
		
		return NTC_CastSkill(NTConfig_AttackSkill[index], _NTA_SkillHand[index], target);
	}

	if(NTConfig_AttackSkill[index + 1] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[index + 1]) <= 99)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[index+1] || !CheckCollision(me, target, 4))
		{
			_pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index + 1], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
		
		return NTC_CastSkill(NTConfig_AttackSkill[index + 1], _NTA_SkillHand[index + 1], target);
	}

	for(var i = 0; i < 25; i++)
	{
		NTC_Delay(NTC_DELAY_FRAME);

		if(me.GetSkillStatus(NTConfig_AttackSkill[index]) != 8)
			break;
	}

	return false;
}

function NTA_AssassinAttackPatternInt()
{
	return true;
}

function NTA_AssassinAttackInt(target, firstorder)
{
	var _pos, _trapPos, _index, _vec;

	if(NTTMGR_CheckCurse(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe))
	{
		if(!NTTMGR_VisitTown())
			return 0;
	}

	if(_MWA_SkipList.indexOf(target.gid) > -1)
		return 1;
		
	if(MWConfig_AttacksBeforeRepositioning > 0 && _MWA_Attack_Time[3] % MWConfig_AttacksBeforeRepositioning == 0)
	{
		_vec = MWA_GetEvasionVector(4, 2, target);
		
		if(_vec && !_vec.isZero())
			NTM_MoveTo(target.areaid, parseInt(target.x + _vec.x), parseInt(target.y + _vec.y), 0);
	}
	
	_immuneTarget = MWA_CheckMonsterImmunity(target);
	
	if(_immuneTarget && NTConfig_BehaviourOnImmuneMonster == 2 && !(target.spectype&0x02) && me.areaid != 131 || MWA_CheckAttackTimeLimit(target)) // Skip the target
	{
		_MWA_SkipList.push(target.gid);

		return 1;
	}

	if(_immuneTarget)
	{	
		if(NTConfig_BehaviourOnImmuneMonster == 3 && NTConfig_AttackSkill[8] > 0) // Attack the target using the selected skill
		{
			if(!NTA_AmazonCastSkillInt(8, target))
				return 2;

			return 3;
		}
		else if(NTConfig_BehaviourOnImmuneMonster == 1 && MWA_FindNearbyMonsters(15, target) < 3 && NTC_GetMerc())// Get close so the merc can attack the target
		{
			if(GetDistance(me, target) > 5)
				NTM_MoveTo(target.areaid, target.x + 2, target.y + 2);

			NTC_Delay(100);

			return 2;
		}
	}
	
	if(firstorder && NTConfig_AttackSkill[0] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[0]) < 100 && me.GetSkillStatus(NTConfig_AttackSkill[0]) != 8)
	{
		if(GetDistance(me, target) > 20 || !CheckCollision(me, target, 4))
		{
			_pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, 20, 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}

		if(!NTC_CastSkill(NTConfig_AttackSkill[0], _NTA_SkillHand[0], target))
			return 2;

		return 3;
	}

	if(!_MWA_Traps)
	{
		_MWA_Traps = new MWA_Traps(target);
		
		return 2;
	}
	
	if(_MWA_Traps.Refresh(target) && _MWA_Traps.Active.length < _MWA_Traps.MAXQUANTITY)
	{
		_index = -1;
		
		if(target.spectype&0x0A)
		{
			if(NTConfig_AttackSkill[1] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[1]) <= 99 && _MWA_Traps.GetQuantity(NTConfig_AttackSkill[1]) < MWConfig_TrapRatio[0][0])
				_index = 1;
			else if(NTConfig_AttackSkill[2] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[2]) <= 99 && _MWA_Traps.GetQuantity(NTConfig_AttackSkill[2]) < MWConfig_TrapRatio[0][1])
				_index = 2;
		}
		else
		{
			if(NTConfig_AttackSkill[3] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[3]) <= 99 && _MWA_Traps.GetQuantity(NTConfig_AttackSkill[3]) < MWConfig_TrapRatio[1][0])
				_index = 3;
			else if(NTConfig_AttackSkill[4] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[4]) <= 99 && _MWA_Traps.GetQuantity(NTConfig_AttackSkill[4]) < MWConfig_TrapRatio[1][1])
				_index = 4;
		}

		if(_index > -1)
		{
			_trapPos = _MWA_Traps.GetTrapPosition(_NTA_SkillRange[_index][1]);
				
			if(_trapPos)
			{
				_trapPos.areaid = target.areaid;

				if(GetDistance(me , _trapPos) > _NTA_SkillRange[_index][0] || !CheckCollision(me.areaid, _trapPos.x, _trapPos.y, 2))
				{
					_pos = me.GetOptimalAttackPos(_trapPos.areaid, _trapPos.x, _trapPos.y, _NTA_SkillRange[_index][0], 2);

					if(_pos)
						NTM_MoveTo(_trapPos.areaid, _pos[0], _pos[1], 0);
				}
				
				if(!NTC_CastSkill(NTConfig_AttackSkill[_index], _NTA_SkillHand[_index], _trapPos.x, _trapPos.y))
					return 2;
			}
			else
				return 2;
			
			return 3;
		}
	}
	
	if(NTC_GetSkillLevel(MWS_TELEPORT) > 0 && MWA_CalcDistToClosestMonster() < 3 && MWConfig_KeepDistanceToMonsters && MWA_AreaCheckEvading(me.areaid))
	{
		if(!MWA_MoveAwayFromMonster(target))
			return 2;

		return 3;
	}
		
	if(NTConfig_AttackSkill[5] > 0 && (NTA_GetResistance(target, _NTA_SkillDamage[5]) <= 99 || NTA_GetResistance(target, _NTA_SkillDamage[6]) <= 99))
	{
		if(!NTA_AssassinCastSkillInt(5, target))
			return 2;

		return 3;
	}
		
	return 1;
}

function NTA_AssassinCastSkillInt(index, target)
{
	if(NTA_GetResistance(target, _NTA_SkillDamage[index]) <= 99 && me.GetSkillStatus(NTConfig_AttackSkill[index]) != 8)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[index] || !CheckCollision(me, target, 4))
		{
			var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
		
		return NTC_CastSkill(NTConfig_AttackSkill[index], _NTA_SkillHand[index], target);
	}
	
	if(NTA_GetResistance(target, _NTA_SkillDamage[index + 1]) <= 99 && NTConfig_AttackSkill[index + 1] > 0)
	{
		if(GetDistance(me, target) > _NTA_SkillRange[index + 1] || !CheckCollision(me, target, 4))
		{
			var _pos = me.GetOptimalAttackPos(target.areaid, target.x, target.y, _NTA_SkillRange[index + 1], 4);

			if(_pos)
				NTM_MoveTo(target.areaid, _pos[0], _pos[1], 0);
		}
		return NTC_CastSkill(NTConfig_AttackSkill[index + 1], _NTA_SkillHand[index + 1], target);
	}

	for(var i = 0; i < 25; i++)
	{
		NTC_Delay(NTC_DELAY_FRAME);

		if(me.GetSkillStatus(NTConfig_AttackSkill[index]) != 8)
			break;
	}

	return false;
}

function MWA_UseStaticOnTarget(monster)
{
	if(MWConfig_StaticTargets.length == 0)
		return true;
		
	if(me.diff == 0 || !monster || !monster.name)
		return false;

	for(var i = 0; i < MWConfig_StaticTargets.length; i++)
	{
		if(MWConfig_StaticTargets[i] == monster.classid || typeof MWConfig_StaticTargets[i] == "string" && monster.name.toLowerCase().indexOf(MWConfig_StaticTargets[i].toLowerCase()) > -1)
			return true;
	}
	
	return false;
}

function MWA_CheckForCloseMonsters(range)
{
	var _monstersClose, _checkMonster;
	
	if(range < 1 || arguments.length < 1)
		return false;
		
	_monstersClose = false;
	_checkMonster = NTC_FindUnit(NTC_UNIT_MONSTER);
	
	if(_checkMonster)
	{	
		do
		{
			if(_checkMonster.IsAttackable() && GetDistance(me.x, me.y, _checkMonster.x, _checkMonster.y) < range && NTA_IsValidMonster(_checkMonster))
			{	
				_monstersClose = true;
				break;
			}
		} while(_checkMonster.GetNext());
	}
	
	return _monstersClose;
}

function MWA_CalcDistToClosestMonster(x, y, calcAverage)
{
	var _dist, _minDist, _checkMonster, _distances;
	
	if(arguments.length < 2)
	{
		x = me.x;
		y = me.y;
	}
	
	if(arguments.length < 3)
		calcAverage = false;
	
	_checkMonster = NTC_FindUnit(NTC_UNIT_MONSTER);
	_dist = 1E3;
	_minDist = 1E3;
	_distances = new Array();
		
	if(_checkMonster)
	{	
		do
		{
			if(_checkMonster.IsAttackable() && NTA_IsValidMonster(_checkMonster))
			{	
				_dist = GetDistance(x, y, _checkMonster.x, _checkMonster.y);
				
				if(calcAverage)
					_distances.push(_dist);
				else if(_dist < _minDist)
					_minDist = _dist;
			}
		} while(_checkMonster.GetNext());
	}
	
	if(calcAverage)
	{
		_dist = 0;
		
		for(var i = 0; i < _distances.length; i++)
			_dist += _distances[i];
			
		if(_distances.length > 0)
			return _dist / _distances.length;
	}
	
	return _minDist;
}

function MWA_AreaCheckEvading(areaid)
{
	if(MWConfig_EvasionExceptions.length > 0 && MWConfig_EvasionExceptions.indexOf(areaid) != -1)
		return false;
	else
		return true;
}

function MWA_GetEvasionVector(length, offset, origin, rotationAngle)
{
	var _vec, _targetVec, _maxDistIndex, _dist, _maxDist, _destx, _desty, _path, _pathX, _pathY;
	
	_targetVec = new Array();
	
	if(arguments.length < 3 || !origin.x || !origin.y || !origin.areaid)
		origin = me;
	
	if(arguments.length < 4 || isNaN(rotationAngle))
		rotationAngle = 22.5;
	
	_vec = new vector(1, 0);
	
	if(!_vec)
		return new vector();
	
	for(var i = 0; i < parseInt(360 / rotationAngle); i++)
	{
		_vec.rotate(rotationAngle);
		_vec.normalize();
		_targetVec.push(new vector(_vec.x, _vec.y));
	}

	_maxDistIndex = -1;
	_maxDist = 0;
	_dist = 0;

	// Find the spot with the largest distance to the next monster
	for(var i = 0; i < _targetVec.length; i++)
	{
		_destx = origin.x + Math.round(_targetVec[i].x * length);
		_desty = origin.y + Math.round(_targetVec[i].y * length);
		_path = GetPath(origin.areaid, origin.x, origin.y, _destx, _desty, true);
		
		if(_path)
		{
			_pathX = _path[_path.length - 1][0];
			_pathY = _path[_path.length - 1][1];
			
			if(GetDistance(_destx, _desty, _pathX, _pathY) > offset || !CheckCollision(origin.areaid, _pathX, _pathY, 0)) // DEBUG !CheckCollision(origin.areaid, origin.x, origin.y, _pathX, _pathY, 0)
				continue;
				
			_dist = MWA_CalcDistToClosestMonster(_pathX, _pathY);
			
			if(_dist > _maxDist)
			{
				_maxDist = _dist;
				_maxDistIndex = i;			
			}
		}
	}
	
	if(_maxDistIndex != -1)
		return _targetVec[_maxDistIndex];
	else
		return new vector();
}

function MWA_MoveAwayFromMonster(target)
{
	var _vec, _targetVec, _spotIndex, _targetDist, _destx, _desty, _path;
	
	const _VEC_LENGTH = 8; // Length of the vector pointing to the target spot
	const _DELTA_DEST = 2; // Maximum distance to the target location after moving
	
	_targetVec = MWA_GetEvasionVector(_VEC_LENGTH, _DELTA_DEST);
		
	if(_targetVec && !_targetVec.isZero())
	{
		_targetVec.setlength(_VEC_LENGTH);
		_targetDist = MWA_CalcDistToClosestMonster(me.x + Math.round(_targetVec.x), me.y + Math.round(_targetVec.y));
		
		if(_targetDist > MWA_CalcDistToClosestMonster() && _targetDist > 4)
		{
			_destx = me.x + Math.round(_targetVec.x);
			_desty = me.y + Math.round(_targetVec.y);

			if(MWConfig_ShowOverheadStatus)
				MWC_PrintOverheadStatus("Evading...");
			
			NTM_MoveTo(me.areaid, _destx, _desty, 1);
				
			if(GetDistance(me.x, me.y, _destx, _desty) < _DELTA_DEST)
				return true;
		}
	}
	
	_targetVec = MWA_GetEvasionVector(_VEC_LENGTH * 2.5, _DELTA_DEST, target);
		
	if(_targetVec && !_targetVec.isZero())
	{
		_targetVec.setlength(_VEC_LENGTH * 2.5);
		_targetDist = MWA_CalcDistToClosestMonster(me.x + Math.round(_targetVec.x), me.y + Math.round(_targetVec.y));

		if(_targetDist > MWA_CalcDistToClosestMonster())
			return NTM_MoveTo(me.areaid, target.x + Math.round(_targetVec.x), target.y + Math.round(_targetVec.y), 1);
	}
	
	return false;
}

function MWA_FindNearbyMonsters(range, target)
{
	var _monster;
	var _count = 0;
		
	if(arguments.length < 1)
		range = 20;
	if(arguments.length < 2)
		target = me;
	
	_monster = NTC_FindUnit(NTC_UNIT_MONSTER);
	
	if(_monster)
	{
		do
		{
			if(_monster.IsAttackable() && NTA_IsValidMonster(_monster) && GetDistance(target, _monster) < range)
				_count++;
		}
		while(_monster.GetNext());
	}
	return _count;
}

function MWA_CheckInfinity()
{
	var _merc, _items;
	
	_merc = NTC_GetMerc();

	if(!_merc)
		return false;
		
	_items = _merc.GetItems();
	
	if(_items)
	{
		for(var i = 0; i < _items.length; i++)
		{
			if(_items[i].itemloc == 4)
			{
				if(_items[i].itemprefix == 0x5056) // Infinity
					_MWA_Merc_Weapon_Type = 1;
				else if( _items[i].GetStat(198) == 0x21) // The Reaper's Toll
					_MWA_Merc_Weapon_Type = 2;
				
				return true;
			}
		}
		
		_MWA_Merc_Weapon_Type = 0;
	}
	
	return false;
}

function MWA_CheckMonsterImmunity(target)
{
	var _resistance;
	
	for(var i = 0; i < MWConfig_CheckImmunitySkills.length; i++)
	{
		if(isNaN(MWConfig_CheckImmunitySkills[i]) || MWConfig_CheckImmunitySkills[i] < 0 || MWConfig_CheckImmunitySkills[i] >= NTConfig_AttackSkill.length)
			return false;
		
		if(NTConfig_AttackSkill[MWConfig_CheckImmunitySkills[i]] == 0)
			continue;
			
		if(MWA_CheckMonsterResistance(target, NTA_GetDamageType(NTConfig_AttackSkill[MWConfig_CheckImmunitySkills[i]], target, MWConfig_CheckImmunitySkills[i])))
			return false;
	}

	return MWConfig_CheckImmunitySkills.length > 0;
}

function MWA_CheckMonsterResistance(target, damageType)
{
	var _res;
	
	if(_MWA_Merc_Weapon_Type == -1)
		MWA_CheckInfinity();
	
	_res = NTA_GetResistance(target, damageType);
	
	if(_res < 100)
		return true;
		
	if(_MWA_Merc_Weapon_Type == 1 && damageType >= NTA_DAMAGE_FIRE && damageType <= NTA_DAMAGE_COLD) // Infinity
	{
		if(target.GetState(28))
			return false;
			
		return (_res < 117 && NTC_GetMerc())
	}
	else if(_MWA_Merc_Weapon_Type == 2 && damageType == NTA_DAMAGE_PHYSICAL) // Reaper's Toll
	{
		if(MWA_GetCurseState(MWS_DECREPIFY, target) || MWA_GetCurseState(MWS_AMPLIFY_DAMAGE, target))
			return false;
	
		return (_res < 150 && NTC_GetMerc());
	}
		
	return false;
}

function MWA_CalcCorpseExplosionRadius()
{
	// Calculate the approximate CE Range using a simple linear regression
	if(me.GetSkill(74, true) > 0)
		return (0.333684 * me.GetSkill(74, true) + 2.29632).toFixed(1);
	else
		return 0.0;
}

function MWA_GetClosestCorpseGID(x, y, range)
{
	var _gid, _dist, _mindist, _corpses;
	
	if(arguments.length < 3)
		range = 50;
		
	_mindist = 10000;
	_gid = 0;
	
	_corpses = NTC_FindUnit(NTC_UNIT_MONSTER);
	
	if(_corpses)
	{
		do
		{
			if(MWL_CheckLootStatus(_corpses) && MWL_IsLootableMonster(_corpses.classid) && _corpses.name != GetLocaleString(5386) && _corpses.mode == 12) // Only check valid corpses that can be used for corpse explosion or minions
			{
				_dist = GetDistance(x, y, _corpses.x, _corpses.y);
				
				if(_dist < _mindist && _dist <= range)
				{
					_mindist = _dist;
					_gid = _corpses.gid;
				}
			}
		} while(_corpses.GetNext());
	}
	
	return _gid;
}


function MWA_IsHazardousMonster(target)
{
	var _viciousness, _damageType, _count;
	
	_viciousness = 0;
	_damageType = -1;
	
	switch(target.classid)
	{
		// Physical damage (type 0)
		case 310: // Doom Knight
		case 312: // Oblivion Knight
		case 472: // Hell Temptress WSK
		case 510: // Death Lord WSK
		case 571: // Minion Of Destruction
		case 638: // Vile Witch WSK
		case 691: // Undead Soul Killer Throne
		case 700: // Doom Knight Throne
		case 702: // Oblivion Knight Throne
			_damageType = 0;
			_viciousness++;
			break;
		// Elemental damage (type 1)
		case 640: // Black Soul WSK
		case 641: // Black Soul Throne
			_damageType = 1;
			_viciousness++;
			break;	
		// Both physical and elemental damage (type -1)
		case 345: // Council Member
		case 346: // Council Member
		case 347: // Council Member
		case 362: // Venom Lord
		case 558: // Venom Lord Throne
			_viciousness++;
			break;	
	}
		
	_count = MWA_FindNearbyMonsters(6, target);
	
	if(_count > 2)
		_viciousness++;
	else if(_count > 4)
		_viciousness += 2;
	else if(_count > 6)
		_viciousness += 3;

	if(target.GetState(29))	// Conviction
		_viciousness += 2;
	
	if(_damageType == 0 || _damageType == -1)
	{
		if(target.GetState(49))	// Fanatism 
			_viciousness += 2;
		
		if(target.GetState(33)	// Might
		|| target.GetState(40))	// Blessed Aim
			_viciousness++;
			
		if(me.GetState(9) 		// Amplify Damage
		|| me.GetState(60))		// Decrepify
			_viciousness++;
	}
	
	if(_damageType == 1 || _damageType == -1)
	{
		if(me.GetState(28) 		// Convicted
		|| me.GetState(61))		// Lower Resist
			_viciousness++;
	}
	
	return _viciousness > 3;
}

function MWA_SetMinionCounts()
{
	// Define the maximum amount of Skeletons
	if(MWConfig_SkeletonMinionCount <= MWC_GetMaxMinionCount(NTConfig_AttackSkill[4]))
		_MWA_Minion_Counts[0] = MWConfig_SkeletonMinionCount;
	else
		_MWA_Minion_Counts[0] = MWC_GetMaxMinionCount(NTConfig_AttackSkill[4]);
		
	// Define the maximum amount of Mages
	if(MWConfig_MageMinionCount <= MWC_GetMaxMinionCount(NTConfig_AttackSkill[5]))
		_MWA_Minion_Counts[1] = MWConfig_MageMinionCount;
	else
		_MWA_Minion_Counts[1] = MWC_GetMaxMinionCount(NTConfig_AttackSkill[5]);

	// Define the maximum amount of Revives
	if(MWConfig_ReviveMinionCount <= MWC_GetMaxMinionCount(NTConfig_AttackSkill[6]))
		_MWA_Minion_Counts[2] = MWConfig_ReviveMinionCount;
	else
		_MWA_Minion_Counts[2] = MWC_GetMaxMinionCount(NTConfig_AttackSkill[6]);
}

function MWA_RaiseMinions()
{
	var _corpse, _gid, _gidsHandled, _count;
	
	if(me.classid != NTC_CHAR_CLASS_NECROMANCER)
		return false;
		
	_gidsHandled = new Array();
	
	MWA_SetMinionCounts();
	
	for(var i = 0; i < 100; i++)
	{
		_gid = MWA_GetClosestCorpseGID(me.x, me.y, 30);
		
		if(_gid == 0) // Stop if there are not any corpses nearby
			break;
		
		if(_gidsHandled.indexOf(_gid) > -1)
			continue;
			
		_corpse = NTC_FindUnit(NTC_UNIT_MONSTER, _gid); // Get the unit of the closest corpse
		
		if(_corpse)
		{
			_gidsHandled.push(_gid);
			
			if(NTC_GetSkillLevel(NTConfig_AttackSkill[4]) > 0) // Summon first minion type until the desired number of minions is reached
			{
				_count = MWC_GetMinionCount(NTConfig_AttackSkill[4]);
				
				if(_count < _MWA_Minion_Counts[0] && (NTConfig_AttackSkill[4] != 95 || !(_corpse.spectype&0x0E)))
				{
					if(MWConfig_ShowOverheadStatus)
					{
						if(NTConfig_AttackSkill[4] == 95)
							MWC_PrintOverheadStatus("Reviving " + _corpse.name + " (" + (_count + 1) + "/" +_MWA_Minion_Counts[0] + ")");
						else
							MWC_PrintOverheadStatus("Summoning " + MWC_GetMinionName(NTConfig_AttackSkill[4]) + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[0] + ")");
					}
					
					if(GetDistance(me, _corpse) > _NTA_SkillRange[4] || !CheckCollision(me, _corpse, 4) || !CheckCollision(me, _corpse, 2))
						NTM_MoveTo(_corpse.areaid, _corpse.x, _corpse.y, 0);

					NTC_CastSkill(NTConfig_AttackSkill[4], _NTA_SkillHand[4], _corpse);
					
					continue;
				}
			}
			
			if(NTC_GetSkillLevel(NTConfig_AttackSkill[5]) > 0) // Summon second minion type until the desired number of minions is reached
			{
				_count = MWC_GetMinionCount(NTConfig_AttackSkill[5]);
				
				if(_count < _MWA_Minion_Counts[1] && (NTConfig_AttackSkill[5] != 95 || !(_corpse.spectype&0x0E)))
				{
					if(MWConfig_ShowOverheadStatus)
					{
						if(NTConfig_AttackSkill[5] == 95)
							MWC_PrintOverheadStatus("Reviving " + _corpse.name + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[1] + ")");
						else
							MWC_PrintOverheadStatus("Summoning " + MWC_GetMinionName(NTConfig_AttackSkill[5]) + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[1] + ")");
					}
					
					if(GetDistance(me, _corpse) > _NTA_SkillRange[4] || !CheckCollision(me, _corpse, 4) || !CheckCollision(me, _corpse, 2))
						NTM_MoveTo(_corpse.areaid, _corpse.x, _corpse.y, 0);
					
					NTC_CastSkill(NTConfig_AttackSkill[5], _NTA_SkillHand[5], _corpse);
					
					continue;
				}
			}
			
			if(NTC_GetSkillLevel(NTConfig_AttackSkill[6]) > 0) // Summon third minion type until the desired number of minions is reached
			{
				_count = MWC_GetMinionCount(NTConfig_AttackSkill[6]);
				
				if(_count < _MWA_Minion_Counts[2] && (NTConfig_AttackSkill[6] != 95 || !(_corpse.spectype&0x0E)))
				{
					if(MWConfig_ShowOverheadStatus)
					{
						if(NTConfig_AttackSkill[6] == 95)
							MWC_PrintOverheadStatus("Reviving " + _corpse.name + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[2] + ")");
						else
							MWC_PrintOverheadStatus("Summoning " + MWC_GetMinionName(NTConfig_AttackSkill[6]) + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[2] + ")");
					}
					
					if(GetDistance(me, _corpse) > _NTA_SkillRange[4] || !CheckCollision(me, _corpse, 4) || !CheckCollision(me, _corpse, 2))
						NTM_MoveTo(_corpse.areaid, _corpse.x, _corpse.y, 0);
					
					NTC_CastSkill(NTConfig_AttackSkill[6], _NTA_SkillHand[6], _corpse);
					
					continue;
				}
			}
			
			// Stop if the the maximum number of each minion type is reached
			break;
		}
	}
	
	return true;
}

function MWA_CalcAverageMinionDistance(unit)
{
	var _monsters, _parent, _distances, _averageDist;
	
	_averageDist = 0.0;
	_distances = new Array();
	
	if(arguments.length < 1)
		unit = me;
	
	_monsters = NTC_FindUnit(NTC_UNIT_MONSTER);

	if(_monsters)
	{
		do
		{
			if(GetDistance(unit, _monsters) < 45)
			{
				_parent = _monsters.GetParent();
				
				if(_parent && _parent.name == me.name) // Check whether the unit (Merc, Skeleton, Mage, Revive or Golem) actually belongs to our char
					_distances.push(GetDistance(unit, _monsters));
			}
		} while(_monsters.GetNext());
	}
	
	// Calculate the average
	for(var i = 0; i < _distances.length; i++)
		_averageDist += _distances[i]; // Add all distances
	
	if(_distances.length != 0)
		_averageDist /= _distances.length; // Divide the sum by the number of distances
			
	return _averageDist; // Return true if the majority of minions is sharing the same position as our char --> minions stuck
}
function MWA_GetCurseState(skillid, target)
{
	if(!target || skillid < 66 || skillid > 91)
		return false;
	
	if((target.spectype & 0x04) && target.name.indexOf(GetLocaleString(11086)) != -1) // Ignore possessed champions that cannot be cursed
		return true;
		
	// Ignore foes that cannot be cursed anyway
	switch(target.classid)
	{
		case 194: // Blood Maggot Egg
		case 207: // Blood Hawk Nest
		case 497: // Catapult
		case 498: // Catapult
		case 499: // Catapult
		case 500: // Catapult
		case 516: // Catapult
		case 517: // Catapult
		case 518: // Catapult
		case 519: // Catapult
			return true;
	}
	
	switch(skillid)
	{
		case 66: // Amplify Damage
			return (target.GetState(9) != 0);
		case 71: // Dim Vision
			return (target.GetState(23) != 0);
		case 72: // Weaken
			return (target.GetState(19) != 0);
		case 76: // Iron Maiden
			return (target.GetState(55) != 0);
		case 77: // Terror
			return (target.GetState(56) != 0);
		case 81: // Confuse
			return (target.GetState(59) != 0);
		case 82: // Life Tap
			return (target.GetState(58) != 0);
		case 86: // Attract
			return (target.GetState(57) != 0);
		case 87: // Decrepify
			return (target.GetState(60) != 0);
		case 91: // Lower Resist
			return (target.GetState(61) != 0);
	}
	
	return false;
}

function MWA_CheckAttackTimeLimit(target)
{
	var _tickLimit;
	
	if(_MWA_Attack_Time.length > 0 && _MWA_Attack_Time[0] == target.gid) // If the target has been attacked before and its gid is saved in the array
	{
		_MWA_Attack_Time[3]++;
				
		if(GetTickCount() > _MWA_Attack_Time[1] + _MWA_Attack_Time[2]) // Check if the time limit exceeded yet
		{
			Print("ÿc1Attack time limit exceeded! Skipping " + target.name + "...");
			return true;
		}
	}
	else // The target has not been attacked before
	{
		// Determine the end time in ticks using the limits specified in the char config
		if((target.spectype & 0x02) && MWConfig_AttackTimeLimit[4] > 0) // Super Unique
			_tickLimit = 1E3 * MWConfig_AttackTimeLimit[1];
		else if((target.spectype & 0x04) && MWConfig_AttackTimeLimit[3] > 0) // Champion
			_tickLimit = 1E3 * MWConfig_AttackTimeLimit[2];
		else if((target.spectype & 0x08) && MWConfig_AttackTimeLimit[2] > 0) // Boss
			_tickLimit = 1E3 * MWConfig_AttackTimeLimit[3];
		else if((target.spectype & 0x10) && MWConfig_AttackTimeLimit[1] > 0) // Minion
			_tickLimit = 1E3 * MWConfig_AttackTimeLimit[4];
		else if(MWConfig_AttackTimeLimit[0] > 0) // All
			_tickLimit = 1E3 * MWConfig_AttackTimeLimit[0];
		else
			_tickLimit = 2 * GetTickCount(); // Set Attack time to "infinite" if no time limit is defined

		_MWA_Attack_Time = [target.gid, GetTickCount(), _tickLimit, 1]; // Save both the target's gid and the end time
	}
	
	return false;
}

function MWA_IsUndead(target)
{
	if(arguments.lenth < 1 || !target)
		return false;
		
	switch(target.classid)
	{
		case 0: // Skeleton
		case 1: // Returned
		case 2: // Bone Warrior
		case 3: // Burning Dead
		case 4: // Horror
		case 5: // Zombie
		case 6: // Hungry Dead
		case 7: // Ghoule
		case 9: // Plague Bearer
		case 38: // Ghost
		case 40: // Specter
		case 41: // Apparition
		case 96: // Dried Corpse
		case 98: // Embalmed
		case 99: // Preserved Dead
		case 101: // Hollow One
		case 102: // Guardian
		case 103: // Unraveler
		case 104: // Horadrim Ancient
		case 105: // Unraveler
		case 111: // Undead Scavenger
		case 131: // Ghoul Lord
		case 132: // Night Lord
		case 133: // Dark Lord
		case 134: // Blood Lord
		case 135: // The Banished
		case 170: // Skeleton Archer
		case 171: // Returned Archer
		case 172: // Bone Archer
		case 174: // Horror Archer
		case 215: // Undead Soul Killer
		case 276: // Bone Ash
		case 306: // Storm Caster
		case 310: // Doom Knight
		case 311: // Abyss Knight
		case 312: // Oblivion Knight
		case 365: // Griswold
		case 381: // Death Mage
		case 383: // Returned Mage
		case 384: // Bone Mage
		case 385: // Burning Dead mage
		case 387: // Returned Mage
		case 388: // Bone Mage
		case 390: // Horror Mage
		case 437: // Reanimated Horde
		case 438: // Prowling Dead
		case 440: // Defiled Warrior
		case 578: // Returned Archer
		case 608: // Carrion Bird
		case 620: // Returned Mage
		case 622: // Returned Mage
		case 623: // Horror Mage
		case 624: // Bone Mage
		case 626: // Horror Mage
		case 640: // Black Soul
		case 641: // Black Soul Throne
		case 669: // Horadrim Ancient
		case 670: // Horadrim Ancient
		case 696: // Ghoul Lord
		case 697: // Dark Lord
		case 698: // Unholy Corpse
		case 691: // Undead Soul Killer
		case 700: // Doom Knight
		case 702: // Oblivion Knight
		case 713: // Oblivion Knight
		case 726: // Horror Archer
		case 727: // Burning Dead Mage
		case 728: // Horror Mage
		case 729: // Bone Mage
		case 730: // Horror Mage
		case 731: // Dark Lord
			return true;
	}

	return false;
}

function MWA_IsPriorityTarget(target)
{
	if(arguments.lenth < 1 || !target)
		return false;
		
	switch(target.classid)
	{
		case 58: // Fallen Shaman
		case 59: // Carver Shaman
		case 60: // Devilkin Shaman
		case 61: // Dark Shaman
		case 62: // Warped Shaman
		case 68: // Sand Maggot
		case 69: // Rock Worm
		case 70: // Devourer
		case 101: // Hollow One
		case 102: // Guardian
		case 103: // Unraveler
		case 104: // Horadrim Ancient
		case 105: // Unraveler
		case 207: // Blood Hawk Nest
		case 238: // Sexton
		case 240: // Heirophant
		case 279: // Fetish Shaman
		case 280: // Flayer Shaman
		case 281: // Soul Killer Shaman
		case 298: // Flesh Spawner
		case 299: // Stygian Hag
		case 300: // Grotesque
		case 646: // Devilkin Shaman
		case 669: // Horadrim Ancient
		case 670: // Horadrim Ancient
		case 674: // Heirophant
		case 676: // Flesh Spawner
			return true;
	}

	return false;
}

function MWA_PrintAttackStatus(type, target)
{
	var _output, _attackTimeString;
	
	if(!MWConfig_ShowOverheadStatus || arguments.length < 2)
		return false;
		
	_attackTimeString = "";
	
	switch(type)
	{
		case 1:
			_output = "Killing ";
			break;
		default:
			_output = "Attacking ";
			break;
	}

	if(target.gid == _MWA_Attack_Time[0] && GetTickCount() - _MWA_Attack_Time[1] > 5E3)
		_attackTimeString = " [" + MWC_ConvertTicksToTimeString(GetTickCount() - _MWA_Attack_Time[1]) + "]";
	
	if(target.hp / target.hpmax > 0)
		return MWC_PrintOverheadStatus(_output + target.name + " " + (target.hp * 100 / target.hpmax).toFixed(0) + "%" + _attackTimeString);
	else
		return MWC_PrintOverheadStatus("Killed " + target.name + "!");
}

function MWA_Traps(target)
{
	this.Active;
	this.Target = target;
	
	this.MAXQUANTITY = 5;
	
	this.GetTrapPosition = MWA_Traps_GetTrapPosition;
	this.Refresh = MWA_Traps_Refresh;
	this.GetQuantity = MWA_Traps_GetQuantity;
	
	this.Refresh();
}

function MWA_Trap(unit)
{
	this.X = unit.x;
	this.Y = unit.y;
	this.GID = unit.gid;
	this.ClassID = unit.classid;
	this.Mode = unit.mode;
	
	this.RANGE = 20;
	
	this.IsValid = MWA_Trap_IsValid;
}

function MWA_Trap_IsValid(target)
{
	var _trap;
	
	if(!target)
		return false;
		
	_trap = NTC_FindUnit(NTC_UNIT_MONSTER, this.GID);
	
	if(!_trap || _trap.mode == 12) // The trap is either really far aways or already fired all its shots
		return false;
		
	if(_trap.mode == 8) // Traps that are currently fireing are considered valid
		return true;
		
	if(!CheckCollision(target, _trap, 2)) // The trap cannot attack the current target due to obstacles
		return false;
		
	if(GetDistance(this.X, this.Y, target.x, target.y) > this.RANGE) // The target is too far away from the trap
		return false;
		
	if(GetDistance(this.X, this.Y, me.x, me.y) > 40) // The trap is too far away from us
		return false;
		
	return true;
}

function MWA_Traps_GetTrapPosition(range)
{
	var _pos, _trapPos, _vec, _vecOrtho;
	const _DIST = 4;
	
	if(!this.Target || arguments.length < 1)
		return null;
		
	_pos = me.GetOptimalAttackPos(this.Target.areaid, this.Target.x, this.Target.y, range, 4);
	
	if(_pos)
	{
		_vec = new vector(this.Target.x - _pos[0], this.Target.y - _pos[1]);
		
		if(_vec)
		{
			_vecOrtho = new vector(_vec.x, _vec.y);
			
			if(_vecOrtho)
			{
				_vecOrtho.rotate(90);
					
				switch(this.Active.length)
				{
					case 4:
						_vec.setlength(_DIST);
						_vecOrtho.setlength(_DIST);
						break;
					case 3:
						_vec.setlength(_DIST);
						_vecOrtho.setlength(-1 * _DIST);
						break;
					case 2:
						_vec.setlength(_DIST / 2);
						_vecOrtho.setlength(_DIST / 2);
						break;
					case 1:
						_vec.setlength(_DIST / 2);
						_vecOrtho.setlength(_DIST / -2);
						break;
					default:
						return new coord(_pos[0], _pos[1]);
				}
				
				_trapPos = new coord(Math.round(_pos[0] + _vec.x + _vecOrtho.x), Math.round(_pos[1] + _vec.y + _vecOrtho.y));
				
				if(_trapPos && CheckCollision(this.Target.areaid, _trapPos.x, _trapPos.y, 0))
					return _trapPos;
			}
		}
		
		return new coord(_pos[0], _pos[1]);
	}

	return null;
}

function MWA_Traps_GetQuantity(skillid)
{
	var _count, _classid;
	
	_count = 0;
	
	switch(skillid)
	{
		case MWS_CHARGED_BOLT_SENTRY:
			_classid = MWC_MINION_CHARGED_BOLT_SENTRY;
			break;
		case MWS_WAKE_OF_FIRE:
			_classid = MWC_MINION_WAKE_OF_FIRE;
			break;
		case MWS_LIGHTNING_SENTRY:
			_classid = MWC_MINION_LIGHTNING_SENTRY;
			break;
		case MWS_WAKE_OF_INFERNO:
			_classid = MWC_MINION_WAKE_OF_INFERNO;
			break;
		case MWS_DEATH_SENTRY:
			_classid = MWC_MINION_DEATH_SENTRY;
			break;
	}
	
	for(var i = 0; i < this.Active.length; i++)
	{
		if(this.Active[i].IsValid(this.Target) && this.Active[i].ClassID == _classid)
			_count++;
	}
	
	return _count;
}

function MWA_Traps_Refresh(target)
{
	var _unit, _trap;
	
	this.Active = new Array();
	this.Target = target;
	
	_unit = NTC_FindUnit(NTC_UNIT_MONSTER);
	
	if(_unit)
	{
		do
		{
			if(!_unit.IsAttackable() && (_unit.classid >= MWC_MINION_WAKE_OF_FIRE && _unit.classid <= MWC_MINION_LIGHTNING_SENTRY || _unit.classid >= MWC_MINION_WAKE_OF_INFERNO && _unit.classid <= MWC_MINION_DEATH_SENTRY))
			{
				if(NTC_CheckOwner(_unit))
				{
					_trap = new MWA_Trap(_unit);
					
					if(_trap && _trap.IsValid(this.target))
						this.Active.push(_trap);
				}
			}
		} while(_unit.GetNext());
		
		return true;
	}
	
	return false;
}
Quote:
Originally Posted by koonak View Post
Hey mal ne frage zu den blauen/gelben items die er lootet um sie beim Vendor zu verkaufen. kann man das abstellen das er die lootet? mein inv ist eigentlich immer recht voll und wenn er dann 2 items lootet um die nur zu verkaufen geht er alle paar mob gruppen in die stadt und verkauft die, was natürlich das Mfn verlangsamt. habe bis jetzt nichts gefunden wo man das ausstellen kann.

ach und muddy falls du das liest, <3 das avoid feature.

hast du für die aktuelle eine neue pickit?(für die neue ladder) wenn ja könntest die vllt mal uppen?

mfg
Du meinste die Moneymaker? Diese werden grundsätzlich nur dann eingesammelt, wenn der Char danach unmittelbar in die Stadt geht und diese werden auch nur aufgehoben, solange Platz vorhanden ist.

Alle anderen Items gehen auf deine .nip Files zurück und für die bist du selber verantwortlich.

Und ja, natürlich habe ich meine .nip Files angepasst, aber das sind prinzipiell nur ein paar minimale Änderungen gegenüber meinen ursprünglichen .nips, die man eigentlich auch in 5 Minuten selber durchführen könnte.

Das hat dann auch den Vorteil, dass du selbst bestimmen kannst, was du gerne haben möchtets. Ich halte einfach wenig davon das von anderen zu übernehmen, denn was man haben möchte und was nicht ist doch eine recht subjektive Angelegenheit.

Denke ich werde meine aktuellen .nips trotzdem gleich mal vorne anhängen, aber ob dort alles drin ist kann ich nicht sagen, da müsst ihr selber nachschauen.

Quote:
Originally Posted by kal_el View Post
ich kriegte paar mal den snagit fehler...
deshalb die frage...
kommt der fehler wenn er das bestimmte item aufgehoben hat, oder bereits dann wenn er scant was rumliegt?
Sowohl als auch.

Für beide Fälle sind Szenarien denkbar. Hatte mich ein paar Seiten vorher mal darüber ausgelassen, wie dieser Abgleich im Grunde abläuft und wann kleinere Fehler zum Tragen kommen. .

Quote:
Originally Posted by gery68 View Post
Ich vermisse irgendwie das Pindl Script ohne Nilla!!!!!!!!!!

mfg
Gery
Fehlt aber nur in der Config, habe ich irgendwie vergessen.

Versuch es mal so:
Code:
MWConfig_Script.push(["NTPindleskin.ntj", 5]); NTConfig_NihlathakExtension = false;
Lg
Muddy
Muddy Waters is offline  
Thanks
1 User
Old 04/03/2011, 15:11   #1079
 
elite*gold: 0
Join Date: Oct 2010
Posts: 2
Received Thanks: 0
Danke schonmal, werds später ausprobieren. Wenn ich mich nicht wieder melde hats wohl funktioniert und ich hab vergessen, nochmal was zu schreiben. Quasi ein sorry im Vorraus ^^
hanshase99 is offline  
Old 04/03/2011, 16:37   #1080
 
elite*gold: 0
Join Date: Oct 2007
Posts: 32
Received Thanks: 1
Huhu, ich hab folgendes Problem:



Bot is soweit alles eingestellt. Der name ist auch richtig geschrieben. Also dadran kann es schonmal nicht liegen.
aduSe is offline  
Reply


Similar Threads Similar Threads
[Release] D2NT 3.1 1.13c
07/17/2016 - Diablo 2 - 91 Replies
hi, hab eben den d2nt3.1 gefunden. ein neues baba script is dabei. release thread eon D2NT3.1
[Realease] Muddy's Waypoint Catcher
08/21/2013 - Diablo 2 Programming - 46 Replies
Moin zusammen, hier mal die erste Release Version eines kleinen Scripts genannt Waypoint Catcher. Das ganze ist jetzt nichtmal 24h alt, dementsprechend sind vermutlich noch einige Bugs vorhanden. Hinweise dazu nehme ich gerne entgegen. ;) Features: - Suchen sämtlicher Wegpunkte mit Ausnahme, wobei in Akt ein durch Probleme im Jail Bereich nach dem Wegpunkt Outer Cloister abgebrochen wird - Wahlweise auch mit TP an jedem gefundenen Wp, sodass man damit auch anderen (nicht-Bots) die...
[D2NT] Long Dia Release
05/10/2011 - Diablo 2 Programming - 28 Replies
Ein kleines Script für diablo, es startet beim eingang macht ein tp cleart den weg zum star macht am star noch ein tp dann läufts wie das normale nur cleart es schöner :) hoffe euch gefällts ich habs noch nicht wirklich getestet (2-3 runs) bugs können gerne hier gepostet werden verbesserungs vorschläge auch :D installation: 1.)Script in den Bot ordner kopieren 2.)Script im editor oder vergleichbaren öffnen 3.) Msg´s anpassen (ist nicht schwer) 4.) in der char config die zeile...
D2NT 3.0 Pickit release
10/22/2010 - Diablo 2 - 77 Replies
edit
Muddy's D2NT Help
07/29/2010 - Diablo 2 - 3 Replies
hi i just started to use the bot it work's great. how do i set up the skill's i use on my Sorc and pick up itme's? ..... if you reply to this post please use english



All times are GMT +1. The time now is 05:27.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.