|
-
Pflanzenrespawn mit PermMem
Hi, da ich mir mal PermMem näher anschauen wollte, hab ich einen Pflanzenrespawn mit Hilfe von PermMem realisiert.
An der Stelle möcht ich mich gleich nochmal bei Lehona und Gottfried für LeGo bedanken, wenn ich denke das man früher für etwas in der Art mit 100terten von Waypoints und Abfragen kämpfen musste....
Als erstes muss man die Pflanzenitems ergänzen mit einer Zeile, und zwar mit der ungenutzen Varible nutrition der Klasse C_Item/oCItem.
So könnte es dann z.B. aussehen:
Code:
INSTANCE ItPl_Survival_Plant_2 (C_Item)
{
name = "Plant 2";
mainflag = ITEM_KAT_FOOD;
flags = ITEM_MULTI;
value = Value_Plant_1;
visual = "SURVIVAL_ITEMPLANT_02.3DS";
material = MAT_LEATHER;
on_state[0] = Use_Plant_2;
scemeName = "FOOD";
description = name;
nutrition = 1; //nur Pflanzen
TEXT[5] = NAME_EFFEKT;
};
func void Use_Plant_2 ()
{
Npc_ChangeAttribute (self, ATR_HITPOINTS, HP_Plant_2);
};
Als nächstes müssen wir die Stelle hooken, an der der Spieler die Items aufhebt.
Dazu muss folgendes in die InitGlobals der Startup.d
Code:
if (!Hlp_StrCmp(GOTHIC_RESTART, "Y"))
{
Hook_oCNpc__DoTakeVob();
GOTHIC_RESTART = "Y";
};
So jetzt zum eigentlichen Hook.
Code:
///////////////////////////////////////////////////////////////////////////////
// Hook: Item aufheben
//////////////////////////////////////////////////////////////////////////////
func void Hook_oCNpc__DoTakeVob() {
const int oCNpc__DoTakeVob = 7621056; //0x7449C0
HookEngine(oCNpc__DoTakeVob, 6, "EVT_NPCTAKEVOB");
};
func void EVT_NpcTakeVob()
{
// ----- an den NPC und das item kommen -----
var c_npc slf; slf = MEM_PtrToInst(ECX); // der NPC, der das Item einsammelt
var oCItem itm; itm = MEM_PtrToInst(MEM_ReadInt(ESP + 4)); // Pointer auf das Item
// ----- an den NPC und das item kommen -----
// ----- stimmt das item? -----
if (!Hlp_IsValidItem (itm))
{
return;
}
else
{
if ((itm.nutrition == 1) && ((itm.flags & ITEM_DROPPED) != ITEM_DROPPED))
{
CreateRespawnObject(itm);
};
};
};
Jetzt zum eigentlich Teil, nähmlich den RespawnObjekt.
Code:
/*****************************************
* RespawnObject
* Verantwortlich für den Pflanzen respawn
*****************************************/
class RespawnObject {
var int inst;
var int spawnPosition[16];
var int respawnDay;
var string WorldName;
};
instance RespawnObject@(RespawnObject);
//*************************************
// Erzeuge ein RespawnObject
//*************************************
func void CreateRespawnObject(var oCItem slf) {
var int hndl; hndl = new(RespawnObject@);
var RespawnObject myRespawnObject; myRespawnObject = get(hndl);
myRespawnObject.inst = Hlp_GetInstanceID(slf);
MEM_CopyWords(_@(slf._zCVob_trafoObjToWorld), _@(myRespawnObject.spawnPosition), 16);
myRespawnObject.respawnDay = Wld_GetDay() + 2; // Irgendeine Formel z.b: Wld_GetDay() + (slf.value/20)+2;
myRespawnObject.WorldName = MEM_World.worldName;
};
//*************************************
// Entferne ein RespawnObject
//*************************************
func void RemoveRespawnObject(var int hndl) {
delete(hndl);
};
//************************************************
// Iteminstance an Koordinaten einfügen
//************************************************
func void MEM_InsertItemInstance (var int inst, var int fX, var int fY, var int fZ) {
var zCWaynet wayNet; wayNet = MEM_PtrToInst(MEM_World.wayNet);
var zCWaypoint wp; wp = MEM_PtrToInst(MEM_ReadInt(wayNet.wplist_next+4));
var int x; x = wp.pos[0];
var int y; y = wp.pos[1];
var int z; z = wp.pos[2];
wp.pos[0] = fX;
wp.pos[1] = fY;
wp.pos[2] = fZ;
Wld_InsertItem(inst, wp.name);
wp.pos[0] = x;
wp.pos[1] = y;
wp.pos[2] = z;
};
/* Wer die Funktionen von Sektenspinner noch nicht hat....
//************************************************
// Set Position of Vob
//************************************************
func void GetPositionWorldVec(var int vobPtr, var int vecPtr) {
var zCVob vob; vob = MEM_PtrToInst(vobPtr);
MEM_WriteIntArray(vecPtr, 0, vob.trafoObjToWorld[3]);
MEM_WriteIntArray(vecPtr, 1, vob.trafoObjToWorld[7]);
MEM_WriteIntArray(vecPtr, 2, vob.trafoObjToWorld[11]);
};
func void SetPositionWorldVec(var int vobPtr, var int vecPtr) {
const int zCVob_SetPositionWorld = 6404976; //0x61BB70
CALL_PtrParam(vecPtr);
CALL__thiscall(vobPtr, zCVob_SetPositionWorld);
};
//Wenn manuell an der Position rumgeschmiert wird, werden Bounding Box usw. nicht angepasst.
//Vobs flackern oder haben Fokusnamen an der falschen Stelle etc.
func void VobPositionUpdated(var int vobPtr) {
var int pos[3];
GetPositionWorldVec(vobPtr, _@(pos));
SetPositionWorldVec(vobPtr, _@(pos));
};
*/
//***************************************
// Überprüfe ob gespawned werden darf
//***************************************
func void CheckRespawns() {
foreachHndl (RespawnObject@, _CheckRespawns);
};
func int _CheckRespawns(var int hndl) {
var RespawnObject myRespawnObject; myRespawnObject = get(hndl);
if (myRespawnObject.respawnDay <= Wld_GetDay() && (Hlp_StrCmp (myRespawnObject.WorldName, MEM_World.worldName))) {
MEM_InsertItemInstance(myRespawnObject.inst, myRespawnObject.spawnPosition[3], myRespawnObject.spawnPosition[7], myRespawnObject.spawnPosition[11]);
var zCPar_Symbol a; a = _^(MEM_ReadIntArray (currSymbolTableAddress, myRespawnObject.inst));
var oCItem itm; itm = _^(a.offset);
var int itmPtr; itmPtr = MEM_InstToPtr (itm);
MEM_CopyWords(_@(myRespawnObject.spawnPosition),_@(itm._zCVob_trafoObjToWorld), 16);
VobPositionUpdated(itmPtr);
RemoveRespawnObject(hndl);
};
return rContinue;
};
Zum Schluss muss die Funktion CheckRespawns(); noch aufgerufen werden, dass kann z.B.: in der SleepABit.d in der Funktion PC_Sleep() gemacht werden.
Code:
func void PC_Sleep (var int t)
{
AI_StopProcessInfos(self);
PLAYER_MOBSI_PRODUCTION = MOBSI_NONE;
self.aivar[AIV_INVINCIBLE]=FALSE;
if (Wld_IsTime(00,00,t,00))
{
Wld_SetTime (t,00);
}
else
{
t = t + 24;
Wld_SetTime (t,00);
};
CheckRespawns();
[...]
};
Und das wars schon 70 Zeilen Code (ohne Hooks usw.) reichen um ein funktionierendes Pflanzenrespawnsystem zu implementieren.
Kommentiert hab ich den Code jetzt nicht, aber das könnt ihr ja in Lehonas Tutorial nachlesen.
Geändert von Umfi (11.04.2012 um 16:12 Uhr)
-
Wollte ich auch schon machen, aber weil ich's nicht in XR einbauen durfte, hab ich's gelassen
Aber das tolle ist, dass ich es jetzt nicht mehr machen muss, wenn ich es doch mal irgendwo einbauen will.
Was man berücksichtigen sollte in Mods mit mehreren Leveln (also Ladezonen), ist, dass die Pflanzen im richtigen Level respawnt werden, das gilt aber ja auch schon für Lehonas Monsterrespawn.
Braucht es das Struct zum Speichern nicht unbedingt oder hast du es vergessen?
-
Zitat von Bonne6
Wollte ich auch schon machen, aber weil ich's nicht in XR einbauen durfte, hab ich's gelassen
Aber das tolle ist, dass ich es jetzt nicht mehr machen muss, wenn ich es doch mal irgendwo einbauen will.
Was man berücksichtigen sollte in Mods mit mehreren Leveln (also Ladezonen), ist, dass die Pflanzen im richtigen Level respawnt werden, das gilt aber ja auch schon für Lehonas Monsterrespawn.
Braucht es das Struct zum Speichern nicht unbedingt oder hast du es vergessen?
Warum durftest du das denn nicht einbauen? Balancing?
Solange sich eine Klasse durch "auto|x" zusammenfassen lässt, ist eine Strukturbeschreibung unnötig
-
Schwächen (zum Teil schon genannt):
- Die Respawn Objekte müssen die Welt kennen für die sie gelten.
- 256 Objekte ist ein künstliche und unnötige Beschränkung (und viel zu klein). Nutze zCArray, LeGo kann damit umgehen (hat Archiver und Unarchiver) und Ikarus bietet Funktionen zum einfügen und entfernen. Also new(zCArray@) und ab gehts.
Vielleicht kannst du dir sogar das Array sparen und etwas wie foreachHndl(RespawnObject@, CheckPlant) machen, allerdings ist da die Dokumentation etwas dünn. - Die Positionswerte zu speichern ist nicht immer ausreichend. Man bedenke, dass moos- und pilzartige Pflanzen auch gedreht an Steinen wachsen können. Ich würde empfehlen die gesammte Transformationsmatrix zu kopieren:
Code:
MEM_CopyWords(_@(vob._zCVob_trafoObjToWorld), _@(myRespawnObject.spawnPosition), 16);
die gespeicherten Werte dann beim Einfügen des Vobs in die Tranformationsmatrix zu kopieren und VobPositionUpdated oder vergleichbares aufzurufen. - Wenn du die Schleifenbedingung direkt ins while packst, sieht das etwas besser aus und du brauchst den Spezialfall nextRespawnIndex == 0 nicht.
- Du solltest auf das flag ITEM_DROPPED prüfen, aus naheliegenden Gründen.
-
-
Zitat von Lehona
ForEachHndl() ist vermutlich in der Tat die schönere Lösung und meiner Meinung nach ist die Dokumentation vollkommen ausreichend, aber ich kenn es ja quasi auch
Nun, ist wohl etwas unfair von mir, der Dokumentation vorzuwerfen sie sei dünn, ohne das zu konkretisieren. Zunächst sei festgehalten, dass in der Doku nicht steht, dass die behandelnde Funktion einen Rückgabewert haben muss (rBreak bzw. rContinue).
Bedenken hatte ich zudem, weil die Doku kein Wort darüber verliert, inwiefern es zulässig ist Objekte zu zerstören während iteriert wird. Zumindest, falls ein Handle freigegeben wird über das eigentlich gleich noch iteriert werden wird, wird bei der Funktion ein ungültiges Handle ankommen. Der vorliegene Fall scheint allerdings unkritisch zu sein und es scheint zulässig das Handle über das gerade iteriert wird freizugeben.
-
Zitat von Sektenspinner
Nun, ist wohl etwas unfair von mir, der Dokumentation vorzuwerfen sie sei dünn, ohne das zu konkretisieren. Zunächst sei festgehalten, dass in der Doku nicht steht, dass die behandelnde Funktion einen Rückgabewert haben muss (rBreak bzw. rContinue).
Bedenken hatte ich zudem, weil die Doku kein Wort darüber verliert, inwiefern es zulässig ist Objekte zu zerstören während iteriert wird. Zumindest, falls ein Handle freigegeben wird über das eigentlich gleich noch iteriert werden wird, wird bei der Funktion ein ungültiges Handle ankommen. Der vorliegene Fall scheint allerdings unkritisch zu sein und es scheint zulässig das Handle über das gerade iteriert wird freizugeben.
Ersteres war mir selber nicht mal bewusst (Gottfried hatte das mal erwähnt, war aber eher eine flüchtige Erinnerung ) und das gerade benutzte Objekt darf man löschen, da hat sich Gottfried drum gekümmert (Hatte er erst selber mit Probleme). Zukünftige Handles zu löschen wird wohl nicht funktionieren, da hast du Recht... Die Frage ist, wann das mal vorkommt und wie gut es lösbar ist? Aber das ist in der Tat sinnvolle Kritik, das besser ich entweder selber aus oder hau Gottfried mal an (Er hat die Funktion schließlich geschrieben), der sollte heute eh aus dem Urlaub kommen.
-
Zitat von Sektenspinner
Schwächen (zum Teil schon genannt):
- Die Respawn Objekte müssen die Welt kennen für die sie gelten.
- 256 Objekte ist ein künstliche und unnötige Beschränkung (und viel zu klein). Nutze zCArray, LeGo kann damit umgehen (hat Archiver und Unarchiver) und Ikarus bietet Funktionen zum einfügen und entfernen. Also new(zCArray@) und ab gehts.
Vielleicht kannst du dir sogar das Array sparen und etwas wie foreachHndl(RespawnObject@, CheckPlant) machen, allerdings ist da die Dokumentation etwas dünn. - Die Positionswerte zu speichern ist nicht immer ausreichend. Man bedenke, dass moos- und pilzartige Pflanzen auch gedreht an Steinen wachsen können. Ich würde empfehlen die gesammte Transformationsmatrix zu kopieren:
Code:
MEM_CopyWords(_@(vob._zCVob_trafoObjToWorld), _@(myRespawnObject.spawnPosition), 16);
die gespeicherten Werte dann beim Einfügen des Vobs in die Tranformationsmatrix zu kopieren und VobPositionUpdated oder vergleichbares aufzurufen. - Wenn du die Schleifenbedingung direkt ins while packst, sieht das etwas besser aus und du brauchst den Spezialfall nextRespawnIndex == 0 nicht.
- Du solltest auf das flag ITEM_DROPPED prüfen, aus naheliegenden Gründen.
Danke, ich werd's versuchen gleich um/einzubauen und dann den Code oben zu aktualisieren.
@ flag ITEM_DROPPED
Stimmt, dass ich das vergessen habe.
(das hab ich gleich mal ausgebessert.)
-
Okay, oben findet ihr jetzt die aktuellste Version des Skriptes. Danke noch mal an Lehona, der mir bei (aus meiner Sicht unlösbaren Problemen) geholfen hat.
Das Skript arbeitet jetzt mit den foreachhandles, sie sind wirklich einfach zubedienen, im Vergleich zu den Daedalus Arrays.
mfg Umfi
Geändert von Umfi (11.04.2012 um 17:39 Uhr)
-
Wird die Rotation da jetzt auch berücksichtigt?
Und ich finde das sollte dann wie im Ikarus-Thread im ersten Beitrag verlinkt werden, ist ja doch was Nützliches und dann muss man nicht immer wieder suchen, wenn man mal gucken will
-
Zitat von Bonne6
Wird die Rotation da jetzt auch berücksichtigt?
Und ich finde das sollte dann wie im Ikarus-Thread im ersten Beitrag verlinkt werden, ist ja doch was Nützliches und dann muss man nicht immer wieder suchen, wenn man mal gucken will
Die komplette Transformationsmatrix wird überschrieben.
Ich werde Gottfried sofort dazu zwingen, sobald er wieder da ist. Eigentlich sollte ich die Threads einfach eröffnen, als Mod kann er meinen Beitrag eh editieren.
Übrigens sollte ich mein Tutorial zu PM auch auf ForEachHndl() aktualisieren - das hat vieles einfacher gemacht.
-
Zitat von Sektenspinner
Nun, ist wohl etwas unfair von mir, der Dokumentation vorzuwerfen sie sei dünn, ohne das zu konkretisieren. Zunächst sei festgehalten, dass in der Doku nicht steht, dass die behandelnde Funktion einen Rückgabewert haben muss (rBreak bzw. rContinue).
Bedenken hatte ich zudem, weil die Doku kein Wort darüber verliert, inwiefern es zulässig ist Objekte zu zerstören während iteriert wird. Zumindest, falls ein Handle freigegeben wird über das eigentlich gleich noch iteriert werden wird, wird bei der Funktion ein ungültiges Handle ankommen. Der vorliegene Fall scheint allerdings unkritisch zu sein und es scheint zulässig das Handle über das gerade iteriert wird freizugeben.
Eigentlich wollte ich zum Thema foreachHndl auch noch ein Beispiel beisteuern, das ist offensichtlich untergegangen. Ich werde das in den folgenden Tagen nachholen.
(Achso. Ich sehe gerade.. Die Beispiele zu PermMem wurden noch gar nicht übertragen. Ich mache das so bald wie möglich.)
Dann verliere ich mal ein paar Worte zur Funktionalität der Funktion:
Wenn ein handle über "new" erzeugt wird (und auch wirklich nur bei new), landet es direkt in der foreachTable. Die kann man sich ungefähr so vorstellen: Für jede Instanz-ID existiert ein zCArray in dem alle Handles ebendieser gespeichert sind.
Ruft der Nutzer also new(1205) auf, wird der Rückgabewert in das zCArray foreachTable[1205] geschrieben. Sinngemäß.
Angenommen new(1205) wird fünf Male hintereinander gecallt, so ist foreachTable[1205]->numInArray (die Anzahl der Elemente des zCArrays) mindestens fünf.
Was genau passiert nun beim Aufruf foreachHndl(1205, myFunc)?
Zuerst wird der gesamte Inhalt des zCArrays foreachTable[1205], sprich foreachTable[1205]->array, in einen neu alloziierten Pointer kopiert. Da dieser eigene Speicherbereich von new und delete absolut unabhängig ist, ist es möglich aus einer Funktion die von foreachHndl gecallt wurde heraus, das übergebene Handle zu löschen. Die Kopie wird nach Abschließen des Vorganges wieder freigegeben.
Folgendes ist also denkbar:
Code:
func void deleteAll(var int inst) {
foreachHndl(inst, deleteAll_sub);
};
func void deleteAll_sub(var int handle) {
delete(handle);
};
Was passiert? Alle handles dieser Instanz werden gelöscht. Beispiel: deleteAll(FFItem@); um sämtliche FrameFunctions zu stoppen.
Aber war da nicht etwas mit Rückgabewert? Ja. Im Prinzip ist der eben gezeigte Code nicht ganz korrekt. Richtig wäre es so:
Code:
func void deleteAll(var int inst) {
foreachHndl(inst, deleteAll_sub);
};
func int deleteAll_sub(var int handle) {
delete(handle);
return rContinue;
};
Wie Sektenspinner bereits erwähnt hat, gibt es die beiden Symbole rContinue und rBreak. Einigen dürfte das bekannt vorkommen. Wird rContinue zurückgegeben passiert "nichts" und alle folgenden Handles werden ebenfalls durchgegangen. Eine Rückgabe von rBreak hingegen stoppt die Schleife.
Beispiel: Ich möchte nur das erste Handle in der Liste löschen.
Code:
func void deleteFirst(var int inst) {
foreachHndl(inst, deleteFirst_sub);
};
func int deleteFirst_sub(var int handle) {
delete(handle);
return rBreak;
};
Warum es in obigem Beispiel trotz "func void" funktioniert ist einfach: Es wird nur der Sonderfall rBreak behandelt, rContinue ist nur eine symbolische Variable.
Was foreachHndl macht ist den Rückgabewert vom Stack zu popen. In dieser Hinsicht kommt uns das Verhalten des Parsers zugute: Wird von einem leeren Stack gepopt kommt einfach eine null zurück, und da 0 != rBreak ergibt sich aus keinem Rückgabewert vergleichsweise ein Rückgabewert von rContinue.
Trotzdem hat Sektenspinner natürlich Recht. Liegt zB. noch etwas Müll auf dem Stack der zufällig den Wert von rBreak beinhaltet, kann das zu unerwünschten Nebeneffekten führen. Sicher ist sicher.
Doch zurück zu der anderen Problematik.
Bedenken hatte ich zudem, weil die Doku kein Wort darüber verliert, inwiefern es zulässig ist Objekte zu zerstören während iteriert wird. Zumindest, falls ein Handle freigegeben wird über das eigentlich gleich noch iteriert werden wird, wird bei der Funktion ein ungültiges Handle ankommen.
Der erste Fall ist klar. Es ist problemlos möglich das aktuelle Objekt zu zerstören, da durch die Kopie des Arrays nichts verrutschen kann.
Der zweite Fall ist schon etwas verzwickter. foreachHndl prüft trotz der Kopie vor jedem Handle erneut ob es gültig ist, damit ist auf jeden Fall gewährleistet, dass keine ungültigen Handles in der Schleife landen können. So weit so gut. Wenn eine Schleife also lustig herumlöscht sollte das im Prinzip keine Probleme machen, da die handles dadurch automatisch ungültig werden.
Jetzt gibt es aber ein Problem. Ich glaube das lässt sich mit einem Beispiel wieder am besten erläutern:
Code:
1. Handle 1 und 2 werden mit der Instanz A erzeugt.
2. Für die Instanz A wird foreachHndl ausgeführt.
3. Während Handle 1 abgearbeitet wird, löscht es sich selbst und Handle 2.
4. Handle 2 ist ungültig und wird übersprungen.
Perfekt. Wo ist da das Problem? Noch keines. Das ist der Fall der in der Regel funktionieren sollte. Was passiert nun wenn ich Punkt 3 etwas abändere? So vielleicht:
Code:
3. Während Handle 1 abgearbeitet wird, löscht es sich selbst und Handle 2. Danach erzeugt es ein neues Handle der Instanz B.
Und schon ist das Problem da: Handle 2 ist nach dem Löschvorgang natürlich frei, kann also wenn es schlecht läuft direkt danach wieder befüllt werden, dummerweise mit einer Instanz B.
Wie geht es weiter?
Code:
4. Handle 2 ist nicht ungültig und wird als nächstes aufgerufen.
Ich hoffe das war alles weitestgehend verständlich. (Bin etwas müde.)
Bis zur nächsten Version wird ein Check auf die Instanz mit drin sein, damit dürfte man bunt rumlöschen können
Achja.. Sektenspinner hat mich letztens auf eine nette Funktion des Renderers aufmerksam gemacht. Es ist nun möglich zweidimensionale Bildchen dreh- und zoombar auf dem Bildschirm darzustellen, sogar mit frei einstellbaren UV-Koordinaten der zugewiesenen Textur. Wer will kann es sich bereits vom SVN runterziehen. Das Paket ist die "Sprite.d".
In den folgenden Tagen (Ich glaube ich sollte diese Phrase nicht all zu oft nutzen?) werde ich dazu zwei/drei Tutorials schreiben, die Möglichkeiten sind da ja beinahe endlos
(Kompass, Minimap, Sektenspinner hat ein Minispiel für das Schlösserknacken vorgeschlagen..)
MfG Gottfried
-
Zu der Problematik mit ForEachHndl(): Es steht momentan im Raum (Von Sektenspinner angesprochen), mit Hashtabellen zu arbeiten. Das würde dann a) Hlp_IsValidHandle() "sicher" machen, würde also besser funktionieren und b) dieses Problem mit ForEachHndl() beheben (Was sich aber eh auf Hlp_IsValidHandle() zurückführen lässt). Desweiteren hat new() dann eine Laufzeit von O(1), also konstant, wobei das auch ohne Hashtabelle möglich wäre.
-
Moin Moin,
Wenn eine Funktion in die AI_Queue geschoben wird, ist dann innerhalb der Funktion "self" schon der Queuenbesitzer?
edit: Mir Idiot ist natürlich nicht eingefallen, das eben selbst auszuprobieren...
Die Antwort ist nein.
Die Felder haben Augen, die Wälder Ohren.
Geändert von waldhoppser (14.04.2012 um 12:05 Uhr)
-
Zitat von waldhoppser
Moin Moin,
Wenn eine Funktion in die AI_Queue geschoben wird, ist dann innerhalb der Funktion "self" schon der Queuenbesitzer?
edit: Mir Idiot ist natürlich nicht eingefallen, das eben selbst auszuprobieren...
Die Antwort ist nein.
Das ist allerdings keine dumme Frage. Self sollte über einen Register ansprechbar sein, ich such das eben raus.
Edit:
Code:
var oCNpc slf; slf = _^(ECX);
Das tut's
-
Apprentice
Hello again, today I am not writhing to you to trouble you with some bugs I have found, but to ask for your permission to make a polish wiki about LeGo. The idea was mine and i have been thinking about it for a while now. Edeksumo offered his help so whole process shouldn't take long, but before we start we would like to know if you don't have any problem with that.
-
Zitat von Roshi
Hello again, today I am not writhing to you to trouble you with some bugs I have found, but to ask for your permission to make a polish wiki about LeGo. The idea was mine and i have been thinking about it for a while now. Edeksumo offered his help so whole process shouldn't take long, but before we start we would like to know if you don't have any problem with that.
We obviously don't have a problem with that, but what about some kind of cooperation and hosting the wiki at http://gottfried.milgo.de/LeGo/pl/? So you just have to care about the wiki (it's done mostly in MediaWiki-Syntax), everything else will be taken care of
Do you have any sort of Instant Messenger where we can discuss things further?
-
Apprentice
Here is my ICQ number 634401572, we can sort all of the things when we start talking, just when you will find some time to talk to me? I am not very often on ICQ so I would need to know that.
-
Ich habe mal eine Frage zu den Focusnames...
Wann werden die Farbzuordnungen geupdatet?
Folgende Situation: Der Held hat zu Spielbeginn die GIL_NONE. Im Laufe des Spiels erhält er nun die GIL_MIL. Theoretisch (laut Scripten) müssten jetzt ja alle Milizen freundlich sein, also grün angezeigt werden. Doch sie bleiben weiß.
Nun also meine Frage, zu welchem Zeitpunkt werden die Focusnames geupdatet?
-
Es wird jeden Frame aktualisiert.
Vermutlich aktualisiert Gothic die Gildenattitüden nicht zuverlässig. Wie genau weist du die Gilde denn zu?
MfG Gottfried
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|
|