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

 

Ergebnis 1 bis 12 von 12
  1. Beiträge anzeigen #1 Zitieren
    Waldläufer
    Registriert seit
    May 2022
    Beiträge
    123
     
    Jackydima ist offline

    Logik von NPC, Combat (class: Mage)

    Hallo,

    ich wollte nur mal fragen an welche Stelle ich die Logik von NPC über den Kampf mit Magie finde.

    Soweit ich weiß, wurde seit dem Community Patch / Content Mod, auch verschiedene Beschwörungszauber von bestimmten Magiern eingesetzt (Zumindest wenn der Player der Angegriffene ist).
    Es wurde auch für die Feuergolems und Icegolems der type "Paladin" gegeben, womit sie sogar in ihrem Element angelehnt an G2 zaubern können.

    Mich würde es interessieren, ob ich bestimmte Zauber für gewisse Magiertypen geben kann und diese exklusiv nur von den "zugehörigen" Göttern nutzen lassen kann. Vor allem Schwarzmagiern den Zauber Blitzschlag geben, damit der Energie-Abwehr-Status einen Sinn bekommt.

    Es gibt ja ein paar NPC Klassen die nicht benutzt werden. Da könnte man doch eine neue Klasse Mage_Innos, Mage_Beliar, Mage_Adanos einbauen.

    Wo würde ich da ansetzen? Ist das mit dem SDK möglich? Welche dll files sind hier von relevanz?

    Danke schon mal für die Antworten

  2. Beiträge anzeigen #2 Zitieren
    Moderator Avatar von George
    Registriert seit
    Sep 2010
    Beiträge
    684
     
    George ist offline
    Zitat Zitat von Jackydima Beitrag anzeigen
    Wo würde ich da ansetzen? Ist das mit dem SDK möglich? Welche dll files sind hier von relevanz?
    Ist möglich mit dem Gothic 3 SDK. Relevant sollte hierbei eigentlich nur die Script_Game.dll sein.
    Insbesondere eine Funktion, ich habe sie bei mir MageSelectSpell genannt, du findest sie an RVA 0x49890 in der Script_Game.dll.
    Dort wird entscheiden welchen Spell ein NPC verwendet.

  3. Beiträge anzeigen #3 Zitieren
    Waldläufer
    Registriert seit
    May 2022
    Beiträge
    123
     
    Jackydima ist offline
    Cool danke schaue ich mal rein.

    Hast du zufällig noch die Script_Game.dll Source files. Oder ist das so eine Kombination aus dem SDK.

  4. Beiträge anzeigen #4 Zitieren
    Moderator Avatar von George
    Registriert seit
    Sep 2010
    Beiträge
    684
     
    George ist offline
    Zitat Zitat von Jackydima Beitrag anzeigen
    Hast du zufällig noch die Script_Game.dll Source files. Oder ist das so eine Kombination aus dem SDK.
    Die ganzen Header-Files wurden aus den von den DLLs exportierten Klassen und Funktionen rekonstruiert. Die Script_Game.dll exportiert keinerlei Klassen oder Funktionen, daher gibt es keine Header/Source-Files dafür im SDK.

    Klassennamen und Funktionsnamen muss man daher selbst herausfinden, z.B. anhand von Strings, Nutzung von importierten Funktionen oder RTTI (Runtime Type Information).

  5. Beiträge anzeigen #5 Zitieren
    Waldläufer
    Registriert seit
    May 2022
    Beiträge
    123
     
    Jackydima ist offline
    Zitat Zitat von George Beitrag anzeigen
    Die ganzen Header-Files wurden aus den von den DLLs exportierten Klassen und Funktionen rekonstruiert. Die Script_Game.dll exportiert keinerlei Klassen oder Funktionen, daher gibt es keine Header/Source-Files dafür im SDK.

    Klassennamen und Funktionsnamen muss man daher selbst herausfinden, z.B. anhand von Strings, Nutzung von importierten Funktionen oder RTTI (Runtime Type Information).
    Ah verstehe. Ja den Funktionscode habe ich nun fast vollkommen verstanden. Ich habe mich nur gewundert, ob diese Script_Game.dll File von der Community über die Patches/Mods geschrieben wurde. Ich glaube nicht, dass Xardas im Standard Spiel Beschörungszauber sprechen konnte.

    Ich wollte auch wissen, ob die Funktion irgendwo reingehooked wurde, um wie ich es verstanden habe pro Tickrate (oder halt per Aufruf) den Zauber auszuwählen.

    Ich hatte ja wie schon ober erwähnt die Idee gehabt, neue NPC Klassen anzulegen, doch damit muss ich wissen wie genau diese Funktion mit eingebracht wird. Es ist mir bestimmt möglich nach ner Weile das herauszufinden, falls du es aber schon hast wäre es cool mit hierbei zu helfe

    Damit müsste ich zu allen Klassen mit mage auf diese Funktion mit den anderen auch herein. Dann müsste ich nur noch in der MageSelectSpell die einen switch mit NPC-classen einbauen


    Ich muss mir auch noch klar machen, wie ich mit dem SDK richitg reinhooke

  6. Beiträge anzeigen #6 Zitieren
    Moderator Avatar von George
    Registriert seit
    Sep 2010
    Beiträge
    684
     
    George ist offline
    Zitat Zitat von Jackydima Beitrag anzeigen
    Ah verstehe. Ja den Funktionscode habe ich nun fast vollkommen verstanden. Ich habe mich nur gewundert, ob diese Script_Game.dll File von der Community über die Patches/Mods geschrieben wurde. Ich glaube nicht, dass Xardas im Standard Spiel Beschörungszauber sprechen konnte.
    Gut möglich, dass die Beschwörungszauber einer der Community Patches eingebaut hat.

    Zitat Zitat von Jackydima Beitrag anzeigen
    Ich wollte auch wissen, ob die Funktion irgendwo reingehooked wurde, um wie ich es verstanden habe pro Tickrate (oder halt per Aufruf) den Zauber auszuwählen.
    Die Funktion wird vom Spiel immer dann aufgerufen, wenn ein NPC Magie wirken möchte. Die Entscheidung ob Magie oder eine andere Art Waffe verwendet werden soll passiert an anderer Stelle.
    Beteiligt ist dabei die Funktion "GetIntendedWeaponCategory" an Script_Game RVA 0x4A030. Dieser wird aus der gleichen Funktion wie MageSelectSpell aufgerufen, nämlich AI_SelectWeapon.


    Zitat Zitat von Jackydima Beitrag anzeigen
    Ich hatte ja wie schon ober erwähnt die Idee gehabt, neue NPC Klassen anzulegen, doch damit muss ich wissen wie genau diese Funktion mit eingebracht wird. Es ist mir bestimmt möglich nach ner Weile das herauszufinden, falls du es aber schon hast wäre es cool mit hierbei zu helfe

    Damit müsste ich zu allen Klassen mit mage auf diese Funktion mit den anderen auch herein. Dann müsste ich nur noch in der MageSelectSpell die einen switch mit NPC-classen einbauen
    Dafür eine neue NPC-Klasse nutzen zu wollen ist vermutlich keine gute Idee (ich nehme an du meinst PSNpc::PropertyClass).
    Daran hängt nämlich noch viel mehr als nur die Entscheidung welche Waffe genutzt wird.
    D.h. wenn du hier einen neuen Wert einführst müsstest du an ganz vielen Stellen Behandlung für diesen einbauen.

    Meiner Erfahrung bieten sich hier andere Wege eher an. Könntest es z.B. über den Namen des NPCs machen, z.B. wenn der ein Signalwort enthält.
    Problem ist da aber, dass du dann auch einen neuen Eintrag in der Stringtable für diesen veränderten Namen eintragen musst, weil der NPC sonst keinen Fokusnamen hat.

    Alternativ könntest du die Eigenschaft Description in gCNPC_PS verwenden. Das ist ein Textfeld, dessen Inhalt soweit ich weiß für nichts verwendet wird.

    Oder du verwendest die TreasureSets eines NPCs als Indikator welche(n) Zauber er nutzen soll.

    Fürs Community Story Project habe ich es über den Namen von TreasureSet5 gelöst:
    Individuelle Zauber für Magierarten

    Über den Namen des TreasureSet5 wird entschieden, was für einen Zauber ein NPC verwendet.

    Es wird überprüft, ob der Name des TreasureSet5 folgendes enthält:

    IsFiremage: It_Spell_Fireball wird verwendet
    IsWatermage: It_Spell_Icelance wird verwendet
    IsBlackmage: It_Spell_Lightningbolt wird verwendet

    Wenn keines der drei enthalten ist, wird It_Spell_Fireball verwendet.

    Es wurden drei Dummy-TreasureSets erstellt, die genau diese Namen haben, aber keine Items enthalten.
    Diese könnt ihr in TreasureSet5 eintragen, wenn ein NPC über weniger als fünf TreasureSets verfügt.

    Wenn der fünfte Slot schon belegt ist, müsst ihr ein neues TreasureSet erstellen, welches mit dem alten von den Eigenschaften übereinstimmt, aber zusätzlich eines der oben genannten Schlüsselwörter im Namen hat.
    Hier die DummyTreasureSets.zip von denen in der Dokumentation gesprochen wird, es ist notwendig diese in seinem Gothic 3 Datenverzeichnis zu haben.

    Code:
    #include "util/Hook.h"
    #include "util/Memory.h"
    #include "util/ScriptUtil.h"
    #include "util/Util.h"
    
    namespace
    {
        bCString GetSpell(Entity const & a_Mage)
        {
            bCString treasureSetName = a_Mage.Inventory.GetTreasureSet5().GetName();
            if(treasureSetName.Contains("IsFiremage"))
                return "It_Spell_Fireball";
    
            if(treasureSetName.Contains("IsWatermage"))
                return "It_Spell_Icelance";
    
            if(treasureSetName.Contains("IsBlackmage"))
                return "It_Spell_Lightningbolt";
    
            return "It_Spell_Fireball";
        }
    
        bCString GetSummonerSpell(Entity const & a_Mage)
        {
            bCString strName = a_Mage.GetName();
    
            if(strName == "Xardas")
                return "It_Spell_ArmyOfDarkness";
    
            if(strName == "Tizgar" || strName == "Grok")
                return "It_Spell_SummonDemon";
    
            if(strName == "Ningal")
                return "It_Spell_SummonSkeleton";
    
            if(strName == "Runak")
                return "It_Spell_SummonMonster";
    
            if (strName == "Saturas")
                return "It_Spell_SummonGolem";
    
            return "";
        }
    
        GEBool GE_STDCALL CanSummonCreatures(Entity a_Entity)
        {
            eSSetupEngine const & EngineSetup = eCApplication::GetInstance().GetEngineSetup();
            if(!EngineSetup.AlternativeBalancing || !EngineSetup.AlternativeAI)
                return GEFalse;
    
            if(!a_Entity.NPC.GetCurrentTarget().IsPlayer())
                return GEFalse;
    
            if(a_Entity.Party.GetMembers(GEFalse).GetCount() > 0)
                return GEFalse;
    
            bCString entityName = a_Entity.GetName();
            if(entityName == "Xardas" || entityName == "Grok" || entityName == "Ningal" || entityName == "Tizgar" || entityName == "Saturas" || entityName == "Runak")
                return GETrue;
    
            return GEFalse;
        }
    
        void GE_STDCALL MageSelectWeapon(Entity & a_Mage, GEInt & o_iLeftHandIndex, GEInt & o_iRightHandIndex)
        {
            o_iLeftHandIndex = o_iRightHandIndex = -1;
    
            // Gewisse Magier können Kreaturen beschwören
            if(CanSummonCreatures(a_Mage))
            {
                bCString strSummonerSpell = GetSummonerSpell(a_Mage);
                Template SummonerSpell = Template(strSummonerSpell);
                if(SummonerSpell.IsValid())
                {
                    o_iRightHandIndex = a_Mage.Inventory.AssureItems(SummonerSpell, 0, 1);
                    return;
                }
            }
    
            bCString strSpell;
            switch(a_Mage.NPC.Species)
            {
                case gESpecies_FireGolem:
                case gESpecies_Dragon:
                    strSpell = "It_Spell_Fireball";
                    break;
                case gESpecies_IceGolem:
                    strSpell = "It_Spell_Icelance";
                    break;
                case gESpecies_Goblin:
                    strSpell = "It_Spell_Fireball";
                    break;
                default:
                    if(AI_Memory::GetHitPointsPercent(a_Mage) < 40 && Entity::GetRandomNumber(100) < 50)
                        strSpell = "It_Spell_Healing";
                    else
                        strSpell = GetSpell(a_Mage);
            }
    
            o_iRightHandIndex = a_Mage.Inventory.AssureItems(Template(strSpell), 0, 1);
    
        }
    }
    
    /*
        Individuelle Zauber für Magier
    */
    void ApplyHooks
    {
        static mCFunctionHook Hook_CanSummonCreatures;
        Hook_CanSummonCreatures.Hook(RVA_ScriptGame(0x4A370), &CanSummonCreatures);
    
        static mCFunctionHook Hook_MageSelectWeapon;
        Hook_MageSelectWeapon
            .Prepare(RVA_ScriptGame(0x49890), &MageSelectWeapon)
            .AddRegArg(mCRegisterBase::mERegisterType_Ecx) // Entity & a_Mage
            .AddRegArg(mCRegisterBase::mERegisterType_Eax) // GEInt & o_iLeftHandIndex
            .AddRegArg(mCRegisterBase::mERegisterType_Edi) // GEInt & o_iRightHandIndex
            .Hook();
    }

  7. Beiträge anzeigen #7 Zitieren
    Waldläufer
    Registriert seit
    May 2022
    Beiträge
    123
     
    Jackydima ist offline
    Zitat Zitat von George
    Die Funktion wird vom Spiel immer dann aufgerufen, wenn ein NPC Magie wirken möchte. Die Entscheidung ob Magie oder eine andere Art Waffe verwendet werden soll passiert an anderer Stelle.
    Beteiligt ist dabei die Funktion "GetIntendedWeaponCategory" an Script_Game RVA 0x4A030. Dieser wird aus der gleichen Funktion wie MageSelectSpell aufgerufen, nämlich AI_SelectWeapon.
    Hallo George, danke dir nochmals, ich war noch unterwegs, und habe es auch gefunden tatsächlich

    Zitat Zitat von George
    Dafür eine neue NPC-Klasse nutzen zu wollen ist vermutlich keine gute Idee (ich nehme an du meinst PSNpc::PropertyClass).
    Daran hängt nämlich noch viel mehr als nur die Entscheidung welche Waffe genutzt wird.
    D.h. wenn du hier einen neuen Wert einführst müsstest du an ganz vielen Stellen Behandlung für diesen einbauen.

    Meiner Erfahrung bieten sich hier andere Wege eher an. Könntest es z.B. über den Namen des NPCs machen, z.B. wenn der ein Signalwort enthält.
    Problem ist da aber, dass du dann auch einen neuen Eintrag in der Stringtable für diesen veränderten Namen eintragen musst, weil der NPC sonst keinen Fokusnamen hat.

    Alternativ könntest du die Eigenschaft Description in gCNPC_PS verwenden. Das ist ein Textfeld, dessen Inhalt soweit ich weiß für nichts verwendet wird.

    Oder du verwendest die TreasureSets eines NPCs als Indikator welche(n) Zauber er nutzen soll.

    Fürs Community Story Project habe ich es über den Namen von TreasureSet5 gelöst:


    Das mit dem TreasureSet finde ich tatsächlich eine gute Idee. Ich hatte auch schon in Erwähnung gezogen das Description Feld dafür zu verwenden, wollte aber etwas semantisch passendes wählen wie eine NPC-Klasse. Aber der Gedanke, dass es doch nur die Klasse ge_Class_Mage gibt, dafür aber unterschiedliche verpackte "Items" für unterschiedliche Magier gibt ist sehr gut. Macht auch Sinn eventuell für bestimmte Magier besondere Zauber zu geben, die unter geringen Wahrscheinlichkeiten benutzt werden. (Saturas könne unter kleinen Bedingungen eine Frostwave oder Ähnliches zaubern als Beispiel)

    Zitat Zitat von George
    Hier die Anhang 52372 von denen in der Dokumentation gesprochen wird, es ist notwendig diese in seinem Gothic 3 Datenverzeichnis zu haben.

    Danke dafür, ja sieht gut aus, sieht so aus wie die MageSelectSpell mit den richtigen Anpassungen I

    Ich habe es davor nochmals probiert mit Klassen, in dem Ich die Funktion selber nochmals angefasst habe. Das war bevor ich deine Nachricht gelesen habe. Habe bei der Logic der Funktion darüber, die entscheidet ob Spells verwendet werden davor auch den Enum Value 3 für die lehren Klassen mit Enum-Value 5,6,7 ergänzt. Hat auch gut funktioniert. Jedoch heilt sich der Magier nicht, wenn er außerhalb des Kampfes ist, da dies an einer anderen Stelle nur für ge_Class_Mage funktioniert. Das ist auch das was du gemeint hast, dass es auch wo anders verwendet wird. Wird es sonst noch wo anders verwendet eigentlich, wo es relevant ist? Sonst kann ich den Versuch zusammenmixen.

    Weiß du auch, warum der Blitzschlag bei NPC so RIESEN Effekte schmeißt. Deshalb hat den auch niemand im Spiel eingebaut bisher hahaha. Hast du das im Story Project fixen können?

    LG
    Jackydima

  8. Beiträge anzeigen #8 Zitieren
    Moderator Avatar von George
    Registriert seit
    Sep 2010
    Beiträge
    684
     
    George ist offline
    Zitat Zitat von Jackydima Beitrag anzeigen
    Weiß du auch, warum der Blitzschlag bei NPC so RIESEN Effekte schmeißt. Deshalb hat den auch niemand im Spiel eingebaut bisher hahaha. Hast du das im Story Project fixen können?
    Mhm, keine Ahnung ehrlich gesagt, kann mich zumindest nicht daran erinnern

  9. Beiträge anzeigen #9 Zitieren
    Waldläufer
    Registriert seit
    May 2022
    Beiträge
    123
     
    Jackydima ist offline
    Zitat Zitat von George Beitrag anzeigen
    Mhm, keine Ahnung ehrlich gesagt, kann mich zumindest nicht daran erinnern
    Ja das Problem war, dass der NPC der Blitzschlag nutzte große geglitchte Blitzeffekte erzeugt hat, doe immer größer wurden.

  10. Beiträge anzeigen #10 Zitieren
    Waldläufer
    Registriert seit
    May 2022
    Beiträge
    123
     
    Jackydima ist offline
    Zitat Zitat von George Beitrag anzeigen
    Mhm, keine Ahnung ehrlich gesagt, kann mich zumindest nicht daran erinnern
    So nun bin ich zu Hause und konnte ein paar Screenshots machen, so sieht das aus

    Imgur link:
    https://imgur.com/a/FUJX1VI

    [Bild: FUJX1VI]

  11. Beiträge anzeigen #11 Zitieren
    Adventurer
    Registriert seit
    Jun 2023
    Beiträge
    59
     
    Giovani goth ist offline
    Hallo, ich bin kein Informatiker, würde aber trotzdem gerne die Zaubersprüche der NPCs ändern. Ich habe versucht, It_Spell_Lightningbolt in eine der TPL-Dateien einzufügen. zum Inventar des NPCs. Aber es funktioniert nicht. Gibt es eine andere Möglichkeit, die Zauber zu ändern? wie Infodateien.?

  12. Beiträge anzeigen #12 Zitieren
    Waldläufer
    Registriert seit
    May 2022
    Beiträge
    123
     
    Jackydima ist offline
    Zitat Zitat von Giovani goth Beitrag anzeigen
    Hallo, ich bin kein Informatiker, würde aber trotzdem gerne die Zaubersprüche der NPCs ändern. Ich habe versucht, It_Spell_Lightningbolt in eine der TPL-Dateien einzufügen. zum Inventar des NPCs. Aber es funktioniert nicht. Gibt es eine andere Möglichkeit, die Zauber zu ändern? wie Infodateien.?
    Jo, der George hat das schon oben beantwortet. Du muss dafür etwas Wissen in Reverse Engineering haben und auch gute C++ / Assembly Kenntnisse haben...

    Aber hier ist das wichtige:

    Zitat Zitat von George
    Ist möglich mit dem Gothic 3 SDK. Relevant sollte hierbei eigentlich nur die Script_Game.dll sein.Insbesondere eine Funktion, ich habe sie bei mir MageSelectSpell genannt, du findest sie an RVA 0x49890 in der Script_Game.dll.
    Dort wird entscheiden welchen Spell ein NPC verwendet.
    Heiß du muss die Logik hierbei ändern an den gewollten Stellen. Hierbei einen bCString verwenden der It_Spell_Lightningbolt beinhaltet für die Inventory.AssureItems() Funktion und den zurückgegebenen Indexwert in das Register edi packen beim returnen.

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