LeGo [LehonaGottfried] ist, wie aus dem Titel ersichtlich, ein Skriptpaket das auf Ikarus aufbaut. Während Ikarus grundlegende Möglichkeiten bereitstellt, wird hier der Fokus auf die praktische Anwendung gelegt. Alle enthaltenen Funktionen sind sehr einfach gehalten und müssen nicht in ein tolles Script eingeflochten werden um Sinn zu ergeben, sondern sind auch alleinstehend mächtig. Über pixelgenaues Erzeugen von Texten und Texturen auf dem Bildschirm und einem schönen Interface für Trialoge (eigentlich "Polyloge"), bis hin zu "Triggerlosen Triggerschleifen" die mit nur einer Zeile aktiviert werden können beinhaltet LeGo sicher für jeden Scripter eine interressante Erweiterung die ihm von Nutzen sein kann.
Sicher sind manche Pakete sehr speziell oder einfach nur nutzloser als andere, das liegt daran dass LeGo nicht aus einer Idee "Lass uns ein Scriptpaket machen!" entstanden ist. Ursprünglich war alles was hier zu finden ist als Grundlage für unseren Beitrag zum Modding-Contest gedacht, da Lehona und ich aber leider nicht fertig geworden sind (aus eigener Faulheit, zugegebenermaßen) lag dieser Featurehaufen noch ungeordnet und ohne Nutzen auf unseren Platten. Nun, da wir beide nette Menschen sind haben wir uns überlegt den ganzen Kram zu sortieren, kommentieren und zu erklären (was bei unserer Arbeitweise beim besten Willen nicht einfach war) und hier zur Verfügung zu stellen.
Sektenspinners zweifellos vorhandene Unterstützung sei natürlich auch noch erwähnt. Ohne ihn hätte sich der Release entweder noch um ein paar Jahren hingezogen oder es gäbe gar keinen
13.11.2011
Es ist vollbracht. Nun ist die neue Version 2.0 fertig und veröffentlicht.
Die Unterstützung von Sektenspinner (und diesmal auch ein wenig von Ingenieur) und unser Dank dafür sind ja beinahe Routine.
Obwohl es sehr lange gedauert hat waren wir nicht faul. (Gut, die ersten zwei Monate vielleicht. Oder drei. Mehr nicht!)
Dank PermMem konnten einige Pakete maßgeblich optimiert und verbessert werden. FF_ApplyExt mit beliebigem Zeitintervall (Trigger adieu!), Anim8 mit dem man beinahe vollwertige Mover zusammenschrauben kann, Views die auch nach einem Neustart noch existieren, Bloodsplats die keine Abstürze mehr erzeugen, und.. Also gut. Viel Spaß damit!
20.11.2011
LeGo 2.1 ist seit wenigen Minuten zum Download verfügbar und wir haben weder Kosten noch Mühen gescheut, um es noch ein wenig mehr auf Pepp zu bringen. Neben einem nun wirklich funktionierendem Cursor, der hervorragend zu einer Maussteuerung geeignet ist, und simplen Funktionen um lang ersehnte Exp-Bars zu erstellen, haben wir unsere mehr oder weniger eigene Website!
Unschwer zu erkennen gibt es dort 4 Sachen zu sehen:
Downloads: Hier wird die jeweils neueste LeGo-Version zu downloaden sein, vernünftige Releases wird's aber auch weiterhin im WoG geben. Da wir aus diversen Gründen euch leider keinen Zugang zum SVN bieten können (Außer ihr fragt ganz lieb), werden wir eventuell auch hin und wieder Beta-Versionen hier hochladen, die eigentlich nur ein SVN-Dump unserer momentan Fortschritte sind und eher zum Anschauen als zum Verwenden gedacht sind.
Doc:
Falls ihr euch ärgert, dass sich der Release so lange hinausgezögert habt, findet ihr hier euren Schuldigen - wir haben Herzblut investiert (Und mit Herzblut meine ich Langeweile), um die LeGo-Dokumentation vernünftig zu formatieren und hier einzufügen! Sie ist immer auf dem neuesten Stand und ersetzt die Dokumentation innerhalb der Scripte komplett. Falls ihr dort etwas ändern wollt, wäre es ganz nett, wenn ihr hinzufügt, was denn geändert worden ist - dafür gibt es eine extra Zeile
Wenn irgendwas doof oder missverständlich formuliert ist, könnt ihr uns auch gerne im Forum oder sonstwie benachrichtigen, dann ändern wir das selber.
Einen aktuellen Changelog findet man dort auch.
Blog:
Dort werden Neuigkeiten, die LeGo oder einen von uns beiden betreffen veröffentlicht, aber es wird auch den ein oder anderen Post geben, in dem einfach nur ein paar Sachen zur zEngine stehen, die uns während unserer Scriptarbeiten auffallen - einerseits, weil sowas immer praktisch und wissenswert ist, andererseits, weil es einfach sehr viel zu lachen gibt, so toll Gothic auch sein mag. Und auch wenn es mir Leid tut, unsere etwaigen Groupies zu enttäuschen: Nacktbilder werden dort nicht vorzufinden sein
Issues:
Das ist einfach ein Bugtracker - wenn ihr dort einen Bug meldet, wird dem zu 100% nachgegangen, bis wir den Fehler gefunden haben oder sicher sind, dass es nicht an uns liegt.
Eventuell werden wir auch ein Forum hinzufügen - wirklich sicher sind wir uns da aber noch nicht - ein paar Rückmeldungen dazu sind immer willkommen.
Das war's quasi auch schon - wir freuen uns über jegliches Feedback sowohl bezüglich LeGo als auch bezüglich unserer Seite
Aber um es jetzt nicht unnötig hinauszuzögern:
Inhalt
Werkzeuge
PermMem
Sehr mächtiges Paket um mit Klassen/Pointern vollständig arbeiten zu können. (Normalerweise verfliegen diese spätestens nach einem Neustart)
HookEngine
Scriptfunktionen an beliebigen Punkten von Enginefunktionen aufrufen
AI_Function
Scriptfunktionen in die AI-Queue von Npcs einreihen
FrameFunctions
Scriptschleifen ohne Trigger
Interface
Pixelgenaues Printen von Texten oder Texturen mit einstellbarer Textfarbe (+ einem weich scrollenden Print wie er aus Risen/Gothic 3 bekannt ist)
View
Arbeiten mit Texturen auf dem Bildschirm
Random
Eine verbesserte Zufallsfunktion
BinaryMachines
Lesen und schreiben von Dateien
Locals
Erlaubt Variablen temporär auf einem Pseudo-Stack zu sichern
List
Vereinfachter Umgang mit zCList und zCListSort
Int64
Grundlegende Arithmetik für 64bit Integer
Anwendungen
Anim8
"Animieren" von Werten (Mover ohne Scripte zB.)
Names
Den Namen eines Npcs erst anzeigen wenn er bekannt ist
Dialoggestures
Emotionen in Dialogen
Cursor
Ingame mit der Maus arbeiten
Bloodsplats
Blutspritzer auf den Bildschirm
Trialoge
Dialoge mit beliebig vielen Npcs und Kamerafahrten
Saves
Eigene Speicherdateien um zB. Strings zu sichern
Shields
Scriptseitige Methode um Schilde zu verwenden
Focusnames
Farbige Fokusnamen nach Attitüde des Npcs
LeGo wird (wenn interresse besteht) laufend erweitert, nicht zuletzt wenn DU gute Vorschläge für weitere Funktionen hast, daher eröffnen wir hier mal ganz konservativ mit der Version 1.0
Zur Version 1.0 sei noch folgendes gesagt: Da LeGo mit momentan 15 Päckchen ziemlich umfangreich geworden ist können wir beide keine Fehlerfreiheit garantieren. Jedes Paket wurde bereits genutzt und sollte im Normalfall funktionieren, allerdings wurde in den letzten Tagen noch sehr viel modifiziert um es möglichst Nutzerfreundlich zu gestalten. Wenn du einen Fehler entdecken solltest (oder ein grundlosen Absturz bekommst, was auch immer ) dann schreib doch ein paar Zeilen in diesen Thread in denen du kurz erläuterst was genau du getan hast und welche der Pakete aktiv waren.
Changelog
1.010.07.2011
Release
1.0.112.07.2011
Bloodsplat_Tex korrigiert
Print_CloseView gefixt
Levelchange-Absturz beseitigt
2.013.11.2011
Header.src hinzugefügt, damit nicht mehr alles einzeln inkludiert werden muss (Siehe ReadMe)
Paket PermMem hinzugefügt
Paket Locals hinzugefügt
Paket List hinzugefügt
Paket Anim8 hinzugefügt
Paket View hinzugefügt
Paket Int64 hinzugefügt
FrameFunctions
FF_Apply(string) zu FF_Apply(func)
FF_Remove(string) zu FF_Remove(func)
FF_ApplyExt hinzugefügt
FF_Active hinzugefügt
AI_Function_*(C_Npc, string, ...) zu AI_Function_*(C_Npc, func, ...)
Views sind nun im Paket View und nicht mehr in Interface
View
Print_CreateView zu View_Create
Print_CreateViewPxl zu View_CreatePxl
Print_SetViewTexture zu View_SetTexture
Print_OpenView zu View_Open
Print_CloseView zu View_Close
View_Delete hinzugefügt
View_Get hinzugefügt
Views arbeiten nun mit PermMem und sind Fehlerfrei
Views sind nun keine Pointer mehr sondern Handles
Interface
Print_ToVirtual hinzugefügt, um Pixel in virtuelle Koordinaten umzuwandeln
Print_ToPixel hinzugefügt, um virtuelle Koordinaten in Pixel umzuwandeln
Print_Extended zu Print_ExtPxl (Pixelgenaue Koordinaten)
Print_Ext hinzugefügt (Virtuelle Koordinaten)
Print_CreateText, Print_Ext und Print_ExtPxl geben nun Handles zurück
Print_DeleteText nimmt nun Handles an
Print_GetText hinzugefügt, um mit den Handles arbeiten zu können
Mit Print_* erstellte Texte überleben nun das Laden (Dank PermMem)
PrintS komplett überarbeitet und mit Anim8 versehen
Trialoge funktionieren nun auch mit unterschiedlich großen/dicken Npcs
Kleines Problem in AI_Function behoben
Bloodsplats komplett gefixt und mit neuen View-Funktionen versehen
Dialoggestures in richtige Reihenfolge gebracht
Problem mit Cursor_Show behoben
Schwerwiegendes Problem in Saves behoben
Fehler in BR_ReadBytes behoben
Die Schilde sind noch sehr fehleranfällig und unfertig. Seit dem Release wurde daran nichts geändert
Gottfried wollte diese Version 1.1 nennen, Lehona wollte 2.0. Gottfried hat irgendwann zugestimmt.
2.0.114.11.2011
Zwei kleinere Fehler in den Beispielen behoben
Absturz bei Levelchange beseitigt
Objekte von PermMem bleiben nun auch nach einem Levelchange erhalten
PrintS finalisiert
2.120.11.2011
Bars hinzugefügt (mit Beispielen)
Fehler in Saves behoben der keine Quicksaves zugelassen hat
Feinschliff an PrintS vorgenommen und Konstanten nach oben verschoben
Cursor
Cursor_Wheel hinzugefügt
Cursor_NoEngine hinzugefügt
Cursor_Left hinzugefügt
Cursor_Right hinzugefügt
Cursor_Mid hinzugefügt
Cursor_X() zu Cursor_X
Cursor_Y() zu Cursor_Y
Funktioniert ab jetzt nur wenn in Gothic die Maus aktiviert ist
Da sind sie ja endlich, du hattest mir ja schon ein paar davon in Aussicht gestellt. Jetzt muss ich da nur erstmal noch die Versionen, die du mir so zugespielt hast, entwirren.
Zitat von Milgo
Ich würd mich natürlich auch weiterhin über ne Funktion freuen um quasi in Echtzeit den Helden zu wechseln.
Wenn ich mich richtig erinnere, sind die Trialoge hier auf eine Art und Weise implementiert, die sich vielleicht auch dafür nutzen lässt.
EDIT: "Die Datei [...] kann nicht als Archiv geöffnet werden." 7zip ist installiert. Kann das einer bestätigen (und / oder beheben) ?
EDIT 2: Scheint an Opera zu liegen, mit Firefox funktioniert es. Mal schauen, was passiert, wenn ich die Datei selbst mit Opera anhänge...
EDIT 3: Mittlerweile funktioniert es auch mit deinem Link.
Ich würd mich natürlich auch weiterhin über ne Funktion freuen um quasi in Echtzeit den Helden zu wechseln.
Ja, da könnte man was machen.
Zitat von Milky-Way
Wenn ich mich richtig erinnere, sind die Trialoge hier auf eine Art und Weise implementiert, die sich vielleicht auch dafür nutzen lässt.
Korrekt. Sehr viel muss man da nicht mehr ändern um es für einen kompletten Tausch zu verwenden.
Zitat von Milky-Way
Da sind sie ja endlich, du hattest mir ja schon ein paar davon in Aussicht gestellt. Jetzt muss ich da nur erstmal noch die Versionen, die du mir so zugespielt hast, entwirren.
Na dann viel Spaß dabei
Zitat von Milky-Way
EDIT: "Die Datei [...] kann nicht als Archiv geöffnet werden." 7zip ist installiert. Kann das einer bestätigen (und / oder beheben) ?
Ich habe mir eben die Datei nochmal runtergeladen und konnte sie Problemlos öffnen.. Hast du es vielleicht versucht während sie noch heruntergeladen wurde?
Okay, hat sich ja erledigt.
Mir hat sich grad beim Durchgucken eine Frage gestellt: Bei den Bloodsplats, hookst du da die PERC_AssessDamage? Wenn man nämlich eine alternative Schadensberechnung hat und daher nur den Minimalschaden macht, dann funktioniert das ja nicht, oder? Müsste ich dann manuell bei meiner Schadensverteilung aufrufen mit dem Schaden.
EDIT:
Scheint so zu sein, wenn ich das richtig sehe, hab's mal etwas getestet.
Was mir als Fehler aufgefallen ist: Bei den Blutspritzern kommt hin und wieder die Default-Textur, fehlt vllt. eine Textur? Im Archiv sind ja 7 und als Maximum ist auch 7 angegeben
Ein sehr nützliches Paket. Insbesondere die Trialoge und Dialoggesten sind gleichzeitig wahnsinnig nützlich und einfach zu benutzen.
HookEngine ist so nützlich und elementar, dass es eigentlich in Ikarus rein müsste.
Was man noch tun könnte:
Savegames: In der jetzigen Form muss eine zentrale Stelle, nämlich BW_Savegame genau wissen welche Daten es gibt. Und das Beispiel mit dem Point hinkt schon, weil nicht klar ist, wer den Punkt beim Beenden der Session frei gibt. Was man eigentlich will ist automatisch verwalteter Speicher. Das System sollte fähig sein, Objekte einer bestimmten Klasse zu konstruieren zu speichern, zu laden und zu destruieren, evtl. mithilfe nutzerdefinierter Funktionen aber nicht an zentraler Stelle. Evtl. so:
Code:
/* Paket stellt zur Verfügung:
handle new(string className)
void delete(handle h)
instance get(handle h)
void* get_ptr(handle h)
Dabei ist in Wirklichkeit handle = int und void* = int
Automatisch erkannt werden methoden:
[classname]_new:
wird, falls vorhanden, von new aufgerufen.
wird außerdem vor dem Laden des Objekts aus dem savegame aufgerufen.
Standardimplementierung lässt alles auf 0.
[classname]_cleanup
wird, falls vorhanden von delete aufgerufen
und beim zerstören der Session (mit HookEngine erkannt)
Standardimplementierung tut nichts. In dem Fall wird
nur das Objekt freigegeben, aber nicht evtl. im Objekt enthaltene Pointer
[classname]_archive
wird, falls vorhanden, beim Speichern aufgerufen.
Standardimplementierung speichert die enthaltenen Strings und integer
einfach so ab (das zum Beispiel beim zCArray nicht sinnvoll, weil dann
nur ein Pointer auf die Daten gespeichert wird, nicht aber die Daten)
[classname]_unarchive
wird, falls vorhanden, aufgerufen, wenn ein Objekt aus dem Savegame
geladen wird, nachdem dieses Objekt konstruiert wurde (mit new oder
default implementierung).
Standardimplementierung kompatibel mit Standardimplementierung von _archive
Um das Paket so zu bauen ist es nötig die Existenz von Parsersymbolen zu prüfen
sowie die Struktur einer Klasse in Erfahrung zu bringen von der man nur
den Namen (als String) kennt. Beides ist aber möglich.
Beispiel:
*///************************************************
// zCArray:
//************************************************
/* new nicht nötig, da Standardimplementierung genügt.
Drei Nuller entsprechen einem leeren Array *//* archive speichert alle Daten, aber z.B. nicht arr.array */
func void zCArray_archive(var zCArray arr){
BW_Int(arr.numInArray);
/* pseudo code: */
for (int i = 0; i < arr.numInArray; ++i){
BW_Int(MEM_ReadIntArray(arr.array, i));
};
};
func void zCArray_unarchive(var zCArray arr){
arr.numInArray = BR_Int();
arr.array = MEM_Alloc(arr.numInArray * 4);
arr.numAlloc = arr.numInArray;
/* pseudo code: */
for (int i = 0; i < arr.numInArray; ++i){
MEM_WriteIntArray(arr.array, i, BR_Int());
};
};
/* wichtig: Daten müssen freigegeben werden */
func void zCArray_cleanup(var zCArray arr){
MEM_Free(arr.array);
};
//************************************************
// Point
//************************************************
class Point {
var int x;
var int y;
};
func void Point_new(var Point p){//Standardkonstruktor erzeugt meinen Lieblingspunkt
p.x = 42;
p.y = 23;
};
/* archive und unarchive nicht nötig, da Standardimplementierung
die Datenmember x und y speichert, genau das, was wir wollen. *//* cleanup nicht nötig, da der Punkt nur primitive Datentypen beinhaltet *///************************************************
// Anwendung:
//************************************************
var int Mein_PunktArray; /* handle */
func void MerkePunkt(var int x, var int y){
var int neuerPunkt; /* handle */
neuerPunkt = NEW("Point"); //gibt Handle zurück mit dem der Punkt identifiziert wird.
var Point p; p = GET(neuerPunkt);
p.x = x; p.y = y;
if (!Mein_PunktArray){
Mein_PunktArray = NEW("zCArray");
};
var int arr_ptr;
arr_ptr = GET_PTR(Mein_PunktArray);
MEM_ArrayInsert(arr_ptr, neuerPunkt);
};
func void HolePunkt(var int result, var int index){
if (!Mein_PunktArray){
MEM_Error("Du hast dir noch keinen Punkt gemerkt");
return;
};
var zCArray arr;
arr = GET(Mein_PunktArray);
var int punkt;
punkt = MEM_ReadIntArray(arr.array, index);
MEM_AssignInst(result, GET_PTR(punkt));
};
{
MerkePunkt(3, 4);
MerkePunkt(5, 6);
MerkePunkt(22, 23);
/*... speichern laden etc ... */
var Point p;
HolePunkt(p, 1);
//es gilt:
p.x == 5 && p.y == 6;
}/* optional:
eine BIND Funktion könnte eine instanz an ein bestimmtes Handle binden:
var Point myImportantPoint;
BIND(myImportantPoint, NEW("Point"));
Ab jetzt wird in myImportantPoint immer eine Referenz auf den neuen
Punkt stehen, auch nach Speichern und laden.
*/
Bei den Texten wäre es natürlich nett, wenn das Scrollen und Ausblenden nicht selbst implementiert werden muss. Noch dazu muss man sich ja von allen Texten, die zum Beispiel scrollen sollen eine Referenz merken. Das ist sehr unpraktisch.
Mir hat sich grad beim Durchgucken eine Frage gestellt: Bei den Bloodsplats, hookst du da die PERC_AssessDamage? Wenn man nämlich eine alternative Schadensberechnung hat und daher nur den Minimalschaden macht, dann funktioniert das ja nicht, oder? Müsste ich dann manuell bei meiner Schadensverteilung aufrufen mit dem Schaden.
Nein, die Perc_AssessDamage wird nicht gehookt, nur dem Helden wird _B_HeroDamage als genau diese Perception zugewiesen:
Was mir als Fehler aufgefallen ist: Bei den Blutspritzern kommt hin und wieder die Default-Textur, fehlt vllt. eine Textur? Im Archiv sind ja 7 und als Maximum ist auch 7 angegeben
Du hast Recht. Die Bloodsplats.d wurde letztens auf LeGo-Random umgebaut. r_Max(7) gibt alle Zahlen von 0 bis einschließlich 7 zurück. Bloodsplat_Tex muss also 6 sein.
Zitat von Sektenspinner
[...] Savegames [...]
Stimmt, die Saves.d ist momentan noch ziemlich primitiv. Lehona arbeitet momentan an einer Methode ähnlich der die du hier erklärt hast, aber diesen Vorschlag könnte man direkt 1:1 übernehmen. Mal sehen was wird
Zitat von Sektenspinner
Bei den Texten wäre es natürlich nett, wenn das Scrollen und Ausblenden nicht selbst implementiert werden muss. Noch dazu muss man sich ja von allen Texten, die zum Beispiel scrollen sollen eine Referenz merken. Das ist sehr unpraktisch.
Dafür gibt es ja PrintS, aber ich glaube ich verstehe was du meinst. Es sollte erweiterte Methoden geben mit dem Text umzugehen. (Wird dank den FrameFunctions auch kein großes Problem darstellen.)
Zitat von Umfi
Aber ich habe ein Problem, nähmlich bei jedem (!) Levelchange stürzt G2 ab. Egal von welchen Level ich wechsel, es stürzt immer ab.
Genau dieses Problem hatte ich letztens auch, konnte aber den Fehler noch nicht identifizieren. Wir arbeiten daran
Hab's grad gemerkt, hatte mich schon gewundert, warum immer nur Minimalschaden kam, aber kein Wunder, wenn meine B_AssessDamage_Hero nimmer aufgerufen wird Aber mit manuell Bloodsplats aufrufen scheint es ja auch zu klappen.
Zitat von Gottfried
Du hast Recht. Die Bloodsplats.d wurde letztens auf LeGo-Random umgebaut. r_Max(7) gibt alle Zahlen von 0 bis einschließlich 7 zurück. Bloodsplat_Tex muss also 6 sein.
sieht gut aus! Wenn mein PC wieder heil ist() werd ichs mir anschauen
Wo ich grad dabei bin und weil ich den Ikarus-Thread nicht rausholen will: wie macht man sowas eig.? also Sachen wie an Klassen kommen wie bei Ikarus oder solche Sachen aben würde mich mal interessieren
gruß Lemon