|
-
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
-
Zitat von Jackydima
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.
-
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.
-
Zitat von Jackydima
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).
-
Zitat von George
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
-
Zitat von Jackydima
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 von Jackydima
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 von Jackydima
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();
}
-
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 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 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
-
Zitat von Jackydima
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
-
Zitat von George
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.
-
-
Adventurer
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.?
-
Zitat von Giovani goth
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 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
|
|