-
[Scriptpaket] Arrays
Es gibt mittlerweile eine bessere Lösung als die hier vorgestellten Arrays, nämlich das Paket PermMem aus LeGo.
Die nativen Daedalus Arrays sind wenig hilfreich. Jedes Arrayelement muss wie eine eigenständige Variable behandelt werden, ein variabler Index ist nicht gestattet und die Arraylänge muss zur Übersetzungszeit bekannt sein.
Ich habe mich mit NicoDE auf dem Moddertreffen über dieses Problem unterhalten, woraus die Idee entstanden ist, über eine verkettete Liste von Npcs Array-artige Strukturen zu implementieren.
Die Umsetzung ist mir nun auch tatsächlich gelungen. Mit dem entstandenen Code ist es möglich:
- Eine beliebige Menge an 1D Integer Arrays, 2D Integer Arrays oder 1D String Arrays beliebiger Ausmaße zu erzeugen
- Die Länge der Arrays zur Laufzeit zu verändern
- Auf einem beliebigen Index zu schreiben und zu lesen
- Den Speicher wieder freizugeben um ihn für zukünftige Arrays zu nutzen
Ein Nachteil der Verwaltung in Npcs ist, dass die Arrays, die in einer Welt erzeugt wurden (Beispielsweise in Khorinis) in einer anderen Welt (beispielsweise dem Minental) nicht zur Verfügung stehen.
Ich denke das Ergebnis kann auch anderen helfen, daher möchte ich hier den Code zur freien Verfügung stellen.
Dokumentation der Funktionen:
Code:
//#################################################################
//
// Array Dokumentation
//
//#################################################################
//************************************
// Die Idee
/************************************
-Der Gothic Compiler duldet nur konstante Indizes in Arrays. Dies
widerspricht der Idee der Arrays grundlegend. Es wäre also wünschenswert
"vernünftige" Arrays in Gothic zur Verfügung zu haben.
-Die beiliegende Funktionssammlung verwaltet eine verkettete Liste von
Npcs, die in ihrem aivar-Array Variablen speichern können. Das ganze ist
soweit abstrahiert, dass der anwendende Scripter sich nicht näher damit
auseinandersetzen muss und sofort Strukturen zur Verfügung hat, die sich
wie wirkliche Arrays verhalten.
-Beispielhaft ist der ArrayMan implementiert (einfach mal über die
Konsole einfügen) sowie eine Funktion KillCounter (auskommentiert am
Ende der Datei).
//************************************
// Was ist zu beachten?
//************************************
-Die Datei Array_AivarHandler.d ist vor Arrays.d zu parsen.
-Vor Benutzung der Arrays ist nach jedem Laden unbedingt einmal
Arr_ReInitStartAndHigh(); auszuführen. Diese Funktion ist am besten in
INIT_GLOBAL() (Content\Story\Startup.d) aufgehoben.
-Die Konstante FARFARAWAY (Arrays.d) heißt nicht umsonst so. Tragt hier
einen gültigen Waypoint ein, der weit vom Spielgeschehen entfernt ist (>
40 m entfernt von allen begehbaren Stellen). Zu viele Arrays könnten
sonst evtl. die Performance drücken (zu Testzwecken reicht aber auch
irgendein Waypoint).
-Die Fehleranzeige kann über die Konstante ARR_PRINT_ERRORS_DEF und zur
Laufzeit über die Variable Arr_Print_Errors beeinflusst werden. Je nach
Wert werden Error Meldungen und Warnungen bei ungültigen Eingaben auf
dem Bildschirm ausgegeben, zum Beispiel beim lesen und schreiben
jenseits von Array Grenzen.
-Arrays verschwinden beim Wechsel der Welt. Anders gesagt: Ein Array
bleibt beim Weltenwechsel in der Welt zurück, in der es erzeugt wurde.
In der neue Welt können neue Arrays angelegt werden.
-NAN (= "Not a Number") ist eine Konstante (in der -1 steht). Bei
ungültigen Anfragen an die Array-Schnittstelle wird oft NAN
zurückgegeben.
//************************************
// Benutzung der Funktionen:
//************************************
/************/
/* 1D Array */
/************/
func int Arr_Create()
/* -> Erzeugt ein neues Array und gibt einen integer Wert zurück, der im
Folgenden zur Identifikation des Arrays dient. */
func int Arr_Length (int arr_ID)
/* -> Gibt die Länge des Arrays 'arr_ID' zurück. Ist arr_ID ungültig
wird NAN zurückgegeben. */
func int Arr_High (int arr_ID)
/* -> Gibt den Index des letzten Elements im Array 'arr_ID' zurück
(dieser ist stets um 1 kleiner als die Länge des Arrays, da die Zählung
bei 0 beginnt). */
func void Arr_SetLength (int arr_ID, int newLength)
/* -> Setzt die Länge des Arrays 'arr_ID' auf den Wert 'newLength' (dann
gibt es in dem Array newLength gültige Positionen, diese sind 0, 1, 2,
..., newLength - 1). */
func void Arr_SetValue (int arr_ID, int offset, int value)
/* -> Setzt den Wert mit dem Index 'offset' des Arrays 'arr_ID' auf den
Wert 'value'. Anmerkung: Wird jenseits der rechten Array Grenze
geschrieben, wird das Array automatisch verlängert und eine Warnung
ausgegeben. */
func int Arr_GetValue (int arr_ID, int offset)
/* -> Gibt den Wert mit dem Index 'offset' des Arrays 'arr_ID' zurück.
Bei ungültigen Paramtern wird NAN zurückgegeben. */
func void Arr_Free (int arr_ID)
/* -> Gibt das Array 'arr_ID' frei. Der Speicher steht nun für andere
Arrays zur Verfügung. */
func int Arr_IndexOf (int arr_ID, int value)
/* -> Gibt den Index des ersten Elements im Array 'arr_ID' das den Wert
'value' hat zurück. Wird kein passendes Element gefunden wird NAN
zurückgegeben. */
func void Arr_Append (int arr_ID, int value)
/* -> Verlängert das Array 'arr_ID' um 1 und schreibt den Wert 'value'
in das neu erzeugte Element. */
/************/
/* 2D Array */
/************/
/* Die 2D-Funktionen sind entsprechend der 1D-Funktionen aufgebaut. */
/* Anmerkung 1: Unterscheiden sich die Nutzbereiche der beiden
Dimensionen X und Y stark voneinander,
/* so sollte auf der X-Komponente der große Bereich abgelegt werden.
Beispiel:
/* [0..99;0..2] ist performanter und Speicherschonender als
[0..2][0..99].
/* In diesem Beispiel um das über 30 Fache!
/* Anmerkung 2: Wenn Arr2D Funktion auf 1D-Arrays angewendet werden oder
umgekehrt
/* können merkwürdige oder schlimme Dinge geschehen. Dies wird von der
Schnittstelle
/* NICHT abfangen und ist Sache des Nutzers! */
func int Arr2D_Create()
/* -> Erzeugt ein 2D-Array und gibt einen integer Wert zurück, der im
Folgenden zur Identifikation des Arrays dient. */
func int Arr2D_LengthX(int arr_ID)
/* -> Gibt die Länge in X-Richtung des 2D-Arrays 'arr_ID' zurück. Ist
arr_ID ungültig wird NAN zurückgegeben. */
func int Arr2D_LengthY(int arr_ID)
/* -> Gibt die Länge in Y-Richtung des 2D-Arrays 'arr_ID' zurück. Ist
arr_ID ungültig wird NAN zurückgegeben. */
func int Arr2D_HighX(int arr_ID)
/* -> Der größte gültige X-Index im 2D-Array 'arr_ID'. Dieser ist stets
um 1 kleiner als die Länge in X-Richtung. */
func int Arr2D_HighY(int arr_ID)
/* -> Der größte gültige Y-Index im 2D-Array 'arr_ID'. Dieser ist stets
um 1 kleiner als die Länge in Y-Richtung. */
func void Arr2D_SetLengthX (int arr_ID, int newlength)
/* -> Setzt die Länge in X-Richtung des Arrays arr_ID auf den Wert
newLength. */
func void Arr2D_SetLengthY (int arr_ID, int newLength)
/* -> Setzt die Länge in Y-Richtung des Arrays arr_ID auf den Wert
newLength. */
func void Arr2D_SetValue (int arr_ID, int offsetX, int offsetY, int
value)
/* -> Setzt den Wert an der Stelle [offsetX|offsetY] des 2D-Arrays
'arr_ID' auf den Wert 'value'. Anmerkung: Wird jenseits der Arraygrenzen
(aber nicht im negativen Bereich) geschrieben, wird das 2D-Array
automatisch entsprechend vergrößert und eine Warnung ausgegeben. */
func int Arr2D_GetValue(int arr_ID, int offsetX, int offsetY)
/* -> Gibt den Wert an der Stelle [offsetX|offsetY] des 2D-Arrays
'arr_ID' zurück. Bei ungültigen Paramtern wird NAN zurückgegeben. */
/****************/
/* String Array */
/****************/
/* Für String Arrays stehen exakt die selben Funktionen wie für
1D-Arrays zur Verfügung.
/* Alle haben zusätzlich das Präfix "Str". Schlägt StrArr_GetValue
aufgrund eines
/* ungültigen Parameters fehl, wird "UNDEFINED" zurückgegeben.
/* Gültige Array-Positionen, die noch nie beschrieben wurden sind mit
dem leeren String initialisiert. */
func int StrArr_Create()
/* -> Erzeugt ein neues String Array und gibt einen integer Wert zurück,
der im Folgenden zur Identifikation des String Arrays dient. */
func int StrArr_Length (int arr_ID)
/* -> Gibt die Länge des String Arrays 'arr_ID' zurück. */
func int StrArr_High (int arr_ID)
/* -> Gibt den Index des letzten Elements im String Array 'arr_ID'
zurück (dieser ist stets um 1 kleiner als die Länge des Arrays, da die
Zählung bei 0 beginnt). */
func void StrArr_SetLength (int arr_ID, int newLength)
/* -> Setzt die Länge des String Arrays 'arr_ID' auf den Wert
'newLength' (dann gibt es in dem String Array newLength-viele gültige
Positionen, diese sind 0, 1, 2, ..., newLength - 1). */
func void StrArr_SetValue (int arr_ID, int offset, string value)
/* -> Setzt den Wert mit dem Index 'offset' des String Arrays 'arr_ID'
auf den String 'value'. Anmerkung: Wird jenseits der rechten Array
Grenze geschrieben, wird das Array automatisch verlängert und eine
Warnung ausgegeben. */
func string StrArr_GetValue (int arr_ID, int offset)
/* -> Gibt den Wert mit dem Index 'offset' des Arrays 'arr_ID' zurück.
Bei ungültigen Paramtern wird "UNDEFINED" zurückgegeben. */
func void StrArr_Free (int arr_ID)
/* -> Gibt das String Array 'arr_ID' frei. Der Speicher steht nun für
andere Arrays zur Verfügung. */
func int StrArr_IndexOf (int arr_ID, string value)
/* -> Gibt den Index des ersten Elements im String Array 'arr_ID' das
den Wert 'value' hat zurück. Wird kein passendes Element gefunden wird
NAN zurückgegeben. */
func void StrArr_Append (int arr_ID, string value)
/* -> Verlängert das String Array 'arr_ID' um 1 und schreibt den String
'value' in das neu erzeugte Element. */
/************/
/* sonstige */
/************/
func void Arr_ReInitStartAndHigh(void)
/* -> Sollte nach jedem Laden der Welt aufgerufen werden. Am besten
einfach in aus Init_Global heraus. */
func int Arr_IsValidArray (var int arr_ID)
/* -> Gibt TRUE zurück, falls arr_ID ein gültiges Array indentifiziert.
FALSE sonst. Funktioniert mit allen Array Arten. */
func void Npc_SetAivar (C_NPC slf, int offset, int value)
/* -> Wird intern benutzt kann aber auch ansonsten recht nützlich sein.
Setzt slf.aivar[offset] = value. */
Hier noch ein konstruiertes Beispiel, wie die Arrays genutzt werden könnten:
Code:
//#################################################################
//
// Beispiel für eine Anwendung (an den Haaren herbeigezogen)
//
//#################################################################
//Es soll gezählt werden, wieviel Monster von welchem Typ der Spieler getötet hat.
//Diese Funktion könnte von ZS_Dead heraus aufgerufen werden.
var int MonsterTypen;
var int MonsterCount;
func void KillCounter(var C_NPC totesMonster)
{
if (MonsterTypen == 0) //noch nicht initialisiert
{
MonsterTypen = Arr_Create();
MonsterCount = Arr_Create();
};
var int inst_ID;
inst_ID = Hlp_GetInstanceID (totesMonster);
var int index;
index = Arr_IndexOf (MonsterTypen, inst_ID);
if (index == NAN) //Sowas hat er noch nicht getötet!
{
Print ("Hui, sowas habe ich noch nicht getötet!");
Arr_Append (MonsterTypen, inst_ID);
Arr_Append (MonsterCount, 1); //einen getötet
}
else
{
var int count;
var string prt;
count = Arr_GetValue (MonsterCount, index);
prt = "Davon habe ich jetzt schon ";
prt = ConcatStrings (prt, IntToString (count + 1));
prt = ConcatStrings (prt, " getötet!");
Print (prt);
Arr_SetValue (MonsterCount, index, count + 1);
};
};
Und hier die Scripte (incl. der Doku und dem Beispiel) zum Download: *klick*.
Eine Erwähnung in den Credits ist nicht nötig.
Über Rückmeldungen würde ich mich aber freuen. 
Edit (Februar 2010): Folgende Probleme bei 2D-Arrays behoben:
- Die Verkürzung der 2D-Arrays funktionierte nicht richtig. Aufgrund einer fehlerhaften Freigabereihenfolge entstanden sowohl Zugriffsverletzungen als auch Speicherlöcher (Schlug sich in Printmeldungen auf dem Bildschirm wieder). Dies betrifft die Routinen Arr2D_SetLengthY und Arr2D_Free. Der Fehler ist behoben.
- Beim Schreiben jenseits der x-Grenzen eines 2D-Arrays wurde das Array nicht angepasst. Nun sollte das Array dokumentationsgetreu in X-Richtung verlängert werden. Dabei wird eine Warnung ausgegeben.
- Debugmeldungen werden nun auch im ZSpy ausgegeben. Dazu ist es nötig im Spy Informationen anzuschalten sowie im Spiel über die Konsole "toggle debug" auszuführen.
Edit (Februar 2010): String Arrays hinzufügefügt.
Edit (Mai 2010): Folgendes wurde verändert
- Schnittstelle geändert
- Alle SetValue Funktionen haben keinen Rückgabewert mehr. Das verhindert, dass der Datenstack überlastet wird, wenn der Rückgabewert vom Aufrufer nicht verwendet wird. Der Rückgabewert ("waren Eingaben gültig?") war sowieso wenig hilfreich.
- Alle Append Funktionen haben aus ähnlichem Grund keinen Rückgabewert mehr.
- Fehler behoben: Die Indizes 0 und 100 wurden vom Paket synonym behandelt (will heißen: Wer auf 100 schrieb, schrieb sozusagen gleichzeitig auf 0 und umgekehrt.). Weitere Paare von Indizes waren nicht betroffen.
- Es sollten nun keine Probleme mit Datastack-Overflows auftreten (insbesondere bei 2D Arrays war das problematisch).
- Funktion Arr_IsValidArray hinzugefügt (siehe Doku).
- self und other sollten nun bei der Nutzung des Scriptpakets nicht mehr überschrieben werden.
Last edited by Sektenspinner; 16.11.2011 at 16:36.
Reason: Update / Bugfix
-
Ist eher an Forgeschrittene gerichtet oder ?
Hab mir das mal durchgelesen und bin immernoch so schlau wie vorher ^^
-
Ja das wohl doch eher fortgeschritten.
Ich könnte zwar manchmal schon arrays benutzen, aber der Hacken mit der Zenabhängigkeit ist mir zu mieß.
Ich werd mir die Scripts trotzdem mal ansehen, vllt fällt mir was ein wo ich brauchen könnte.
-
Big 
Die Idee für den Workaround ist schon ziemlich genial.
Soweit ich das verstanden hab, speichert jeder NPC den jeweils Nächsten bei sich als Target?
Darauf muss man ermal kommen 
Mit den Arrays kann man ziemlich viele Sachen, wie z.B. einen Respawn stark vereinfachen.
Vielen Dank für dieses Scriptset!
Zwar ists nicht mit mehreren Welten kompatibel, aber einige Sachen kann man damit trotz mehreren Zens umsetzen.
Vielleicht noch als Frage: Könnte man nicht eventuell den StartIndexNPC dem Helden kurz vor Betreten des Levelchangetriggers als Target geben und so die Arraystruktur mit in die andere Zen nehmen(mit anschließenden Nachspawn und aufbau in der anderen Zen)? Klappt wohl eh nicht, aber man kanns ja mal versuchen.
-
 Originally Posted by Sumpfkrautjunkie
Vielleicht noch als Frage: Könnte man nicht eventuell den StartIndexNPC dem Helden kurz vor Betreten des Levelchangetriggers als Target geben und so die Arraystruktur mit in die andere Zen nehmen(mit anschließenden Nachspawn und aufbau in der anderen Zen)? Klappt wohl eh nicht, aber man kanns ja mal versuchen.
Keine schlechte Idee, ich habs gerade ausprobiert. Aber das Target des Helden ist immer sein Fokus, d.h. egal was ich reinsetze, es wird sofort wieder überschrieben.
Auch eine gefüllte C_NPC Variable hält sich nicht bis nach dem Levelwechsel.
 Originally Posted by XPLOSIV
Ist eher an Forgeschrittene gerichtet oder ?
Ja, eher für Fortgeschrittene, und selbst ob die es brauchen ist fraglich. 
Arrays sind für die meisten alltägliche Scriptprobleme einfach nicht nötig. Ich habe das auch mehr als "Grundlagenforschung" betrieben. Eine wirkliche sinnvolle Anwendung dafür ist mir noch nicht eingefallen. Ich werde aber nochmal drüber nachdenken.
-
Einfach genial.
Riesen Respekt, das ist echt ne tolle Sache 
Damit kann ich so manches meiner Scripte extrem vereinfachen, die Engstirnigkeit der Engine in Bezug auf array hat mich schon immer gestört, und hatte sehr unschöne umwege zur Folge (Ein bestimmtes Script würde so unter Umständen 20x so lang, wie es jetzt schon ist, und es ist bereits sehr lang^^)
Werd mir die Sache gleich mal genauer ansehen.
-
Könnte man damit ein neues Schadenssystem initialisieren?
So, dass alle NPCs mit z.B. einer zweihändigen stumpfen Waffe eine geringe Chance haben den Helden KO zu schlagen.
Bisher hat diese Art von Script nur chaos ausgelöst, da das Spiel self/other nicht richtig erkannt hat und man immer betäubt wurde, wenn einer der kämpfenden NPCs eine solche Waffe besaß.
Hier mal ein Scriptausschnitt, damit iuhr nachvollziehen könnnt, was ich machen wollte.
Code:
var c_item item_equipped;
item_equipped = Npc_GetReadiedWeapon(hero);
var C_ITEM AktiveWaffe; AktiveWaffe = Npc_GetReadiedWeapon(other);
var C_ITEM Ruestung; Ruestung = Npc_GetEquippedArmor(self);
var int Schaden;
// ITEM_2HD_SWD = Zweihandschwert
// ITEM_2HD_AXE = Zweihandaxt
// ITEM_AXE = Einhandaxt
// ITEM_SWD = Einhandaxt
// ITEM_BOW = Bogen
// ITEM_CROSSBOW = Armbrust
//Normale Schadensberechnung
// StumpferSchaden (zweihändig)
if C_ItmHasFlag(AktiveWaffe,ITEM_2HD_SWD)
|| C_ItmHasFlag(AktiveWaffe,ITEM_2HD_AXE)
&& C_WeaponHasdamagetype(AktiveWaffe,DAM_BLUNT)
{
if Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
{
schaden = ((other.attribute[ATR_STRENGTH]+other.attribute[ATR_DEXTERITY])/10+AktiveWaffe.hp)- Ruestung.protection[PROT_BLUNT];
Schadenerleiden (other, schaden);
};
if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
{
schaden = (other.attribute[ATR_STRENGTH]+other.attribute[ATR_DEXTERITY]/10+AktiveWaffe.hp)- Ruestung.protection[PROT_BLUNT];
Schadenerleiden (other, schaden);
};
if (other.attribute[ATR_HITPOINTS] <= other.attribute[ATR_HITPOINTS_MAX]/7)
{
AI_StartState (other, ZS_Unconscious, 0, "");
};
var int Prozentige_Chance;
Prozentige_Chance = Hlp_Random (16);
if (Prozentige_Chance < 1)
{
if (other.attribute[ATR_DEXTERITY] >= 10) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 0.15);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
&& (other.attribute[ATR_DEXTERITY] >= 10)
{
Wld_PlayEffect("HALBBLIND1", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
if (Prozentige_Chance < 2)
{
if (other.attribute[ATR_DEXTERITY] >= 20) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 0.20);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
&& (other.attribute[ATR_DEXTERITY] >= 20)
{
Wld_PlayEffect("HALBBLIND2", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
if (Prozentige_Chance < 3)
{
if (other.attribute[ATR_DEXTERITY] >= 30) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 0.25);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
&& (other.attribute[ATR_DEXTERITY] >= 30)
{
Wld_PlayEffect("HALBBLIND3", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
if (Prozentige_Chance < 4)
{
if (other.attribute[ATR_DEXTERITY] >= 40) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 0.3);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
&& (other.attribute[ATR_DEXTERITY] >= 40)
{
Wld_PlayEffect("HALBBLIND4", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
if (Prozentige_Chance < 5)
{
if (other.attribute[ATR_DEXTERITY] >= 50) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 0.35);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
&& (other.attribute[ATR_DEXTERITY] >= 50)
{
Wld_PlayEffect("HALBBLIND5", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
if (Prozentige_Chance < 6)
{
if (other.attribute[ATR_DEXTERITY] >= 55) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 0.4);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 0)
&& (other.attribute[ATR_DEXTERITY] >= 55)
{
Wld_PlayEffect("HALBBLIND6", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
if (Prozentige_Chance < 7)
{
if (other.attribute[ATR_DEXTERITY] >= 60) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 1)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 0.45);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 1)
&& (other.attribute[ATR_DEXTERITY] >= 60)
{
Wld_PlayEffect("HALBBLIND7", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
if (Prozentige_Chance < 8)
{
if (other.attribute[ATR_DEXTERITY] >= 70) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 1)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 0.5);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 1)
&& (other.attribute[ATR_DEXTERITY] >= 70)
{
Wld_PlayEffect("HALBBLIND8", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
if (Prozentige_Chance < 9)
{
if (other.attribute[ATR_DEXTERITY] >= 80) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 1)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 0.55);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 1)
&& (other.attribute[ATR_DEXTERITY] >= 80)
{
Wld_PlayEffect("HALBBLIND9", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
if (Prozentige_Chance < 10)
{
if (other.attribute[ATR_DEXTERITY] >= 99) //KoSchlag
&& Npc_IsPlayer(other) //beim SC bleibt der Gegner nur stehen
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 2)
{
AI_PlayAni (self, "t_Search");
//AI_Wait(self, 1.0);
PrintScreen ("Kurzzeitig zu Boden gerungen!", -1,-1,"font_old_10_white.tga",2);
}
else if !Npc_IsPlayer(other) //bei allen anderen (nicht SC) wird Gegner geblendet
&& (Npc_GetTalentSkill (other,NPC_TALENT_2H) == 2)
&& (other.attribute[ATR_DEXTERITY] >= 99)
{
Wld_PlayEffect("HALBBLIND10", other, other, 0, 0, 0, FALSE );
}
else
{
};
};
};
Daran saß ich schon monate lang und war am Rande der Verzweiflung.
(Sodass ich die Datei einfach in meinen "Geht-noch-nicht-aber-wird-im-Hinterköpfchen-aufbewahrt"-Backupordner geschmissen habe und das Problem gaaanz anders angehen wollte indem ich JEDEN NPC in einem Trigger eine Variable verpasse, mit der dann seine dezeitige Waffe einem Schadenssystem angepasst werdensollte...)
Aufjedenfall ist es interessant.
Leider gibt es nur eine Sache, die ich nicht begreife und sich auch nicht in meinem Wortschatz finden lassen.
Arrays.
Was sind also Arrays - keine normalen Variabeln, aber etwas ähnliches. Soviel kann ich sagen - mehr leider auch nicht.
mfg Oparilames
Oparilames nachdem er seinen Gesellenbrief erhalten hat:
»Das war's mit dir, du Mistvieh!«
-
Auf die Gefahr hin mit Stöcken und Steinen aus dem "Club der fortgeschrittenen Scripter" geprügelt zu werden:
Was zum Teufel sind Arrays?
-
Hmm, Wikipedia hat folgendes ausgespuckt:
Ein Array [əˈɹeɪ, Betonung auf 2. Silbe] (v. engl. Array „Anordnung“, „Aufstellung“, „Reihe“, „Reihung“, „Feld“, „Bereich“), zu deutsch Feld, ist der Sammelbegriff für eine Anordnung, Aufstellung, Reihe von gleichen Elementen in festgelegter Art und Weise.
Verwendung findet der Begriff Array als Beschreibung für eine Datenstruktur in der Informatik. Dabei wird zwischen dem Standard-Array und dem assoziativen Array unterschieden.
Arrays aus Strahlungssensoren werden u. a. in CCD- und CMOS-Bildsensoren, in sogenannten Focal Plane Arrays aus Infrarot-Fotodioden oder Mikrobolometern als Bildsensor für sichtbares Licht und Infrarot verwendet.
Spezielle Richtfunk-Antennen benutzen Arrays von Antennen (siehe Phased Array Antenne).
In der Akustik werden Mikrofonarrays zur Ortung von Schallquellen eingesetzt.
Falls euch das weiterhilft..
-
Ein Array ist quasi ne Variablensammlung. Du kannst beispielsweise Variable[1] einen Wert geben, Variable[2] nen Wert und so weiter. So könnte man beispielsweise irgendwie Waffen anlegen und mit Waffe[Damage] den Schaden abfragen und mit Waffe[Value] den Wert der Waffe (mal abgesehen davon, dass das ehr unpraktisch ist, aber immerhin ein Beispiel ^^).
Naja, schöne Arbeit.
-
Nichts anderes als Tabellen, wie ich es aus C und C++ kenne, oder nicht?
Im Prinzip sehr nützlich, danke.
-
Arrays sind... mit Worten imo schwer zu erklären. Ich denke, jeder hat sie schonmal benutzt, jeder, der scriptet. Die Aivars sind z.B. Arrays. Arrays sind eigentlich... zweidimensionale "Kästen".
Code:
7|_______
6|_______
5|___5___
4|_______
3|_______
2|_______
1|_______
x1234567
Im obigen Beispiel liegt der Wert 5 am Punk (4|5). Oben sieht man einen zweidimensionalen Array.
Die Bezeichnung eindimensionaler Array ist an sich falsch, da es sich einfach um einen Array mit einer y-Ausdehnung von 1 handelt.
Da lassen sich auch wieder Werte drin speichern.

Alle fragen sich wie kann ich noch schöner werden,
aber keiner fragt sich für wen.
-
 Originally Posted by Dead Frank
Auf die Gefahr hin mit Stöcken und Steinen aus dem "Club der fortgeschrittenen Scripter" geprügelt zu werden:
Was zum Teufel sind Arrays?
*hau und prügel*
Nehmen mir mal an du willst eine Liste erstellen. Ganz simpel eine Einkaufsliste.
Da du vorher nicht weist vieviel du auf die Liste schreibst, sagst du einfach Liste sei ein Array.
Für jeden Eintrag in der Liste kannst du dann sagen: Liste.push "Tomaten" oder so.
Wenn du ein 2 dimensionales Array hast, dann kannst du damit eine Art Tabelle erstellen. zum Beispiel:
Punktestand[Spieler][ArtDerPunkte]
Dann hat Spieler1 den Punktestand fürs Würfeln: Punktestand[1][Würfeln]
oder: Punktestand[1][Kartenspielen]
Das System dahinter ist einfach: Du hast eine Liste von Listen.
Das Standartarray lässt sich mit Zahlen im Index ansprechen. Also Array[0] ist meistens der Start.
Es gibt auch Arrays mit Variablen Start und End-indexen
Außerdem gibt es etwas das nennt sich Hash.
Das sind dann Arrays die sich mit Zeichenketten oder sogar komplexen Klassen ansprechen lassen:
PunkteStand['Harry']
Die Arrays verhalten sich in nahezu jeder Programmiersprache anders. Ruby ist zum Beispiel in Sachen Array sehr flexibel. Du kannst dort ALLES in einem Array speichern. Und dabei auch verschiedene Klassen.
Hier sind die Möglichkeiten zb sehr eingeschränkt.
Der Startindex ist immer 0. du hast keine Hashmöglichkeit und du kannst ausschließlich Zahlen speichern.
@Shadowblade:
Die Bezeichnung 1D Array ist sehr wohl sehr treffend.
Schau:
1D-Array: [2,4,4,nil,87,2,"Aua"]
2D-Array: [[1,2,3],[4,5,6],[7,8,9]]
3D-Array: [[[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]]]
So kannst du beliebig weitermachen.
Das geht bei Sektenspinner übrigens auch, in dem man in einem Array eine Array_ID speichert.
Last edited by Nodrog; 22.03.2008 at 11:41.
-
Hey, danke, die Einkaufslisten- und Würfelspiel-Situationen haben's als Erklärung echt drauf
-
Ich hab mir die Scripts mal angesehen. Und mir ist folgendes aufgefallen.
Du nutzt die aivar für die Speicherwerte. und wenn du über die 100 kommst, vergrößerst du dein Array um einen Npc
Das heist doch aber auch, dass du statt Npcs Items nutzen könntest.
Dabei würden sich in deinen Scripts die Instanzen ändern, du müsstest andere Variablen für level und exp nutzen und du müsstest andere Externals nehmen.
Der erste Nachteil ist, dass du ein maximales Feld von 4 nutzen kannst, statt 100, was du aber durch dynamisches Verlängern kompensierst.
Vorteil ist, dass man Items in das Inventar des Helden legen kann. Dann müsste man mal sehen, ob die in den Itemobjekten gespeicherten Werte den Levelchange überleben.
-
Das ist doch kein Gegenbeweis.
Ein 3D-Array hat einen x, y und z-Wert >= 1.
Ein 2D-Array hat einen x und y-Wert >=1.
Und ein 1D-Array hat einen x-Wert >=1.
Gleichzeitig ist aber ein 1D-Array mit einem dreidimensionalen Koordinatensystem vergleichbar, bei dem die y- und die z-Achse die Maximalausdehnung 1 haben.
Verstehst du, was ich meine?

Alle fragen sich wie kann ich noch schöner werden,
aber keiner fragt sich für wen.
-
Das mit dem Koordinatensystem ist doch nur eine Darstellungsweise.
Eine sehr unzureichende, denn wie stellst du ein 4D Array dar?
-
Mehrere Koordinatensystem nebeneinander.
Sozusagen ein System aus Koordinatensystem.
4D ist eine Reihe von Koordinatensystemen, 5D eine Fläche und 6D ein Würfel.
7D ist schließlich ein System aus Systemen von Koordinatensystemen

Alle fragen sich wie kann ich noch schöner werden,
aber keiner fragt sich für wen.
-
Also ich glaub ich hab das ansatzweiße verstanden, aber irgendwie fehlt bei mir dieser *klick ich habs verstanden*.
Ich kenne jetzt zb. sowas VAR int XY_Variable[6];
Jetzt konnte man XY_Variable[1] nen Wert zuweißen XY_Variable[2] nen wert zu weißen etc...
Ist das auch ein Array?
-
Ja, ein eindimensionaler.
Leider musste die 6 in den eckigen Klammern aber konstant sein, was dem Sinn eines Arrays entgegen wirkte.
Danke Sektenspinner und NicoDe ( ) ist es nun möglich, flexible sowie mehrdimensionale (oder war das schon vorher möglich?) Arrays zu erstellen.

Alle fragen sich wie kann ich noch schöner werden,
aber keiner fragt sich für wen.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
|