[Editor1] Tingil's Scripting Thread

Tingil

Lord of the Links
Registriert
14.07.2000
Beiträge
7.884
Ich hab' mich 'mal in den 2DAs, auch im Override-Verzeichnis, umgesehen und auch nichts gefunden. Sieht so aus, als wäre die Datei, die ich suche, in irgendeiner BIF-Datei versteckt, aber leider kann das Bifftool, das für die Infinity-Spiele gedacht ist, diese BIFs nicht öffnen. Gibt es vielleicht ein extra Bifftool für Aurora Engine BIFs?
Ansonsten wird mir wohl wirklich nichts anderes übrig bleiben, als mich ('mal wieder :D) vertrauensvoll ans offizielle Scripting-Forum von BioWare zu wenden.

PS: Danke für den heißen Tip! Hab's hinbekommen. :)
 
Zuletzt bearbeitet:

Gags

Headhunter
Registriert
11.07.2000
Beiträge
1.487
Hallo

Ich habe auch mal eine Frage, weiss jemand wie man es möglich macht, das sich die Türen nachdem man sie geöffnet hat, selbsttätig schließen? :)

gruss Gags
 

Silpion

Traumtänzer
Registriert
10.04.2001
Beiträge
2.104
Im OnOpen ein Script hinterlegen, dass mit DelayCommand die Tür schließt. ;)

Ich kann heute abend auch nochmal das komplette Script tippen, hab jetzt leider keine Zeit.

Nachtrag:
Hier das Script, das ich zur Zeit verwende, einfach in das OnOpen-Event setzen.
Code:
void Close(){
  ClearAllActions();
  ActionCloseDoor(OBJECT_SELF);
}

void main(){
  DelayCommand(30.0, Close());
}
 
Zuletzt bearbeitet:

Gags

Headhunter
Registriert
11.07.2000
Beiträge
1.487
@Silpion

Danke für deine Hilfe. :)
 

Tingil

Lord of the Links
Registriert
14.07.2000
Beiträge
7.884
Kann mir jemand erklären, wie seit SoU Geheimtüren funktionieren? Irgendwie funktioniert das Ganze viel anders, als es bei den früheren Versionen der Fall war. Ich habe mir die Skripte und die entsprechende Include File einmal angesehen, aber so recht schlau werde ich daraus nicht.
Also: Was muß ich bei SoU machen, um in mein Modul eine funktionierende Geheimtür einzubauen?
 

Silpion

Traumtänzer
Registriert
10.04.2001
Beiträge
2.104
Ha, ich wusste doch, dass ich da irgendwas gesehen hatte.

http://nwn.bioware.com/forums/viewtopic.html?topic=225345&forum=46

Erklären kann ich's nicht, für die nächsten zwei Wochen ist für mich NWN noch Tabu.
Ich lerne für die Klausuren und starte nicht NWN, ich lerne für die Klausuren und starte nicht NWN, ich lerne für die Klausuren und starte nicht NWN, ich lerne für die Klausuren und starte nicht NWN... Arg! :rolleyes:
 

Tingil

Lord of the Links
Registriert
14.07.2000
Beiträge
7.884
Ist zwar ein bißchen spät, aber ich habe erst jetzt wieder in den Thead geschaut.

Danke, es funktioniert! :D
 

Jansuro

Cespenarr
Registriert
13.11.2001
Beiträge
399
Nachdem ich es nun glücklicherweise geschafft habe, die Anzahl der Henchies BG-Verhältnissen anzupassen - 3 weitere Newbfragen:

1. Kann ich per Skript Einträge in den persönlichen Notizen des Tagebuchs vornehmen?

2. Lässt sich ein Spielercharakter über sein Gepäck/Natürliche Ausrüstung durch eine "Haut" mit Talenten/Skills ausrüsten: wenn ja - wie?

3. Gut gefallen in HdU hat mir die "Dämonische Kralle". Habe die jetzt mal in andere Module mitgenommen, aber da bleibt sie ohne Wirkung. Ex - und Import der Kralle in ein anderes Modul liefert auch kein Ergebnis. Nachgeschaut im 3.HdU Kapitel lassen sich auch keine Auslöser oder Skripte finden. Wie funktioniert dieses geniale Teil nur...? :)
 

Tingil

Lord of the Links
Registriert
14.07.2000
Beiträge
7.884
Mit HotU sind mehrere Henchmen standardmäßig möglich. :D

zu 1.) Nein.

zu 2.) Du kannst mit ActionEquipItem (oder wie die Funktion heißt) SC dazu bringen, verschiedene Ausrüstungsgegenstände anzulegen.

zu 3.) Für die Kralle gibt es ein entsprechendes Skript. Da nützt es nichts, nur den Gegenstand zu exportieren. Das Skript ist vermutlich ein Teil des OnItemActivated Skripts des Moduls, in dem die Kralle vorkommt.
In dem Skript müßte sich auch ablesen lassen, welche speziellen Eingenschaften die Ziele dieser Kralle haben müssen (vermutlich einen bestimmten Tag).


@Silpion: Was denn? :shine:
 
Zuletzt bearbeitet:

Silpion

Traumtänzer
Registriert
10.04.2001
Beiträge
2.104
Tingil: Standard. :p

C Zee no Rî:
Wenn du wichtige Informationen für den Spieler abrufbereit halten möchtest, kannst du sie als offene oder abgeschlossene Quest tarnen. ;)
 

Jansuro

Cespenarr
Registriert
13.11.2001
Beiträge
399
@ Tingil
Standardmässig jein, ohne einige kleine Änderungen beim Modulladen (-Setmaxhenchmen n oder so ) und in dem X0_io_henchman script (Zeile 75) bleibt es bei 2 henchies. Und bis ich das gecheckt hatte, waren die meisten schon bei einem anderen Meister gelandet....;)
Danke übrigens, die Kralle funktioniert jetzt auch in anderen maps.

@ Silpion
Ich fand die Gliederung bei BG (Quest - erledigt - Tagebucheintrag) irgendwie übersichtlicher und angenehmer zu lesen.

Und ganz ..verschämt gleich eine weitere Frage:

Mit der Funktion - TLChangeAreaGroundTiles - könnte z. Bsp. aus einem Fluss in der Abyss ein Lavastrom werden. Bei mir fliesst weiterhin leider nur Wasser in der Karte (OnEnter)....?
 

Silpion

Traumtänzer
Registriert
10.04.2001
Beiträge
2.104
Hmm... das ist wohl Geschmackssache. Ich bin gerade wieder dabei BG2 zu spielen und das Journal... *kopfschüttel*
Da ist mir das von NWN tausendmal lieber. Du kannst wenn du möchtest die Einträge sortieren, indem du für Quests und Tagebucheinträge unterschiedliche Prioritäten festlegst.

Zu Tile Magic:
Du kannst nicht aus einem Fluss etwas anderes machen. Du kannst nur Effekte hinzufügen. Eine Schlucht kannst du daher beliebig aussehen lassen, aber wenn du z.B. in einem Dungeon Wasser haben willst, wird man immer die Lava durchsehen.
Letztendlich ist es nichts anderes als ein InvisibleObject, dem ein dauerhafter visueller Effekt angeheftet wird.
Für gute Beispiele schau dir mal in diesem Topic den Post mit der Überschrift "An introduction to Tile Magic" an. Allerdings muss ich dazu sagen, dass die Beispiele bei mir nicht alle so funktioniert haben. Der letzte Parameter in der Funktion TLChangeAreaGroundTiles, die Höhe des Effektes, war teilweise zu niedrig. Mit ausnahme der Tilesets, in denen eine Schlucht vorkommt, musste ich die Höhe abändern, damit die Beispiele funktionierten.
 

Jansuro

Cespenarr
Registriert
13.11.2001
Beiträge
399
Dieses -
Code:
#include "x2_inc_toollib"
void main()
{
        int nX = 7;
        int nY = 17;
        TLChangeAreaGroundTiles(GetArea(OBJECT_SELF),
X2_TL_GROUNDTILE_LAVA,nX,nY,0.7f);
}
- hatte genau den gesuchten Effekt und den Fluss in einen Lavastrom verwandelt. Leider wurde die map (12x17) danach extrem laggy und lässt sich nicht mehr vernünftig spielen. Schade drum, werde es vielleicht mal mit einer kleineren Karte probieren...:)
 

Tingil

Lord of the Links
Registriert
14.07.2000
Beiträge
7.884
Hat jemand Erfahrung mit Fallen-Skripten? Um genau zu sein mit dem OnDisarm Event von Fallen. Ich habe nämlich folgendes Skript geschrieben, um EP für das Entschärfen von Fallen zu vergeben:
Code:
//::///////////////////////////////////////////////
//:: EP fuer das Entschaerfen einer Falle
//:: t1_disarm_xp.nss
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*

*/
//:://////////////////////////////////////////////
//:: Created By: Tingil
//:: Changed On: July 22, 2004
//:://////////////////////////////////////////////

#include "tin_i0_generic"

// Gibt den HG der Falle auf oTrap zurueck.
int GetTrapCR(object oTrap = OBJECT_SELF);

void main()
{
    GiveXPRewardFromTableToParty(GetLastDisarmed(), GetTrapCR());
}

//::///////////////////////////////////////////////
//:: GetTrapCR
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*

*/
//:://////////////////////////////////////////////
//:: Created By: Tingil
//:: Created On: July 22, 2004
//:://////////////////////////////////////////////
int GetTrapCR(object oTrap = OBJECT_SELF)
{
    int iCR;
    int iTrapBaseType = GetTrapBaseType(oTrap);
    switch (iTrapBaseType)
    {
        case TRAP_BASE_TYPE_MINOR_ACID:
        case TRAP_BASE_TYPE_MINOR_ACID_SPLASH:
        case TRAP_BASE_TYPE_MINOR_ELECTRICAL:
        case TRAP_BASE_TYPE_MINOR_FIRE:
        case TRAP_BASE_TYPE_MINOR_FROST:
        case TRAP_BASE_TYPE_MINOR_GAS:
        case TRAP_BASE_TYPE_MINOR_HOLY:
        case TRAP_BASE_TYPE_MINOR_NEGATIVE:
        case TRAP_BASE_TYPE_MINOR_SONIC:
        case TRAP_BASE_TYPE_MINOR_SPIKE:
        case TRAP_BASE_TYPE_MINOR_TANGLE:
            iCR = 2;
        break;

        case TRAP_BASE_TYPE_AVERAGE_ACID:
        case TRAP_BASE_TYPE_AVERAGE_ACID_SPLASH:
        case TRAP_BASE_TYPE_AVERAGE_ELECTRICAL:
        case TRAP_BASE_TYPE_AVERAGE_FIRE:
        case TRAP_BASE_TYPE_AVERAGE_FROST:
        case TRAP_BASE_TYPE_AVERAGE_GAS:
        case TRAP_BASE_TYPE_AVERAGE_HOLY:
        case TRAP_BASE_TYPE_AVERAGE_NEGATIVE:
        case TRAP_BASE_TYPE_AVERAGE_SONIC:
        case TRAP_BASE_TYPE_AVERAGE_SPIKE:
        case TRAP_BASE_TYPE_AVERAGE_TANGLE:
            iCR = 4;
        break;

        case TRAP_BASE_TYPE_STRONG_ACID:
        case TRAP_BASE_TYPE_STRONG_ACID_SPLASH:
        case TRAP_BASE_TYPE_STRONG_ELECTRICAL:
        case TRAP_BASE_TYPE_STRONG_FIRE:
        case TRAP_BASE_TYPE_STRONG_FROST:
        case TRAP_BASE_TYPE_STRONG_GAS:
        case TRAP_BASE_TYPE_STRONG_HOLY:
        case TRAP_BASE_TYPE_STRONG_NEGATIVE:
        case TRAP_BASE_TYPE_STRONG_SONIC:
        case TRAP_BASE_TYPE_STRONG_SPIKE:
        case TRAP_BASE_TYPE_STRONG_TANGLE:
            iCR = 6;
        break;

        case TRAP_BASE_TYPE_DEADLY_ACID:
        case TRAP_BASE_TYPE_DEADLY_ACID_SPLASH:
        case TRAP_BASE_TYPE_DEADLY_ELECTRICAL:
        case TRAP_BASE_TYPE_DEADLY_FIRE:
        case TRAP_BASE_TYPE_DEADLY_FROST:
        case TRAP_BASE_TYPE_DEADLY_GAS:
        case TRAP_BASE_TYPE_DEADLY_HOLY:
        case TRAP_BASE_TYPE_DEADLY_NEGATIVE:
        case TRAP_BASE_TYPE_DEADLY_SONIC:
        case TRAP_BASE_TYPE_DEADLY_SPIKE:
        case TRAP_BASE_TYPE_DEADLY_TANGLE:
            iCR = 8;
        break;

        case TRAP_BASE_TYPE_EPIC_FIRE:
        case TRAP_BASE_TYPE_EPIC_FROST:
        case TRAP_BASE_TYPE_EPIC_SONIC:
            iCR = 10;
        break;
    }
    return iCR;
}
Das Skript benutzt folgende Teile meines tin_i0_generic Skriptes:
Code:
//::///////////////////////////////////////////////
//:: GiveXPRewardFromTableToParty
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Verteilt EP an die Gruppe von oMember gegen
    eine Herausforderung mit HG iCR.
    Benutzt dazu die Funktion GetXPFromTable.
*/
//:://////////////////////////////////////////////
//:: Created By: Tingil
//:: Created On: July 18, 2004
//:://////////////////////////////////////////////
void GiveXPRewardFromTableToParty(object oMember, int iCR, int iPercentage = 10)
{
    object oArea = GetArea(oMember);

    // Mitglieder und Henchmen in oMembers Faction zaehlen
    int i, iMembers = 0, iHenchmen = 0;
    object oHen;
    object oPC = GetFirstFactionMember(oMember);
    while (oPC != OBJECT_INVALID)
    {
        if (GetArea(oPC) == oArea)
        {
            iMembers++;
            i = 1;
            oHen = GetHenchman(oPC);
            while (oHen != OBJECT_INVALID)
            {
                iHenchmen++;
                i++;
                oHen = GetHenchman(oPC, i);
            }
        }
        oPC = GetNextFactionMember(oMember);
    }

    // EP pro Mitglied errechnen
    int iXP = GetXPFromTable(GetFactionAverageLevel(oMember), iCR) /
        (iMembers + iHenchmen);
    iXP = iXP + ((iHenchmen * (iXP / 2)) / iMembers);

    // EP verteilen
    oPC = GetFirstFactionMember(oMember);
    while (oPC != OBJECT_INVALID)
    {
        if (GetArea(oPC) == oArea)
        {
            GiveXPToCreature(oPC, iXP);
        }
        oPC = GetNextFactionMember(oMember);
    }
}

//::///////////////////////////////////////////////
//:: GetXPFromTable
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Gibt die EP fuer eine Gruppe der Stufe iLevel
    und einer Herausforderung des HG iCR zurueck.
*/
//:://////////////////////////////////////////////
//:: Created By: Tingil
//:: Created On: July 18, 2004
//:://////////////////////////////////////////////
int GetXPFromTable(int iLevel, int iCR, int iPercentage = 10)
{
    if (iLevel < 1)
    {
        iLevel = 1;
    }
    else if (iLevel > 40)
    {
        iLevel = 40;
    }

    if (iCR < 0)
    {
        iCR = 0;
    }
    else if (iCR > 40)
    {
        iCR = 40;
    }

    if (iPercentage < 0)
    {
        iPercentage = 0;
    }
    else if (iPercentage > 200)
    {
        iPercentage = 200;
    }

    // EP auslesen
    float fXP = StringToFloat(
        Get2DAString("xptable.2DA", "C" + IntToString(iCR), iLevel - 1));

    // Die in xptable.2DA gespeicherten Werte sind bereits 1/10 der
    // eigentlichen Werte.
    return FloatToInt(fXP * (IntToFloat(iPercentage) / 10));
}
Das Problem ist nun, daß der Disarmer trotzdem keine EP bekommt und es kommt auch keine EP-Meldung. :confused:
 

Kamiryn

Senior Member
Registriert
21.07.2003
Beiträge
1.357
Wird das Skript denn überhaupt ausgeführt bzw. geben deine Funktionen die richtigen Werte zurück? Lass dir doch mal den Namen des Entschärfers ausgeben, nur um zu sehen, dass da nicht schon das Problem liegt.

Führt ein Placeable, eine Tür oder ein Trigger das Skript aus? Keine Ahnung, ob das einen Unterschied macht. Existiert die Falle überhaupt noch, wenn sie entschärft wurde bzw. lässt sich dann noch der Typ feststellen?

Ansonsten würde ich mal nachschauen, wie es in anderen Modulen gemacht wird, die XP fürs Entschärfen von Fallen vergeben.
 
Zuletzt bearbeitet:

Tingil

Lord of the Links
Registriert
14.07.2000
Beiträge
7.884
Das Skript wird von einem Trigger ausgeführt. Es wäre schon ziemlich dämlich von BioWare, wenn das OnDisarm Skript eines Triggers überhaupt nicht mehr ausgeführt werden kann, weil er bzw. die Falle nicht mehr da ist. :D
Naja, wer weiß, die haben sich bei der Skriptsprache ja schon einige Dinge geleistet. Ich werd' das wohl nachprüfen müssen.

Edit: Hab' den Fehler gefunden: Bei der Funktion Get2DAString muß man den Namen der Datei ohne Erweiterung angeben. :rolleyes:
 
Zuletzt bearbeitet:

Tingil

Lord of the Links
Registriert
14.07.2000
Beiträge
7.884
Nach langer Zeit 'mal wieder eine Frage: Gibt es eine Möglichkeit, Immunitäten gegen bestimmte Effekte per Skript zu umgehen? Konkret möchte ich einen EffectSleep auf einen Elfen legen. Ich hab's schon mit einem SupernaturalEffect und mit einem ExtraordinaryEffect versucht, aber keins der beiden hat funktioniert und mehr fällt mir dazu im Moment nicht ein.
 

Kamiryn

Senior Member
Registriert
21.07.2003
Beiträge
1.357
Benutze mal diesen Thread, weils ja doch irgendwie zum Thema passt:

Drei kurze Fragen, auf die vielleicht jemand eine Antwort weiß:

1) Gibt es eine Möglichkeit, die -10 Grenze zwischen OnPlayerDeath und OnPlayerDying zu ändern, so dass auch bei etwas weniger Trefferpunkten trotzdem der OnPlayerDying Event ausgelöst wird und der Spieler nicht gleich tot ist.

2) Gibt es eine Möglichkeit, innerhalb eines Skripts zu erfahren, ob ein Modul die Default-Zeiteinstellung benutzt (also 2 Minuten = 1 Stunde) oder ob diese Einstellung irgendwie geändert wurde.

3) Kann man in einem Skript das in den Moduleigenschaften eingestellte Startjahr feststellen, außer es selbst beim Starten des Moduls über das Datum zu ermitteln.

[edit]Tingil, zu deiner Frage fällt mir leider nichts ein.[/edit]
 

Tingil

Lord of the Links
Registriert
14.07.2000
Beiträge
7.884
zu 1.) Ich hab's noch nie ausprobiert aber theoretisch kann ein SC bis sonstwohin negative TP haben. Es OnDeath Event wird erst dann ausgelöst, wenn der EffectDeath auf den SC angewendet wird. Dies macht das Standard-OnPlayerDying Skript sofort, wenn es ausgelöst wird, daher ist der SC standardmäßigig sofort tot.


zu 2.) Es gibt die Funktion HoursToSeconds die die übergebene Stundenzahl basierend auf den Moduleinstellungen in Sekunden umrechnet. Wenn man die Minuten pro Stunde haben will, muß man einfach nur

HoursToSeconds(1) / 60

rechnen.


zu 3.) Nein, da kenne ich auch keine Methode außer beim allerersten Start des Moduls die Funktion GetCalendarYear aufzurufen. Den Wert kann man dann z.B. als Modulvariable speichern und dann von überall darauf zugreifen und daß nicht bei jedem Laden der Wert neu gesetzt wird, kann man durch eine weitere Modulvariable absichern.


Ich selbst habe gerade vor ein paar Tagen ein Timestamp-System für NwN-Module entwickelt. Wenn Du so etwas brauchen kannst, kann ich den Code hier 'mal posten und erklären.

Was meine Frage angeht, so wurde die inzwischen an anderer Stelle geklärt. ;)
 

Kamiryn

Senior Member
Registriert
21.07.2003
Beiträge
1.357
Danke für die Antworten :)

1) So wie ich das sehe, wird, falls der Spieler weniger als -10 Trefferpunkte hat, das OnPlayerDying Skript gar nicht mehr aufgerufen, sondern der Spieler ist sofort tot.

2) Hmmm, das ist ja einfach (da hätte ich ja auch selber drauf kommen können :D).

3) Ja, so ähnlich mache ich es jetzt auch. Beim ersten Erzeugen eines Zeitstempels wird das aktuelle Jahr als Basis genommen.

Hat etwas gedauert, bis ich drauf gekommen bin, dass für das vollständige Jahr, Monate, Tage, Stunden, Minuten und Sekunden kein Platz in einem float ist. Habe mich immer gewundert, wieso Minuten und Sekunden immer verloren gingen. Allerdings hatte ich da auch noch mit 60 Minuten pro Stunde gerechnet :D.
 
Oben