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