[Tutorial] Moddingerfahrungen - Tricks und Kniffe

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Transactions: Reihenfolge muss beachtet werde Teil 2: Actions, die nur am Anfang der Liste ausgeführt werden

Weiter oben hatte ich schon mal geschrieben, dass es Aktionen gibt, die am Ende der Transaction-Liste stehen müssen - weil sonst dahinter befindliche Aktionen nicht mehr ausgeführt werden. Dazu gehören JoinParty(), LeaveParty(), MoveToArea(), EscapeAreaMove().

Es gibt aber auch Aktionen die dürfen nicht am Ende der Transaktions-Liste stehen, sonst werden sie schlichtweg nicht ausgeführt. Dazu gehört GiveItemCreate().

In folgender Riehenfolge wird kein Gegenstand übergeben:
Code:
DO ~ActionOverride("C#Q01004",TakePartyGold(20))
SetGlobal("C#Q01_TalkedToTulbor","GLOBAL",2)
SetGlobal("C#Q01_BoughtAlternative","GLOBAL",1)
GiveItemCreate("C#Q01004",[PC],1,0,0) //wird hier NICHT ausgeführt!
~ GOTO 27

Der Gegenstand wird nur übergeben, wenn die Aktion GiveItemCreate() weiter vorne steht:

Code:
DO ~ActionOverride("C#Q01004",TakePartyGold(20))
GiveItemCreate("C#Q01004",[PC],1,0,0) //so wird es ausgeführt
SetGlobal("C#Q01_TalkedToTulbor","GLOBAL",2)
SetGlobal("C#Q01_BoughtAlternative","GLOBAL",1)
~ GOTO 27

(Dies gilt erstmal vor allem für die EE, ob es dieses Problem auch in der alten Engine gab, weiß ich nicht.)
 
Zuletzt bearbeitet:

Acifer

Senior Member
Registriert
27.04.2019
Beiträge
1.051
Es ist ja sowohl möglich, Scripte über das Cre-File als auch über das Are-File den Kreaturen zuzuordnen. Was ich bisher nicht wusste, war, dass die im are-File angegebenen Scripte die Scripte im cre-file "overriden". Das bedeutet z.B., wenn im cre-file das Override-Script "SHOUTDLG" zugewiesen ist, im are-file aber nicht, wird der Dialog nicht gestartet.
Normalerweise ist das kein Problem, wenn die Kreaturen einfach in der Area platziert werden.
Dann zählt das Script aus dem cre-file und alles läuft problemlos.

Aber:

Falls jemand außer mir noch den DLTCEP fürs Area-Editing verwendet, spielt das schon eine gewisse Rolle. Dort gibt es im "Actor"-Header den Button "refresh fields", der mit einem Knopfdruck alle Scripte aller Kreaturen im Area-Bereich updatet. Praktisch, um dort zu sehen, welche Scripte den Kreaturen zugewiesen wurden. Unpraktisch, wenn man im Nachhinein ein Script einer Kreatur ändert. Dann läuft in der Area nämlich noch das "alte" Cre-File-Script ab. Die Lösung ist einfach: Einfach wieder "refresh fields" drücken.

Ich bin vorhin fast verzweifelt, weil ein Dialog nicht losgegangen ist, obwohl im cre-File alles richtig war. Aber eben nicht in der Area, in der die Kreatur platziert wurde.
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Sehr guter Hinweis! Das ist einem beim normalen Modden echt nicht klar.
 

Acifer

Senior Member
Registriert
27.04.2019
Beiträge
1.051
Danke! Vielleicht eine etwas doofe Frage, aber:
Gibt es eigentlich Erfahrungen, einem gleichen cre-file im Area-Actor-Header unterschiedliche Scripte zuzuweisen? Ich bin bisher immer den dilettantischen Weg gegangen und habe dafür unterschiedliche cre-files erstellt, weil ich die Befürchtung hatte, dass es sonst Chaos gibt.
So könnte man ja z.B. ein Wolf-cre-file erstellen, 20 Wölfe in die Area setzen und jedem Wolf unterschiedliche Scripte (und Dialoge?) zuweisen. Nur die DeathVariable bliebe immer gleich. Funktioniert das zuverlässig?
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Ich vermute schon. Hast Du mal nach Beispielen in den Originalareas geschaut?
Man kann übrigens über die area auch Deathvariables zuweisen, die die in der cre überschreiben. Ich hatte das letzthin im Originalspiel gesehen, aber vergessen, wo. War glaube ich in der EE von daher weiß ich nicht, ob es auch im Originalspiel ging.
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Das mit der Deathvariablen hat mich fast zum Verzweifeln gebracht, weil ich esnlange nicht verstanden habe, was da abgeht. Wenn ich mich wieder erinnere wo.das war, sage ich bescheid.
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Meine unsichtbare Helfer-Kreatur startet den Dialog nicht!

Unsichtbare Kreaturen kann man als Helferlein einsetzen, z.B. wenn der Spieler mit einem Gegenstand interagieren können soll. Dabei ist zu beachten, dass nicht alle unsichtbaren Kreaturen einen Dialog starten können. Ich glaube, die kreatur darf nicht "Disbale Creature(271)" als effekt haben. Invisibility und Remove feef circle(287) sollten gehen.
Es ist jedenfalls ein Tipp an den man denken kann, wenn das Starten des Dialogs über die unsichtbare Kreatur einfach nicht klappen will. Daneben gibt es noch die Standardsachen wie: hat die cre die richtige Skriptvariable und Dialog- und Skriptfile zugewiesen etc.

Auch ganz wichtig: in der alten Engine konnten zu viele unsichtbare Kreaturen zu Problemen führen. Wenn sie z.B. auch Remove Fog of War als Effekt hatten, dann kann es zu Problemen führen, da die Engine nur 8 Kreaturen mit dieser Eigenschaft pro Area berücksichtigt - davon sind die Gruppe mit HC bereits 6. Werden es mehr als 8, dann versagt der RFW bei einigen, was z.B. zu "schwarzen" Cutscenes führen kann. Soweit ich weiß, besteht dieses Problem in der EE weiterhin. Daher unsichtbare Helferkreaturen nach dem Dienst immer über DestroySelf() wieder verschwinden lassen.
 
Zuletzt bearbeitet:

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
EE Modding: was tun, wenn der NPC "Invalid" Referenzen im Textfenster ausgibt

In der EE erhält man plötzlich aus dem "Nichts" im Dialogfenster die Nachricht, dass ein NPC was sagen wollte aber alles was da steht ist "NPC XY: Invalid"? Ohne dass ein Dialogfenster aufpoppen würde oder der NPC so aussah, als hätte er was sagen wollen.
Dann handelt es sich um eine ungültige der cre-Datei zugewiesene Soundreferenz. Hier ein Beispiel:
blacksmith_soundref.jpg

Wie zu sehen, ist die Soundreferenz Nummer "2147483647" zugewiesen. Diese gibt es nicht. Die alte Engine hat diese Einträge ignoriert. Die EE tut das nicht, und meldet gehorsam: "Invalid", also ungültig!

Um das zu verhindern, müssen alle nichtgewollten Soundrefs die Zahl -1 zugewiesen bekommen. Dann passiert das nicht. Leider kann man über den angezeigten Eintrag "No such index" nicht sehen, ob die gewollte -1 oder eine "zu hohe" Zahl dort steht, so dass man alle Soundreferenzen von Hand durchgehen und ändern muss. Um das zu tun, einfach im Feld "StringRef:" die -1 eintragen und über den Knopf "Update value" diesen Wert zuweisen.
Wie gesagt muss man das leider für alle Soundreferenzen einzeln machen. Also der Tipp: am besten gleich mit einer "unverseuchten" cre-Datei starten! ;)
 
Zuletzt bearbeitet:

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Modding Imoen im Irenicus Dungeon: Unterschiede zwischen den BGII-Spielen

Es gibt ja mittlerweile diverse BGII-Spiele: BGII original, BGT, BGII:EE und EET. Imoen hat durch ihre besondere Stellung im Spiel und dem Umstand, dass die Entwickler ihr leider unterschiedliche Death Varibalen innerhalb und außerhalb vom ID gegeben haben aber dies für BGT und EET für die Kontinuität vereinheitlicht werden muss eine besondere Stellung in der Komplexität der Dateien und Namen, die verwendet werden müssen, um für sie Inhalte in Ireniucs Dungeon einzufügen.

Sobald der ID verlassen ist, gilt für alle Spiele:
Imoen Death Variable = Imoen2
Imoen Joined Dialoge = Imoen2J.dlg
Imoen Kickout Dialoge = Imoen2P.dlg
Imoens Override Skript = Imoen2.bcs
Dream Skript = Imoen2D.bcs

Aber innrhalb von Irenicus Dungeon gilt folgende Konstellation:
Imoens Override Skript im ID ist in allen Spielen Imoen.bcs. Ansonsten:

BGII und BGII:EE:
Imoen Death Variable = Imoen --> Imoen nach dem ID ist eine andere
Imoen Joined Dialoge = ImoenJ.dlg
Imoen Kickout Dialoge = ImoenP.dlg
Dream Skript = ImoenD.bcs

BGT:
Imoen Death Variable = Imoen2 --> vereinheitlicht über das ganze Spiel
Imoen Joined Dialoge = Imoen2J.dlg --> Inhalte aus ID sind an das Ende der dlg für "draußen" angehängt. Achtung! Dadurch verschieben sich die Statenummern für Imoens Dialoge innerhalbdes ID, s.u.!
Imoen Kickout Dialoge = Imoen2P.dlg --> Inhalte aus ID sind an das Ende der dlg für "draußen" angehängt. Achtung! Dadurch verschieben sich die Statenummern für Imoens Dialoge innerhalbdes ID, s.u.!
Dream Skript = Imoen2D.bcs --> vereinheitlicht über das ganze Spiel

EET:
Imoen Death Variable = Imoen2 --> vereinheitlicht über das ganze Spiel
Imoen Joined Dialoge = ImoenJ.dlg --> wird dann von der EET_End.exe mit imoen2J.dlg fürs Spielen vereint, aber zum Modden muss dieser verwendet werden.
Imoen Kickout Dialoge = ImoenP.dlg --> wird dann von der EET_End.exe mit imoen2P.dlg fürs Spielen vereint, aber zum Modden muss dieser verwendet werden.
Dream Skript = Imoen2D.bcs --> vereinheitlicht über das ganze Spiel

Um nun Inhalte für Imoen in ID einzufügen und eine Verdopplung gleicher Dateien zu umgehen, kann hier ganz einfach mit defnierten Variablen gearbeitet werden.
Für Imoens Death Variable in ID z.B. die %ImoenDV_ID%, Imoens Joined Dialog in ID die %IMOENJ_ID%, Imoens Kickout Dialoge in ID die %IMOENP_ID%, für Imoens Dream Skript die %IMOEND_ID%.
Dann fügt man z.B. in der tp2 in den ALWAYS Block das folgende ein:
Code:
/* Imoen in ID! */

ACTION_IF GAME_IS "tob bg2ee" AND !GAME_IS "bgt" BEGIN
  OUTER_SPRINT ~ImoenDV_ID~ ~imoen~
  OUTER_SPRINT ~IMOENJ_ID~ ~imoenj~
  OUTER_SPRINT ~IMOENP_ID~ ~imoenp~
  OUTER_SPRINT ~IMOEND_ID~ ~imoend~
END

ACTION_IF GAME_IS ~bgt~ THEN BEGIN
  OUTER_SPRINT ~ImoenDV_ID~ ~imoen2~
  OUTER_SPRINT ~IMOENJ_ID~ ~imoen2j~
  OUTER_SPRINT ~IMOENP_ID~ ~imoen2p~
  OUTER_SPRINT ~IMOEND_ID~ ~imoen2d~
END

ACTION_IF GAME_IS "eet" BEGIN
  OUTER_SPRINT ~ImoenDV_ID~ ~imoen2~
  OUTER_SPRINT ~IMOENJ_ID~ ~imoenj~
  OUTER_SPRINT ~IMOENP_ID~ ~imoenp~
  OUTER_SPRINT ~IMOEND_ID~ ~imoen2d~
END
Und schwupps, muss man sich um nichts mehr kümmern und Imoen spricht in allen Spielen in ID wie sie soll. Jedoch gilt noch folgendes zu beachten:

Achtung! Dadurch, dass BGT die Dialogstates aus ID an die Dialoge von "außerhalb" anhängt, habe diese in BGT andere Nummern als im original BGII-Dialog.
So ist z.B. der erste Dialog von Imoen in ID in BGII, BGII:EE und EET der State "0" in ImoenJ.dlg. In BGT ist es jedoch die "48" in der Imoen2J.dlg.
Der erste Kickout-Dialog-State in ID ist in BGII, BGII:EE und EET der State "0" in ImoenP.dlg. In BGT ist es jedoch die "12" in der Imoen2P.dlg.

Breagar hat z.B. einen Einmischdialog, wenn Imoen eine Bemerkung zu den Duergar in der Schmiede macht. Der Dialogstate, bei dem das stattfinden soll, ist im Original die "26":
IF ~~ THEN BEGIN 26 // from: 59.0
SAY #38628 /* ~Duergar, I think. Kind of evil, I guess, so I'm not surprised they would be working for our captor.~ */
IF ~~ THEN REPLY #38629 /* ~Quite the little setup down here. Got everything he needs, including smiths.~ */ DO ~SetGlobal("ImoenIlyich","LOCALS",2)
~ GOTO 27
IF ~~ THEN REPLY #38630 /* ~He tolerates some company, or are they little more than skilled packhorses to him?~ */ DO ~SetGlobal("ImoenIlyich","LOCALS",2)
~ GOTO 28
END

In BGT, dies ist dann entsprechend die "74". Gelöst habe ich auch das über die Verwendung von entsprechend definierten Variablen:
Code:
ACTION_IF GAME_IS "tob bg2ee" AND !GAME_IS "bgt" BEGIN
  OUTER_SPRINT ~IMOENJ_ID_STATE26~ ~26~
END

ACTION_IF GAME_IS ~bgt~ THEN BEGIN
  OUTER_SPRINT ~IMOENJ_ID_STATE26~ ~74~
END

ACTION_IF GAME_IS "eet" BEGIN
  OUTER_SPRINT ~IMOENJ_ID_STATE26~ ~26~
END

In meinem .d-File verwende ich dann ganz einfach %IMOENJ_ID_STATE26% anstelle der Zahl, und der richtige State wird gepatcht:
Code:
INTERJECT_COPY_TRANS %IMOENJ_ID% %IMOENJ_ID_STATE26% ACIMOEN2J74
==ACBREB IF ~InParty("ACBRE")InMyArea("ACBRE")!StateCheck("ACBRE",CD_STATE_NOTVALID)~ THEN
@128
==%IMOENJ_ID% IF ~InParty("ACBRE")InMyArea("ACBRE")!StateCheck("ACBRE",CD_STATE_NOTVALID)~ THEN
@129
==ACBREB IF ~InParty("ACBRE")InMyArea("ACBRE")!StateCheck("ACBRE",CD_STATE_NOTVALID)~ THEN
@130
==%IMOENJ_ID% IF ~InParty("ACBRE")InMyArea("ACBRE")!StateCheck("ACBRE",CD_STATE_NOTVALID)~ THEN
@131
END
 
Zuletzt bearbeitet:

Acifer

Senior Member
Registriert
27.04.2019
Beiträge
1.051
Dass Sound-Dateien einer Area für die klassische BG(2)-Installation in den override-Ordner kopiert werden müssen, dürfte mittlerweile allgemein bekannt sein.

Was ich nicht wusste, ist, dass dies auch für einige Sounds gilt, die per Script mittels PlaySound("...") angetriggert werden sollen. Befindet sich die wav(c)-Datei noch in einem Biff-Ordner, stürzt das Spiel ab, wenn der Scriptblock gestartet wird.
Dann gilt auch hier, zunächst die Sounddatei mittels COPY_EXISTING in den Override-Ordner zu verschieben.
Ich hatte mich gestern über merkwürdige Abstürze gewundert, die ich mir nicht erklären konnte. Ursache war dieser besagte Skriptblock.
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Danke, das ist gut zu wissen!
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Namensgebung in der IE - Anzahl an Zeichen für Datei- und Variablennamen ist begrenzt

In der IE müssen folgende Zeichenlängen beachtet werden:

-Dateinamen dürfen nicht länger als 8 Zeichen sein. Dies gilt ausnahmslos für dlg, bcs, are*, bmp, cre, spl, etc.
* are im Grunde sogar nur 6 Zeichen, da entsprechend noch die Search Map, Height Map und Light Map als xx.bmp dazukommen.

-die death Varibalen (Skriptname) der cre darf nicht länger als 32 Zeichen sein

-globale Variablen dürfen nicht länger als 32 Zeichen sein

-lokale Variablen dürfen nicht länger ais 26 zeichen sein

Was passiert, wenn diese Längen überschritten werden ist, dass die Variablen / files im Spiel nicht mehr erkannt werden, d.h. Skripte werden nicht verwendet, die Abfrage von Variablen funktioniert nicht etc.
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
MoveBetweenAreas() verschiebt Charaktere in derselben Area nur bis die Gruppe einmal rastet

Ihr habt einen Questcharater, der über CreateCreature() in einer Area gespwnt wurde.
Wenn Ihr diesen Charakter nun in dieser Area auf einen anderen Platz stellen wollt, und der da bleiben soll, dann dürft Ihr nicht MoveBetweenAreas() dafür verwenden: wird dieser Befehl verwendet, dann befindet sich der Charakter, nachdem die Gruppe einmal gerastet hat, wieder auf dem Platz, wo er ursprünglich stand.
Soll er auf dem neuen PLatz bleiben, dann könnt Ihr z.B. EscapeAreaMove() verwenden. EDIT: das scheint auch nicht zu funktionieren.

Andersrum geht es natürlich auch: wenn Ihr wollt, dass Euer Charakter auf dem neuen Platz nur solange bleibt, bis der Hc einmal gerastet hat und dann wieder auf dem alten PLatz steht, dann verwendet MoveBetweenAreas().
 
Zuletzt bearbeitet:

Maus

Senior Member
Registriert
07.08.2002
Beiträge
7.184

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Hö, das zweite sollte natürlich EscapeAreaMove() sein! Danke, korrigiert.
 

Acifer

Senior Member
Registriert
27.04.2019
Beiträge
1.051
Der Befehl CloseDoor(O:Object*) funktioniert in Area-Scripts nicht, wenn sich eine Kreatur (PC oder NPC) nur einen Bruchteil über einem Bereich befindet, der im closed-door-Zustand als „impassable“ markiert ist. Dann schließt die Tür nicht und das Script wird teilweise nicht richtig ausgeführt bzw. bleibt in diesem Script-Block hängen, was auch Auswirkungen auf die Befehle nach „CloseDoor“ hat, die teilweise ebenfalls nicht ausgeführt werden.
Die Lösung: Darauf achten, dass sich keine Kreatur über einem Bereich in der Area befindet, der durch eine Tür beeinflusst wird.
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Ein Fund durch Trial and Error:
Es scheint so zu sein, dass eine Kreatur wenn sie in einer Area erzeugt wird in der.are-Datei im Save mit diesen Koordinaten als "Ziel"koordinaten eingetragen wird. Sprich, wenn man rastet und wiederkommt oder lange weg war etc, dann steht die Kreatur wieder auf diesen Koordinaten, auf denen sie das erste mal erzeugt wurde (per Skript oder per AreaMove - bis auf "MoveToPointNoInterrupt" wie von Acifer hier erwähnt) - auch wenn sie in der Zwischenzeit durch einen Befehl in der Area woanders hinbewegt wurde. Das ist etwas ärgerlich aber wichtig zu wissen.
Ich versuche das in einer Mod zu umgehen, indem ich die Kreatur ganz verschwinden lasse über DestroySelf() und dann an der neuen Stelle neu erschaffe.
Eine andere prinzipielle "Lösung" hierzu wäre, die Kreatur erst an der späteren Stelle zu spawnen und sie dann für den kurzen Austausch zu Beginn zur ersten Stelle zu verschieben. Das ist natürlich nur dann eine Lösung, wenn die Kreatur nicht mehrere Tage an der ersten Stelle stehen bleiben soll, bevor sie woanders hin soll.
 
Zuletzt bearbeitet:

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
8.869
Der Befehl CloseDoor(O:Object*) funktioniert in Area-Scripts nicht, wenn sich eine Kreatur (PC oder NPC) nur einen Bruchteil über einem Bereich befindet, der im closed-door-Zustand als „impassable“ markiert ist.
Ich möchte nicht wissen, wie oft Du in die Tischkante gebissen hast, bis Du das rausgefunden hast. Weißt Du, ob das auch für das Öffnen von Türen gilt?
 

Acifer

Senior Member
Registriert
27.04.2019
Beiträge
1.051
Weißt Du, ob das auch für das Öffnen von Türen gilt?
Das weiß ich ehrlich gesagt nicht genau, schlechte Erfahrung hatte ich diesbezüglich noch nicht gemacht. Ich glaube, dabei werden die Kreaturen dann nur "beiseite geschoben".
Es scheint so zu sein, dass eine Kreatur wenn sie in einer Area erzeugt wird in der.are-Datei im Save mit diesen Koordinaten als "Ziel"koordinaten eingetragen wird. Sprich, wenn man rastet und wiederkommt oder lange weg war etc, dann steht die Kreatur wieder auf diesen Koordinaten, auf denen sie das erste mal erzeugt wurde (per Skript oder per AreaMove) - auch wenn sie in der Zwischenzeit durch einen Befehl in der Area woanders hinbewegt wurde.
Das überrascht mich. Bist Du Dir da sicher? Ich habe bisher die Erfahrung gemacht, dass die Kreatur durch "MoveToPointNoInterrupt" ständig und sicher am neuen Zielort bleibt. Lästig wird das nur, wenn der Spieler zwischendurch das Gebiet wechselt und die Kreatur noch nicht am Zielort angekommen ist. Dann scheint es nicht zu funktionieren.
Aber dass sie wieder auf den Ausgangspunkt zurückspringt habe ich noch nie erlebt.

EDIT: Es gibt einen Unterschied zwischen

207 MoveToPointNoInterrupt(P:Point*)
This action causes the active creature to move to the specified coordinates. The action will update the position of creatures as stored in ARE files (first by setting the coordinates of the destination point, then by setting the coordinates of the current point once the destination is reached). Conditions are not checked until the destination point is reached.


...und

208 MoveToObjectNoInterrupt(O:Object*)
This action instructs the active creature to move to the specified object. The action does not update the current position of the actor, saved in ARE files. Conditions are not checked until the destination point is reached.
 
Zuletzt bearbeitet:
Oben