[Modding] Scripting Fragen

Maus

Senior Member
Registriert
07.08.2002
Beiträge
10.337
Blöde Frage: brauchst du die "~" wenn du die Tilden schon in die Variable reingeschrieben hast?
 

Argent

Senior Member
Registriert
13.07.2010
Beiträge
535
READ_ASCII/WRITE_ASCII sollte als Längenangabe *immer* die Länge des Feldes beinhalten, und nicht die Länge des Strings, da es ansonsten zu undefiniertem Verhalten kommen kann (bei Resref-Feldern also immer #8).

Ansonsten schau dir mal die WeiDU-Funktion ALTER_AREA_ACTOR in den WeiDU Docs an. Diese Funktion sollte für deine Zwecke ausreichen.
 

Genwa

Betrachter
Registriert
08.01.2018
Beiträge
472
Blöde Frage: brauchst du die "~" wenn du die Tilden schon in die Variable reingeschrieben hast?
Wenn ich sie entferne, ändert sich zumindest nichts (weder positiv noch negativ)

READ_ASCII/WRITE_ASCII sollte als Längenangabe *immer* die Länge des Feldes beinhalten, und nicht die Länge des Strings, da es ansonsten zu undefiniertem Verhalten kommen kann (bei Resref-Feldern also immer #8).
Danke!
Ansonsten schau dir mal die WeiDU-Funktion ALTER_AREA_ACTOR in den WeiDU Docs an. Diese Funktion sollte für deine Zwecke ausreichen.
Dazu habe ich jetzt nur eine Anwenung bei "Kiara-Zaiya" gefunden.

Code:
ALTER_AREA_ACTOR AR0301
  actor_name = "ZAIYA"
  x_coord = 1000
  y_coord = 2000
  orientation = 2
  wander = 4
  follow = 5
  times_talked = 1
  script_override = "ZAIYASCRIPT"

Mein Einduck ist, dass der actor_name entscheidet, welche .cre überschrieben wird. Sprich in meinem Beispiel würde es gehen, da es nur einen Maevar in der area gibt, aber bei cre die es mehrfach gibt nicht. Dazu hatte ich den Part mit der Überprüfung der Position hinzugefügt.
 

Argent

Senior Member
Registriert
13.07.2010
Beiträge
535
Okay, in dem Fall gehen wir mal das Skript durch.

Code:
OUTER_SPRINT find_X_position ~968~
OUTER_SPRINT find_Y_position ~302~

OUTER_SPRINT all_values_found ~0~
Diesen Variablen werden numerische Werte zugewiesen. Daher wäre es besser, OUTER_SET zu verwenden. SPRINT funktioniert theoretisch auch, aber erzwingt intern eine String-to-Int Konvertierung, die nur unnötig Rechenleistung und Zeit benötigt.

Das eigentliche Problem sehe ich aber im weiteren Skriptcode. So, wie er definiert wurde, geht er jedes einzelne Byte aller Actor-Strukturen der Area durch und prüft auf bestimmte Werte. Das funktioniert so nicht, da dadurch irgendwelche Zufallswerte eingelesen werden, die auch mal zufälligerweise mit den Vergleichswerten identisch sein können. Und erst nachdem innere und äußere Schleifen vollständig durchlaufen wurden, schreibt WRITE_ASCII einen String an die Position, die durch "ofs" und "j" definiert wurden. Zu dem Zeitpunkt beinhaltet zumindest "j" einen ungültigen Wert und schreibt den Wert daher an eine zufällige Position.

Actor-Strukturen haben eine definierte Struktur. Wenn nur auf CRE resref und X/Y-Koordinaten geprüft werden soll, dann reicht dieser Code aus:
Code:
OUTER_SPRINT find_resref ~MAEVAR~
OUTER_SPRINT new_resref ~orc01~
OUTER_SET find_X_position = 968
OUTER_SET find_Y_position = 302

OUTER_SET all_values_found = 0

COPY_EXISTING ~AR0301.ARE~ ~override~
  READ_LONG 0x54 ofs_actors
  READ_SHORT 0x58 num_actors
  PATCH_PRINT ~Num Actors: %num_actors%~
 
  FOR (i = 0; i < num_actors && all_values_found = 0; ++i) BEGIN
    SET ofs = ofs_actors + i * 272
   
    // Read actor name
    READ_ASCII (ofs + 0x0000) actor_name (32) NULL
   
    // Output actor name and index
    PATCH_PRINT ~Actor Name: %actor_name%, Index: %i%~

    // Read actor cre resref and x/y coordinates
    READ_ASCII (ofs + 0x80) cre_resref (8)
    READ_SHORT (ofs + 0x20) pos_x
    READ_SHORT (ofs + 0x22) pos_y
    PATCH_IF (~%cre_resref%~ STR_EQ ~%find_resref%~ &&
              pos_x = find_X_position &&
              pos_y = find_Y_position) BEGIN
      PATCH_PRINT ~Treffer!~
      // Update cre resref
      WRITE_ASCIIE (ofs + 0x80) ~%new_resref%~ (8)
      SET all_values_found = 1
    END
  END
BUT_ONLY

Edit: "all_values_found"-Vergleich korrigiert ("!=" -> "=").
 
Zuletzt bearbeitet:

Genwa

Betrachter
Registriert
08.01.2018
Beiträge
472
Danke, für die Überarbeitung! Wenn ich die Überprüfung der resref (~%cre_resref%~ STR_EQ ~%find_resref%~) rausnehme läuft es.

Setze ich dazu diese Kontrolle ein:

Code:
    PATCH_IF ("%cre_resref%" STR_EQ %find_resref%) BEGIN
      PATCH_PRINT ~ResRef stimmt: %cre_resref% = %find_resref%~
    END ELSE BEGIN
      PATCH_PRINT ~ResRef stimmt nicht: %cre_resref% != %find_resref%~
    END

gibt er mir Folgendes aus:

"ResRef stimmt nicht: MAEVAR != MAEVAR"
 

Genwa

Betrachter
Registriert
08.01.2018
Beiträge
472
Stimmt, aber macht leider nicht den Unterschied :(. Ich werde noch mal etwas daran rumbasteln, wenndas nächste Wochenende kommt.
 

Maus

Senior Member
Registriert
07.08.2002
Beiträge
10.337
Weiß jemand, was das Object "StrongestOf" ist? Bspw. zu finden hier: Gnoll5.bcs im Kontext von HitBy(StrongestOf) und Dialogue(StrongestOf). Ich würde auf das Partymitglied mit der höchsten Stärke tippen, aber was, wenn da zwei dieselbe Stärke haben?
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
15.648
Die letzte Frage ist eine gute. Hast Du ins IESDP geschaut? Ich müsste da erstmal suchen, wo das erklärt wird (Wald und Bäume und so).
 

Maus

Senior Member
Registriert
07.08.2002
Beiträge
10.337
"5 StrongestOf
Returns the strongest player character (in the party)."

Hilft halt auch nicht, ob da wirklich Stärke gemeint ist.
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
15.648
Kann ich über Skript die "KI" abschalten?
Ich stelle mir das so vor: Eine erste Variable ist gesetzt.
Über die "dplayer2.bcs", die nur läuft, wenn der Spieler die "KI" Laterne an hat, wird eine zweite Variable gesetzt und die KI ausgemacht. Dann geschieht eine Szene.
Wenn diese fertig ist und die zweite Variable detektiert wird, wird über das Areascript die KI Laterne wieder angemacht.
Wenn die zweite Variable nicht gesetzt ist, geschieht nichts, KI war aus und bleibt aus.
 

Jastey

Matron Modderholic
Registriert
16.05.2004
Beiträge
15.648
OK, hat sich erledigt insofern, als dass ich statt CLERIC_RAISE_DEAD + CLERIC_HEAL gleich CLERIC_RESURRECTION verwende.
Da gibt es diesen Moment mit 1 HP nicht.
 
Oben