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 1 von 7 12345 ... Letzte »
Ergebnis 1 bis 20 von 131
  1. Beiträge anzeigen #1 Zitieren
    Ritter Avatar von Kirides
    Registriert seit
    Jul 2009
    Ort
    Norddeutschland
    Beiträge
    1.780
     
    Kirides ist offline

    Bätsch [Patch] Manaregeneration für alle

    Ich habe vor kurzem angefangen zu lernen, wie man Scripte für Gothic (2) schreibt, da kam es gelegen, dass ich schon immer mal Manaregeneration in jeder möglichen Mod haben wollte und Ninja dies ermöglichen kann.


    Gerne akzeptiere ich konstruktive Kritik, wenn vorhanden


    Konfiguration des Patches
    Um die Standardwerte (THRESHOLD/Schwellenwert: 50 Mana, PERMILLE: 10) zu überschreiben,
    trägt man folgendes (z.B. ans Ende) in die System\Gothic.ini ein:

    Code:
    [NINJA_MANAREG]
    THRESHOLD=50
    PERMILLE=10
    TICKRATE=1000
    #PER_TICK=1
    Erklärung
    THRESHOLD: Der "Maximales Mana"-Wert, den der Held benötigt, damit die Manaregeneration freigeschaltet wird. (Standard: 50)
    PERMILLE: Der Wert mithilfe dessen, die Regenerationsrate bestimmt wird. (Standard: 10 => 1% Pro Tick)
    TICKRATE: Frequenz/Tickrate der Manaregeneration in Millisekunden (1000=1 Sekunde)
    PER_TICK: Feste Menge Mana welche Pro Tick regeneriert wird. (Sinnvoll für G1, wo Manakosten gering sind)

    Vorraussetzungen:
    - Gothic 2 DndR mit Reportversion 2.6.0.0 / Gothic 1.08k
    - Ninja 2+

    Installation:
    ManaReg.vdf nach "C.\Spiele\[Gothic2 oder Gothic1]\Data" kopieren. (Pfad entsprechen anders bei euch)

    Download (extern) : GitHub Release

    Quellcode: GitHub
    Geändert von Kirides (14.07.2021 um 08:39 Uhr) Grund: v3.0.0

  2. Beiträge anzeigen #2 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Zitat Zitat von johnnyboyy Beitrag anzeigen
    Gerne akzeptiere ich konstruktive Kritik, wenn vorhanden
    Na dann leg ich mal los

    In der *_INIT.d:

    Code:
        Timer_SetPauseInMenu(1);
        if(!FF_Active(Ninja_ManaReg_Regeneration)) {
            FF_ApplyExt(Ninja_ManaReg_Regeneration, 2000, -1);
        };
    Die If-Klausel kannst du dir mit FF_ApplyOnceExt sparen (die macht genau das).

    Das setzen des Timers ist ein bisschen gefährlich, denn das ist eine globale Einstellung. Falls sich andere Teile der Mod darauf verlassen, dass die Timer im Menü weiterlaufen, machst du das damit kaputt. Ist allerdings nicht unbedingt deine Schuld: Man kann das in LeGo 2.5 nicht für einzelne FFs einstellen. Im nächsten Release gibt es eine Möglichkeit, FFs an den Gametimer zu hängen, dann brauchst du das nicht mehr. Insgesamt gibt es dann zwei getrennte Timer, anstatt einem, den man umstellen kann.

    Dann in der Manareg_Init(): Das meiste kannst du dir da sparen, scheinst du ja von mud-freaks Vorlage kopiert zu haben. Die Kommentare sind ziemlich irreführend oder mud-freak und ich verwenden andere Begrifflichkeiten. Zumindest wird die ManaReg_InitOnce() einmal pro Spielstand aufgerufen, nicht einmal pro Session (das heißt für mich: Zwischen Starten und Beenden der Anwendung). Um es wirklich 1x pro Session zu machen, müsste die Variable Ninja_ManaReg_Initialized eine Konstante mit dem Wert 0 sein.


    In der *_REGENERATION.d:

    Die Funktion wird nur einmal alle zwei Sekunden aufgerufen, aber Float-Operationen sind dennoch nicht soo billig (zumindest im Vergleich zum Rechnen mit Integern). In deinem Fall lässt sich die Mana-Menge auch problemlos ohne Floats berechnen:

    Code:
    var int mreg_div; mreg_div = n.attribute[ATR_MANA_MAX]/50; 
    // Falls du korrekt runden möchtest:
    var int mreg_div; mreg_div = (n.attribute[ATR_MANA_MAX]+25)/50;
    Das ist zwar eher eine Mikro-Optimierung, aber der Code wird lesbarer und du kannst den Faktor jetzt (einfacher) als Konstante ausdrücken. Insgesamt solltest du deine Einstellungen als Konstanten deklarieren und nicht in einer Init-Funktion befüllen.

  3. Beiträge anzeigen #3 Zitieren
    Ritter Avatar von Kirides
    Registriert seit
    Jul 2009
    Ort
    Norddeutschland
    Beiträge
    1.780
     
    Kirides ist offline
    Zitat Zitat von Lehona Beitrag anzeigen
    Das setzen des Timers ist ein bisschen gefährlich, denn das ist eine globale Einstellung. Falls sich andere Teile der Mod darauf verlassen, dass die Timer im Menü weiterlaufen, machst du das damit kaputt. Ist allerdings nicht unbedingt deine Schuld: Man kann das in LeGo 2.5 nicht für einzelne FFs einstellen. Im nächsten Release gibt es eine Möglichkeit, FFs an den Gametimer zu hängen, dann brauchst du das nicht mehr. Insgesamt gibt es dann zwei getrennte Timer, anstatt einem, den man umstellen kann.
    D.h. um das sauberer zu implementieren sollte ich warten, verstehe ich das richtig? (Oder gibt es eine Variable/Methode mit der ich "pausieren/überspringen" kann)


    Ich habe mal bisschen aufgeräumt, da war ja noch viel nicht verwendeter Code aus der inspirierenden Vorlage.

    refactor-wog (GitHub, diff)
    Geändert von Kirides (28.08.2018 um 21:12 Uhr) Grund: Quote gefixt

  4. Beiträge anzeigen #4 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Code:
    var int menge; menge = (n.attribute[ATR_MANA_MAX] + 25) / NINJA_MANAREG_MAX_MANA_DIVISOR;
    // nicht eher
    var int menge; menge = (n.attribute[ATR_MANA_MAX] + (NINJA_MANAREG_MAX_MANA_DIVISOR/2)) / NINJA_MANAREG_MAX_MANA_DIVISOR;
    Wegen dem Timer-Problem kannst du einfach das in deine FF schreiben:

    Code:
    if (MEM_Game.timeStep) {
        return;
    };
    Dann wird der Code nicht ausgeführt, falls das Spiel gerade pausiert ist. Ist dann ein bisschen ungenau wegen dem 2-Sekunden Timer, der ja trotzdem läuft, aber fürs erste funktioniert das.

  5. Beiträge anzeigen #5 Zitieren
    Ritter Avatar von Kirides
    Registriert seit
    Jul 2009
    Ort
    Norddeutschland
    Beiträge
    1.780
     
    Kirides ist offline
    Zitat Zitat von Lehona Beitrag anzeigen
    Code:
    var int menge; menge = (n.attribute[ATR_MANA_MAX] + 25) / NINJA_MANAREG_MAX_MANA_DIVISOR;
    // nicht eher
    var int menge; menge = (n.attribute[ATR_MANA_MAX] + (NINJA_MANAREG_MAX_MANA_DIVISOR/2)) / NINJA_MANAREG_MAX_MANA_DIVISOR;
    Du hast natürlich recht - hatte schon viel zu lange nicht wirklich mit Mathe zu tun, sogar simple Mathematik kann man vergessen

    Bezüglich des Timers, genau sowas hatte ich mir als workaround gedacht - aber kannte / kenne die ganzen variablen noch nicht wirklich. Kommt noch

    refactor-wog (GitHub, diff)


    EDIT:
    Zitat Zitat von Lehona Beitrag anzeigen
    Wegen dem Timer-Problem kannst du einfach das in deine FF schreiben:

    Code:
    if (MEM_Game.timeStep) {
        return;
    };
    Dann wird der Code nicht ausgeführt, falls das Spiel gerade pausiert ist. Ist dann ein bisschen ungenau wegen dem 2-Sekunden Timer, der ja trotzdem läuft, aber fürs erste funktioniert das.

    Das scheint leider nicht zu funktionieren, mit diesem Code wird die Methode nicht ausgeführt :/
    Geändert von Kirides (28.08.2018 um 22:11 Uhr)

  6. Beiträge anzeigen #6 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Zitat Zitat von johnnyboyy Beitrag anzeigen
    Das scheint leider nicht zu funktionieren, mit diesem Code wird die Methode nicht ausgeführt :/
    Vielleicht hab ich die Bedingung umgedreht - überprüf mal das Gegenteil.

  7. Beiträge anzeigen #7 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Ich habe auch noch ein bisschen Feedback (für Übersichtlichkeit nummeriert).
    1. Cool, dass du dich bei dem Patch so an die Vorlagen gehalten hast. Das macht alles recht übersichtlich!

    2. Wünschenswert wäre sowohl eine Readme_Ninja_ManaReg.txt als auch eine Info-Beschreibung in der VDF-Datei (siehe GFA Patch). Da ist es auch wichtig zu erwähnen, dass es ich eben nicht um LeGo 2.5 handelt, sondern um eine angepasste Version (die du scheinbar aus dem GFA Patch übernommen hast):
      Zitat Zitat von Readme vom GFA-Patch
      LeGo 2.5.0-rev-170*
      [...]
      * For compatibility with LeGo 2.4, some functions are not included
      (ViewPtr_AddText, View_AddText, View_AddTextColored, Button_SetCaption)
    3. Die Dateinamen der angepassten LeGo-Version solltest du auch an deinen Patchnamen anpassen, diese heißen noch
      Code:
      __BUTTONS_NINJA_GFA.D
      __VIEW_NINJA_GFA.D
      (Entsprechende Referenzen in der HEADER.SRC auch anpassen.) Das ist wichtig, falls sich die Inhalte der beiden Patches mal unterscheiden sollten, denn jede Datei mit identischem Pfad wird nur einmal aus den VDF-Dateien geladen (daher müssen alle Patch-spezifischen Dateien einzigartige Namen tragen).


    4. Zitat Zitat von Lehona Beitrag anzeigen
      Dann in der Manareg_Init(): Das meiste kannst du dir da sparen, scheinst du ja von mud-freaks Vorlage kopiert zu haben. Die Kommentare sind ziemlich irreführend oder mud-freak und ich verwenden andere Begrifflichkeiten. Zumindest wird die ManaReg_InitOnce() einmal pro Spielstand aufgerufen, nicht einmal pro Session (das heißt für mich: Zwischen Starten und Beenden der Anwendung). Um es wirklich 1x pro Session zu machen, müsste die Variable Ninja_ManaReg_Initialized eine Konstante mit dem Wert 0 sein.
      In den GFA-Skripten, wo johnnyboyy das glaube ich her hat, ist das eine Konstante mit null. Ich denke wir haben da das gleiche Verständnis von Session und Spielstand.

    5. Damit die Mana-Regeneration auch nach Weltenwechsel problemlos läuft, solltest du hier lieber hero anstatt PC_Hero verwenden.


    6. Zitat Zitat von johnnyboyy Beitrag anzeigen
      Das scheint leider nicht zu funktionieren, mit diesem Code wird die Methode nicht ausgeführt :/
      Du könntest auch folgendes probieren:
      Code:
      if (MEM_Game.pause_screen) {
          return;
      };

    7. Ich habe den Patch nicht getestet. Hast du mal ein paar Tests mit einer handvoll verschiedener und verschieden-alter Mods gemacht? Auch in Verbindung mit anderen Patches? Hast du Randfälle überprüft (während Regeneration Spiel speichern/laden, Weltenwechsel, Spiel beenden und neu starten, neues Spiel, usw.).
      Meiner Meinung nach ist das Testen von Patches besonders wichtig, denn sonst verursachst du Mod-Entwicklern eine Menge Ärger, wenn sie sich um Bugs kümmern sollen, die gar nicht durch ihre Mod entstanden sind (außerdem wird bei Problemen gern schnell pauschalisiert, z.B. "Patches sind alle von Vornherein verbuggt!").


    Gute Arbeit!


    EDIT: Ein Verbesserungsvorschlag wäre, dass sich der Schwellenwert von 50 Mana und die Regenerierungsgeschwindigkeit/-menge in der Gothic.ini einstellen ließe.
    Geändert von mud-freak (15.01.2021 um 11:29 Uhr)

  8. Beiträge anzeigen #8 Zitieren
    Ritter Avatar von Kirides
    Registriert seit
    Jul 2009
    Ort
    Norddeutschland
    Beiträge
    1.780
     
    Kirides ist offline
    Zitat Zitat von Lehona Beitrag anzeigen
    Vielleicht hab ich die Bedingung umgedreht - überprüf mal das Gegenteil.
    Damit gehts


    Zitat Zitat von mud-freak Beitrag anzeigen
    Gute Arbeit!


    EDIT: Ein Verbesserungsvorschlag wäre, dass sich der Schwellenwert von 50 Mana und die Regenerierungsgeschwindigkeit/-menge in der Gothic.ini einstellen ließe.
    D.h. aus den Konstanten werden wieder Variablen, die ich im "initOnce" befülle, korrekt?


    Sporadisch erhalte ich beim Speichern eine Access Violation, hier kann ja eigentlich nur "hero" der pointer sein, oder irre ich mich?
    Gibt es beim Speichern/Levelwechsel etwas wichtiges zu beachten, was ich nicht tue?

    EDIT: Kann es zurückführen auf den Marvin-Modus, sobald ich ihn Aktiviere und Deaktiviere (c42c) tritt das verhalten auf. Auch ohne mein Script. (Nur LeGo und Ikarus)
    Reproduzierbar durch Marvin->"edit abilities" -> Attribute -> 2 = 80 -> c42c -> speichern. Zufällig (häufig) Fehler und crash

    Code (Ninja_ManaReg_Regeneration)
    Spoiler:(zum lesen bitte Text markieren)
    Code:
    func void Ninja_ManaReg_Regeneration() {
        // HACK: Entfernen wenn es FF gibt, welche nur im nicht pausierten Modus feuern.
        if (!mem_game.timestep) {
            return;
        };
        //var c_npc n; n = Hlp_GetNpc(PC_Hero);
        var c_npc n; n = Hlp_GetNpc(hero);
        
        if (n.attribute[ATR_MANA_MAX] >= NINJA_MANAREG_MANA_THRESHOLD) {
            if (n.attribute[ATR_MANA] < n.attribute[ATR_MANA_MAX]) {
                var int menge; menge = (n.attribute[ATR_MANA_MAX] + (NINJA_MANAREG_MAX_MANA_DIVISOR/2)) / NINJA_MANAREG_MAX_MANA_DIVISOR;
                Npc_ChangeAttribute(n, ATR_MANA, menge);
            };
        };
    };


    Stacktrace
    Spoiler:(zum lesen bitte Text markieren)
    [f] 03:08 Fault: 0 Q: MEM_PtrToInst: Invalid pointer: -2141662528
    [i] 03:08 Info: 5 X: Vid_SetScreenMode: No changes ... .... <zRndD3D_Vid.cpp,#559>
    [i] 03:08 Info: 5 X: Vid_SetScreenMode: No changes ... .... <zRndD3D_Vid.cpp,#559>
    [i] 03:20 Info: 2 U: PAR: Adressing an empty Instance : ZCARRAY.ARRAY .... <zParser_Symbol.cpp,#365>
    [i] 03:20 Info: 2 U: PAR: Adressing an empty Instance : ZCARRAY.NUMALLOC .... <zParser_Symbol.cpp,#365>
    [i] 03:20 Info: 2 U: PAR: Adressing an empty Instance : ZCARRAY.NUMALLOC .... <zParser_Symbol.cpp,#365>
    [i] 03:20 Info: 2 U: PAR: Adressing an empty Instance : ZCARRAY.ARRAY .... <zParser_Symbol.cpp,#365>
    [i] 03:20 Info: 2 U: PAR: Adressing an empty Instance : ZCARRAY.ARRAY .... <zParser_Symbol.cpp,#365>
    [i] 03:20 Info: 2 U: PAR: Adressing an empty Instance : ZCARRAY.NUMINARRAY .... <zParser_Symbol.cpp,#365>
    [f] 03:20 Fault: 0 Q: [start of stacktrace]
    [f] 03:20 Fault: 0 Q: MEM_WRITEINT_() + 35 bytes
    [f] 03:20 Fault: 0 Q: MEM_WRITEINTARRAY(0, 0, 827877824) + 45 bytes
    [f] 03:20 Fault: 0 Q: MEM_ARRAYINSERT(-2141662528, 827877824) + 238 bytes
    [f] 03:20 Fault: 0 Q: PM_SAVESTRING('loop', 'NINJA_MANAREG_REGENERATION') + 52 bytes
    [f] 03:20 Fault: 0 Q: PM_SAVEFUNCID('loop', 10000) + 58 bytes
    [f] 03:20 Fault: 0 Q: PM_SAVEFUNCOFFSET('loop', 123832) + 32 bytes
    [f] 03:20 Fault: 0 Q: PM_SAVEFUNCPTR('loop', 246088664) + 33 bytes
    [f] 03:20 Fault: 0 Q: FFITEM_ARCHIVER((instance)1755378040) + 26 bytes
    [f] 03:20 Fault: 0 Q: MEM_CALLBYID(8266) + 224 bytes
    [f] 03:20 Fault: 0 Q: _PM_DATATOSAVESTRUCT_ARCHIVER(0, 8266) + 59 bytes
    [f] 03:20 Fault: 0 Q: _PM_DATATOSAVEOBJECT('', 'FFITEM') + 633 bytes
    [f] 03:20 Fault: 0 Q: _PM_INSTTOSAVESTRUCT(1755378040, 8265) + 275 bytes
    [f] 03:20 Fault: 0 Q: _PM_ARCHIVE_LISTSUB(1906445232) + 84 bytes
    [f] 03:20 Fault: 0 Q: MEM_CALLBYID(8266) + 224 bytes
    [f] 03:20 Fault: 0 Q: MEM_CALL(LIST_FORF.FNC) + 21 bytes
    [f] 03:20 Fault: 0 Q: LIST_FORF(1906445232, _PM_ARCHIVE_LISTSUB) + 75 bytes
    [f] 03:20 Fault: 0 Q: MEM_CALLBYID(8266) + 224 bytes
    [f] 03:20 Fault: 0 Q: MEM_CALL(LIST_FORF.FNC) + 21 bytes
    [f] 03:20 Fault: 0 Q: _PM_ARCHIVE() + 199 bytes
    [f] 03:20 Fault: 0 Q: _BW_SAVEGAME() + 89 bytes
    [f] 03:20 Fault: 0 Q: MEM_CALLBYID(8266) + 224 bytes
    [f] 03:20 Fault: 0 Q: _HOOK(1755714816, 1554527544, 159025696, 159025696, 20314684, 1, 20578304, 2, 180250296) + 498 bytes
    [f] 03:20 Fault: 0 Q: [UNKNOWN] +847941955 bytes
    [f] 03:20 Fault: 0 Q: [end of stacktrace]


    EDIT:
    Update 1.1.0
    (Siehe start-post)
    Geändert von Kirides (29.08.2018 um 22:21 Uhr)

  9. Beiträge anzeigen #9 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von johnnyboyy Beitrag anzeigen
    D.h. aus den Konstanten werden wieder Variablen, die ich im "initOnce" befülle, korrekt?
    Das sieht im Code auf Github ganz gut aus. Sollte so klappen.

    Zitat Zitat von johnnyboyy Beitrag anzeigen
    Sporadisch erhalte ich beim Speichern eine Access Violation, hier kann ja eigentlich nur "hero" der pointer sein, oder irre ich mich?
    Nein, der Pointer ist ein nicht vorhandenes Array (_PM_Head.content) beim Schreiben in PermMem in Zusammenhang mit deiner FrameFunction. Wenn das wie du schreibst auch ohne dein Skript vorkommt, stimmt da was nicht. Kann es sein, dass das mit einem geladenem Speicherstand passiert ist?

    Speicherst du mit deinem Patch, wird die FrameFunction mit in den Speicherstand gelegt. Lädst du dann den Speicherstand ohne den Patch, kann PermMem den Funktionsnamen "Ninja_ManaReg_Regeneration" keinem Symbol zuordnen. Ich meine aber, das war kein Problem und LeGo würde in solchen Fällen lediglich eine Warnung auswerfen. Vor allem kann ich mir nicht vorstellen, dass es an einem nicht existierendem Array (_PM_Head.content) scheitert...

    Kannst du versuchen, den Fehler etwas mehr einzugrenzen? (Mit/ohne Patch, neues Spiel/geladenes Spiel jeweils mit/ohne Patch, ...) Hast du noch andere Änderungen in Gothic, die die Ursache dafür sein könnten?
    Geändert von mud-freak (15.01.2021 um 11:30 Uhr)

  10. Beiträge anzeigen #10 Zitieren
    Ritter Avatar von Kirides
    Registriert seit
    Jul 2009
    Ort
    Norddeutschland
    Beiträge
    1.780
     
    Kirides ist offline
    Vorweg: mein Gothic2 Verzeichnis für das Scripten ist ein frisch installiertes, nach empfohlener Reihenfolge + Mdk mit Rohdaten


    Ich habe einen Speicherstand, welchen ich ohne Mod-Starter / Scripts & Ninja erstellt habe, "START1" diesen habe ich als Basis für alle meine Tests benutzt.

    Diesen habe ich immer geladen (Modstarter + Scripte parsen) und anschließend auf "START2" gespeichert. Soweit so gut.
    Wenn ich jedoch, im Marvin Modus meine Attribute ändere und den Marvin-Modus dann beende, anschließend versuche auf START3 zu speichern, bekomme ich teilweise eine Access Violation.
    Diese tritt auch auch, wenn ich die FF_ApplyOnce-Zeile auskommentiere (d.h. nur der INIT-Code mit dem Mergen von Flags wird ausgeführt).

    Nach der Arbeit versuche ich das noch genauer zu reproduzieren.


    EDIT: Also sind Speicherstände kaputt, wenn man den Ninjapatch wieder entfernt? // derp
    Geändert von Kirides (30.08.2018 um 18:26 Uhr)

  11. Beiträge anzeigen #11 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Versuch es am besten immer mit neuen Spielen als Basis anstatt einem geladenen Spielstand (ausgenommen du willst eben gerade das Speicher- und Ladeverhalten mit und ohne Patch testen).
    Wenn du nur Änderungen an Ninja vornimmst, brauchst du übrigens nicht das Häkchen bei "Skripte parsen" im Mod-Starter, dann geht's schneller. Ninja parst immer seine Skripte.

    Vielleicht finde ich am Wochenende Zeit zu probieren, ob ich den Fehler reproduzieren kann.

    Zu deinem Edit:
    Nein. Im Normalfall kann man sie problemlos entfernen und hinzufügen (solang sie keine Symbolindices abspeichern, was mir nur vom EventHandler in LeGo bekannt ist, den man aber auch ohne PermMem-Handle benutzen kann, um das Problem zu umgehen). Allerdings hatte ich in meinen Patches nie eine fortlaufende FrameFunction und kann mich nicht mehr erinnern, ob das ein Problem war.
    Geändert von mud-freak (15.01.2021 um 11:30 Uhr)

  12. Beiträge anzeigen #12 Zitieren
    Ritter Avatar von Kirides
    Registriert seit
    Jul 2009
    Ort
    Norddeutschland
    Beiträge
    1.780
     
    Kirides ist offline
    Mein Ziel ist es einen Patch zu kreieren, welcher mit vorhandenen Spielständen verwendet werden kann, deswegen hatte ich das als Basis genommen.

    Mein Script lasse ich aktuell noch über Gothic.src Parsen und erst nach dem testen landet das im separaten "ninjasrc" Verzeichnis, mit der Struktur vom Patch

  13. Beiträge anzeigen #13 Zitieren
    Ritter Avatar von Kirides
    Registriert seit
    Jul 2009
    Ort
    Norddeutschland
    Beiträge
    1.780
     
    Kirides ist offline
    Bloßes speichern nach einem neuen Spiel hat das Spiel zum absturz gebracht.
    Aktive Mods / Patches: Ninja_ManaReg


    Video auf YouTube (Xardas bei ~50 Sekunden)

    zSpy Log auf Pastebin
    Geändert von Kirides (30.08.2018 um 18:20 Uhr)

  14. Beiträge anzeigen #14 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von johnnyboyy Beitrag anzeigen
    Bloßes speichern nach einem neuen Spiel hat das Spiel zum absturz gebracht.
    Aktive Mods / Patches: Ninja_ManaReg


    Video auf YouTube (Xardas bei ~50 Sekunden)

    zSpy Log auf Pastebin
    Danke für den zSpy Log. Bis ich mir das genauer angucken kann, kannst du einmal unter deiner Funktion "Ninja_ManaReg_Init()" eine "leere" Funktion anfügen? Also in /NINJA/CONTENT/NINJA_ManaReg_INITCONTENT.D nach Zeile 57 etwas wie:
    Code:
    func void Ninja_ManaReg_Dummy() {
        var int i; i = i;
        return;
    };

  15. Beiträge anzeigen #15 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Ikarus weigert sich, negative Pointer zu dereferenzieren (MEM_PtrToInst), was dann später zu einem MEM_WriteInt(0, x) führt (und MEM_WriteInt hat aus Performance-Gründen keine Sanity-Checks) Wenn ich mich nicht irre ist es aber keinesfalls unmöglich, negative Pointer zu erzeugen. Eine kurze Google-Suche hat bestätigt, dass alle 32bit-Werte ungleich NULL gültige Pointer sind.

    Die Frage ist natürlich, warum das jetzt mehr oder weniger zum ersten Mal aufgetreten ist (bzw. ich davon gehört habe). Benutzt das neuste SystemPack vielleicht das Flag, dass den Adressraum von 2 auf 4 GiB erweitert?

    Du kannst mal versuchen, in MEM_PtrToInst nur bei ptr == 0 abzubrechen bzw. gar nicht abzubrechen und nur eine Warnung auszugeben.

    Edit: Eh, da gehen unsere Lösungsansätze aber ganz schön auseinander

  16. Beiträge anzeigen #16 Zitieren
    Ritter Avatar von Kirides
    Registriert seit
    Jul 2009
    Ort
    Norddeutschland
    Beiträge
    1.780
     
    Kirides ist offline
    Da fällt mir ein: Ich hab ja das LAA-FLAG gesetzt auf meiner gothic.exe!

    Hab mal ohne den FLAG getestet: Das Problem tritt nicht mehr auf (zumindest in meinen tests)


    Hatte den mal auf meine "clean" installation gesetzt, weil das früher mal vor OutOfMemory geholfen hatte, meine ich mich zu erinnern

    EDIT:
    Zitat Zitat von mud-freak Beitrag anzeigen
    Danke für den zSpy Log. Bis ich mir das genauer angucken kann, kannst du einmal unter deiner Funktion "Ninja_ManaReg_Init()" eine "leere" Funktion anfügen? Also in /NINJA/CONTENT/NINJA_ManaReg_INITCONTENT.D nach Zeile 57 etwas wie:
    Code:
    func void Ninja_ManaReg_Dummy() {
        var int i; i = i;
        return;
    };
    Warum zum Geier hilft das gegen das Problem?? *interessiert*

    Habe das mal eingebaut, und die gothic2.exe mit LAA-Flag getestet und das Problem scheint nicht mehr aufzutreten

    EDIT2:
    Zitat Zitat von Lehona Beitrag anzeigen
    Du kannst mal versuchen, in MEM_PtrToInst nur bei ptr == 0 abzubrechen bzw. gar nicht abzubrechen und nur eine Warnung auszugeben.
    Ich habe mal Ikarus.d->MEM_PtrToInst geändert und damit getestet:
    Code:
    func MEMINT_HelperClass MEM_PtrToInst (var int ptr) {
        var MEMINT_HelperClass hlp;
        const int hlpOffsetPtr = 0;
        if (!hlpOffsetPtr) {
            hlpOffsetPtr = MEM_ReadIntArray (currSymbolTableAddress, hlp) + zCParSymbol_offset_offset;
        };
    
        if (ptr == 0) {
            if (!MEM_AssignInstSuppressNullWarning) {
                /* Instanzen die Null sind, will man eigentlich nicht, die machen nur Ärger. */
                MEM_Warn ("MEM_PtrToInst: ptr is NULL. Use MEM_NullToInst if that's what you want.");
            };
    
            MEM_WriteInt(hlpOffsetPtr, 0);
        } else {
            MEM_WriteInt(hlpOffsetPtr, ptr);
        };
        MEMINT_StackPushInst (hlp);
    };
    Damit tritt das Problem auch nicht auf
    Geändert von Kirides (30.08.2018 um 19:22 Uhr)

  17. Beiträge anzeigen #17 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Zitat Zitat von johnnyboyy Beitrag anzeigen
    Warum zum Geier hilft das gegen das Problem?? *interessiert*

    Habe das mal eingebaut, und die gothic2.exe mit LAA-Flag getestet und das Problem scheint nicht mehr aufzutreten


    Das würde ich allerdings auch gerne wissen

  18. Beiträge anzeigen #18 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Vorher noch die Frage: Bist du wirklich sicher, dass das Problem durch die leere Funktion behoben ist (inkl. gesetztem LAA-Flag) oder hast du es nur ein-zwei mal getestet?


    Was FrameFunctions in Patches angeht: Entfernst du den Patch von einer Mod, die LeGo benutzt, stürzt das Spiel beim Laden der zuvor gespeicherten Spiele ab. Das liegt daran, dass die FrameFunctions mitgespeichert/-geladen werden, aber die Funktion ohne den Patch nicht mehr existiert. LeGo anzupassen, dass es erst schaut, ob eine entsprechende Funktion existiert, wird nichts bringen, weil sich das ja nicht rückwirkend auf ältere Mods auswirkt. Die Spieler müssten also die "SCRPTSAVE.SAV" editieren und die FrameFunction herauslöschen, was nicht besonders Benutzerfreundlich ist. Das ist aber nun ein spezieller Fall, denn die bisherigen Patches benutzen keine (fortlaufenden) FrameFunctions.
    Mir fallen einige Alternativen ein (FrameFunction-Handle beim Speichern ausschließen, FrameFunction über Hooks emulieren, FrameFunctions Handle-los nachbauen), die aber alle mehr oder weniger große Probleme mit sich bringen.

    Dass das nun nicht von Haus aus funktioniert, liegt nicht an Ninja, geschweige denn an LeGo. (Ninja öffnet ja nur die Tür für Skriptpatches, setzt aber nicht die Verwendung von LeGo voraus. Und niemand hätte bei der Entwicklung von LeGo so etwas ahnen können oder Rücksicht darauf nehmen müssen.) Es ist also beim Erstellen des Patches, wo man sich etwas einfallen lassen muss, wie man seine Ideen realisiert. Deshalb ist das Ganze nicht so ganz geradlinig wie normales Skripten und ein bisschen mehr herausfordernd. Ich hoffe, das ging schon aus der Dokumentation von Ninja etwas hervor.

    Hier meine Empfehlung:

    Anstatt einer FrameFunction erstellst du einen Hook (z.B. an selber Adresse), mit dem du die verstrichene Zeit mit der Verzögerung von 2 Sekunden abgleichst und entsprechend die Manapunkte erhöhst (wenn das Spiel gerade nicht pausiert ist). Das ist aber sehr speziell für diesen Fall und löst das Problem nicht in anderen Fällen. Denn durch den Hook läuft diese "Schleife" in jedem geladenen Spielstand und lässt sich nicht von Spielstand zu Spielstand de-/aktivieren, oder mitspeichern. Bei der Manaregeneration ist das ja kein Problem, weil sie immer stattfindet und nicht beispielsweise erst gelernt werden muss o.ä.
    Geändert von mud-freak (15.01.2021 um 11:30 Uhr)

  19. Beiträge anzeigen #19 Zitieren
    Ritter Avatar von Kirides
    Registriert seit
    Jul 2009
    Ort
    Norddeutschland
    Beiträge
    1.780
     
    Kirides ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Vorher noch die Frage: Bist du wirklich sicher, dass das Problem durch die leere Funktion behoben ist (inkl. gesetztem LAA-Flag) oder hast du es nur ein-zwei mal getestet?

    ...

    Hier meine Empfehlung:

    Anstatt einer FrameFunction erstellst du einen Hook (z.B. an selber Adresse), mit dem du die verstrichene Zeit mit der Verzögerung von 2 Sekunden abgleichst und entsprechend die Manapunkte erhöhst (wenn das Spiel gerade nicht pausiert ist). Das ist aber sehr speziell für diesen Fall und löst das Problem nicht in anderen Fällen. Denn durch den Hook läuft diese "Schleife" in jedem geladenen Spielstand und lässt sich nicht von Spielstand zu Spielstand de-/aktivieren, oder mitspeichern. Bei der Manaregeneration ist das ja kein Problem, weil sie immer stattfindet und nicht beispielsweise erst gelernt werden muss o.ä.
    Ich hatte es ca 5x probiert, jeweils Neigeladen und neuen Spielstand (10x Ges.)
    Kann natürlich auch einfach sein, dass in den Speichervorgängen einfach kein negativer Pointer aufgetreten ist. Ich probiere das nach der Arbeit noch ein paar Mal.

    Zum anderen Thema:
    Gibt es da eine (verständliche) Anleitung wie man die Adresse herausbekommt und hooks in die gewünschte Adresse einbindet?

  20. Beiträge anzeigen #20 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von johnnyboyy Beitrag anzeigen
    Ich probiere das nach der Arbeit noch ein paar Mal.
    Das wäre gut zu wissen, denn ich glaube es liegt nicht zwingend am LAA-Flag, bzw. mich wundert dass beide Lösungsansätze funktionieren.


    Zitat Zitat von johnnyboyy Beitrag anzeigen
    Gibt es da eine (verständliche) Anleitung wie man die Adresse herausbekommt und hooks in die gewünschte Adresse einbindet?
    Im LeGo-Thread hatte sich glaube ich Lehona mal die Mühe gemacht eine verständliche Anleitung zu Hooks zu schreiben, aber ich habe den Post jetzt auf die schnelle nicht gefunden. Hier ist es aber ziemlich einfach: mit "an selber Adresse" meinte ich die Adresse von FrameFunctions aus LeGo ("oCGame__Render"). Es ginge zwar auch eleganter (z.B. in oCAIHuman::PC_walkcycle oder so ähnlich, dann würde die Funktion direkt nur während des laufenden Spiels aufgerufen werden), aber das sollte so passen (code ungetestet):

    Code:
    func void Ninja_ManaReg_Regeneration() {
        // Not during loading
        if (!Hlp_IsValidNpc(hero)) {
             return;
        };
    
        // Only in-game
        if (!MEM_Game.timestep) {
            return;
        };
    
        // Only in a certain interval
        var int delayTimer; delayTimer += MEM_Timer.frameTime;
        if (delayTimer < 2000) {
            return;
        };
        delayTimer -= 2000;
    
        // Increase mana
        if (hero.attribute[ATR_MANA_MAX] >= Ninja_ManaReg_Mana_Threshold) {
            if (hero.attribute[ATR_MANA] < hero.attribute[ATR_MANA_MAX]) {
                var int menge; menge = (hero.attribute[ATR_MANA_MAX] + (Ninja_ManaReg_Max_Mana_Divisor/2)) / Ninja_ManaReg_Max_Mana_Divisor;
                Npc_ChangeAttribute(hero, ATR_MANA, menge);
            };
        };
    };
    Die Initialisierung von LeGo kann man sich so komplett sparen, weil die HookEngine auf keinem Paket aufbaut (seit 2.4), d.h. die ganze "MergeLeGoFlags"-Geschichte kannst du dir so sogar sparen.
    Code:
    func void Ninja_ManaReg_Init() {
        MEM_Info(ConcatStrings(ConcatStrings("Initialize ", NINJA_MANAREG_VERSION), "."));
    	
        Ninja_ManaReg_ApplyINI();
        HookEngineF(oCGame__Render, 7, Ninja_ManaReg_Regeneration);
    
        MEM_Info(ConcatStrings(NINJA_MANAREG_VERSION, " was initialized successfully."));
    };

Seite 1 von 7 12345 ... 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