Quote:
Originally Posted by fuuch
Code:
function NTA_ClearPosition(range, pickitem, safelevel)
{
var _orgx, _orgy;
var _spectype = [0x0A, 0x01, 0x01];
var _skiplist;
var _attackcount = 0;
var _target;
var _distance, _mingid, _mindistance;
var _result;
var _monsters;
_monsters = new Array();
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;
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;
_monsters.push(new MonsterData(_mingid, NTA_GetResistance(_target, NTA_DAMAGE_FIRE), NTA_GetResistance(_target, NTA_DAMAGE_COLD), NTA_GetResistance(_target, NTA_DAMAGE_LIGHTNING), NTA_GetResistance(_target, NTA_DAMAGE_POISON), NTA_GetResistance(_target, NTA_DAMAGE_PHYSICAL), NTA_GetResistance(_target, NTA_DAMAGE_MAGIC)));
}
}
}
else
_skiplist.push(_target.gid);
}
} while(_target.GetNext());
}
_monsters.sort(MW_SortByResistance);
if(_mindistance < 100000)
{
var tempMob = _monsters.pop();
if(NTC_FindUnit(NTC_UNIT_MONSTER, tempMob.gid))
{
_target = NTC_FindUnit(NTC_UNIT_MONSTER, tempMob.gid);
}
else
{
_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:
if(NTConfig_PickItemsInstantly && (_target.hp <= 0 || _target.mode == 0 || _target.mode == 12))
NTSI_PickItems();
_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(2000);
}
}
if(NTConfig_UseFindItem && me.classid == NTC_CHAR_CLASS_BARBARIAN && _attackcount > 2)
{
if(!NTA_CheckForCloseMonsters(10))
NTL_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(NTConfig_OpenAllNearbyChests)
NTL_OpenNearbyChests();
switch(safelevel)
{
case 1:
return NTTMGR_CheckSafe(0x00, NTConfig_CheckMercSafe&0x01);
case 2:
return NTTMGR_CheckSafe(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe);
}
return true;
}
function MonsterData(gid, fres, cres, lres, pres, phys, magic)
{
this.gid = gid;
this.res = new MonsterRes(fres, cres, lres, pres, phys, magic);
}
function MonsterRes(fres, cres, lres, pres, phys, magic)
{
this.fire = fres;
this.cold = cres;
this.light = lres;
this.poison = pres;
this.phys = phys;
this.magic = magic;
}
// Simpler Bubble Sort Algorithmus zur aufsteigenden Sortierung nach physischer Resistenz
function MW_SortByResistance(a, b)
{
if(a.res.phys > b.res.phys)
return 1;
else if(a.res.phys < b.res.phys)
return -1;
else
return 0;
}
ich weiß nicht, ob pop() der richtige aufruf ist, da ich kp von bubblesort habe unter javascript..
geradeeben hat er einen phys immunen stehen lassen, aber irgendwie klappt es nicht immer
|
Sind auch noch ein paar kleine Denkfehler drin, sieht aber schon sehr viel besser aus als dein vorheriger Ansatz. :)
Wenn du dir die normale Funktion anschaust, wird ja jeweils das nächstgelegene Monster angegriffen (natürlich spielt hier auch noch der derzeit betrachtete spectype eine Rolle).
Prinzipiell wollen wir uns ja alle naheliegenden Monster bzw. deren
gid und Resistenzen merken, um sie danach den jeweiligen Resistenzen nach anzugreifen, wobei wir mit den niedrigeren anfangen.
Bei dem aktuellen Aufbau merkst du dir aber nicht alle Monster, sondern nur die, die jeweils näher beim Charakter sind, als das letzte Monster, welches dem Char am nächsten war.
Es werden darum längst nicht alle Monster gespeichert, sodass das Array deutlich weniger Elemente enthält, als es eigentlich der Fall sein sollte.
Man könnte sich leicht einen Schlimmstfall vorstellen: Ein PI Monster steht direkt neben dir (soll also insgesamt den geringsten Abstand von allen anderen Monstern haben) und das dazugehörige Objekt ist im ersten Durchlauf der do-while-Schleife ausgewählt.
In diesem Fall würde dem Array zur Resistenzenauswertung nur genau ein Datensatz hinzugefügt werden.
Natürlich würde dann entsprechend das passende Objekt über die gespeicherte
gid instantiiert und angegriffen - die durchgeführte Änderung hätte gar keine Bedeutung.
Ein Extrembeispiel, aber ich denke man kann das Problem dabei ganz gut nachvollziehen.
Damit das funktioniert, müssen wirklich alle Monster im gültigen Radius im Array gespeichert werden. Der Abstand spielt dann auch erstmal pauschal keine Rolle mehr.
Um das zu Ändern müsste man das nun entstandene Array nochmal sortieren, wobei man sich diesmal nur den Anfang des Arrays anschaut (also die kleinsten Resistenzen), weil ja vermutlich am Anfang eine ganze Gruppe von Monstern stehen wird, deren Resistenzen identisch sind - es gilt nun diese Gruppe nochmal nach dem Abstand zu sortieren, sodass wir im Endeffekt das Monster mit den niedrigsten Resistenzen, welches uns gleichzeitig am nächsten ist, angreifen.
Um nochmal auf deine Funktion zurückzukommen:
Die Methode
pop() trennt das letzte Element eines Arrays ab und gibt es zurück - das letzte Element entspricht bei unserer Sortierung aber gerade den höchsten Resistenzen, ist also nicht wirklich das was wir wollen. ;)
Achja, das mit der alternativen Instantiierung des nächstgelegenen Monsters im Fehlerfall gefällt mir gut, soll ja auch mal vorkommen. :)
Versuchs mal in etwa so:
Code:
function NTA_ClearPosition(range, pickitem, safelevel)
{
var _orgx, _orgy;
var _spectype = [0x0A, 0x01, 0x01];
var _skiplist;
var _attackcount = 0;
var _target;
var _distance, _mingid, _mindistance;
var _result;
var _monsters;
_monsters = new Array();
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;
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;
}
_monsters.push(new MonsterData(_mingid, NTA_GetResistance(_target, NTA_DAMAGE_FIRE), NTA_GetResistance(_target, NTA_DAMAGE_COLD), NTA_GetResistance(_target, NTA_DAMAGE_LIGHTNING), NTA_GetResistance(_target, NTA_DAMAGE_POISON), NTA_GetResistance(_target, NTA_DAMAGE_PHYSICAL), NTA_GetResistance(_target, NTA_DAMAGE_MAGIC)));
}
}
else
_skiplist.push(_target.gid);
}
} while(_target.GetNext());
}
_monsters.sort(MW_SortByResistance);
var _mingidRes = 0;
var _mindistRes = 1E6;
var _tempTarget;
for(var i = 0; i < _monsters.length; i++)
{
_tempTarget = NTC_FindUnit(NTC_UNIT_MONSTER, _monsters[i].gid);
if(_tempTarget)
{
if(i > 0 && _monsters[i].res.phys != _monsters[i-1].res.phys)
break;
/* Alternativ: Nicht niedrigste Resistenz prüfen, sondern nächstes Monster angreifen, das nicht immun ist
if(i > 0 && _monsters[i].res.phys > 99)
break;
*/
_distance = GetDistance(me, _target);
if(_distance < _mindistance)
{
_mingidRes = _tempTarget.gid;
_mindistRes = _distance;
}
}
}
if(_mindistance < 100000)
{
if(!(_target = NTC_FindUnit(NTC_UNIT_MONSTER, _mingidRes)))
_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:
if(NTConfig_PickItemsInstantly && (_target.hp <= 0 || _target.mode == 0 || _target.mode == 12))
NTSI_PickItems();
_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(2000);
}
}
if(NTConfig_UseFindItem && me.classid == NTC_CHAR_CLASS_BARBARIAN && _attackcount > 2)
{
if(!NTA_CheckForCloseMonsters(10))
NTL_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(NTConfig_OpenAllNearbyChests)
NTL_OpenNearbyChests();
switch(safelevel)
{
case 1:
return NTTMGR_CheckSafe(0x00, NTConfig_CheckMercSafe&0x01);
case 2:
return NTTMGR_CheckSafe(NTConfig_CheckSelfSafe, NTConfig_CheckMercSafe);
}
return true;
}
Achja, es ist offensichtlich, dass der spectype hier ziemlich negativ reinfunkt, weil PI Bosse trotzdem immer zuerst angegriffen werden. ;)
Lg
Muddy