Portal-Zone Gothic-Zone Gothic II-Zone Gothic 3-Zone Gothic 4-Zone Modifikationen-Zone Download-Zone Foren-Zone RPG-Zone Almanach-Zone Spirit of Gothic

 

Seite 3 von 21 « Erste 12345671014 ... Letzte »
Ergebnis 41 bis 60 von 402
  1. Beiträge anzeigen #41
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    11.789
     
    Milky-Way ist offline
    Kann ich mit Ikarus irgendwie den Walkmode eines NPC abfragen?
    Es gibt in oCNPC zwar state_walkmode_routine, das war aber (für den PC_Hero) immer 0.

  2. Homepage besuchen Beiträge anzeigen #42
    Exodus Avatar von Sektenspinner
    Registriert seit
    Jul 2004
    Ort
    Karlsruhe
    Beiträge
    7.827
     
    Sektenspinner ist offline
    Das ist in bisher undokumentierten Klassen versteckt.
    Es gibt aber eine passende Funktion, die du aufrufen kannst, und zwar:

    zString oCAniCtrl_Human::GetWalkMode()

    Dabei wäre der this Pointer hero.anictrl.

    Mit den CALL_ Funktionen kommst du somit ans Ziel:

    Code:
    const int oCAniCtrl_Human__GetWalkModeString = 6991424; //6AAE40
    oCNpc oCHer = Hlp_GetNpc(hero);
    
    CALL_RetValIszString();
    CALL_thiscall(oCHer.anictrl, oCAniCtrl_Human__GetWalkModeString);
    var string result;
    result = CALL_RetValAszString();
    Der Grund, warum das hier etwas komplizierter ausfällt (es muss angekündigt werden, dass das Ergebnis ein zString ist) ist der, dass zString große Strukturen sind und anders zurückgegeben werden als normale Rückgabewerte.
    Für Spieler:
    Velaya # Velaya in English # Exodus Demo # Irrwichtel
    Tools für Modder:
    DiaDepp # DOPA-PARTER # zSlang
    Scripte für Modder:
    Ikarus Skriptpaket # Floats # Broadcasts

  3. Beiträge anzeigen #43
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    11.789
     
    Milky-Way ist offline
    Danke! Ich benutze jetzt diese Funktion:
    Code:
    /*===================================================================
    Npc_GetWalkMode 
    Den Walkmode eines NPC zurückgeben.
    "RUN" - normales laufen
    "WALK" - gehen
    "SNEAK" - schleichen
    "" - schwimmen, durch Wasser waten
    ==================================================================*/
    
    const int NPC_INWATER	=	3;
    
    FUNC int Npc_GetWalkMode (VAR C_NPC slf)
    {
    	const int oCAniCtrl_Human__GetWalkModeString = 6991424; //6AAE40
    	var oCNpc oCslf; oCslf = Hlp_GetNpc(slf);
    	
    	CALL_RetValIszString();
    	CALL__thiscall(oCslf.anictrl, oCAniCtrl_Human__GetWalkModeString);
    	var string result;
    	result = CALL_RetValAszString();
    	
    	if (Hlp_StrCmp (result, "RUN"))
    	{
    		return NPC_RUN;
    	}
    	else if (Hlp_StrCmp (result, "WALK"))
    	{
    		return NPC_WALK;
    	}
    	else if (Hlp_StrCmp (result, "SNEAK"))
    	{
    		return NPC_SNEAK;
    	} else if (Hlp_StrCmp (result, ""))
    	{
    		return NPC_INWATER;
    	};
    };
    (im Kommentar stehen die Strings, die Sektenspinners Funktion bekommt)
    NPC_INWATER ist natürlich mit Vorsicht zu genießen und eigentlich nur für Rückgabewerte dieser Funktion gedacht. Bei meinen kurzen Tests gab es aber sonst keine Situation, in der "" zurückgegeben wurde.

  4. Beiträge anzeigen #44
    Ehrengarde Avatar von Gottfried
    Registriert seit
    Mar 2006
    Beiträge
    2.512
     
    Gottfried ist offline
    Hätte es nicht gereicht den Bodystate abzufragen?
    Code:
    const int BS_STAND  = 0 | BS_FLAG_INTERRUPTABLE | BS_FLAG_FREEHANDS;
    const int BS_WALK   = 1 | BS_FLAG_INTERRUPTABLE;
    const int BS_SNEAK  = 2 | BS_FLAG_INTERRUPTABLE;
    const int BS_RUN    = 3;
    const int BS_SPRINT = 4;
    const int BS_SWIM   = 5;
    const int BS_CRAWL  = 6;
    const int BS_DIVE   = 7;
    const int BS_JUMP   = 8;
    [...]
    MfG Gottfried

  5. Beiträge anzeigen #45
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    11.789
     
    Milky-Way ist offline
    Das war meine Alternative, die mir aber weniger gut gefallen hat, da man so immer auf mindestens zwei Sachen abfragen müsste (z.B. BS_STAND und BS_WALK). Und da ich mir recht sicher war, dass man mit Ikarus irgendwie auch an den Walkmode kommen müsste, habe ich nachgefragt.

  6. Beiträge anzeigen #46
    Ehrengarde Avatar von Gottfried
    Registriert seit
    Mar 2006
    Beiträge
    2.512
     
    Gottfried ist offline
    Ich habe mal eine kleine STR_Replace-Funktion niedergeschrieben. Vielleicht hat jemand Verwendung dafür
    Code:
    //========================================
    // String replace
    //========================================
    /* Ersetzt in "res" jedes Vorkommen von "s0" durch "s1" */
    func string STR_Replace(var string res, var string s0, var string s1) {
        var zString zs0; zs0 = MEM_PtrToInst(STRINT_GetStringAddress(s0));
        var int s0l; s0l = zs0.len;
        if(!s0l) {
            return res;
        };
        var zString zres; zres = MEM_PtrToInst(STRINT_GetStringAddress(res));
        var int l; l = zres.len;
        if(!l) {
            return res;
        };
        var int s0i; s0i = MEM_ReadInt(zs0.ptr)&255;
        var int s; s = zres.ptr;
        var int io; io = 0;
        var int i; i = 0;
        var string resC; resC = "";
        var int p; p = MEM_StackPos.position;
        if(i < l) {
            if((MEM_ReadInt(s+i)&255) == s0i) {
                var string bs; bs = STR_SubStr(res, i, s0l);
                if(Hlp_StrCmp(bs, s0)) {
                    var int r; r = i-io;
                    if(r) {
                        resC = ConcatStrings(resC, STR_SubStr(res, io, r));
                    };
                    resC = ConcatStrings(resC, s1);
                    i += s0l;
                    io = i;
                    MEM_StackPos.position = p;
                };
            };
            i += 1;
            MEM_StackPos.position = p;
        };
        r = i-io;
        if(r) {
            resC = ConcatStrings(resC, STR_SubStr(res, io, r));
        };
        return resC;
    };
    MfG Gottfried

  7. Beiträge anzeigen #47
    Ranger Avatar von Mark56
    Registriert seit
    Sep 2010
    Beiträge
    189
     
    Mark56 ist offline
    I've got idea[g2].... when its raining ikarus increses value of water wave and amplitude so even sea at the harbor will look a bit dangerous ..... I don't know if it's possible but maybe somebody will do it ....

  8. Beiträge anzeigen #48
    Ehrengarde Avatar von Gottfried
    Registriert seit
    Mar 2006
    Beiträge
    2.512
     
    Gottfried ist offline
    Bonne6 hat mich letztens unbewusst auf die Idee gebracht eine Möglichkeit zu basteln Dateien frei speichern und laden zu können, deshalb habe ich das mal spontan umgesetzt.
    Ich denke es kann recht nützlich sein, gerade um eigene Klassen, Listen oder Arrays abzuspeichern.

    Es sind recht viele Funktionen dabei herausgekommen und der Code ist meiner Meinung nach recht unübersichtlich, daher habe ich zu jeder eine kurze Erklärung verfasst. (Oft sind aber sowieso die Namen Programm.)

    Alle Funktionen sind sehr simpel gestrickt, aber ich finde sie reichen für den vorgesehenen Gebrauch absolut aus.

    Es folgt der Code mit einer kurzen Funktionsübersicht:
    Code:
    /* ==============================================
     * BinaryWriter - Dateien anlegen und beschreiben
     * ==============================================
     * Grundfunktionen:
     *   int    BW_NewFile  (string file)
     *   void   BW_Close    ()
     *   void   BW          (int data, int length)
     * Daten speichern:
     *   void   BW_Int      (int data)
     *   void   BW_Char     (string data)
     *   void   BW_String   (string data)
     *   void   BW_Byte     (int data)
     *   void   BW_Bytes    (int dataPtr, int length)
     * Text schreiben:
     *   void   BW_TextLine (string data)
     *   void   BW_Text     (string data)
     *   void   BW_NextLine ()
     *
     * ==============================================
     * BinaryReader - Dateien auslesen
     * ==============================================
     * Grundfunktionen:
     *   int    BR_OpenFile (string file)
     *   void   BR_Close    ()
     *   int    BR          (int length)
     * Daten lesen:
     *   int    BR_Int      ()
     *   string BR_Char     ()
     *   string BR_String   ()
     *   int    BR_Byte     ()
     *   int    BR_Bytes    (int length)
     * Text lesen:
     *   string BR_TextLine ()
     *   string BR_Text     (int length)
     */
    
    /*--------------------
      Enginecalls
    --------------------*/
    const int CREATE_ALWAYS = 2;
    const int OPEN_EXISTING = 3;
    const int GENERIC_ALL = 1073741824;
    const int GENERIC_READ = -2147483648;
    const int FILE_SHARE_READ = 1;
    const int FILE_ATTRIBUTE_NORMAL = 128;
    
    func int WIN_CreateFile(
        var string lpFileName,
        var int dwDesiredAccess,
        var int dwShareMode,
        var int lpSecurityAttributes,
        var int dwCreationDisposition,
        var int dwFlagsAndAttributes,
        var int hTemplateFile) {
        const int CreateFileA = 8079286; //0x7B47B6
        CALL_IntParam(hTemplateFile);
        CALL_IntParam(dwFlagsAndAttributes);
        CALL_IntParam(dwCreationDisposition);
        CALL_IntParam(lpSecurityAttributes);
        CALL_IntParam(dwShareMode);
        CALL_IntParam(dwDesiredAccess);
        CALL_cStringPtrParam(lpFileName);
        CALL__stdcall(CreateFileA);
        return CALL_RetValAsPtr();
    };
    func void WIN_WriteFile(
        var int hFile,
        var int lpBuffer,
        var int nNumberOfBytesToWrite,
        var int lpNumberOfBytesWritten,
        var int lpOverlapped) {
        const int WriteFile = 8079292; //0x7B47BC
        CALL_IntParam(lpOverlapped);
        CALL_IntParam(lpNumberOfBytesWritten);
        CALL_IntParam(nNumberOfBytesToWrite);
        CALL_IntParam(lpBuffer);
        CALL_IntParam(hFile);
        CALL__stdcall(WriteFile);
    };
    func void WIN_ReadFile(
        var int hFile,
        var int lpBuffer,
        var int nNumberOfBytesToRead,
        var int lpNumberOfBytesRead,
        var int lpOverlapped) {
        const int ReadFile = 8272388; //0x7E3A04
        CALL_IntParam(lpOverlapped);
        CALL_IntParam(lpNumberOfBytesRead);
        CALL_IntParam(nNumberOfBytesToRead);
        CALL_IntParam(lpBuffer);
        CALL_IntParam(hFile);
        CALL__stdcall(ReadFile);
    };
    func void WIN_CloseHandle(
        var int hObject) {
        const int CloseHandle = 8079190; //0x7B4756
        CALL_IntParam(hObject);
        CALL__stdcall(CloseHandle);
    };
    func int WIN_GetFileSize(
        var int hFile,
        var int lpFileSizeHigh) {
        const int GetFileSize = 8079310; //0x7B47CE
        CALL_IntParam(lpFileSizeHigh);
        CALL_IntParam(hFile);
        CALL__stdcall(GetFileSize);
        return CALL_RetValAsInt();
    };
    
    /*--------------------
      Konstanten
    --------------------*/
    const int _BIN_BufferLength = 1024;
    
    /*--------------------
      Variablen
    --------------------*/
    var int _bin_open; // Handle des Streams
    var int _bin_mode; // Mode (Write/Read)
    var int _bin_ccnt; // Aktueller Content
    var int _bin_crsr; // Cursor
    var int _bin_clen; // Aktuelle Streamlänge
    var string _bin_buffer; // Stringbuffer
    var string _bin_prefix; // Debug-Präfix
    
    /*--------------------
      Hilfsfunktionen
    --------------------*/
    func string _BIN_Err(var string msg) {
        msg = ConcatStrings(": ", msg);
        MEM_Warn(ConcatStrings(_bin_prefix, msg));
    };
    func int _BIN_nRunning() {
        if(_bin_open) {
            _BIN_Err("Der aktuelle Stream muss zuerst geschlossen werden bevor ein weiterer geöffnet werden kann.");
            return 0;
        };
        return 1;
    };
    func int _BIN_Running() {
        if(!_bin_open) {
            _BIN_Err("Es ist kein Stream aktiv.");
            return 0;
        };
        return 1;
    };
    func int _BIN_nMode(var int m) {
        if(_bin_mode != m) {
            _BIN_Err("Falscher Modus.");
            return 0;
        };
        return 1;
    };
    func void _BIN_StreamLen(var int nlen) {
        nlen += _bin_crsr;
        if(nlen >= _bin_clen) {
            var int len; len = _bin_clen;
            var int pos; pos = MEM_StackPos.position;
            if(nlen >= len) {
                len = len<<1;
                pos = MEM_StackPos.position;
            };
            _bin_ccnt = MEM_Realloc(_bin_ccnt, _bin_clen, len);
            _bin_clen = len;
        };
    };
    func int _BIN_EOF(var int len) {
        if(_bin_crsr + len > _bin_clen) {
            _BIN_Err("Das Ende des Streams wurde bereits erreicht.");
            return 1;
        };
        return 0;
    };
    
    /*============
      BinaryWriter
      ============*/
    
    func int BW_NewFile(var string file) {
        _bin_prefix = "BW_NewFile";
        if(!_BIN_nRunning()) { return 0; };
    
        _bin_open = WIN_CreateFile(file, GENERIC_ALL, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
        if(_bin_open==-1) {
            _BIN_Err("Datei konnte nicht erstellt werden.");
            return 0;
        };
    
        _bin_clen = _BIN_BufferLength;
        _bin_mode = 0;
        _bin_crsr = 0;
        _bin_ccnt = MEM_Alloc(_bin_clen);
        return 1;
    };
    
    func void BW(var int data, var int length) {
        _bin_prefix = "BW";
        if(!_BIN_Running()||!_BIN_nMode(0)) { return; };
    
        if(length < 1) { length = 1; };
        if(length > 4) { length = 4; };
    
        _BIN_StreamLen(4);
        MEM_WriteInt(_bin_ccnt + _bin_crsr, data);
        _bin_crsr += length;
    };
    func void BW_Int(var int data) { BW(data, 4); };
    func void BW_Byte(var int data) { BW(data, 1); };
    func void BW_Char(var string data) { BW(Str_GetCharAt(data, 0), 1); };
    
    func void BW_String(var string data) {
        _bin_prefix = "BW_String";
        if(!_BIN_Running()||!_BIN_nMode(0)) { return; };
    
        var zString zdata; zdata = MEM_PtrToInst(STRINT_GetStringAddress(data));
        var int len; len = zdata.len;
        if(!zdata.len) {
            BW(0, 1);
            return;
        };
        _BIN_StreamLen(len+4);
        MEM_CopyBytes(zdata.ptr, _bin_ccnt + _bin_crsr, len);
        _bin_crsr += len;
        BW(0, 1);
    };
    
    func void BW_Bytes(var int dataPtr, var int length) {
        _bin_prefix = "BW_Struct";
        if(!_BIN_Running()||!_BIN_nMode(0)||!length||!dataPtr) { return; };
    
        _BIN_StreamLen(length);
        MEM_CopyBytes(dataPtr, _bin_ccnt + _bin_crsr, length);
        _bin_crsr += length;
    };
    
    func void BW_NextLine() { BW(2573, 2); };
    
    func void BW_Textline(var string data) {
        BW_String(data);
        _bin_crsr -= 1;
        BW(2573, 2);
    };
    
    func void BW_Text(var string data) {
        BW_String(data);
        _bin_crsr -= 1;
    };
    
    func void BW_Close() {
        _bin_prefix = "BW_Close";
        if(!_BIN_Running()||!_BIN_nMode(0)) { return; };
    
        var int ptr; ptr = MEM_alloc(4);
        WIN_WriteFile(_bin_open, _bin_ccnt, _bin_crsr, ptr, 0);
        MEM_Free(ptr);
        MEM_Free(_bin_ccnt);
        WIN_CloseHandle(_bin_open);
        _bin_open = 0;
    };
    
    /*============
      BinaryReader
      ============*/
    
    func int BR_OpenFile(var string file) {
        _bin_prefix = "BR_OpenFile";
        if(!_BIN_nRunning()) { return 0; };
    
        _bin_open = WIN_CreateFile(file, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
        if(_bin_open==-1) {
            _BIN_Err("Datei konnte nicht geöffnet werden.");
            return 0;
        };
        var int len; len = WIN_GetFileSize(_bin_open, 0);
        _bin_ccnt = MEM_Alloc(len);
        var int ptr; ptr = MEM_Alloc(4);
        WIN_ReadFile(_bin_open, _bin_ccnt, len, ptr, 0);
        MEM_Free(ptr);
        _bin_clen = len;
        _bin_mode = 1;
        _bin_crsr = 0;
        return 1;
    };
    
    func int BR(var int length) {
        _bin_prefix = "BR";
        if(!_BIN_Running()||!_BIN_nMode(1)) { return 0; };
    
        if(length < 1) { length = 1; };
        if(length > 4) { length = 4; };
    
        if(_BIN_EOF(length)) { return 0; };
    
        var int b; b = MEM_ReadInt(_bin_ccnt + _bin_crsr);
        if(length < 4) {
            b = b&((256<<((length-1)<<3))-1);
        };
        _bin_crsr += length;
        return b;
    };
    func int BR_Int() { return BR(4); };
    func int BR_Byte() { return BR(1); };
    func string BR_Char() {
        _bin_buffer = " ";
        var zString zs; zs = MEM_PtrToInst(STRINT_GetStringAddress(_bin_buffer));
        MEM_WriteByte(zs.ptr, BR(1));
        var string str; str = _bin_buffer;
        _bin_buffer = "";
        return str;
    };
    
    var int _BR_StringRes;
    func string _BR_String(var string cond) {
        _bin_prefix = "BR_String";
        if(!_BIN_Running()||!_BIN_nMode(1)) { return ""; };
    
        var int scpy; scpy = _bin_crsr;
        var int pos; pos = MEM_StackPos.position;
        MEM_CallByString(cond);
        if(_BR_StringRes) {
            MEM_StackPos.position = pos;
        };
    
        var zString zres; zres = MEM_PtrToInst(STRINT_GetHelpStringAddress());
        var int len; len = _bin_crsr - scpy;
        zres.ptr = MEM_Alloc(len);
        zres.res = len;
        MEM_CopyBytes(_bin_ccnt + scpy, zres.ptr, len);
        zres.len = len;
        var string str; str = MEMINT_HlpString;
        MEMINT_HlpString = "";
        return str;
    };
    
    func string BR_String() {
        return _BR_String("_BR_STRING_DEFAULT");
    };func void _BR_String_Default() {
        _BR_StringRes = BR(1);
    };
    
    func int BR_Bytes(var int length) {
        var int ptr;
        if(length <= 4) {
            ptr = MEM_Alloc(4);
            MEM_WriteInt(ptr, BR(4));
            return ptr;
        };
        _bin_prefix = "BR_Bytes";
        if(!_BIN_Running()||!_BIN_nMode(1)) { return 0; };
        if(_bin_crsr + length > _bin_clen) {
            _bin_Err("Die angegebene Struktur ist in dieser Datei nicht vollständig enthalten.");
            return 0;
        };
        ptr = MEM_Alloc(length);
        MEM_CopyBytes(_bin_ccnt + _bin_crsr, ptr, length);
        return ptr;
    };
    
    func string BR_Textline() {
        return _BR_String("_BR_STRING_NEXTLINE");
    };func void _BR_String_NextLine() {
        var int curr; curr = BR(2);
        if(!curr) { _BR_StringRes = 0; }
        else {
            _BR_StringRes = !(curr == 2573);
            _bin_crsr -= 1;
        };
    };
    
    func string BR_Text(var int length) {
        if(length <= 0) { return ""; };
        if(length == 1) { return BR_Char(); };
        _BR_StringRes = length;
        return _BR_String("_BR_STRING_LENGTH");
    };func void _BR_String_Length() {
        var int tmp; tmp = BR(1);
        _BR_StringRes -= 1;
    };
    
    func void BR_Close() {
        _bin_prefix = "BR_Close";
        if(!_BIN_Running()||!_BIN_nMode(1)) { return; };
    
        MEM_Free(_bin_ccnt);
        WIN_CloseHandle(_bin_open);
        _bin_open = 0;
    };
    Erklärungen zu dem Schreiber:
    Spoiler:(zum lesen bitte Text markieren)
    Code:
    //-----------------------------
    int BW_NewFile(string file)
    //-----------------------------
      Legt eine neue Datei an und lässt diese mit den 'BW' Funktionen beschreiben.
      Ist die Datei bereits vorhanden wird sie ersetzt.
      Um die Funktion verwenden zu können müssen alle Streams geschlossen sein.
        -file   : Der absolute oder relative Pfad zu der gesuchten Datei.
                  Bei relativen Pfaden wird das Gothic-II Verzeichnis von dem aus gestartet wurde verwendet.
                  Infos zur Verwendung von absoluten Pfaden:
                    http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx#file_and_directory_names
        -return : Gibt bei Erfolg 1 zurück, ansonsten 0
    
    //-----------------------------
    void BW_Close()
    //-----------------------------
      Schließt einen laufenden Schreibvorgang der über 'BW_NewFile' gestartet wurde.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -return : -
    
    //-----------------------------
    void BW(int data, int length)
    //-----------------------------
      Beschreibt den laufenden Stream.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -data   : Der Wert der gespeichert werden soll.
        -length : Die ersten 'length' Bytes von 'data' werden gespeichert.
                  length sollte > 0 und < 5 sein.
        -return : -
    
    //-----------------------------
    void BW_Int(int data)
    //-----------------------------
      Schreibt einen kompletten 32-Bit Integer in den laufenden Stream.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -data   : Der Wert der gespeichert werden soll.
        -return : -
    
    //-----------------------------
    void BW_Char(string data)
    //-----------------------------
      Schreibt einen 8-Bit Buchstaben in den laufenden Stream.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -data   : Der erste Buchstabe des Strings wird gesichert.
        -return : -
    
    //-----------------------------
    void BW_String(string data)
    //-----------------------------
      Schreibt den kompletten Inhalt eines Strings in den laufenden Stream.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -data   : Der gesamte Inhalt des Strings wird gesichert.
                  Es wird ein Nullbyte angehängt.
        -return : -
    
    //-----------------------------
    void BW_Byte(int data)
    //-----------------------------
      Schreibt ein Byte in den laufenden Stream.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -data   : Der Wert der gespeichert werden soll. (0..255)
        -return : -
    
    //-----------------------------
    void BW_Bytes(int dataPtr, int length)
    //-----------------------------
      Schreibt eine ganze Reihe von Bytes in den laufenden Stream.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -dataPtr : Pointer zu den Daten die gesichert werden sollen.
        -length  : Die zu lesende Länge in Bytes.
        -return  : -
    
    //-----------------------------
    void BW_TextLine(string data)
    //-----------------------------
      Schreibt eine Textzeile in den laufenden Stream.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -data   : Der gesamte Inhalt des Strings wird gesichert.
                  Es wird ein Zeilenumbruch angehängt.
        -return : -
    
    //-----------------------------
    void BW_Text(string data)
    //-----------------------------
      Schreibt den Text in den laufenden Stream.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -data   : Der gesamte Inhalt des Strings wird gesichert.
                  Es wird KEIN Nullbyte angehängt.
        -return : -
    
    //-----------------------------
    void BW_NextLine()
    //-----------------------------
      Schreibt einen Zeilenumbruch in den laufenden Stream.
      Um die Funktion verwenden zu können muss ein Schreibstream geöffnet sein.
        -return : -
    Erklärungen zu dem Leser:
    Spoiler:(zum lesen bitte Text markieren)
    Code:
    //-----------------------------
    int BR_OpenFile(string file)
    //-----------------------------
      Öffnet eine bereits existierende Datei und lässt sie mit den 'BR' Funktionen auslesen.
      Ist die Datei nicht vorhanden schlägt die Operation fehl.
      Um die Funktion verwenden zu können müssen alle Streams geschlossen sein.
        -file   : Der absolute oder relative Pfad zu der gesuchten Datei.
                  Bei relativen Pfaden wird das Gothic-II Verzeichnis von dem aus gestartet wurde verwendet.
                  Infos zur Verwendung von absoluten Pfaden:
                    http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx#file_and_directory_names
        -return : Gibt bei Erfolg 1 zurück, ansonsten 0
    
    //-----------------------------
    void BR_Close()
    //-----------------------------
      Schließt einen laufenden Lesevorgang der über 'BR_OpenFile' gestartet wurde.
      Um die Funktion verwenden zu können muss ein Lesestream geöffnet sein.
        -return : -
    
    //-----------------------------
    int BR(int length)
    //-----------------------------
      Liest aus dem laufenden Stream.
      Um die Funktion verwenden zu können muss ein Lesestream geöffnet sein.
        -length : Anzahl Bytes die gelesen werden.
                  length sollte > 0 und < 5 sein.
        -return : Die ersten 'length' Bytes werden zurückgegeben.
    
    //-----------------------------
    int BR_Int()
    //-----------------------------
      Liest aus dem laufenden Stream.
      Um die Funktion verwenden zu können muss ein Lesestream geöffnet sein.
        -return : Gibt einen 32-Bit Integer zurück.
    
    //-----------------------------
    string BR_Char()
    //-----------------------------
      Liest aus dem laufenden Stream.
      Um die Funktion verwenden zu können muss ein Lesestream geöffnet sein.
        -return : Gibt das folgende Byte als String zurück
    
    //-----------------------------
    string BR_String()
    //-----------------------------
      Liest aus dem laufenden Stream.
      Um die Funktion verwenden zu können muss ein Lesestream geöffnet sein.
        -return : Gibt einen String zurück der durch ein Nullbyte begrenzt ist.
    
    //-----------------------------
    int BR_Byte()
    //-----------------------------
      Liest aus dem laufenden Stream.
      Um die Funktion verwenden zu können muss ein Lesestream geöffnet sein.
        -return : Gibt ein Byte zurück. (0..255)
    
    //-----------------------------
    int BR_Bytes(int length)
    //-----------------------------
      Liest aus dem laufenden Stream.
      Um die Funktion verwenden zu können muss ein Lesestream geöffnet sein.
        -length : Liest 'length' Bytes und
        -return : gibt einen Pointer auf eine Kopie davon zurück.
                  Diese Kopie kann mit MEM_Free entfernt werden.
    
    //-----------------------------
    string BR_TextLine()
    //-----------------------------
      Liest aus dem laufenden Stream.
      Um die Funktion verwenden zu können muss ein Lesestream geöffnet sein.
        -return : Gibt einen String zurück der durch einen Zeilenumbruch begrenzt ist.
    
    //-----------------------------
    string Text(int length)
    //-----------------------------
      Liest aus dem laufenden Stream.
      Um die Funktion verwenden zu können muss ein Lesestream geöffnet sein.
        -length : Länge des gesuchten Strings
        -return : Liest 'length' Bytes und gibt diese als String zurück
    Und noch drei kleine Beispiele:
    Spoiler:(zum lesen bitte Text markieren)
    Code:
    =======================================
    ==== Variablen speichern und laden ====
    =======================================
    
    const string filename = "System\MySave.sav";
    
    var string s0; // string
    var int    i1; // int
    var int    b2; // byte
    var string c3; // char
    
    func void SaveMyData() {
        if(BW_NewFile(filename)) { // Neue Datei versuchen anzulegen:
            BW_String(s0);
            BW_Int(i1);
            BW_Byte(b2);
            BW_Char(c3);           // Mein Zeug speichern..
            BW_Close();            // ..und zumachen.
        };
    };
    
    func void LoadMyData() {
        if(BR_OpenFile(filename)) { // Datei versuchen zu öffnen:
            s0 = BR_String();
            i1 = BR_Int();
            b2 = BR_Byte();
            c3 = BR_Char();         // Bei Erfolg Werte einlesen..
            BR_Close();             // ..und zumachen.
        }
        else {
            SaveMyData();           // Ansonsten Speicherdatei anlegen.
        };
    };
    
    ===========================================
    ==== Dem Spieler eine Urkunde schenken ====
    ===========================================
    
    func void Urkunde(var string Username, var int Score) {
        var string filename; filename = ConcatStrings(Username, "s Urkunde.txt");
        BW_NewFile(filename); // Username + "s Urkunde.txt". Die Datei liegt dann im Gothic-II Verzeichnis.
        BW_Text("Herzlichen Glückwunsch "); BW_Text(Username);
        BW_TextLine("!");
    
        BW_Text("Du hast bei diesem lustigen Spiel ");
        BW_Text(IntToString(Score)); // Nicht BW_Int!
        BW_TextLine(" Punkte erreicht.");
    
        BW_NextLine();
    
        BW_Text("MfG Gottfried");
        BW_Close();
    
        /*
           Bei einem Aufruf von
             Urkunde("Mustermann", 1000);
           käme eine Datei mit dem Namen 'Mustermanns Urkunde.txt' heraus die folgendes beinhalten würde:
    
             Herzlichen Glückwunsch Mustermann!
             Du hast bei diesem lustigen Spiel 1000 Punkte erreicht.
    
             MfG Gottfried
        */
    };
    
    =================================
    ==== Die Position eines Npcs ====
    =================================
    
    func void BW_NpcPosition(var c_npc slf) {
        var int ptr; ptr = MEM_Alloc(60);                // 16 * 4
        MEM_CopyBytes(MEM_InstToPtr(slf) + 60, ptr, 60); // Kopiert ab slf.trafoObjToWorld
        BW_Bytes(ptr, 60);                               // Schreibt die 60 kopierten Bytes
        MEM_Free(ptr);                                   // Und wieder sauber machen..
    };
    
    func void BR_NpcPosition(var c_npc slf) {
        var int ptr; ptr = BR_Bytes(60);                 // 60 Bytes lesen
        MEM_CopyBytes(ptr, MEM_InstToPtr(slf) + 60, 60); // Wieder in slf einfügen
        MEM_Free(ptr);                                   // Und wieder sauber machen..
    };
    
    /*
       Anwendung ganz normal:
         BW_NewFile(file);
         BW_NpcPosition(hero);
         BW_Close();
       Oder ähnliches...
    */

    Sinnvollerweise könnte man die EngineHooks verwenden um die Speicherfunktion abzufangen und dort den Slot herausfinden um eine zweite Speicherdatei für strings anzulegen oä., darauf hatte ich jetzt nur gerade keine Lust

    MfG Gottfried
    Geändert von Gottfried (24.05.2011 um 22:38 Uhr)

  9. Homepage besuchen Beiträge anzeigen #49
    Hero Avatar von Shadowblade
    Registriert seit
    Aug 2006
    Beiträge
    5.353
     
    Shadowblade ist offline
    Cool, das ist genau das, wofür ich eigentlich mal anfangen wollte, mir Ikarus anzugucken.
    Jetzt lass ich das wohl erstmal wieder bleiben

    Alle fragen sich wie kann ich noch schöner werden,
    aber keiner fragt sich für wen.

  10. Beiträge anzeigen #50
    Legende der Amazonen Avatar von Bisasam
    Registriert seit
    Dec 2006
    Ort
    Meine Faust in Sinis Gesicht
    Beiträge
    8.316
     
    Bisasam ist offline
    ich hab im moment ne ziemliche diskussion mit zaphod darüber ob es möglich ist Items auszutauschen.

    ich meinte aber nicht so einfach, sondern folgende situation:

    ich hab ja die krallen gemacht, an der hand passen sie perfekt aber wenn ich die wegstecke dann schweben sie an der hüfte rum und das sieht vollkommen.... naja aus.
    darum dachte ich, ich bastel eine zweite kralle die perfekt an der Hüfte anliegt, dafür aber nicht gut an der hand und wenn der Held die Waffe zieht soll sie augenblicklich gegen die passende ausgetauscht werden.
    dafür müsste ich aber abfragen können ob der Held gerade mit der unpassenden Kralle (also Dummy-item) in den Fightmode gegangen ist und dann auch noch darauf zugreifen können um das dummyitem gegen die waffe zu tauschen. dazu müsste das Dummy-item natürlich auch direkt aus dem inv entfernt werden sonst macht der spieler das inv auf und hat dummy-item und echte waffe drin. umgekehrt wenn der spieler das wieder wegsteckt muss man das auch wieder austauschen und den dummy kreiren sowie die waffe entfernen.

    ist das möglich oder verlange ich da zu viel?
    die normalen equipfunktionen sorgen nämlich dafür, dass der held garnichts mehr in der hand hat und das item an seinem gürtel erscheint obwohl es in die hand müsste


    "Das erinnert doch sehr erfreulich an das, was man sich als Gothicfan wünscht!"
    -Korallenkette

  11. Homepage besuchen Beiträge anzeigen #51
    Teutonic Team Avatar von Bonne6
    Registriert seit
    Jun 2004
    Ort
    Erlangen
    Beiträge
    10.861
     
    Bonne6 ist offline
    Mit den Hooks von Lehona könnte es klappen, wenn du folgende Funktionen hookst:

    oCNpc::EquipItem(oCItem *)
    oCNpc::UnequipItem(oCItem *)

    Ich hab's nicht getestet, aber vllt. klappt's damit, wenn du eben überprüfst ob ECX der Hero ist und der Paramter deine Klaue (bei Equip und Unequip eben die richtige raussuchen) und die dann austauscht zu dem Zeitpunkt.

    Kann das später auch mal versuchen, ich meld mich dann mal per PN

    EDIT: Quatsch, du willst ja nicht beim Equippen, sondern beim ziehen. Ich guck nochmal ^^
    Geändert von Bonne6 (25.05.2011 um 18:57 Uhr)

  12. Homepage besuchen Beiträge anzeigen #52
    Exodus Avatar von Sektenspinner
    Registriert seit
    Jul 2004
    Ort
    Karlsruhe
    Beiträge
    7.827
     
    Sektenspinner ist offline
    Ich würde
    Code:
    virtual void __thiscall zCVob::SetVisual(class zSTRING const &)
    oder
    Code:
    virtual void __thiscall oCItem::SetVisual(class zCVisual *)
    ausprobieren. Für letzteres bräuchte man wohl Objekten mit den passenden Visuals in der Welt um passende zCVisual Pointer herzubekommen.

    Reagieren würde ich über eine Triggerschleife und auf Npc_GetReadiedWeapon oder Npc_GetEquippedMeleeWeapon arbeiten.
    Aber das braucht einiges an Erfahrung im Skripten um das hinzukriegen.
    Nichts, was man mal schnell aus dem Hut zaubert, wenn man noch nicht viel mit Ikarus gearbeitet hat.
    Für Spieler:
    Velaya # Velaya in English # Exodus Demo # Irrwichtel
    Tools für Modder:
    DiaDepp # DOPA-PARTER # zSlang
    Scripte für Modder:
    Ikarus Skriptpaket # Floats # Broadcasts

  13. Beiträge anzeigen #53
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    11.789
     
    Milky-Way ist offline
    EDIT: eine noch erweiterte Version gibt es hier:
    http://forum.worldofplayers.de/forum...5#post18324335

    Es wurde einmal gefragt, ob es möglich ist, die Tageszeit festzuhalten, so dass Himmel, Helligkeit, Sonne, Mond,... praktisch von der Uhrzeit entkoppelt werden, gleichzeitig aber die Uhrzeit weiterläuft (für Tagesabläufe wichtig).
    Das Problem habe ich schon vor einiger Zeit mit großer Hilfe von Sektenspinner gelöst und bevor ich irgendwann versehentlich das Skript lösche, veröffentliche ich es hier:

    Code:
    FUNC void FixSkyTime (VAR int skyHour, VAR int skyMinute)
    {
    	var int desiredSkyTime;
    	desiredSkyTime = divf(mkf(((skyHour+12)%24)*60 + skyMinute), mkf(24*60));
    	//Ein Float zwischen 0 ( = 12 Uhr) und 1 ( = 12 Uhr nächster Tag)
    
    	//Pointer auf desiredSkyTime
    	var int ptr;
    	ptr = MEM_GetParserSymbol("FIXSKYTIME.DESIREDSKYTIME"); //Annahme: desiredSkyTime ist in der Funktion FIXSKYTIME deklariert
    	ptr += 24; //die Variable steht an offset 0x18 im zCPar_Symbol (nachzulesen in zCParser.d).
    
    	
    	var int cursor; //wo wir grade schreiben
    	cursor = 7868992; //das ist die Adresse wo GetSkyTime losgeht. 0x781240 -> IDA
    	MemoryProtectionOverride(cursor, 20);		//Jetzt dürfen wir in GetSkyTime 20 Bytes schreiben (auch wenn wir hier nur 10 brauchen)
    
    	MEM_WriteInt (cursor, 1497); //der Opcode von fld 0x05D9 -> IDA (Achtung: Bytereihenfolge umdrehen!)
    	cursor += 2; //0x0509 war zwei Bytes lang, also die schreibposition um zwei weiter bewegen.
    	MEM_WriteInt(cursor, ptr); //ptr ist die oben berechnete Adresse von desiredSkyTime
    	cursor += 4; //ein Pointer ist vier Byte groß.
    	MEM_WriteInt(cursor, 195); //retn. 0xC3
    	//Jetzt gibt die Funktion GetSkyTime dem Spiel also die Uhrzeit aus, die in desiredSkyTime angegeben ist 
    };
    
    FUNC void UnFixSkyTime ()
    {
    	//Hier wird oCWorldTimer :: GetSkyTime wieder zurückgesetzt
    	//0xD9 05 68 E1 83 00 D8 0D D4 E8		-> IDA
    
    	var int cursor; //wo wir grade schreiben
    	cursor = 7868992; //das ist die Adresse wo GetSkyTime losgeht. 0x781240 -> IDA
    	MemoryProtectionOverride(cursor, 20);		//Jetzt dürfen wir in GetSkyTime 20 Bytes schreiben (auch wenn wir hier nur 10 brauchen)
    	MEM_WriteByte  (cursor, 217);	//0xD9
    	cursor += 1;					//ein Byte weiter
    	MEM_WriteByte  (cursor, 5);		//0x05
    	cursor += 1;					//ein Byte weiter
    	MEM_WriteByte  (cursor, 104);	//0x68
    	cursor += 1;					//ein Byte weiter
    	MEM_WriteByte  (cursor, 225);	//0xE1
    	cursor += 1;					//ein Byte weiter
    	MEM_WriteByte  (cursor, 131);	//0x83
    	cursor += 1;					//ein Byte weiter
    	MEM_WriteByte  (cursor, 0);		//0x00
    	cursor += 1;					//ein Byte weiter
    	MEM_WriteByte  (cursor, 216);	//0xD8
    	cursor += 1;					//ein Byte weiter
    	MEM_WriteByte  (cursor, 13);	//0x0D
    	cursor += 1;					//ein Byte weiter
    	MEM_WriteByte  (cursor, 212);	//0xD4
    	cursor += 1;					//ein Byte weiter
    	MEM_WriteByte  (cursor, 232);	//0xE8
    };
    Zu Benutzen so:
    Ikarus notwendig!
    Floatpaket notwendig!
    (beides findet man in der Signatur von Sektenspinner)
    Das Skript irgendwo danach parsen lassen.
    FixSkyTime (stunde, minute); //aufrufen mit der Uhrzeit, auf die der Himmel gesetzt werden soll
    UnFixSkyTime (); //aufrufen, damit sich der Himmel wieder normal verändert - der Himmel springt SOFORT auf den Zustand der aktuellen Uhrzeit

    Wie es funktioniert: Es wird an die Stelle, an der normalerweise steht, dass sich die Funktion die aktuelle Uhrzeit holt (um den Himmel entsprechend zu setzen) geschrieben, dass die Variable desiredSkyTime als Uhrzeit für den Himmel genutzt wird.

    Das Feststellen des Himmels bleibt auch nach dem Laden erhalten. Beim Starten eines neuen Spiels ist der Himmel auf die Startzeit festgesetzt und ändert sich erstmal nicht. Ein Neustart von Gothic stellt alle Änderungen zurück. Deshalb sollte man möglichst in der Init_Global die FixSkyTime und UnFixSkyTime aufrufen, je nachdem, wie es gerade sein soll.

    Ich habe es schon ein kleines bisschen getestet, wenn euch noch was auffällt, dann kann ich das natürlich noch versuchen, auszubessern.


    EDIT: den flüssigen Übergang wie von Ingenieur im verlinkten Beitrag beschrieben, kann man heutzutage bestimmt auch wunderbar mit Anim8 aus LeGo lösen. Das Floatpaket ist, glaube ich, mittlerweile Teil von Ikarus. Wenn da also eine float.d im Download beiliegt, braucht das Floatpaket wohl nicht extra installiert zu werden.
    Geändert von Milky-Way (27.08.2016 um 17:42 Uhr) Grund: kleine Notiz zum aktuellen Stand / aktuellen Möglichkeiten hinzugefügt

  14. Beiträge anzeigen #54
    Demigoddess
    Registriert seit
    Jul 2007
    Beiträge
    9.801
     
    Lehona ist offline
    Schöne Arbeit

    Aber mich interessiert, woher fld kommt? Das IntelManual kennt nur D9, das Präfix verwirrt mich.

  15. Beiträge anzeigen #55
    General Avatar von Lemon
    Registriert seit
    Nov 2009
    Ort
    Haus der Gelehrten, Jharkendar
    Beiträge
    3.628
     
    Lemon ist offline
    Heyho Leute!

    Aufgrund diesem Threads wollte ich fragen ob das machbar wäre oder schon gemacht wurde. Im Spacer gibts das doch schon

    gruß Lemon
    Odyssee - Im Auftrag des Königs

    "Ich will die Welt verändern, aber Gott gibt mir den Quellcode nicht!"


  16. Homepage besuchen Beiträge anzeigen #56
    Exodus Avatar von Sektenspinner
    Registriert seit
    Jul 2004
    Ort
    Karlsruhe
    Beiträge
    7.827
     
    Sektenspinner ist offline
    Ich verstehe nicht, was genau du willst. Natürlich haben die Objekte Koordinaten und wenn du die Adresse eines Objektes hast, kannst du auch dessen Koordinaten in Erfahrung bringen oder ändern.
    Für Spieler:
    Velaya # Velaya in English # Exodus Demo # Irrwichtel
    Tools für Modder:
    DiaDepp # DOPA-PARTER # zSlang
    Scripte für Modder:
    Ikarus Skriptpaket # Floats # Broadcasts

  17. Beiträge anzeigen #57
    General Avatar von Lemon
    Registriert seit
    Nov 2009
    Ort
    Haus der Gelehrten, Jharkendar
    Beiträge
    3.628
     
    Lemon ist offline
    Und wie schaut das ganze dann im Code aus?
    Odyssee - Im Auftrag des Königs

    "Ich will die Welt verändern, aber Gott gibt mir den Quellcode nicht!"


  18. Homepage besuchen Beiträge anzeigen #58
    Exodus Avatar von Sektenspinner
    Registriert seit
    Jul 2004
    Ort
    Karlsruhe
    Beiträge
    7.827
     
    Sektenspinner ist offline
    In der Dokumentation von Ikarus gibt es folgendes Beispiel:
    Code:
    func void PrintCameraPos() {
        /* Globale Instanzen (die es nur einmal gibt) initialisieren: */
        /* Initialisiert MEM_World, MEM_Game, etc. u.a. auch MEM_Camera */
        MEM_InitGlobalInst();
        
        /* Das Kameraobjekt ist kein vob (sondern was abstraktes),
         * weiß nicht wo und wie da Positionsdaten stehen.
        Ich arbeite lieber auf dem Kameravob: */
        var zCVob camVob;
        camVob = MEM_PtrToInst (MEM_Camera.connectedVob);
        
        /*Hier muss man wissen wie die Transformationsmatrix aufgebaut ist:
    
            Sie besteht aus drei Vektoren, die x, y und z Richtung
            des lokalen Koordinatensystem des Kameravobs
            in Weltkoordinaten angeben (dabei müsste z die
            Blickrichtung sein). Ich habe diese Vektoren hier
            mit v1, v2, v3 Bezeichnet.
            Zusätzlich gibt es in der 4. Spalte die Translation,
            das heißt die Position der Kamera.
        
            v1_x    v2_x    v3_x    x
            v1_y    v2_y    v3_y    y
            v1_z    v3_z    v3_z    z
            0       0       0       0
            
            Die Matrix ist Zeilenweise im Speicher abgelegt.
            Da wir uns für die letzte Spalte interessieren sind die Indizes
            im trafoWorld Array 3, 7 und 11, die wir brauchen.
        */
        
        Print (ConcatStrings ("x: ", IntToString(roundf(camVob.trafoObjToWorld[ 3]))));
        Print (ConcatStrings ("y: ", IntToString(roundf(camVob.trafoObjToWorld[ 7]))));
        Print (ConcatStrings ("z: ", IntToString(roundf(camVob.trafoObjToWorld[11]))));
    };
    Ist das das, was du wissen willst?
    Für Spieler:
    Velaya # Velaya in English # Exodus Demo # Irrwichtel
    Tools für Modder:
    DiaDepp # DOPA-PARTER # zSlang
    Scripte für Modder:
    Ikarus Skriptpaket # Floats # Broadcasts

  19. Beiträge anzeigen #59
    General Avatar von Lemon
    Registriert seit
    Nov 2009
    Ort
    Haus der Gelehrten, Jharkendar
    Beiträge
    3.628
     
    Lemon ist offline
    ja ich glaub schon da mein Computer wieder heil ist kann ich mich jetzt auch ein bisschen damit beschäftigen und hoffen dass ichs dann versteh

    Gut hab mich jetzt ein wenig damit beschäftigt. Meine größten Probleme sind aber die mathematischen Begriffe da solche lineare Algebra noch nicht bei uns in der 7. durchgenommen wurde. Dennoch hab ich mir ein paar Bücher angeschaut um ein kleinen Überblick zu bekommen. Jetzt meine Fragen:
    -Die x,y,z Koordinaten sind die (globalen/Welt) Koordinaten oder?
    - Warum so viele Vektoren? würden nicht die Weltkoordinaten und ein Vektor für die Blickrichtung reichen?
    -die vorerst Letzte: Warum sind die x,y und z Werte an Stelle 3,7 und 11? Ich dachte Integer hätten immer 4 und Strings 20 Bit oder sind Array-Plätze nur durchnummeriert und Speichergröße wird ignoriert? Oder hab ich da was überhaupt nicht verstanden


    PS: Achja, könnt ihr mir vielleicht ein Buch oder ähnliches empfehlen, in dem Informatik und dafür benötigtes mathematischen Wissen erklärt von Anfang an erklärt werden?

    gruß Lemon
    Odyssee - Im Auftrag des Königs

    "Ich will die Welt verändern, aber Gott gibt mir den Quellcode nicht!"


  20. Beiträge anzeigen #60
    Demigoddess
    Registriert seit
    Jul 2007
    Beiträge
    9.801
     
    Lehona ist offline
    Das sind die Indizes, das hat mit dem Speicherabbild wenig zu tun. Bei einem Integer-Array berechnet sich die Adresse halt aus Index*4.

Seite 3 von 21 « Erste 12345671014 ... Letzte »

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
Impressum | Link Us | intern
World of Gothic © by World of Gothic Team
Gothic, Gothic 2 & Gothic 3 are © by Piranha Bytes & Egmont Interactive & JoWooD Productions AG, all rights reserved worldwide