|
You last visited: Today at 19:11
Advertisement
Wie binde ich das Script ein und ist es so "korrekt"?
Discussion on Wie binde ich das Script ein und ist es so "korrekt"? within the Diablo 2 Programming forum part of the Diablo 2 category.
10/03/2011, 19:03
|
#1
|
elite*gold: 0
Join Date: Sep 2011
Posts: 6
Received Thanks: 0
|
Wie binde ich das Script ein und ist es so "korrekt"?
Hallo
ich habe mir ein Script gebaut das ich gerne in anderen Scripts wie "precast" aufrufen würde wenn das script beendet ist oder in der Char config nach jedem script laufen lasse
Das Script soll folgendes tuen;
- bereich nach corpses absuchen und die maximal mögliche anzahl skelette und Skeletmages summonen;
ich hab das Script aus der atacksequenz herraus genommen da es genau der teil ist der skelette erzeugt nun würde ich diesen gerne seperat triggern wenn ein boss besiegt wurde
Code:
// Summon skeletons until the desired number is reached
var _MWA_Attack_Slot = -1;
var _MWA_Corpse_Damage_Radius = -1.0;
var _MWA_Minion_Counts = new Array(-1, -1, -1);
function MWA_SetMinionCounts()
{
// Maximum Number of Skeletons
_MWA_Minion_Counts[0] = MWC_GetMaxMinionCount(MWS_RAISE_SKELETON);
// Define the maximum amount of Mages
_MWA_Minion_Counts[1] = MWC_GetMaxMinionCount(MWS_RAISE_SKELETAL_MAGE);
// Define the maximum amount of Revives
if(MWConfig_ReviveMinionCount <= MWC_GetMaxMinionCount(MWS_REVIVE))
_MWA_Minion_Counts[2] = MWConfig_ReviveMinionCount;
else
_MWA_Minion_Counts[2] = MWC_GetMaxMinionCount(MWS_REVIVE);
}
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);
// Summon skeletons until the desired number is reached
if(NTC_GetSkillLevel(MWS_RAISE_SKELETON) > 0 && MWConfig_SkeletonMinionCount > 0)
{
_count = MWC_GetMinionCount(MWS_RAISE_SKELETON);
if(_count < _MWA_Minion_Counts[0])
{
if(MWConfig_ShowOverheadStatus)
MWC_PrintOverheadStatus("Summoning " + MWC_GetMinionName(MWS_RAISE_SKELETON) + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[0] + ")");
if(GetDistance(me, _corpse) > 15 || !CheckCollision(me, _corpse, 4) || !CheckCollision(me, _corpse, 2))
NTM_MoveTo(_corpse.areaid, _corpse.x, _corpse.y, 0);
NTC_CastSkill(MWS_RAISE_SKELETON, NTC_HAND_RIGHT, _corpse);
continue;
}
}
// Summon skeletal mages until the desired number is reached
if(NTC_GetSkillLevel(MWS_RAISE_SKELETAL_MAGE) > 0 && MWConfig_MageMinionCount > 0)
{
_count = MWC_GetMinionCount(MWS_RAISE_SKELETAL_MAGE);
if(_count < _MWA_Minion_Counts[1])
{
if(MWConfig_ShowOverheadStatus)
MWC_PrintOverheadStatus("Summoning " + MWC_GetMinionName(MWS_RAISE_SKELETAL_MAGE) + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[1] + ")");
if(GetDistance(me, _corpse) > 15 || !CheckCollision(me, _corpse, 4) || !CheckCollision(me, _corpse, 2))
NTM_MoveTo(_corpse.areaid, _corpse.x, _corpse.y, 0);
NTC_CastSkill(MWS_RAISE_SKELETAL_MAGE, NTC_HAND_RIGHT, _corpse);
continue;
}
}
// Summon revives until the desired number is reached
if(NTC_GetSkillLevel(MWS_REVIVE) > 0 && MWConfig_ReviveMinionCount > 0)
{
_count = MWC_GetMinionCount(MWS_REVIVE);
if(_count < _MWA_Minion_Counts[2] && !(_corpse.spectype&0x0E))
{
if(MWConfig_ShowOverheadStatus)
MWC_PrintOverheadStatus("Reviving " + _corpse.name + " (" + (_count + 1) + "/" + _MWA_Minion_Counts[2] + ")");
if(GetDistance(me, _corpse) > 15 || !CheckCollision(me, _corpse, 4) || !CheckCollision(me, _corpse, 2))
NTM_MoveTo(_corpse.areaid, _corpse.x, _corpse.y, 0);
NTC_CastSkill(MWS_REVIVE, NTC_HAND_RIGHT, _corpse);
continue;
}
}
// Stop if the the maximum number of each minion type is reached
break;
}
}
return true;
}
|
|
|
10/03/2011, 20:16
|
#2
|
Administrator
elite*gold: 41624
Join Date: Jan 2010
Posts: 22,728
Received Thanks: 12,655
|
Was du da hast ist kein Script sondern lediglich zwei Funktionen aus einer library.
Man sollte da klar differenzieren, da man sonst völlig durcheinander kommt:
Es gibt zum einen Scripts, welche die sich dadurch auszeichnen, dass sie immer eine Funktion namens NTMain() enthalten. Ein Script wird typischerweise ausgeführt, was nichts anderes bedeutet, als dass ein neuer Thread gestartet wird und die Funktion NTMain() aufgerufen wird.
Scripts haben typischerweise die Dateiendung .ntj.
Dann wären da die libabries.
Libraries enthalten zwar auch JavaScript Code, werden aber nicht aufgerufen. Stattdessen werden in ihnen verschiedene Funktionen oder Variablen implementiert bzw. definiert.
Eine library dient dazu, von einem laufendem Script eingebunden zu werden. Nach dem Einbinden, was man im Fachjargon auch als Inkludieren bezeichnet, sind sämtliche in der library implementierten Funktionen in dem Kontext vorhanden, in den die library inkludiert wurde (also typischerweise das laufende Bot Script).
Libraries haben typischerweise die Dateiendung .ntl.
Bei D2NT gibt es die common libraries, was eigentlich nichts anderes ist als eine vielzahl verschiedener libraries mit mehr oder weniger mächtigen Funktionen. Sämtliche dieser libraries werden zu Beginn eines Botscripts inkludiert und sind somit in diesem nutzbar.
Was du dort gemacht hast, ist im Grunde nur das Rauskopieren zweier Funktionen aus der Attack library. Nachdem du nun aber weißt, wozu eine library dient und wozu die common libraries im speziellen dienen, wirst du diesen Schritt aber hoffentlich nochmal überdenken.
Denn was du da machst, macht überhaupt keinen Sinn.
Wenn du eine Funktion aus einer der common libraries verwenden möchtest, dann kopierst du diese nicht, sondern rufst sie ganz einfach in deinem Botscript auf.
Womit ich zu meiner eigentlichen Frage komme, die sich mir aufgrund deiner etwas unpräzisen Beschreibung stellt:
Wann genau soll die Funktion aufgerufen werden? Und willst du wirklich ein eigenes Bot Script schreiben, in dem nur diese Funktion aufgerufen wird (klingt wenig sinnvoll)?
LG
Muddy
|
|
|
10/04/2011, 00:24
|
#3
|
elite*gold: 0
Join Date: Sep 2011
Posts: 6
Received Thanks: 0
|
naja der hintergedanke ist das meist nach einem kampf als necro unendlich viele leichen liegen bleiben statt diese aber zu verwerten sammelt er schön gegenstände auf und geht zum nächsten script
mir würde es aber viel besser gefallen wen der necro eh in einem gesäuberten bereich steht und bevor er mit dem aufsammeln anfängt dass er einfach mal hingeht und schaut ob er noch skelette beschwören kann;
Dadurch könnte man in deiner version sozusagen eine art "skeletcounter" in fight haben
sprich ich setze im Necroscript MaxSkele/Max Skelemages jeweils auf 6 und da ich keine summons mag setz ich diese mal auf 0
nun sorgt dies daführ das solange ich 6 oder mehr skelette habe der necro die leichen für corpsexplosion nimmt also im kampf nur wirklich dann skelette holt wen diese zu neige gehen;
Aber wenn der kamf vorbei ist wird fleissig aufgefüllt auf +15 und mehr skelette/Magier
Grade diese spielweise ist sinvoll denn meist sorgt eine corpsexplsion für mehr sicherheit als ein 7. skelett da dies den ganzen bereich säubert.. aber generell will man trozdem 15 skeltte haben
daher wollte ich diese funktion als eigenständige library bauen einbinden und in den botscripten gegen ende aufrufen
vorallem wäre es eine leicht abgewandelte funktion von deiner da ich den max wert der skelette setze und nicht die angegebenen werte im necro file nehme
hast du einen tipp wie ich dies realisieren kann?
|
|
|
10/05/2011, 12:02
|
#4
|
Administrator
elite*gold: 41624
Join Date: Jan 2010
Posts: 22,728
Received Thanks: 12,655
|
Ich sehe irgendwie den Sinn nicht, da meine Implementierung das an sich schon ungefähr so vorsieht, wie du es sagst.
Skelette werden als wichtigste Minions auch im Kampf beschworen. Sprich bei vorhandener Leiche, wird zunächst kontrolliert, ob die gewünschte Anzahl an Skeletten vorhanden ist und erst wenn dies nicht der Fall ist, CE benutzt.
Nach dem Säubern einer Position werden automatisch sämtliche in Leichen in einem Radius von 30 yards verwendet, um die Armee aufzufüllen.
Das passiert so von Haus aus, sollte das bei dir nicht so sein, solltest du mal einen Blick in deine Config werfen.
Für mich scheint es irgendwie immernoch so, als wolltest du etwas umsetzen, was es so eigentlich schon gibt, oder sehe ich das doch falsch?
LG
Muddy
|
|
|
10/08/2011, 15:27
|
#5
|
elite*gold: 0
Join Date: Sep 2011
Posts: 6
Received Thanks: 0
|
Genau dieses verhalten ist für einen Necro nicht immer sinvoll daher habe ich dies umgeschrieben und benötige nun eine möglichkeit skeltte aufzustocken
Ich habe es so umgeschrieben das er im kampf nurnoch auffülllt wenn die anzahl unter 6 Skelette gefallen ist
Grund ist das tote mobs keinen schaden anrichten man stirbt so deutlich weniger!
leider fehlt nun eine möglichkeit neue skelette zu bekommen zwar führst du es beim säubern aus aber es würde eher nach dem aufsammeln gut passen
Ein kleines beispiel:
Du killst Nihalatak und tötest einen mob nun kannst du mit einer corpse explo den kompletten raum in 1-2 sekunden clearen ODER du erstellst ein Skelet und dann noch eins und so weiter..
Mit meiner Änderung dauert der kampf maximal 5 Sekunden bei dir kann es durchaus schon mal deutlich länger dauern Ergebniss CHICKEN
klar braucht der totenbeschwörer skelette aber in einer kampfhandlung ist fast immer die Corpseexplosion vorzuziehen
Einziger Grund wenn nicht --> das letzte monster ist ein Uniq monster Feuer Imun + Stoneskin UND man hat weniger als c.a. 6 Skelette (dann bekommt man es nicht tot und steht am ende ohne Skelette da)
Am Sinnvollsten wäre also eine Lösung die 2 Skeletstände verwertet
1. Maximale Skelette im Kampf (6)
2. Maximale Skelette nach Kampf (Max) (es gibt eigentlich keinen grund NICHT auf max zu gehen wenn man enigma hat da alle mitteleporten)
Dies hatte ich versucht umzusetzen und daher wollte ich dein Script copieren und es zu einem AFTER CAST umbauen da deine rutine nach dem Kampf nicht immer greift (eventuell liegt es auch an meinen änderrungen waage ich aber zu bezweifeln da ich an dem bereich nichts geändert habe und auch ab und zu nach dem kampf skelette geholt werden) aber nunmal nicht immer ^^
|
|
|
10/10/2011, 13:00
|
#6
|
Administrator
elite*gold: 41624
Join Date: Jan 2010
Posts: 22,728
Received Thanks: 12,655
|
Gut, sehe ich ein, klingt sinnig. Wobei ich zugeben muss, dass ich das Problem nicht habe, da ich grundsätzlich mit einem einfachen Script beginne (also etwa Pit), wo ich problemlos meine Minions aufstocken kann.
Geht man von vollem Equipment aus, ist es höchstselten, dass tatsächlich mal Skelette sterben, somit werden im Normalfall auch so gut wie nie Skelette im Kampf beschworen.
Anyway, zurück zu deinem Problem. Was du da vorhattest ist viel zu kompliziert. Du müsstest lediglich verändern, wann die Funktion zum beschwören aufgerufen wird, den Rest erledigt dann die Funktion von sich aus.
Dazu schauen wir uns zunächst mal an, wie die Funktion derzeit aufgerufen wird, hier der passende Code Schnipsel aus der NTA_ClearPosition() Funktion:
Code:
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();
Damit der Kontext klar ist, sei an dieser Stelle noch gesagt, dass es sich bei _attackcount um eine Variable vom Typ number handelt, die mit dem Wert 0 initialisiert wird und die nach jedem erfolgreichen oder zumindest versuchten Angriff um 1 inkrementiert wird.
Wie man unschwer erkennen kann, wird die Funktion zum Beschwören von Minions derzeit aufgerufen, wenn diese Variable mindestens den Wert 3 hat (was eigentlich auch schon bei kleineren Kämpfen der Fall ist).
Da du aber nu möchtest, dass die Funktion auch nach winzigen Kämpfen aufgerufen wird, also gerade immer dann, wenn auch NTSI_PickItems() aufgerufen wird, passt du dir den obigen Code Schnipsel einfach wie folgt an:
Code:
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;
}
}
if(_attackcount > 0)
{
if(pickitem)
NTSI_PickItems();
if(me.classid == NTC_CHAR_CLASS_NECROMANCER)
MWA_RaiseMinions();
}
Das wars dann auch schon - einfach, oder?
LG
Muddy
|
|
|
10/13/2011, 00:17
|
#7
|
elite*gold: 0
Join Date: Sep 2011
Posts: 6
Received Thanks: 0
|
*** das war echt einfach VIELEN LIEBEN DANK und da worte nicht immer helfen hier villeicht ein Tip der dir auch gefällt um es in dein Packet einzubinden!
Jeder Totenbeschwörer hat normal einen Punkt in Knochenrüstung nun würde ich dir vorschlagen folgenden Schnipsel in deinem Script auf standart zu setzen
NTConfig_AttackSkill[0] = MWS_BONE_ARMOR; // This skill is used once whenever attacking a new target. Set to 0 to deactivate.
PERFEKT *eg* genial einfach und einfach genial verstehe nicht wieso du das bei dir nicht im Pack schon so hattest der Positive aspekt wiegt die kleinen manakosten extra mehr als auf  hoffe du siehst es genauso ansonsten war der tip gut gemeint und ging in die hose HEHE
PS:
mein Problem war glaube ich das der Necro zu gut ausgestattet war und maximal 1-2 Atacks hatte und dann auch schon alle tot waren^^
Infinity + Beast + Enigma + Forti tun halt übelst aua mit dem rest equipt *G*
|
|
|
All times are GMT +1. The time now is 19:12.
|
|