.Hallo zusammen,
nach meinem Patzer beim Itemlog bin ich euch was schuldig glaube ich.
Darum gibts hier nun meine Find Item Implementierung.
Ist in meinen Augen definitiv noch nicht perfekt, auch wenn sie sogesehen ziemlich rund läuft und keine Abstürze produziert. Trotzdem ist dieses Release mehr eine Testversion, die sich an Leute richtet die ein bisschen Erfahrung mitbringen, mit dem Ziel, das ganze noch weiter auszubauen und zu verbessern.
Bevor ich irgendwas genaueres erzähle möchte ich zunächst kurz die Char Anforderungen ansprechen:
Ich selbst benutze einen WW Barb mit Eni und 37fcr. 37fcr empfehle ich stark, wenn ihr auch Area runs macht, ansonsten wird das looten einer Horde Monster zu einer extrem langwierigen Sache, etwas fcr sorgt hingegen direkt für einen deutliche besseren und flotteren Ablauf. Insgesamt sicherlich auch eine effektibe Sache, schließlich hat man bei nem guten Find Item Level schnell mal 50% Chance auf einen Zweitdrop, in Alvl85 Ebenen macht sich das sicherlich gut.
Stichwort Eni: Ist in jedem Fall Vorraussetzung!
Es wäre zwar denkbar Travi und andere Runs mit kurzen und vor allem konstanten Wegen ohne teleport umzusetzen, aber darum habe ich mich bisher nicht gekümmert. Ich denke ich brauche nicht extra erwähnen, dass der Barb ansonsten auch ein halbwegs hellfähiges Equipment haben sollte.
Soweit so gut, nun zu den eigentlichen Funktionen:
Ich habe Find Item fest in die häufig verwendeten Funktionen NTA_ClearPosition() sowie NTA_ClearRoom() eingebunden. Ihr könnte euch das ein bisschen so vorstellen wie beim Pala mit Redemption, an der Stelle wo das eingesetzt würde, kommt nun als Barb Find Item ins Spiel. Es werden alle gültigen Monster in einem gewissen Radius gelootet, welcher per Variable festgelegt werden kann.
"gültige Monster" soll heissen, dass die Monster auch tatsächlich lootbar sind. Dazu habe ich eine Funktion geschrieben, die an sich alle nicht lootbaren Monster ausschließen sollte, ob das wirklich absolut sicher funktioniert kann ich nicht sagen, da ich das ganze noch nicht in allen Situationen getestet habe. Ohne diese Funktion würde beispielsweise versucht, Find Item bei eurem Merc anzuwenden, sofern dieser gerade gestorben ist und im überprüften Radius liegt. Das ist natürlich etwas nervig, darum gibt es diese Funktion.
Es passiert allerdings öfter mal, dass auch eigentlich gültige Monster nicht gelootet werden können, weil der Barb beispielsweise Probleme hat diese zu erreichen. Für diesen Fall sieht meine Funktion eine Neupositionierung nach 1 Sekunde vor, nach 3 Sekunden wird das Monster dann übersprungen. Insgesamt wird also immer 3 Sekunden versucht ein Monster zu looten, meist gehts natürlich deutlich schneller.
Die Waffen, die für Find Item benutzt werden sollen, müssen sich übrigens im zweiten Slot befinden, auf diesen wird immer gewechselt vor dem Einsatz des Skills.
Achja, da das ganze ja noch im Teststadium ist werden Monster, die nicht gelootet werden konnten, in einer Textdatei geloggt. So kann man Auswerten, ob eventuell versucht wurde, ein ungültiges Monster zu looten und so die entsprechende Funktion verbessern, die dies eigentlich ausschließen soll.
Die meisten Ausgaben habe ich aber schonmal entfernt, sonst wird der Bildschirm teilweise sehr vollgespammt.
Das Looten funktioniert so natürlich nur, nachdem die ganz oben erwähnten Funktionen halbwegs erfolgreich durchgelaufen sind. Ihr könnt natürlich auch weitere Aufrufe in eure Bot Scripte einfügen, meine Funktion NTA_FindItem(range) erwartet dabei einen Integer Wert als range als Übergabeparameter. Dieser kann auch weggelassen werden, dann wird range auf den Defaultwert von 25 gesetzt.
Habe ich nun alles?
Nicht ganz. Meine NTAttack.ntl enthält ausserdem andere kleinere Modfikationen, so z.B. wird Statik nurnoch bei Aktbossen eingesetzt.
Ansonsten stecken auch noch Funktionen zum Öffnen sämtlicher Truhen darin, diese Funktionen sind aber an dieser Stelle auskommentiert, da Ich damit noch nicht absolut zufrieden bin und es hier ausserdem erstmal um die Find Item Funktion gehen soll. Ich wollte es nur anmerken, falls sich der ein oder andere wundert.
Hier nun mal meine modifizierte NTAttack.ntl:
Code:
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 _NTA_SkillHand = new Array(8);
var _NTA_SkillDamage = new Array(8);
var _NTA_SkillRange = new Array(8);
function NTA_Initialize()
{
if(NTConfig_AttackSkill[1] == 0 || NTConfig_AttackSkill[3] == 0)
NTA_DetectAttackPattern();
for(var i = 0 ; i < 8 ; 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 44: //Frost Nova
case 48: // Nova
_NTA_SkillRange[i] = 10;
break;
case 64: // Frozen Orb
_NTA_SkillRange[i] = 15;
break;
case 97: //Smite
case 106: //Zeal
case 112: //Blessed Hammer
_NTA_SkillRange[i] = 3;
break;
case 151: //Whirlwind
_NTA_SkillRange[i] = 8;
break;
case 152: //Berserk
_NTA_SkillRange[i] = 3;
break;
default:
_NTA_SkillRange[i] = 25;
break;
}
}
}
}
function NTA_KillMonster(classid)
{
var _target;
if(NTConfig_AttackSkill[1] < 1)
return false;
_target = NTC_FindUnit(NTC_UNIT_MONSTER, classid, 5);
if(!_target)
return false;
if(_target.IsAttackable())
{
var _attackcount = 0;
while(_attackcount < 300 && NTA_IsValidMonster(_target))
{
if(NTA_Attack(_target, (_attackcount%30) == 0) < 2)
break;
_attackcount++;
}
}
return (_target.hp <= 0 || _target.mode == 0 || _target.mode == 12);
}
function NTA_ClearPosition(range, pickitem, safelevel, recursion)
{
var _orgx, _orgy;
var _spectype = [0x0A, 0x01, 0x01];
var _skiplist;
var _attackcount = 0;
var _target;
var _distance, _mingid, _mindistance;
var _result;
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 = 0;
case 3:
recursion = true;
default:
if(NTConfig_CheckSelfSafe < 0x01 && NTConfig_CheckMercSafe < 0x01)
safelevel = 0;
break;
}
_orgx = me.x;
_orgy = me.y;
for(var i = 0 ; i < _spectype.length ; i++)
{
_skiplist = new Array();
while(_attackcount < (i+1)*100)
{
_mindistance = 100000;
_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;
}
}
}
else
_skiplist.push(_target.gid);
}
} while(_target.GetNext());
}
if(_mindistance < 100000)
{
_target = NTC_FindUnit(NTC_UNIT_MONSTER, _mingid);
if(_target)
{
_result = NTA_Attack(_target, (_attackcount%30) == 0);
switch(_result)
{
case 1:
_skiplist.push(_mingid);
break;
case 2:
case 3:
_attackcount++;
break;
default:
return false;
}
}
}
else
break;
}
}
if(me.classid == NTC_CHAR_CLASS_PALADIN)
{
if(_attackcount > 2 && (parseInt(me.hp*100/me.hpmax) < NTConfig_UseRedemptionHP || parseInt(me.mp*100/me.mpmax) < NTConfig_UseRedemptionMP))
{
if(NTC_PutSkill(124, NTC_HAND_RIGHT))
NTC_PingDelay(1000);
}
}
if(NTConfig_UseFindItem && me.classid == NTC_CHAR_CLASS_BARBARIAN && _attackcount > 2)
{
if(!NTA_CheckForCloseMonsters(10))
{
//Print("ÿc<No Monsters close - looting");
NTA_FindItem(NTConfig_FindItemRange);
}
else
{
//Print("ÿc1Close Monster detected - clearing area");
if(recursion)
{
NTA_ClearPosition(15, false, 0, false);
NTA_FindItem(NTConfig_FindItemRange);
}
}
}
if(NTConfig_OpenChest)
{
_target = NTC_GetSpecialChest();
if(_target && GetDistance(_orgx, _orgy, _target.x, _target.y) <= range && NTC_OpenChest(_target))
_attackcount++;
}
if(pickitem && _attackcount > 0)
NTSI_PickItems();
/*
if(!NTA_CheckForCloseMonsters(15))
NTA_OpenChests();
*/
switch(safelevel)
{
case 1:
return NTTMGR_CheckSafe(0x00, NTConfig_CheckMercSafe&0x01);
case 2:
return NTTMGR_CheckSafe(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe);
}
return true;
}
function NTA_ClearLevel(pickitem, safelevel)
{
var i;
var _room, _rooms;
var _distance, _minindex, _mindistance;
_room = GetRoom();
if(!_room)
return false;
switch(arguments.length)
{
case 0:
pickitem = true;
case 1:
safelevel = 2;
default:
if(NTConfig_CheckSelfSafe < 0x01 && NTConfig_CheckMercSafe < 0x01)
safelevel = 0;
break;
}
_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(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))
return false;
NTP_DoPrecast(false);
}
_rooms.splice(_minindex, 1);
}
return true;
}
function NTA_ClearRoom(pickitem, safelevel)
{
var _room;
var _spectype = [0x0A, 0x01, 0x01];
var _skiplist;
var _attackcount = 0;
var _target;
var _distance, _mingid, _mindistance;
var _result;
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;
default:
if(NTConfig_CheckSelfSafe < 0x01 && NTConfig_CheckMercSafe < 0x01)
safelevel = 0;
break;
}
for(var i = 0 ; i < _spectype.length ; i++)
{
_skiplist = new Array();
while(_attackcount < (i+1)*100)
{
_mindistance = 100000;
_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;
}
}
}
else
_skiplist.push(_target.gid);
}
} while(_target.GetNext());
}
if(_mindistance < 100000)
{
_target = NTC_FindUnit(NTC_UNIT_MONSTER, _mingid);
if(_target)
{
_result = NTA_Attack(_target, (_attackcount%30) == 0);
switch(_result)
{
case 1:
_skiplist.push(_mingid);
break;
case 2:
case 3:
_attackcount++;
break;
default:
return false;
}
}
}
else
break;
}
}
if(me.classid == NTC_CHAR_CLASS_PALADIN)
{
if(_attackcount > 2 && (parseInt(me.hp*100/me.hpmax) < NTConfig_UseRedemptionHP || parseInt(me.mp*100/me.mpmax) < NTConfig_UseRedemptionMP))
{
if(NTC_PutSkill(124, NTC_HAND_RIGHT))
NTC_PingDelay(1000);
}
}
if(NTConfig_UseFindItem && me.classid == NTC_CHAR_CLASS_BARBARIAN && _attackcount > 2)
{
if(!NTA_CheckForCloseMonsters(5))
{
//Print("ÿc<No Monsters close - looting");
NTA_FindItem(NTConfig_FindItemRange);
}
}
if(NTConfig_OpenChest)
{
_target = NTC_GetSpecialChest();
if(_target && _room.UnitInRoom(_target) && NTC_OpenChest(_target))
_attackcount++;
}
if(pickitem && _attackcount > 0)
NTSI_PickItems();
/*
if(!NTA_CheckForCloseMonsters(15))
NTA_OpenChests();
*/
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)
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 && monster.mode == 14) // ignore submerged WaterWatchers
return false;
if(monster.GetState(53) || monster.GetState(96)) // Conversion, Revive
return false;
return true;
}
function NTA_GetDamageType(skillid)
{
if(skillid == 74) // Corpse Explosion
return NTA_DAMAGE_PHYSICAL;
if(skillid == 112) // Blessed Hammer
return NTA_DAMAGE_NONE;
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:
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;
if(NTTMGR_CheckCurse(NTConfig_CheckSelfSafe&0x10, NTConfig_CheckMercSafe&0x10))
{
if(!NTTMGR_VisitTown())
return 0;
}
if(firstorder && NTConfig_AttackSkill[0] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[0]) < 100 && 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(NTA_IsActBoss(target.classid) && NTConfig_CastStatic < 100 && parseInt(target.hp*100/target.hpmax) > NTConfig_CastStatic && NTA_GetResistance(target, NTA_DAMAGE_LIGHTNING) <= 80)
{
var _staticlevel = NTC_GetSkillLevel(42);
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(42, NTC_HAND_RIGHT, _castx, _casty))
return 2;
return 3;
}
}
_primaryindex = (target.spectype&0x0A) ? 1 : 3;
if(NTA_GetResistance(target, _NTA_SkillDamage[_primaryindex]) <= 90)
{
if(!NTA_SorceressCastSkillInt(_primaryindex, target))
return 2;
return 3;
}
if(NTConfig_AttackSkill[5] > 0 && NTA_GetResistance(target, _NTA_SkillDamage[5]) <= 80)
{
if(!NTA_SorceressCastSkillInt(5, target))
return 2;
return 3;
}
if(NTA_GetResistance(target, _NTA_SkillDamage[_primaryindex]) < 100 || (_primaryindex == 1 && NTC_GetMerc()))
{
if(!NTA_SorceressCastSkillInt(_primaryindex, target))
return 2;
return 3;
}
return 1;
}
function NTA_SorceressCastSkillInt(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);
}
if(NTConfig_AttackSkill[index+1] > 0)
{
if(NTConfig_AttackSkill[7] > 0 && (NTA_GetResistance(target, _NTA_SkillDamage[index+1]) <= 90 || NTA_GetResistance(target, _NTA_SkillDamage[7]) <= 90))
{
if(NTA_GetResistance(target, _NTA_SkillDamage[index+1]) <= 90)
{
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);
}
else
{
if(GetDistance(me, target) > _NTA_SkillRange[7] || !CheckCollision(me, target, 4))
{
var _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);
}
}
else
{
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 NTA_NecromancerAttackPatternInt()
{
return false;
}
function NTA_NecromancerAttackInt(target, firstorder)
{
return 1;
}
function NTA_NecromancerCastSkillInt(index, target)
{
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;
if(NTTMGR_CheckCurse(NTConfig_CheckSelfSafe&0x10, NTConfig_CheckMercSafe&0x10))
{
if(!NTTMGR_VisitTown())
return 0;
}
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 && !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_SkillDamage[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] == 112)
{
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))
NTM_MoveTo(target.areaid, target.x+2, target.y+2, 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(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(151, 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] = 151;
NTConfig_AttackSkill[3] = 151;
NTConfig_AttackSkill[5] = 152;
break;
}
return (NTConfig_AttackSkill[1] && NTConfig_AttackSkill[3]);
}
function NTA_BarbarianAttackInt(target, firstorder)
{
var _primaryindex;
if(NTTMGR_CheckCurse(NTConfig_CheckSelfSafe&0x10, NTConfig_CheckMercSafe&0x10))
{
if(!NTTMGR_VisitTown())
return 0;
}
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] == 151) && !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] == 151)
{
var _castx, _casty;
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);
}
_castx = target.x > me.x ? target.x+3 : target.x-3;
_casty = target.y > me.y ? target.y+3 : target.y-3;
return NTC_CastSkill(NTConfig_AttackSkill[index], _NTA_SkillHand[index], _castx, _casty);
}
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)
{
return 1;
}
function NTA_DruidCastSkillInt(index, target)
{
return false;
}
function NTA_AssassinAttackPatternInt()
{
return false;
}
function NTA_AssassinAttackInt(target, firstorder)
{
return 1;
}
function NTA_AssassinCastSkillInt(index, target)
{
return false;
}
function NTA_IsActBoss(classid)
{
switch(classid)
{
case 156: //Andariel
case 211: //Duriel
case 242: //Mephisto
case 243: //Diablo
case 544: //Baal
return true;
}
return false;
}
function NTA_FindItem(range)
{
var _corpse;
var _orgx;
var _orgy;
var _startTick;
var _reposition = false;
if(NTC_GetSkillLevel(142) < 1)
return false;
if(arguments.length < 1 || !range)
range = 25;
_corpse = NTC_FindUnit(NTC_UNIT_MONSTER);
_orgx = me.x;
_orgy = me.y;
NTC_PingDelay(100);
NTC_SwapWeapons(2);
if(_corpse)
{
do
{
if(GetDistance(_orgx, _orgy, _corpse.x, _corpse.y) <= range && (_corpse.hp <= 0 || _corpse.mode == 0 || _corpse.mode == 12) && _corpse.GetState(118) == 0 && NTA_IsLootable(_corpse.classid))
{
if(GetDistance(me.x, me.y, _corpse.x, _corpse.y) >= 8)
{
if(!NTM_MoveTo(me.areaid, _corpse.x, _corpse.y))
continue;
}
_startTick = GetTickCount();
while(_corpse.GetState(118) != 0x400000 && (_corpse.hp <= 0 || _corpse.mode == 0 || _corpse.mode == 12) && !_corpse.IsAttackable())
{
NTC_CastSkill(142, NTC_HAND_RIGHT, _corpse);
NTC_PingDelay(50);
if(GetTickCount() >= _startTick + 1000 && !_reposition) // repositioning after 1sec
{
_reposition = true;
if(!NTM_MoveTo(me.areaid, _corpse.x+1, _corpse.y+1))
break;
}
if(GetTickCount() >= _startTick + 2500) // skipping monster after 2.5sec
{
var filehandle = FileOpen("FailedtoLoot.txt", 2);
var dateString = new Date().toLocaleFormat("%a %m/%d/%y %H:%M:%S");
if(filehandle)
{
filehandle.WriteLine("[" + dateString + "] Could not loot: " + _corpse.name +" [" + _corpse.classid + "](Location: " + me.areaid + ")");
filehandle.Close();
}
Print("ÿc;Could not loot: " + _corpse.name +" [" + _corpse.classid + "](Location: " + me.areaid + ")");
break;
}
}
}
} while(_corpse.GetNext());
NTC_PingDelay(100);
NTC_SwapWeapons(0);
NTC_PingDelay(100);
NTSI_PickItems();
return true;
}
return false;
}
function NTA_IsLootable(classid)
{
switch(classid)
{
case 151: // An evil force
case 156: // Andariel
case 180: // Sand Maggot Young
case 181: // Rock Worm Young
case 182: // Devourer Young
case 183: // Giant Lamprey Young
case 184: // World Killer Young
case 190: // Sand Maggot Egg
case 191: // Rock Worm Egg
case 192: // Devourer Egg
case 193: // Giant Lamprey Egg
case 194: // World Killer Egg
case 206: // Fould Crow Nest
case 207: // Blood Hawk Nest
case 208: // Black Vulture Nest
case 209: // Cloud Stalker Nest
case 221: // Duriel
case 227: // Maggot
case 228: // Mummy Generator
case 234: // Flying Scimitar
case 242: // Mephisto
case 243: // Diablo
case 250: // Summoner
case 258: // Water Watcher Limb
case 259: // River Stalker Limb
case 260: // Sygain Watcher Limb
case 261: // Water Watcher Head
case 262: // River Stalker Head
case 263: // Sygain Watcher Head
case 267: // Blood Raven
case 269: // An evil force
case 270: // Rogue Scout (== Merc)
case 273: // Gargoyle Trap
case 289: // Clay Golem
case 290: // Blood Golem
case 291: // Iron Golem
case 292: // Fire Golem
case 301: // Flesh Beast
case 302: // Stygian Dog
case 303: // Grotesque Wyrm
case 326: // A Trap
case 327: // A Trap
case 328: // A Trap
case 329: // A Trap
case 330: // A Trap
case 334: // Sucker Nest
case 335: // Fleeder Nest
case 336: // Blood Hook Nest
case 337: // Blood Wing Nest
case 338: // Act 2 guard (== Merc)
case 348: // Turret
case 349: // Turret
case 350: // Turret
case 351: // Hydra
case 352: // Hydra
case 353: // Hydra
case 354: // A Trap
case 356: // Dopplezon
case 357: // Valkyrie
case 359: // Iron Wolf (== Merc)
case 366: // Compelling Orb
case 369: // A Trap
case 371: // Lightning Spire
case 372: // Fire Tower
case 403: // Traped Soul
case 404: // Traped Soul
case 406: // Izual
// ----------------
case 410: // Wake Of Destruction
case 411: // Charged Bolt Sentry
case 412: // Lightning Sentry
case 413: // Blade Creeper
case 414: // Invisible Pet
case 415: // Inferno Sentry
case 416: // Death Sentry
case 417: // Shadow Warrior
case 418: // Shadow Master
case 419: // Druid Hawk
case 420: // Druid Spirit Wolf
case 421: // Druid Fenris
case 422: // Spirit of Barbs
case 423: // Heart Of Wolverine
case 424: // Oak Sage
case 425: // Druid Plague Poppy
case 426: // Druid Cycle of Life
case 427: // Vine Creature
case 428: // Druid Bear
case 429: // Eagle
case 430: // Wolf
case 431: // Bear
case 432: // Barricaded Door
case 433: // Barricaded Door
case 434: // Prison Door
case 435: // Barricaded Door
case 461: // Fanatic Minion
case 462: // Beserk Slayer
case 463: // Consumed Fire Boar
case 464: // Consumed Ice Boar
case 465: // Frenzied Hell Spawn
case 466: // Frenzied Hell Spawn
case 467: // Insane Hell Spawn
case 468: // Insane Ice Spawn
case 497: // Catapult
case 498: // Catapult
case 499: // Catapult
case 500: // Catapult
case 501: // Frozen Horror 1
case 502: // Frozen Horror 2
case 503: // Frozen Horror 3
case 504: // Frozen Horror 4
case 505: // Frozen Horror 5
case 516: // Catapult
case 517: // Catapult
case 518: // Catapult
case 519: // Catapult
case 522: // Barbarian Fighter
case 523: // Barbarian Fighter
case 524: // Barricade Wall Right
case 525: // Barricade Wall Left
case 526: // Nihlatak
case 528: // Evil Hut
case 535: // Barbarian Fighter
case 536: // Barbarian Fighter
case 537: // Ancient Statue 1
case 538: // Ancient Statue 2
case 539: // Ancient Statue 3
case 540: // Ancient Barbarian 1
case 541: // Ancient Barbarian 2
case 542: // Ancient Barbarian 3
case 543: // Baal Throne
case 544: // Baal Crab
case 545: // Baal Taunt
case 551: // Pain Worm
case 552: // Pain Worm
case 553: // Pain Worm
case 554: // Pain Worm
case 555: // Pain Worm
case 556: // Bunny
case 559: // Baal Crab to Stairs
case 560: // Hireling
case 561: // Hireling
case 562: // Baal Tentacle
case 563: // Baal Tentacle
case 564: // Baal Tentacle
case 565: // Baal Tentacle
case 566: // Baal Tentacle
case 567: // Injured Barbarian
case 568: // Injured Barbarian
case 569: // Injured Barbarian
case 570: // Baal Crab Clone
case 571: // Baals Minions
case 572: // Baals Minionse
case 573: // Baals Minions
case 574: // Worldstone Effect
return false;
break;
default:
return true;
break;
}
}
/*
function NTA_OpenChests()
{
var _orgx;
var _orgy;
var _chest;
if(!NTA_AreaCheckChests(me.areaid))
return false;
_orgx = me.x;
_orgy = me.y;
_chest = NTC_FindUnit(NTC_UNIT_OBJECT);
if(_chest)
{
do
{
if(_chest.mode == 0 && GetDistance(_orgx, _orgy, _chest.x, _chest.y) < 20 && NTA_IsLootableChest(_chest.classid) && !(_chest.classid == 371 && _chest.areaid == 25) && _chest.name.toLowerCase() != "an evil force")
{
NTC_PingDelay(100);
//Print("ÿc2Opening: " + _chest.name + " [" + _chest.classid + "]");
if(!NTC_OpenChest(_chest))
{
Print("ÿc1Could not open: Object (" + _chest.x + "|" + _chest.y + "): " + _chest.name + " [ClassID: " + _chest.classid + ", Mode: " + _chest.mode + "]");
var filehandle = FileOpen("FailedToOpenChest.txt", 2);
var dateString = new Date().toLocaleFormat("%a %m/%d/%y %H:%M:%S");
if(filehandle)
{
filehandle.WriteLine("[" + dateString + "] Failed to open " + _chest.name +" [" + _chest.classid + "] ... Mode|Area: " + _chest.mode + "|" + me.areaid);
filehandle.Close();
}
}
}
} while(_chest.GetNext());
NTSI_PickItems();
return true;
}
return false;
}
function NTA_IsLootableChest(classid)
{
switch(classid)
{
case 1: // Casket
case 3: // Casket
case 4: // Large Urn
case 5: // Chest
case 6: // Chest
case 7: // Barrel
case 8:
case 9: // Urn
case 28: // Undefiled Grave
case 46:
case 50:
case 51: // Casket
case 52: // Urn
case 53: // Casket
case 54: // Dead Rogue
case 55: // Dead Rogue
case 56: // Dead Rogue
case 57: // Dead Rogue
case 58: // Dead Rogue
case 79: // Casket
case 84:
case 85:
case 87: // Chest
case 88: // Chest
case 89:
case 94: // Large Urn
case 95: // Large Urn
case 96:
case 104:
case 105: // Armor Stand
case 106: // Weapon Rack
case 107: // Weapon Rack
case 109:
case 111:
case 113:
case 115:
case 118:
case 120:
case 139: // Chest
case 140: // Chest
case 141: // Chest
case 141:
case 142: // Jug
case 143: // Jug
case 144: // Chest
case 146: // Chest
case 147: // Chest
case 148: // Chest
case 154: // Corpse
case 155: // Hidden Stash
case 158:
case 164:
case 166:
case 167:
case 168:
case 170:
case 171: // Skeleton
case 173:
case 174: // Loose Rock
case 175: // Loose Boulder
case 176:
case 177:
case 178: // Guard Corpse
case 181: // Chest
case 182:
case 183: // Chest
case 185: // Stash
case 186: // Stash
case 198:
case 203: // Stash
case 204: // Stash
case 205: // Stash
case 208: // Basket
case 209: // Basket
case 223:
case 224:
case 225: // Skullpile
case 239: // Body
case 240: // Chest
case 241: // Chest
case 242: // Chest
case 243:
case 244: // Rat's Nest
case 247: // Bed
case 266: // Goo Pile
case 270: // Corpse
case 271: // Corpse
case 329: // Chest
case 330: // Chest
case 331:
case 332: // Chest
case 333:
case 334:
case 335:
case 336:
case 360:
case 362:
case 363:
case 365:
case 371:
case 372:
case 389:
case 390:
case 391:
case 397: // (Super) Chest
case 405: // (Super) Chest
case 413:
case 416:
case 418: // Barrel
case 419: // Barrel
case 420: // Wooden Chest
case 424: // Burial Chest
case 425:
case 430: // Chest
case 431:
case 432:
case 433:
case 443: // Jar
case 444: // Jar
case 445: // Jar
case 455:
case 463:
//case 466: // Evil Urn
case 467:
case 468:
case 469:
case 470:
case 471:
case 477: // Dead Barbarian
case 501:
case 502:
case 504:
case 505:
case 548:
case 549:
case 550:
case 551:
return true;
break;
default:
return false;
break;
}
}
*/
function NTA_CheckForCloseMonsters(range)
{
if(range < 1 || arguments.length < 1)
return false;
var _monstersClose = false;
var _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))
{
//Print("ÿc1Close Monster detected: " + _checkMonster.name);
_monstersClose = true;
break;
}
} while(_checkMonster.GetNext());
}
return _monstersClose;
}
/*
function NTA_AreaCheckChests(areaid)
{
var exeptionsArray = new Array();
exeptionsArray.push(25); // Tower Cellar Level 5
for(var i = 0; i < exeptionsArray.length; i++)
{
if(areaid == exeptionsArray[i])
return false;
}
return true;
}
*/
Beispielsweise so:
Code:
NTConfig_UseFindItem = true; NTConfig_FindItemRange = 40;
In erster Linie Rückmeldungen, um das Ganze auf anständiges release Niveau zu bekommen und es weiter zu verbessern. Interessant wären dazu beispielsweise classids von ungültigen bzw. nicht lootbaren Monstern welche bisher noch nicht in ignoriert werden.
Aber auch andere eventuell auftretenden Fehler oder Probleme würden mich interessieren. Natürlich auch ganz einfach Meinungen dazu.
Also, wer schon immer mal einen Gold- oder Mf-barb Bot haben wollte und ein bisschen Ahnung mitbringt und das ohne weitere Hinweise implementieren kann ist hiermit aufgefordert es zu testen und mir hinterher eine Rückmeldung zu geben.
Ich freue mich auf Rückmeldungen und wünsche viel Spaß beim Testen!
Lg
Muddy






