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 4 « Erste 1234 Letzte »
Ergebnis 41 bis 60 von 77
  1. Beiträge anzeigen #41 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von Lehona Beitrag anzeigen
    Bringt ja nix, wenn man feststellen kann, dass der NPC gerade sitzt, wenn dann das Diebstahlinventar trotzdem nicht aufgeht
    Stimmt. Das habe ich missverstanden. Da müsste man wohl mal in
    Code:
    int __thiscall oCNpc::OpenSteal(void)    0x762430
    hineinschauen.

  2. Beiträge anzeigen #42 Zitieren
    Legende der Amazonen Avatar von Bisasam
    Registriert seit
    Dec 2006
    Ort
    Meine Faust in Sinis Gesicht
    Beiträge
    9.635
     
    Bisasam ist offline
    Änderungen eingefärbt. Ich dachte halt, dass der aus den Farb-Tags code macht und nicht die Farbe übernimmt. Ist aber gut, dass dem nicht so ist. Bis auf 3 Abschnitte betreffen die Änderungen so gut wie alles was darin steht.
    Geht am besten von oben nach unten durch und gleicht ab.

    Wer die Sache mit den Freunden drinlässt, sollte außerdem die AIV_HeroTaschendieb in seiner AI_Constants definieren.


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

  3. Beiträge anzeigen #43 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Ich kann das Skript zur Zeit nicht selbst ausprobieren. Mich würden aber einige Dinge interessieren.
    1. Schliesst sich das Inventar selbstständig, wenn man während dem Taschendiebstahl erwischt wird oder kann man weiterklauen, wenn der NPC einen schon angreift?
    2. Hat man unendlich viel Zeit das Inventar zu leeren (vorausgesetzt man wird nicht gesehen) oder "bemerkt" der NPC es nach einer Weile?
    3. Wird das komplette Inventar geöffnet (inkl. Händlerware und Rüstungen)? Gibt es vielleicht sonstige Itemflags, die verursachen, dass das Item nicht auftaucht?
    Ich kann mich nicht mehr genau daran zurück erinnern wie das in den einzelnen Fällen in Gothic 1 funktionierte.

    Falls (2.) nicht der Fall ist, wäre das eine schöne Erweiterung. Mit mehr Geschick oder einer zweiten Lernstufe von Taschendiebstahl könnte man die Stehlzeit verlängern. Diese könnte man ja ganz leicht mit einer FrameFunction realisieren, die in der Funktion Taschendiebstahl() gestartet wird und nach bestimmter Zeit B_Attack triggert, falls imtaschendiebstahl == 1.

  4. Beiträge anzeigen #44 Zitieren
    Legende der Amazonen Avatar von Bisasam
    Registriert seit
    Dec 2006
    Ort
    Meine Faust in Sinis Gesicht
    Beiträge
    9.635
     
    Bisasam ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    1. Schliesst sich das Inventar selbstständig, wenn man während dem Taschendiebstahl erwischt wird oder kann man weiterklauen, wenn der NPC einen schon angreift?

      Ja, es schließt sich. Der Npc kann danach nicht mehr bestohlen werden.

    2. Hat man unendlich viel Zeit das Inventar zu leeren (vorausgesetzt man wird nicht gesehen) oder "bemerkt" der NPC es nach einer Weile?

      Man hat so viel Zeit wie der Npc einen nicht bemerkt. Da sie sich bei Tagesabläufen auch schonmal umdrehen oder losgehen können oder andere Leute vorbeikommen und den Npc darauf aufmerksam machen, ist da eine soziale Zeitbegrenzung.

    3. Wird das komplette Inventar geöffnet (inkl. Händlerware und Rüstungen)? Gibt es vielleicht sonstige Itemflags, die verursachen, dass das Item nicht auftaucht?


      Angelegte Ausrüstung kann nicht gestohlen werden. Schlüssel, Erzbrocken,
      Gold, Runen (nicht angelegt), Spruchrollen (nicht angelegt), Essen, ect. kann alles gestohlen werden.




    Ich kann mich nicht mehr genau daran zurück erinnern wie das in den einzelnen Fällen in Gothic 1 funktionierte.

    Falls (2.) nicht der Fall ist, wäre das eine schöne Erweiterung. Mit mehr Geschick oder einer zweiten Lernstufe von Taschendiebstahl könnte man die Stehlzeit verlängern. Diese könnte man ja ganz leicht mit einer FrameFunction realisieren, die in der Funktion Taschendiebstahl() gestartet wird und nach bestimmter Zeit B_Attack triggert, falls imtaschendiebstahl == 1.
    Siehe Zitat.

    Ich persönlich bin gegen eine zustätzliche zeitliche Begrenzung, weil (zumindest in meiner Mod) es schon schwer genug ist, mal einen Npc unbeobachtet anzutreffen und auszurauben.
    Würde ich da jetzt noch mehr Restriktionen einbauen, würde sich der Taschendiebstahl überhaupt nicht mehr lohnen.


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

  5. Beiträge anzeigen #45 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von Bisasam Beitrag anzeigen
    Siehe Zitat.

    Ich persönlich bin gegen eine zustätzliche zeitliche Begrenzung, weil (zumindest in meiner Mod) es schon schwer genug ist, mal einen Npc unbeobachtet anzutreffen und auszurauben.
    Würde ich da jetzt noch mehr Restriktionen einbauen, würde sich der Taschendiebstahl überhaupt nicht mehr lohnen.
    Cool, danke für die Erklärungen. Dann hört sich das ja nach einem komplett abgerundeten Feature an - abgesehen von BS_SIT und BS_MOBINTERACT. Wenn das nicht schon ein anderer bis dahin getan hat, würde ich mir demnächst mal die Enginefunktion dem bezüglich anschauen (dauert noch ne Weile bis ich dazu komme). Ich könnte mir allerdings vorstellen, dass das aus "Stabilitätsgründen" deaktiviert ist. Vielleicht würde ein NPC während der Benutzung eines Mobs feststecken bleiben (oder z.B. die Laborflasche in der Hand behalten), wenn er wegen eines Angriff unterbricht.

  6. Beiträge anzeigen #46 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.409
     
    NicoDE ist offline
    Wenn ich mich recht erinnere, muss der NPC (Tote, Monster und Orcs sind ausgeschlossen) beim Stehlen in BS_STAND oder BS_ITEMINTERACT sein.
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  7. Beiträge anzeigen #47 Zitieren
    Legende der Amazonen Avatar von Bisasam
    Registriert seit
    Dec 2006
    Ort
    Meine Faust in Sinis Gesicht
    Beiträge
    9.635
     
    Bisasam ist offline
    Zitat Zitat von NicoDE Beitrag anzeigen
    Wenn ich mich recht erinnere, muss der NPC (Tote, Monster und Orcs sind ausgeschlossen) beim Stehlen in BS_STAND oder BS_ITEMINTERACT sein.
    Wo wird das definiert? Kann man da was ändern?

    Einen Npc zu bestehlen der gerade mit dem Schleifstein beschäftigt ist o.ä. wäre cool.


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

  8. Beiträge anzeigen #48 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.409
     
    NicoDE ist offline
    Zitat Zitat von Bisasam Beitrag anzeigen
    Wo wird das definiert?
    Ich habe hier nur G1 und dort ist die Funktion als Inline-Kopie in oCNpc::OpenSteal und oCNpc::CheckSpecialSituations (letztere prüft alle drei Sekunden den "Klauen"-Status). Ich gehe davon aus, dass sich das bei G2 nicht wesentlich (wenn überhaupt) geändert hat. Dort findet jeweils direkt der Vergleich auf 0 (BS_STAND) und 14 (BS_ITEMINTERACT) statt (wenn der oCNpc::game_mode 2 ist). Die Idee war wahrscheinlich, dass der Beklaute sich nicht bewegen soll - und Sitzen ist insofern schwierig, weil er mindestens in S_BENCH_S1 und S_THRONE_S1 in die andere Richtung sieht...
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
    Geändert von NicoDE (05.05.2017 um 16:24 Uhr)

  9. Beiträge anzeigen #49 Zitieren
    Legende der Amazonen Avatar von Bisasam
    Registriert seit
    Dec 2006
    Ort
    Meine Faust in Sinis Gesicht
    Beiträge
    9.635
     
    Bisasam ist offline
    Den Part werfe ich mit meiner Abfrage ja schon raus. Wenn Npc mich nicht sieht, geht das Menü auch nicht auf.

    Ehrlich gesagt bin ich bei den ganzen Funktionen noch nicht so drin. Könnte mir also jemand Wissendes verständlich erklären wie ich mit Ikarus und ggf. LeGo die Funktion bearbeiten kann, damit die Abfragen richtig sind? ._."


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

  10. Beiträge anzeigen #50 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.409
     
    NicoDE ist offline
    Zitat Zitat von Bisasam Beitrag anzeigen
    Ehrlich gesagt bin ich bei den ganzen Funktionen noch nicht so drin.
    Ich lade mir die Report-Version mal runter und suche die Adressen raus, edit folgt...

    edit: Ändere mal die Bytes an den Speicheradressen 0x007625E2 und 0x00762015 von 0x74 auf 0xEB - damit sollte der BodyState beim Stehlen keine Rolle mehr spielen (und das Plündern noch funktionieren, wenn der Beklaute erwacht).
    Code:
    func void DisableStealBodyStateCheck()
    {
        const int oCNpc_OpenSteal_JzBS                      =     7742946;     // .text:007625E2
        const int oCNpc_CheckSpecialSituations_JzBS         =     7741461;     // .text:00762015
        if ((MEM_ReadInt(oCNpc_OpenSteal_JzBS)              == -125631116) &&  // JZ SHORT +5; CMP EAX, imm8
            (MEM_ReadInt(oCNpc_CheckSpecialSituations_JzBS) ==  -75299468)) {  // JZ SHORT +5; CMP EBX, imm8
            MemoryProtectionOverride(oCNpc_OpenSteal_JzBS,              4);
            MemoryProtectionOverride(oCNpc_CheckSpecialSituations_JzBS, 4);
            MEM_WriteByte(oCNpc_OpenSteal_JzBS,                       235);    // JMP SHORT
            MEM_WriteByte(oCNpc_CheckSpecialSituations_JzBS,          235);    // JMP SHORT
        };
    };
    Muss einmalig vor oCNpc::OpenSteal() aufgerufen werden (die Prüfung findet vor dem Aufruf von G_CanSteal() statt).
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor
    Geändert von NicoDE (05.05.2017 um 22:50 Uhr)

  11. Beiträge anzeigen #51 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Zitat Zitat von Bisasam Beitrag anzeigen
    Den Part werfe ich mit meiner Abfrage ja schon raus. Wenn Npc mich nicht sieht, geht das Menü auch nicht auf.

    Ehrlich gesagt bin ich bei den ganzen Funktionen noch nicht so drin. Könnte mir also jemand Wissendes verständlich erklären wie ich mit Ikarus und ggf. LeGo die Funktion bearbeiten kann, damit die Abfragen richtig sind? ._."
    Prüfen solltest du das trotzdem. Denn was Nico damit ausdrücken wollte - glaube ich - ist, dass der NPC beim Sitzen auf dem Thron (z.B.) anders gedreht ist als es aussieht, d.h. er schaut eigentlich gegen die Stuhllehne (die Vermutung basiert allerdings nur auf Nicos Aussage und der Tatsache, dass man zum Interagieren ja Richtung Lehne schaut).



    Eigentlich ist das ganz einfach: Du findest raus, an welcher Stelle du welche Bytes ändern/schreiben musst und machst das dann einfach per MEM_WriteByte(). Der erste Teil ist leider gar nicht so simpel, denn dafür sollte man wohl ein grundlegendes Verständnis von (x86) Assembly haben. Sektenspinner hat mir mal die Intel-Handbücher empfohlen (IA-32) - kann ich nur weiterempfehlen, wenn man es trocken mag...

  12. Beiträge anzeigen #52 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.409
     
    NicoDE ist offline
    Zitat Zitat von Lehona Beitrag anzeigen
    Prüfen solltest du das trotzdem.
    Testen wird sie da reichlich dürfen...
    Ohne die BS-Einschränkungen verhält sich auch die CheckSpecialSituations deutlich anders (gibt eine Menge, was während des Stehlens passieren kann - und da wird nicht extra eine spezielle Skriptfunktion von der Engine aufgerufen).

    Zitat Zitat von Lehona Beitrag anzeigen
    Eigentlich ist das ganz einfach: [...]
    Genau, siehe oben
    Das Problem ist eher, dabei die anderen Sachen (Plündern von Ohnmächtigen) nicht kaputt zu machen.
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  13. Beiträge anzeigen #53 Zitieren
    Legende der Amazonen Avatar von Bisasam
    Registriert seit
    Dec 2006
    Ort
    Meine Faust in Sinis Gesicht
    Beiträge
    9.635
     
    Bisasam ist offline
    Vielen Dank für eure Hilfe!
    Am Einfachsten wäre es wohl, wenn ich die Bytes von vor der Änderung speichere und nach Beendigung des Diebstahls zurücksetze, müsste eigentlich alles in Butter sein.


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

  14. Beiträge anzeigen #54 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.409
     
    NicoDE ist offline
    Zitat Zitat von Bisasam Beitrag anzeigen
    Vielen Dank für eure Hilfe!
    Am Einfachsten wäre es wohl, wenn ich die Bytes von vor der Änderung speichere und nach Beendigung des Diebstahls zurücksetze, müsste eigentlich alles in Butter sein.
    Bei der Änderung oben wird nur die Zusätzliche BS-Prüfung beim Stehlen entfernt (das was du haben wolltest, oder?). Wenn sie in OpenSteal entfernt wird, dann auch in CheckSpecialSituations (weil der Diebstahl ansonsten sofort endet)... ständige Änderungen im Code-Segment halte ich nicht unbedingt für sinnvoll.
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  15. Beiträge anzeigen #55 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von NicoDE Beitrag anzeigen
    ständige Änderungen im Code-Segment halte ich nicht unbedingt für sinnvoll.
    Meinst du mit "nicht sinnvoll" unnötig oder unratsam? Wenn letzteres, könntest du dafür einen Grund nennen? Das würde mich interessieren.

  16. Beiträge anzeigen #56 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Meinst du mit "nicht sinnvoll" unnötig oder unratsam? Wenn letzteres, könntest du dafür einen Grund nennen? Das würde mich interessieren.
    Im Zweifelsfall könnte es einen Virenscanner auslösen, denke ich Selbstmodifizierender Code ist heutzutage nicht mehr so aktuell, würde ich sagen.

  17. Beiträge anzeigen #57 Zitieren
    research Avatar von NicoDE
    Registriert seit
    Dec 2004
    Beiträge
    7.409
     
    NicoDE ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Meinst du mit "nicht sinnvoll" unnötig oder unratsam? Wenn letzteres, könntest du dafür einen Grund nennen? Das würde mich interessieren.
    Diese kleine Änderung sicher unproblematisch. Zumal die Änderung anscheinend permanent gewünscht zu sein scheint.
    Grundsätzlich ist der Speicher eine geteilte Ressource, auf die man nicht nebenläufig (multi-threading) zugreifen sollte, ohne entsprechende Vorkehrungen zu treffen. Bei mehreren (echten) Prozessorkernen hat jeder seine eigene "Sicht" auf die Speicherseiten. Das kann dazu führen, dass Änderungen einem Prozessor bekannt sind und dem anderen nicht... aber wie gesagt, spielt hier keine Rolle - ich sehe einfach keinen Grund das Feature hin- und herzuschalten
    "Unter diesen schwierigen Umständen bin ich mir sicher, daß diese guten Menschen meinen augenblicklichen Bedarf an deren Gold verstehen werden." -- Connor

  18. Beiträge anzeigen #58 Zitieren
    Legende der Amazonen Avatar von Bisasam
    Registriert seit
    Dec 2006
    Ort
    Meine Faust in Sinis Gesicht
    Beiträge
    9.635
     
    Bisasam ist offline
    Guut... Erster Test beendet.

    Die Funktion von Nico wurde 1 zu 1 übernommen und über DisableStealBodyStateCheck(); in Taschendiebstahl aufgerufen, unter der Bedingung, dass das Diebstahlsfenster noch nicht offen ist.
    Sie wurde über const int call = 0; eingefügt.

    Das Ergebnis:

    1. Npcs im BS_Sit können immer noch nicht ausgeraubt werden. Egal, ob auf einem Thron, auf einer Bank oder über AI_PlayAniBS.

    2. Npcs die gerade die Schmiede benutzen können ausgeraubt werden

    3. Wenn der Held schleicht, bemerken selbst Npcs, die dem Helden den Rücken zugekehrt haben oder durch eine Mesh-Wand von ihm getrennt sind, den Helden und gehen in entsprechende Wahrnehmungen.

    1 und 2 könnte man vielleicht noch fixen, aber 3 ist ein echtes Problem. Wenn Npc_CanSeeNpc durch diesen Aufruf kaputt geht, habe ich absolut nichts verdient. Ich werde deswegen weitere Tests in dieser Richtung abbrechen und mich mit dem Feature begnügen so wie es jetzt ist und funktioniert.

    Nochmal danke für die Unterstützung


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

  19. Beiträge anzeigen #59 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Ich hatte mich im Sommer noch etwas mit dem Taschdiebstahl hier auseinandergesetzt, dazu aber hier nie etwas geschrieben (sorry, aebo ). Jetzt habe ich es mir noch einmal angesehen und ein paar Dinge ergänzt, um es hier zu teilen.

    Letzter Stand (siehe Post vor mir) war ja, dass eigentlich alles klappte, bis auf merkwürdige Nebeneffekte. Nichtsdestotrotz schien mir die sicher mühselige (aber funktionierende!) Reimplementierung in Daedalus von Bisasam etwas zu aufwendig, da wirklich alles schon in der Engine enthalten ist. Mit Umschreiben von nur 16 Bytes in der Engine lässt sich der Taschendiebstahl genau an der selben Stelle wie in Gothic 1 wieder reaktivieren, womit natürlich vergleichsweise hohe Performance und Stabilität gewährleistet ist. D.h. die gesamte Skriptfunktion Taschendiebstahl erübrigt sich, ebenso wie das manuelle Behandeln/Aussenden von Wahrnehmungen. Letztlich braucht es skriptseitig nur ein paar Zeilen in der B_AssessTheft die man nahezu eins zu eins aus Gothic 1 kopieren kann.

    Das einzige was dann zu einem Problem wird, ist das Aushebeln des Bodystate-Checks. Das setzt voraus, wie Nico schon darauf hingewiesen hat, dass man selbst die Bodystates während des Stehlens irgendwie kontrolliert. Ich habe, auf seinem Skript aufbauend, den Bodystate-Check, anstatt ihn zu überspringen, erweiterbar gemacht, sodass man über ein statisches Daedalus Array alle gültigen Bodystates bestimmen kann.

    Ich habe noch ein Problem in der Funktion oCNpc::CreatePassivePerception behoben, das dazu geführt hatte, dass man beim Taschendiebstahl fast immer erwischt wurde.

    Dann habe ich noch die Abfrage, wann ein Taschendiebstahl erfolgreich ist und wann man erwischt wird, skriptseitig zugänglich gemacht. D.h. der Skripter kann das jetzt entscheiden. Standardmäßig ist das eine Wahrscheinlichkeit abhängig vom Diebstahltalent. Das kann man nun aber auch ersetzen und abhängig machen durch, z.B., eine maximale Anzahl von geklauten Items, einem Geschickswert, usw. oder es komplett deaktivieren, sodass man alles klauen kann solange man nicht erwischt wird.

    Lange Rede kurzer Sinn: Unten ein überarbeitetes Skript. Vielleicht ist es nicht zu spät und du/ihr Interessierten könnt es noch gebrauchen. Ich habe es schon getestet und es scheint alles (inkl. sitzender und Mob-nutzender Opfer) zu funktionieren (eingebaut im unveränderten Original + Ikarus und LeGo). Hoffen wir mal dass ich nichts übersehen habe.
    Auch wenn eigentlich gar nichts mehr von Bisasams Code übrig geblieben ist, fände ich es angebracht bei Benutzung Bisasam in den Credits zu erwähnen. Da steckt denke ich einiges an Nachforschungen und Tests drin und angesichts der Datierung der Posts auch eine Menge Zeit.

    Ein paar Worte zum Skript: Es ist letztlich viel länger als es sein müsste, da ich noch ein paar optionale Möglichkeiten, wie oben erwähnt, eingebaut habe. Im Kommentarblock oben steht, wie man es einbindet. Der Diebstahl funktioniert, wie auch in Gothic 1, über das prozentuale Taschendiebstahl-Talent, hier "NPC_TALENT_PICKPOCKET_G1". Funktionen/Definitionen, die man sich anschauen und verändern kann sind:
    - PP_Success: Abändern wann das Stehlen erfolgreich ist oder zum Erwischt werden führt
    - PP_BS: Liste von erlaubten Opfer-Bodystates
    - PP_AssessPickpocket: Taschendiebstahl-Äquivalent zu B_AssessTheft (übertragen aus Gothic 1)


    Code:
    /*
     * Gothic 1 Pickpocketing (PP) for Gothic 2
     * https://forum.worldofplayers.de/forum/threads/?p=26045212
     *
     * Compatible with Gothic 2 only
     *
     * Requirements
     *  - Ikarus >= 1.2.0
     *  - LeGo   >= 2.5.0
     *
     * Usage
     *  - Add this script to the Gothic.src somewhere between 'B_MemorizePlayerCrime.d' and 'B_AssessTheft.d'
     *  - To the end of 'Init_Global' add this line
     *      PP_Init();
     *  - To the end of 'Perception_Set_Normal' and 'Perception_Set_Minimal' add this line
     *      Npc_PercEnable(self, PERC_CATCHTHIEF, PP_CatchThief);
     *  - To the end of 'B_ClearPerceptions' add this line
     *      Npc_PercDisable(slf, PERC_CATCHTHIEF);
     *  - To the >BEGINNING< of 'B_AssessTheft' add this line
     *      if (PP_AssessPickpocket()) { return; };
     *  - To enable pickpocketing for the player, do so with
     *      Npc_SetTalentValue(hero, NPC_TALENT_PICKPOCKET_G1, percent);
     *    where 'percent' is an integer between 0 and 100, that specifies the success rate for every item transfer
     *  - You may change the success condition of item transfer in 'PP_Success' below
     *  - You may change the victim body states that allow pickpocketing in 'PP_BS' below
     *  - You may change the exact reaction of witnesses in 'PP_AssessPickpocket'. They are largely identical to Gothic 1
     */
    
    
    /*
     * Pickpocket talent index
     */
    const int NPC_TALENT_PICKPOCKET_G1 = 6;
    
    
    /*
     * Body states of the victim that allow initiation of PP
     * Caution: non-interruptible mobs (15) include doors and ladders. NPCs move while using these. Use at your own risk.
     */
    const int PP_BS_MAX = 5; //6;
    const int PP_BS[PP_BS_MAX] = {
        0,  // BS_STAND                 (without BS_FLAG_INTERRUPTABLE and BS_FLAG_FREEHANDS)      DEFAULT
        14, // BS_ITEMINTERACT          (without BS_FLAG_INTERRUPTABLE)                            DEFAULT
        11, // BS_SIT                   (without BS_FLAG_FREEHANDS)
        12, // BS_LIE
     // 15, // BS_MOBINTERACT           Caution: Non-interruptible mobs! See MOB_NOTINTERRUPTABLE in BodyStates.d
        16  // BS_MOBINTERACT_INTERRUPT (without BS_FLAG_INTERRUPTABLE)
    };
    
    
    /*
     * This function is called every time the player takes an item while pickpocketing. The return value determines whether
     * the theft was successful (TRUE = nothing happens), or failed (FALSE = player gets caught by victim).
     * Global instances are filled: "item" and "self" (NPC that is being pickpocketed).
     */
    func int PP_Success() {
        // Engine default: Successful if talent greater than random number
        return Npc_GetTalentValue(hero, NPC_TALENT_PICKPOCKET_G1) > Hlp_Random(100);
    };
    
    
    /*
     * This perception function is only called for witnesses while PP (regularly) - never called for victim = self!
     * The return value is important to tell B_AssessTheft whether the theft was pickpocketing.
     */
    func int PP_AssessPickpocket() {
        if ((Hlp_IsValidItem(item)) && (!Hlp_IsValidNpc(victim))) || (!Npc_IsPlayer(other)) {
            // An item was picked up from the world (default of B_AssessTheft)
            return FALSE; // Continue as normal in B_AssessTheft
        };
    
        // Else (method of elimination): Theft is pickpocketing
    
        // Can I (witness) see the theft in progress
        if (Npc_CanSeeNpc(self, other)) && (Hlp_IsValidNpc(victim)) {
    
            // Some obsolete checks copied from Gothic 1
            if (victim.guild < GIL_SEPERATOR_HUM) && (!C_NpcIsDown(victim)) {
    
                // self:   witness
                // other:  thief = player
                // victim: victim
    
                // Am I kind enough to warn the victim about the ongoing theft?
                if ((Wld_GetGuildAttitude(self.guild, victim.guild) == ATT_FRIENDLY)
                || (Wld_GetGuildAttitude(self.guild, victim.guild) == ATT_NEUTRAL)
                || (Npc_GetPermAttitude(self, other) == ATT_ANGRY))  {
                    // I am gonna stop what I am doing
                    Npc_ClearAIQueue(self);
                    B_ClearPerceptions(self);
                    AI_StandUpQuick(self);
    
                    // Look at and point out the thief
                    B_TurnToNpc(self, other);
                    B_LookAtNpc(self, other);
                    AI_PointAtNpc(self, other);
    
                    // Call out a warning to bystanders in range (incl. the victim) and remember/report crime
                    B_Say(self, other, "$HANDSOFF"); // SVM closest to 'Behind you!' from Gothic 1
                    B_MemorizePlayerCrime(self, other, CRIME_THEFT);
                    Npc_SendPassivePerc(self, PERC_ASSESSWARN, self, other); // Alternatively as AI_Function for delay
    
                    // I did my job here. You're welcome, victim
                    AI_StopPointAt(self);
                    B_StopLookAt(self);
    
                    // I stay vigilant towards the thief = player
                    AI_StartState(self, ZS_ObservePlayer, 1, "");
                };
            };
        };
    
        return TRUE; // Theft was pickpocketing: Do not continue with B_AssessTheft
    };
    
    
    /*
     * Perception function only called for the victim if caught - never called for witnesses!
     */
    func void PP_CatchThief() {
        B_Attack(self, other, AR_Theft, 0);
    };
    
    
    /*
     * Reinstate Gothic 1 pickpocketing when sneaking from behind - with just 16 bytes!
     */
    func void PP_Enable() {
        const int oCAIHuman__StandActions__actionSneak = 6918051; //0x698FA3
        const int oCAIHuman__StandActions__cleanUp     = 6918230; //0x699056
        const int oCNpc__OpenSteal                     = 7742512; //0x762430
    
        if (MEM_ReadInt(oCAIHuman__StandActions__actionSneak) != 1354) {
            return; // Already done
        };
    
        ASM_Open(17);
        ASM_2(36235); ASM_4(300);                                                 // mov   ecx, [ebp+0x12C]
        ASM_1(232);   ASM_4(oCNpc__OpenSteal-ASM_Here()-4);                       // call  oCNpc::OpenSteal
        ASM_1(233);   ASM_4(oCAIHuman__StandActions__cleanUp-ASM_Here()-4);       // jmp   .returnTrue
        MemoryProtectionOverride(oCAIHuman__StandActions__actionSneak, 4);
        MEM_WriteInt(oCAIHuman__StandActions__actionSneak, ASM_Close()-(oCAIHuman__StandActions__actionSneak-2+6));
    };
    
    
    /*
     * Overwrite the pickpocketing item transfer success condition
     */
    func void PP_SuccessInit() {
        const int oCStealContainer__HandleEvent_success = 7385842; //0x70B2F2
    
        if (MEM_ReadInt(oCStealContainer__HandleEvent_success) != 39504360) {
            return; // Already done
        };
    
        MemoryProtectionOverride(oCStealContainer__HandleEvent_success, 9);
        MEM_WriteInt(oCStealContainer__HandleEvent_success, 312451);              // add   esp, 0x4
        MEM_WriteInt(oCStealContainer__HandleEvent_success+3, 3229978768);        // nop  /  nop  /  test  eax, eax
        MEM_WriteByte(oCStealContainer__HandleEvent_success+8, 132);              // Change jge to jz
        HookEngineF(oCStealContainer__HandleEvent_success, 5, PP_SuccessHook);
    };
    func void PP_SuccessHook() {
        self = _^(MEM_ReadInt(ESI+160));
        item = _^(EBX);
        EAX = PP_Success();
    };
    
    
    /*
     * Fix the collection range estimation in oCNpc::CreatePassivePerception
     * This function is not specific to PP but a general fix. The NPCs targeted in oCNpc::CreatePassivePerception are
     * collected within a box whose lengths are constructed from the perception range. This includes NPCs that are in fact
     * outside of this range (as a box of length X is larger than a sphere of same radius). This function squeezes in a call
     * to oCNpc::IsInPerceptionRange to exclude any NPCs out of range.
     */
    func void PP_LimitPassivePerceptionRange() {
        const int oCNpc__CreatePassivePerception_loopNpc = 7714011; //0x75B4DB
        const int oCNpc__CreatePassivePerception_contNpc = 7714020; //0x75b4e4
        const int oCNpc__CreatePassivePerception_skipNpc = 7715238; //0x75B9A6
        const int oCNpc__IsInPerceptionRange             = 7726224; //0x75E490
    
        if (MEM_ReadInt(oCNpc__CreatePassivePerception_loopNpc) != -1936914805) {
            return; // Already done
        };
    
        ASM_Open(39);
        ASM_1(86);                                                                // push  esi                    ; Receiver
        ASM_4(472151295);                                                         // push  DWORD [esp+0x10C-0xF0] ; Sender
        ASM_1(87);                                                                // push  edi                    ; PercID
        ASM_1(232);   ASM_4(oCNpc__IsInPerceptionRange-ASM_Here()-4);             // call  oCNpc::IsInPerceptionRange
        ASM_3(836739);                                                            // add   esp, 0xc
        ASM_2(49285);                                                             // test  eax, eax
        ASM_2(33807); ASM_4(oCNpc__CreatePassivePerception_skipNpc-ASM_Here()-4); // jz    .skip
        ASM_2(1675);                                                              // mov   eax, [esi]             ; Rewrite
        ASM_4(-1071346547); ASM_3(0);                                             // lea   ecx, [esp+0x108-0x48]
        ASM_1(233); ASM_4(oCNpc__CreatePassivePerception_contNpc-ASM_Here()-4);   // jmp   .continue
        MemoryProtectionOverride(oCNpc__CreatePassivePerception_loopNpc, 5);
        MEM_WriteByte(oCNpc__CreatePassivePerception_loopNpc, 233);               // jmp   .outside
        MEM_WriteInt(oCNpc__CreatePassivePerception_loopNpc+1, ASM_Close()-oCNpc__CreatePassivePerception_loopNpc-5);
    };
    
    
    /*
     * Overwrite allowed victim body states
     * These functions are a variation of the loosened body states suggested by NicoDE here
     * https://forum.worldofplayers.de/forum/threads/?p=25448726
     * Allowing pickpocketing for any body state is a bit dangerous without manual checks as Nico already pointed out. So
     * instead, the list of acceptable body states is here made "customizable" (see 'PP_BS' above) to include only those
     * body states in which the victim is not moving.
     */
    func void PP_ChangeBodystateCheck_(var int addr, var int reg) {
        if (MEM_ReadByte(addr) != 133) {
            return; // Already done
        };
    
        ASM_Open(9*PP_BS_MAX + 5 + 1);
        repeat(i, PP_BS_MAX); var int i;
            ASM_1(131);   ASM_1(reg); ASM_1(MEM_ReadStatArr(PP_BS, i));           // cmp   reg, xxx
            ASM_2(33807); ASM_4(addr+9-ASM_Here()-4);                             // jz    .valid
        end;
        ASM_1(233); ASM_4(addr+16-ASM_Here()-4);                                  // jmp   .invalid
        MemoryProtectionOverride(addr, 5);
        MEM_WriteByte(addr, 233); MEM_WriteInt(addr+1, ASM_Close()-addr-5);       // jmp   .outside
    };
    func void PP_ChangeBodystateCheck() {
        const int oCNpc__OpenSteal_bs              = 7742944; //0x7625E0
        const int oCNpc__CheckSpecialSituations_bs = 7741459; //0x762013
    
        PP_ChangeBodystateCheck_(oCNpc__OpenSteal_bs, 248);              // eax
        PP_ChangeBodystateCheck_(oCNpc__CheckSpecialSituations_bs, 251); // ebx
    };
    
    
    /*
     * Initialization function to be called from Init_Global
     */
    func void PP_Init() {
        MEM_InitAll();
    
        PP_Enable();                         // Core mechanics
        PP_LimitPassivePerceptionRange();    // Fix/limit perception range
        PP_SuccessInit();                    // Overwrite success condition      (optional)
        PP_ChangeBodystateCheck();           // Allow more body states           (optional)
        Perc_SetRange(PERC_CATCHTHIEF, 150); // Reinstate pickpocket perception
    };
    Geändert von mud-freak (24.02.2021 um 09:21 Uhr) Grund: Stelle "item" und "self" in PP_Success zur Verfügung

  20. Beiträge anzeigen #60 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.205
     
    Milky-Way ist offline
    Super, habe ich direkt mal als nützliches Skript in den Editing FAQ verlinkt

Seite 3 von 4 « Erste 1234 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