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 21 von 24 « Erste ... 10141718192021222324 Letzte »
Ergebnis 401 bis 420 von 468
  1. Beiträge anzeigen #401
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Nun, diese Namen wurden ja auch nicht ganz zufällig ausgewählt

  2. Beiträge anzeigen #402
    Hero Avatar von lali
    Registriert seit
    Feb 2016
    Beiträge
    5.473
     
    lali ist offline
    Bei Ikarus war mir das bewusst, aber dass auch noch Lego dabei ist.
    Phoenix Dev | Website | Discord

  3. Beiträge anzeigen #403
    Held Avatar von GiftGrün
    Registriert seit
    Jun 2011
    Ort
    Gewächshaus des Assassinen
    Beiträge
    5.010
     
    GiftGrün ist offline
    Ist es eigentlich möglich, eine neu erstellte Klasse/Instanz wieder aus einem Savegame rauszukriegen? Bei Funktionen und Variablen hat Gothic ja kein Problem, wenn sie z.B. in Modversion 1.0 vorkommen und im 1.0-Speicherstand gespeichert sind, aber nicht mehr in der 1.1-Mod vorhanden sind, mit der man den alten Speicherstand lädt. Wenn ich aber eine Klasse erstelle (die nur ints enthält) dann stürzt die Version 1.1 beim Laden des alten Speicherstandes ab.

    Konkretes Beispiel:

    Code:
    CLASS AttackObj
    {
    	var int att;       // Pointer
    	var int vic;       // ditto
    	var int mag;       // Spell-ID
    	var int dmg;       // Schaden
    	var int chargeup;  // Aufladungs-Level
    	var int damtype;   // Schadenstyp
    	var int time;      // Zeitpunkt des Castens
    };
    
    INSTANCE AttackObj@ (AttackObj) {};
    Um sicherzustellen, dass kein gespeichertes Objekt mehr diese Instanz nutzt, habe ich folgendes Skript einmal laufen lassen und dann abgespeichert:

    Code:
    func int _DelAttObj (var int hndl) {
    	var AttackObj myAttackObj; myAttackObj = get(hndl);
    	delete(myAttackObj);
    	return continue;
    };
    
    func void DelAttObjs () {
    	ForEachHndl(AttackObj@,_DelAttObj);
    };
    Ist es nicht möglich, das Savegame in einen Zustand zu bringen, sodass es ohne den ersten Codeblock in der Mod lädt? Oder hab ich das Löschen vergeigt?

    Mit und ohne die zwei Codeblöcke funktioniert das Spiel ansonsten einwandfrei, es ist einfach nur Code-Ballast den ich in meinem in 1.0 gestarteten Spiel behalten muss und dann entfernen muss, bevor ich 1.1 release.

    EDIT: Das Problem scheint die Instanz zu sein, nicht die Klasse. Wenn ich die unterste Zeile im ersten Codeblock auskommentiere, kommt es auch zum Crash zu Startup.

    EDIT2: Mir ist gerade erst aufgefallen, dass das Grundproblem gar nichts mit LeGo zu tun hat. Soll ich einen anderen Thread aufmachen?
    “Da ist auch noch ein anderer Geruch in der Luft, der Geruch von Feuern, die in der Ferne brennen, mit einem Hauch Zimt darin - so riecht das Abenteuer!”
    ― aus Walter Moers' "Die 13 1/2 Leben des Käpt'n Blaubär"
    Geändert von GiftGrün (18.05.2017 um 14:35 Uhr)

  4. Beiträge anzeigen #404
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Wenn das Problem nicht an LeGo direkt liegt (du kannst in der SCRPTSAVE.SAV einfach alle Einträge der genannten Klasse/Instanz von Hand löschen zum Testen), kann ich dir wohl nicht weiterhelfen. Generell ist es problematisch, alte Spielstände weiterhin zu benutzen, mehr weiß ich leider auch nicht.
    Geändert von Lehona (18.05.2017 um 15:15 Uhr)

  5. Beiträge anzeigen #405
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist offline
    Mir ist nicht ganz klar, warum die Instanz eine Funktion zugewiesen hat und keine Instanzenreferenz ist (wie Self, Other, ... ohne geschweifte Klammern).
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  6. Beiträge anzeigen #406
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Zitat Zitat von NicoDE Beitrag anzeigen
    Mir ist nicht ganz klar, warum die Instanz eine Funktion zugewiesen hat und keine Instanzenreferenz ist (wie Self, Other, ... ohne geschweifte Klammern).
    Weil entweder Gottfried oder ich mal geschrieben habe, dass beides okay ist.
    Macht das denn einen Unterschied, außer dass der "Konstruktor" bei der einen Variante null ist und bei der anderen "nur" leer?

  7. Beiträge anzeigen #407
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.410
     
    NicoDE ist offline
    Macht nur intern einen kleinen Unterschied, der meist keine Rolle spielen dürfte. Ist mir nur aufgefallen...
    Sollte man vielleicht überprüfen ob get etwas gültiges zurückgibt, bevor man delete aufruft?
    Hab hier kein Gothic zur Hand, also nur ins Blaue geraten :-)
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  8. Beiträge anzeigen #408
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Zitat Zitat von NicoDE Beitrag anzeigen
    Sollte man vielleicht überprüfen ob get etwas gültiges zurückgibt, bevor man delete aufruft?
    Sollte man, aber delete() kommt auch mit ungültigen Werten zurecht.

    Du hast mich aber auf eine Idee gebracht: Man sollte definitv die Dokumentation lesen
    Als Parameter wird natürlich ein Handle erwartet, kein Objekt. Daher lässt sich der oben gezeigte Code auch viel einfacher schreiben:

    Code:
    ForEachHndl(AttackObj@, delete);

  9. Beiträge anzeigen #409
    Held Avatar von GiftGrün
    Registriert seit
    Jun 2011
    Ort
    Gewächshaus des Assassinen
    Beiträge
    5.010
     
    GiftGrün ist offline
    Danke, damit hat's geklappt!
    “Da ist auch noch ein anderer Geruch in der Luft, der Geruch von Feuern, die in der Ferne brennen, mit einem Hauch Zimt darin - so riecht das Abenteuer!”
    ― aus Walter Moers' "Die 13 1/2 Leben des Käpt'n Blaubär"

  10. Beiträge anzeigen #410
    Veteran
    Registriert seit
    Jan 2012
    Beiträge
    681
     
    Frank-95 ist offline
    I might have found a bug (not like the one in my previous thread )

    Do you remember when I told you that FFs did not automatically run on loading? Well you fixed that with one of the previous realeses. Nevertheless it seems that the fix does not apply with FFs with data.

    Code:
    FF_ApplyOnceExt(PoisonDamage, 1000, -1); //automatically starts
    FF_ApplyOnceExtData(DMG_HeavyInjury, 1000, -1, MEM_InstToPtr(hero)); //does not, have to call it explicitly in the init

  11. Beiträge anzeigen #411
    Veteran
    Registriert seit
    Jan 2012
    Beiträge
    681
     
    Frank-95 ist offline
    Also, I found a problem with Wld_SetTime used with FFs. Trivial example:

    Code:
    instance TestPC3(C_Item)
    {
        name = "time";
        mainflag = ITEM_KAT_DOCS;
        flags = ITEM_MISSION;
        value = 0;
        visual = "ItWr_Scroll_01.3DS";
        material = MAT_LEATHER;
        on_state[0] = UseTestPC3;
        scemeName = "MAP";
        description = name;
    };
    
    var int a;
    
    
    func void aaa()
    {
        Wld_SetTime(a+9,10+a);
        a += 1;
    };
    
    
    func void UseTestPC3()
    {
        FF_ApplyOnceExt(aaa,3000,5);
    };
    It just crashes, zspy logs nothing, but I get this window:

    [Bild: Immagine.png]


    The problem seems not to be in the time change itself, but rather in the routines changes. In fact if I did the same thing this way:

    Code:
    func void aaa()
    {
        MEM_WorldTimer.worldTime = addf(MEM_WorldTimer.worldTime,mkf(250000));
    };
    
    
    func void UseTestPC3()
    {
        FF_ApplyOnceExt(aaa,3000,5);
    };
    Hours increase by 1 each time, but I have no change in npcs routine.
    Geändert von Frank-95 (04.06.2017 um 09:29 Uhr)

  12. Beiträge anzeigen #412
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Interesting find. I'll try to find out what' s causing the crash.

  13. Beiträge anzeigen #413
    Veteran
    Registriert seit
    Jan 2012
    Beiträge
    681
     
    Frank-95 ist offline
    If you need more info, this morning I made some reverse engineering to check where the problem could be.

    Daedalus Wld_SetTime changes npcs routines and, if needed, spawn npcs or monsters too. No functions of oCWorldTimer do this, so I supposed that the function that Wld_SeTime calls is:
    .text:006C4DE0 ; void __thiscall oCGame::SetTime(oCGame *this, int, int, int)
    This function, in addition to change the time, calls:
    .text:007764D0 ; void __thiscall oCRtnManager::SetDailyRoutinePos(oCRtnManager *this, int)
    .text:006CACB0 ; void __thiscall oCGame::SetObjectRoutineTimeChange(oCGame *this, int, int, int, int)
    .text:00777A40 ; void __thiscall oCSpawnManager::SpawnImmediately(oCSpawnManager *this, int)
    So I've reimplement that function manually:
    Code:
    func void RtnManager_SetDailyRoutinePos(var int state)
    {
        const int RtnManager_ptr = 11219400;
        CALL_IntParam(state);
        CALL__thiscall(RtnManager_ptr,7824592);
    };
    
    
    func void Game_SetObjectRoutineTimeChange(var int hour1, var int min1, var int hour2, var int min2)
    {
        CALL_IntParam(min2);
        CALL_IntParam(hour2);
        CALL_IntParam(min1);
        CALL_IntParam(hour1);
        CALL__thiscall(MEM_ReadInt(MEMINT_oGame_Pointer_Address),7122096);
    };
    
    
    func void SpawnManager_SpawnImmediately(var int state)
    {
        CALL_IntParam(state);
        CALL__thiscall(MEM_Game.spawnman,7830080);
    };
    
    
    func void Game_ManualSetTime(var int day, var int hour, var int minute)
    {
        var int currentHour; currentHour = Wld_GetHour();
        var int currentMinute; currentMinute = Wld_GetMinute();
        MEM_WorldTimer.day = day;
        MEM_WorldTimer.worldTime = addf(MEM_WorldTimer.worldTime,mulf(mkf(oCWorldTimer_TicksPerHour),mkf(hour)));
        MEM_WorldTimer.worldTime = addf(MEM_WorldTimer.worldTime,mulf(mkf(oCWorldTimer_TicksPerMin_approx),mkf(minute)));
        
        RtnManager_SetDailyRoutinePos(1);
        Game_SetObjectRoutineTimeChange(currentHour,currentMinute,Wld_GetHour(),Wld_GetMinute());
        SpawnManager_SpawnImmediately(1);
    };
    (okay, I've mistakened since my function just adds time and not sets it, but the point is not in there, which is the easiest part)
    My function works, except for what I've just said. Anyway it crashes the same way when I call it via frame function:
    Code:
    func void aaa()
    {
        Game_ManualSetTime(1,12,32);
    };
    
    
    func void UseTestPC3()
    {
        FF_ApplyOnceExt(aaa,3000,1);
    };
    Exactly like the original function
    Code:
    func void Game_SetTime(var int day, var int hour, var int minute)
    {
        CALL_IntParam(minute);
        CALL_IntParam(hour);
        CALL_IntParam(day);
        CALL__thiscall(MEM_ReadInt(MEMINT_oGame_Pointer_Address),7097824);
    };
    Then I commented the last three function and checked which made the game crashes. It resulted to be RtnManager_SetDailyRoutinePos.

  14. Beiträge anzeigen #414
    Veteran
    Registriert seit
    Jan 2012
    Beiträge
    681
     
    Frank-95 ist offline
    Okay I've found out that the problem is not just in that function. If I call SetDailyRoutinePos via FF, it works. If I call SetObjectRoutinePos and/or SpawnImmediately, it works. If I call the three together, it doesn't.

    A hack to make oCGame_SetTime work via FF, is to do something like this:

    Code:
    var int currentHour; currentHour = Wld_GetHour();
    var int currentMinute; currentMinute = Wld_GetMinute();
    FF_ApplyOnceExt(func1, time, 1);
    
    func void func()
    {
        MEM_WorldTimer.worldTime = ...; //change or add time as needed
        RtnManager_SetDailyRoutinePos(1);
        FF_ApplyOnceExt(func2,1000,1);
    };
    
    func void func2()
    {
         Game_SetObjectRoutineTimeChange(currentHour,currentMinute,Wld_GetHour(),Wld_GetMinute());
        SpawnManager_SpawnImmediately(1);
    };
    It's not clean, but it's the best I've come up so far

  15. Beiträge anzeigen #415
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Gibt es eine einfache Möglichkeit zu testen, ob eine Adresse gültig ist?
    Der Hintergrund ist eine Data-FrameFunction, dessen Data ein Pointer ist, der nach Spielladen sicherlich ungültig ist.
    Code:
    func void exampleFF(var int ptr) {
        if (valid(ptr)) {
            MEM_ReadInt(ptr+someoffset); // This would crash after loading a saved game
        };
    };
    Das von PermMem bereitgestellte Handle-System ist ein guter Ansatz. Allerdings zeigt der Pointer auf eine nicht-dokumentierte Klasse, daher komme ich mit wrap so nicht weiter. Gibt es da eine einfache Alternative?
    Der Pointer muss das Laden eines Spiels nicht überleben, ich will nur einen Crash abfangen.

    EDIT: Die Problemstellung ist ein bisschen falsch hier (der Beispiel-Code führt nicht zwingend zum Crash), da die Adresse an sich immer gültig ist. Was ich einfach überprüft habe ist, ob der Wert an bestimmtem Offset vom Pointer den Erwartungen enspricht.
    Geändert von mud-freak (14.06.2017 um 11:38 Uhr)

  16. Beiträge anzeigen #416
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.447
     
    Lehona ist offline
    Dein Beispiel ist etwas sehr minimal, aber deine Frage geht auf jedenfall in die Richtung "geht nicht".
    Ohne deinen Fall besser zu kennen würde ich es so machen:

    Code:
    var int currGen;
    class PtrGeneration {
    var int ptr;
    var int generation;
    };
    instance PtrGeneration@(PtrGeneration);
    
    func int createPtr(var int ptr) {
        var int h; h = new(PtrGeneration@);
        var PtrGeneration PtrG; PtrG = get(h);
        PtrG.ptr = ptr;
        PtrG.generation = currGen;
    };
    
    func int validPtr(var int h) {
        var PtrGeneration PtrG; PtrG = get(h);
        return (PtrG.generation == currGen);
    };
    Dann musst du currGen nur noch an geeigneter Stelle inkrementieren - beim Spielstand laden oder beim Neustart von Gothic.

  17. Beiträge anzeigen #417
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Gibt es ein definiertes Verhalten, wenn man zwei verschiedene Deadalusfunktionen an die gleiche Adresse hooked?
    Beispiel:
    Code:
    HookEngineF(addr1, 5, func1);
    HookEngineF(addr1, 5, func2);
    Ich hätte erwartet, dass beim erreichen der Adresse zuerst func1 und dann func2 aufgerufen wird, aber ich bin mir nicht so sicher. Kann man überhaupt für eine Reihenfolge garantieren, oder ist so etwas so wie etwas gefährlich?

    EDIT: Hat sich erledigt. Hat eine Weile gedauert bis ich nachvollziehen konnte, dass der ursprüngliche Opcode an der Adresse ans Ende kopiert wird und dann durch den rekursiven Aufrufen (wenn man erneut an die Adresse hooken will) erneut überschrieben/verschoben wird. Somit werden also die Hooks natürlich der Reihenfolge entsprechend der Initialisierung nach aufgerufen.
    Geändert von mud-freak (09.08.2017 um 14:45 Uhr)

  18. Beiträge anzeigen #418
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.246
     
    Milky-Way ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Gibt es ein definiertes Verhalten, wenn man zwei verschiedene Deadalusfunktionen an die gleiche Adresse hooked?
    Beispiel:
    Code:
    HookEngineF(addr1, 5, func1);
    HookEngineF(addr1, 5, func2);
    Ich hätte erwartet, dass beim erreichen der Adresse zuerst func1 und dann func2 aufgerufen wird, aber ich bin mir nicht so sicher. Kann man überhaupt für eine Reihenfolge garantieren, oder ist so etwas so wie etwas gefährlich?

    EDIT: Hat sich erledigt. Hat eine Weile gedauert bis ich nachvollziehen konnte, dass der ursprüngliche Opcode an der Adresse ans Ende kopiert wird und dann durch den rekursiven Aufrufen (wenn man erneut an die Adresse hooken will) erneut überschrieben/verschoben wird. Somit werden also die Hooks natürlich der Reihenfolge entsprechend der Initialisierung nach aufgerufen.
    Ich hätte erwartet, dass zuerst func2, dann func1 und dann der ursprüngliche Code ausgeführt wird? (oder ist es das, was du meinst)
    Es könnte aber vielleicht zu Problemen führen, wenn die 5 Bytes nicht passen für den ersten Befehl von func1?

  19. Beiträge anzeigen #419
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    So wie ich es aus dem Code entnehmen konnte, wird die ursprüngliche Instruktion durch einen Jump zu einer neuen Adresse ersetzt. An dieser neuen Adresse wird (u.a.) die Deadalusfunktion aufgerufen und anschliessen wird die ursprüngliche Instruktion drangehängt, bevor es zurück "nach" die usprüngliche Adresse geht.
    Wenn man nun erneut an der selben Adresse hookt, wird dem Jump gefolgt und dann wieder die ursprüngliche Instruktion, die einst an der ursprünglichen Adresse war, durch einen Jump ersetzt und anschliessend wieder angehängt. So geht das immer weiter und die Reihenfolge der Hooks bleibt erhalten.
    Ich bitte um Korrektur wenn ich das falsch verstanden habe.

  20. Beiträge anzeigen #420
    Held Avatar von GiftGrün
    Registriert seit
    Jun 2011
    Ort
    Gewächshaus des Assassinen
    Beiträge
    5.010
     
    GiftGrün ist offline
    Ist es nicht so, dass der Jump ersetzt wird? Wie ich das verstehe:

    Sagen wir, addr1 wäre 00F43960 und die Funktion an dieser Stelle foo (10 bytes). Dann sähe das nach dem ersten Hook doch so aus:

    Code:
    00F43960 - JUMP TO
    00F43961 - 13
    00F43962 - 5A
    00F43963 - 92
    00F43964 - 34
    Und beginnend ab Adresse 135A9234 steht [was auch immer func1 macht] [erste fünf Bytes von foo] RETURN.

    Der zweite Hook macht dann daraus:

    Code:
    00F43960 - JUMP TO
    00F43961 - 24
    00F43962 - AF
    00F43963 - 40
    00F43964 - 19
    Und an Adresse 24AF4019 steht [was auch immer func2 macht] JUMP TO 135A9234 RETURN. Was dann dazu führt, dass func2 vor func1 aufgerufen wird.
    “Da ist auch noch ein anderer Geruch in der Luft, der Geruch von Feuern, die in der Ferne brennen, mit einem Hauch Zimt darin - so riecht das Abenteuer!”
    ― aus Walter Moers' "Die 13 1/2 Leben des Käpt'n Blaubär"

Seite 21 von 24 « Erste ... 10141718192021222324 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