Construction Set Morrowind-Scriptkurs - Lektion 1

Dieses Thema im Forum "[MW] Plugins und Mods" wurde erstellt von Killfetzer, 14. Oktober 2010.

  1. Killfetzer

    Killfetzer Super-Moderator Mitarbeiter

    The Elder Scrolls III: Morrowind - Scriptkurs


    1. Einfache Spielerinteraktion über Messageboxen und das Tagebuch

    In der Einführung wurde euch ein Script vorgestellt:

    Code:
    begin kf_hello_world_script
    
    if ( OnActivate == 1 )
      MessageBox, "Hallo, Welt!"
    endif
    
    end
    
    Dieses Script veranlasste den Activator, sobald er aktiviert wurde, eine Messagebox mit dem Text "Hallo, Welt!" zu öffnen. Das hat immer wieder funktioniert. Wie genau funktioniert dieses Script nun?

    Bedingungen abfragen: if-Blöcke

    In diesem Script wird zuerst eine if-Bedingung abgefragt. Das if ist einer der grundlegenden Befehle in Morrowind Script. Seine Wirkung ist dabei so zu formulieren: Wenn eine Bedingung erfüllt ist, dann mache irgendwas. Wenn die Bedingung nicht erfüllt ist, überspringe diesen Teil. Im Beispielscript ist die einfachste Variante eines if zu sehen. Es gibt auch noch kompliziertere. Die allgemeinste Form eines if-Blocks ist:

    Code:
    if ( a == 1 )
      ;mache irgendwas
    elseif ( a == 2 )
      ;mache irgendwas anderes
    else
      ;mache nochmal was anderes
    endif
    
    Diesen Block kann man in etwas so lesen:
    Wenn a gleich 1 ist, führe alles aus bis zum elseif aus. Wenn a nicht 1 ist, aber a gleich 2 ist, führe alles bis zum else aus. Wenn a weder 1 noch 2 ist, führe alles bis zum endif aus.

    Jeder if-Block muss genau ein if und genau ein endif enhalten. Zusätzlich kann jeder Block beliebig viele elseif, aber nur ein else enhalten. Das else steht dabei immer als letzter Teil vor dem endif.

    Hinter jedem if und elseif steht eine Bedingung beziehungsweise ein Vergleich in Klammern. Ist dieser Vergleich wahr, wird ausgeführt, was sich unter dem Vergleich befindet. Wenn der Vergleich falsch ist, wird zum nächsten Vorkommen eines else(if) oder endif gesprungen.
    Vergleiche bestehen aus zwei Zahlen (ob diese Zahlen nun als tatsächliche Zahen, als Variablen oder als Rückgabewert einer Funktion dort stehen, ist ersteinmal egal) und einem Vergleichsoperator. Einige Beispiele dazu:

    Code:
    if ( a == 1 )     ;wenn a gleich 1
    
    if ( a > 1 )      ;wenn a größer als 1
    
    if ( a < 1 )     ;wenn a kleiner als 1
    
    if ( a >= 1 )     ;wenn a größer oder gleich 1
    
    if ( a <= 1 )     ;wenn a kleiner oder gleich 1
    
    if ( a != 1 )     ;wenn a ungleich 1
    
    Statt der Variablen a könnte man hier auch viele Funktionen hinschreiben, zum Beispiel OnActivate.

    Eine vereinfachte Form der if-Abfrage ist es den Vergleich einfach wegzulassen:

    Code:
    if ( OnActivate )
      ;mache irgendwas
    endif
    
    Bei diesem Beispiel wird ausgenutzt, dass das Script normalerweise erst den Vergleich auswertet. Ist er wahr ersetzt das Script ihn mit einer 1, ist er falsch ersetzt er ihn mit einer 0. Das Script führt den Teil nach dem if immer aus, wenn in der Klammer letztendlich keine 0 steht (0 steht in der Informatik normalerweise für falsch).

    if ( OnActivate ) wird vom Script genauso verstanden wie if ( OnActivate != 0 ).

    Viele verwenden diese Kurzformen, wenn eine Variable oder Funktion normalerweise nur die Werte 0 und 1 annimmt. Ich persönlich mag sie nicht besonders, aber das ist größtenteils Geschmackssache. Mein Argument gegen diese Schreibweise ist, dass zumindest Variablen vielleicht doch mal einen anderen Wert als 0 oder 1 haben könnten. In diesem Fall ist mir eine Gleichheit lieber, als eine Ungleichheit.

    Scriptfunktionen

    Neben den wenigen Befehlen (begin, end, if, while, ...) verfügt Morrowind Script über eine Vielzahl von Funktionen. Diese Funktionen machen die verschiedensten Dinge. Grundsätzlich kann man die Funktionen in zwei Arten einteilen. Einmal gibt es die Funktionen, die irgendeinen Wert des Spiels abfragen (und dabei nichts am Spiel verändern) und es gibt die Funktionen, die irgendwas am Spiel ändern. In dem Beispielscript gab es von jeder Sorte eine dieser Funktionen.


    OnActivate

    Diese Funktion ist eine Funktion die einen Wert abfragt. Sie liefert normalerweise eine 0 (beziehungsweise falsch). Nur in dem Moment, in dem jemand (normalerweise der Spieler) das Objakt auf dem dieses Script liegt, aktiviert, liefert die Funktion eine 1 (also wahr).
    So kann man mit dieser Funktion herausbekommen, wenn der Spieler versucht ein Objekt zu aktivieren. Versucht deshalb, weil das Objekt sich nicht aktivieren lässt, wenn auf ihm ein Script mit OnActivate liegt. Das ist eigentlich eine sehr interessante Möglichkeite für Scripte. Man kann nun (mit Hilfe weiterer ifs) verhindern, dass der Spieler bestimmte Objekte zu einem bestimmten Zeitpunkt aktivieren kann. Ein Beispiel:

    Code:
    if ( OnActivate == 1 )
      PlaySound, "LockedDoor"
    endif
    
    Legt man dieses Script auf eine Tür, wird sie dem Spieler so vorkommen, als wäre sie verschlossen (Sie spielt beim Aktivieren den Sound einer verschlossenen Tür ab.). Aber das Schloss kann er niemals knacken, da die Tür eigentlich gar kein Schloss besitzt.

    Natürlich gibt es auch Situationen, in denen man zwar ein Aktivieren feststellen möchte, der Spieler das Objekt aber trotzdem Aktivieren können soll. Dazu kann man folgende Konstruktion verwenden:

    Code:
    if ( OnActivate == 1 )
      ;mache irgendwas
    
      Activate
    endif
    
    Das Activate sorgt dafür, dass ein Objekt trotzdem aktiviert wird. Activate hat zwar noch mehr Einsatzmöglichkeiten, aber dies ist die wichtigste.

    Noch eine kleine Randbemerkung zu OnActivate: Versucht man eine Aktivierung bei einem Activator (der Objektklasse) festzustellen, muss dieser einen Namen besitzen!


    MessageBox

    Die andere im Beispielscript verwendete Funktion ist MessageBox. Diese Funktion gibt, wie wir ja schon wissen, eine Nachricht im Spiel aus. Aber die Funktion kann noch viel mehr. Tatsächlich ist dies eine der vielseitigsten Funktionen in Morrowind Script.

    Damit die Funktion ihre komplette Funktionalität entfaltet, müssen der Funktion gewisse Parameter übergeben werden. Parameter heißen bestimmte Zahlen, Objekt-IDs oder Variablen, die hinter einem Funktionsnamen geschrieben werden müssen. Die gesamte MessageBox-Funktion sieht so aus:

    Code:
    MessageBox, "Anzuzeigender Text"[, var1, var2, ...][, "Antwort 1", ..., "Antwort 9"]
    Die Messagebox blendet eine Nachricht ein und kann zusätzlich bis zu 9 Buttons erzeugen (Antwort 1 – Antwort 9). Wenn Antwortmöglichkeiten gegeben sind, schließt sich das Fenster erst nach klicken auf eine der Antworten. Welche Antwort geklickt wurde lässt sich mit GetButtonPressed ausgeben. Ist keine Antwortmöglichkeit gegeben, bleibt das Fenster abhängig von der Zeichenanzahl der Nachricht eingeblendet. Die Dauer pro Zeichen wird im GameSetting fMessageTimePerChar festgelegt und ist standardmäßig auf 0,1 Sekunden gestellt.
    Es ist auch möglich Werte von Variablen im Text anzuzeigen. Im Text muss dafür ein Platzhalter verwendet werden: %f oder %.yf. In der ersten Version wird jede Zahl mit 6 Nachkommastellen angegeben. In der zweiten Version wird die Zahl mit der in y festgelegten Anzahl von Nachkommastellen ausgegeben. Somit sollte für Variablen vom Typ short oder long der Platzhalter %.0f verwendet werden. In Messageboxen lassen sich auch einige Stringkonstanten ausgeben. Diese müssen mit einem ^ (Zirkumflex) angeführt
    werden.
    Wird eine Messagebox während eines Dialoges aufgerufen, wird der Inhalt der Messagebox als weiße Schrift in einen neuen Absatz geschrieben. Dies funktioniert allerdings nur mit Messageboxen ohne Antworten.

    Hier einige Beispiele, die die verschiedenen Möglichkeiten der Messagebox zeigen:

    Code:
    MessageBox, "Ganz einfache Messagebox."
    ---
    MessageBox, "Der Name des Spielers ist ^PCName."
    ---
    long gold
    set gold to "Player"->GetItemCount, "Gold_001"
    MessageBox, "Ihr besitzt %.0f Draken.", gold
    ---
    MessageBox, "Es ist der %.0f. %.0f. im Jahr 3Ä %.0f.", Day, Month, Year
    ---
    MessageBox, "Diese Nachricht verschwindet erst, wenn Ihr OK anklickt.", "OK"
    ---
    MessageBox, "Es ist schon nach %.0f Uhr. Ihr solltet schlafen gehen.", GameHour, "OK"
    
    GameHour, Day, Month und Year in den obigen Beispielen sind globale Variablen. Das sind Variablen, die von jedem Script aufgerufen oder verändert werden können. Man muss sie nicht im Script deklarieren, sondern kann dies im Construction Set unter Gameplay->Globals tun.

    [​IMG]

    Verwaltung der globalen Variablen

    In der Beschreibung zur Messagebox habe ich auch verschiedene Antworten erwähnt und dass man über GetButtonPressed heraus bekommt, welcher Button gedrückt wurde:

    GetButtonPressed

    Die Funktion liefert die Nummer des Messagebox-Buttons zurück, den der Spieler angeklickt hat. Der erste Button liefert eine 0, der zweite eine 1 und so weiter. Hat der Spieler noch keinen Button geklickt, liefert die Funktion -1 zurück. Eine Konstruktion kann zum Beispiel so aussehen:

    Code:
    begin kf_beispiel2_script
    
    short state
    short button
    
    if ( state == 0 )
      if ( OnActivate == 1 )
        set state to 1
        MessageBox, "Was ist eure Lieblingszahl?", "1", "2", "3"
      endif
    else
      set button to GetButtonPressed
      if ( button == 0 )
        set state 0
        MessageBox, "Eure Lieblingszahl ist 1."
      elseif ( button == 1 )
        set state 0
        MessageBox, "Eure Lieblingszahl ist 2."
      elseif ( button == 2 )
        set state 0
        MessageBox, "Eure Lieblingszahl ist 3."
      endif
    endif
    
    end
    
    In diesem Script wird auch zum ersten Mal einer Variable ein Wert zugewiesen. Mit dem Befehl set ... to ... lässt sich das erreichen. Zwischen set und to muss der Name der zu verändernden Variable stehen. Hinter dem to kann eine Zahl, eine andere Variable, eine Funktion oder eine Rechnung stehen. Einige Beispiele:

    Code:
    short test1
    short test2
    
    set test1 to 3
    
    set test2 to test1
    
    set test1 to GetButtonPressed
    
    set test2 to test1 - 5
    
    set test2 to ( test1 - 5 ) * 6
    
    Damit wären die beiden Funktionen aus dem Beispielscript erklärt. Um nun noch etwas Neues einzuführen, werde ich noch die Funktion des Tagebuchs erklären:


    Das Tagebuch

    Das Tagebuch des Spielers ist ein einfacher Weg die Fortschritte von Quests festzuhalten. Man kann Tagebucheinträge genauso wie normale Dialoge erstellen. Allerdings gibt es die Besonderheit, dass als einzige Bedingung einen Index angeben kann. Zusammen mit dem Namen des Tagebuchthemas bildet der Index die Möglichkeit jeden Tagebucheintrag eindeutig anzugeben.

    Ihr habt nun also ein Tagebuchthema mit verschiedenen Indizes erstellt. Wie könnt ihr diese nun in das Tagebuch des Spielers eintragen oder (noch wichtiger) wie bekommt ihr heraus, ob sich ein bestimmter Eintrag schon im Tagebuch des Spielers befindet?

    Dafür gibt es zwei Funktionen:

    Journal

    Diese Funktion kann in Scripten aufgerufen werden, wird aber auch sehr oft in Dialogresultboxen verwendet (und in der Konsole ist sie natürlich auch sehr praktisch um Quests abzukürzen ;)).

    Code:
    Journal, "JournalTopic_ID", index
    
    Journal, "C3_DestroyDagoth", 50
    
    Diese Funktion fügt dem Tagebuch des Spielers einfach den mit Journalthema und Journalindex bestimmten Eintrag hinzu.

    GetJournalIndex

    Mit dieser Funktion ist es möglich den Wert des höchsten vorhandenen Indexs zu einem bestimmten Thema, der sich bereits im Tagebuch des Spielers befindet, zu bekommen.

    Code:
    GetJournalIndex, "JournalTopic_ID"
    
    Eine übliche Anwendung ist es, den Wert eines Tagebucheintrags abzufragen und nur bei einem bestimmten vorhandenen Eintrag eine Aktion auszuführen. Ein Beispiel ist folgendes Script, dass beim Aktivieren eines Activators dem Spieler eine Nachricht ins Tagebuch einfügt. Aber nur wenn dieser Eintrag nicht schon vorhanden ist (Wer braucht schon doppelte Tagebucheinträge?):

    Code:
    if ( OnActivate == 1 )
      if ( GetJournalIndex, "C3_DestroyDagoth" < 50 )
        Journal, "C3_DestroyDagoth", 50
      endif
    endif
    

    Aufgaben

    Wie angekündigt, stellen wir am Ende jedes Teils einige Aufgaben, die ihr versuchen sollt zu lösen. Eure Lösungen könnt ihr dann vor Beginn des nächsten Teils hier vorstellen. Präsentiert eure Lösungen aber bitte im Spoiler, damit ihr anderen die Möglichkeit gebt, die Lösung noch selbst herauszufinden.
    Natürlich dürft ihr unter einander über die Aufgaben diskutieren. Hier ist ja keine Schule und ihr müsst nicht still sitzen ;)

    1. Verändert das "Hallo, Welt"-Script aus der Einführung so, dass ihr die Beispiele zur MessageBox-Funktion ausprobieren könnt.
    2. Probiert das zweite Beispielscript aus.
    3. Verändert das "Hallo, Welt"-Script so, dass es zunächst fragt, ob der Spieler ein Mann oder eine Frau ist und danach mit "Hallo Herr y" oder "Hallo Frau x" begrüßt.
    4. Erschafft einen Activator, der sich wie eine Digitaluhr verhält. Sie soll euch mit Namen begrüßen und euch die Zeit (in Stunden und Minuten, nicht nur in Stundenbruchteilen) und das Datum angeben. Ihr sollt die Anzeige bestätigen müssen, bevor ihr weiterspielen könnt.
    5. Erschafft eine Tür, die sich erst öffnet, wenn der Spieler einen bestimmten Tagebucheintrag hat. Hat er ihn noch nicht, soll er eine entsprechende Nachricht bekommen, hat er ihn, soll die Tür beim ersten Betreten einen neuen Tagebucheintrag hinzufügen.

    Lösungen
    Aufgaben - Teil 2
     
    Zuletzt bearbeitet: 7. November 2010
  2. Werbung (Nur für Gäste)
  3. Zeitgeist

    Zeitgeist Ehrbarer Bürger

    Hier ist schonmal meine Lösung für 3

    (Hab,aber nicht getestet da ich momentan CSlos bin)

    Code:
    begin md_what_is_your_gender_script
    
    short state
    short button
    
    if ( OnActivate == 1 )
        set state to 1
        MessageBox, "Was seid ihr,Mann oder Frau?", "Mann", "Frau"
    else
      set button to GetButtonPressed
      if ( button == 0 )
        set state 0
        MessageBox, "Hallo Herr ^PCName!"
      elseif ( button == 1 )
        set state 0
        MessageBox, "Hallo Frau ^PCName!"
      endif
    endif
    
    end
     
    Zuletzt bearbeitet: 14. Oktober 2010
  4. Killfetzer

    Killfetzer Super-Moderator Mitarbeiter

    Du musst innerhalb des Spoilers schon die Code-Umgebung verwenden:

    [noparse]
    Code:
    Hier steht mein Code.
    
    [/noparse]

    Zur Aufgabe an sich, statt x und y sollte da eigentlich der tatsächliche Name des Spielers stehen ;)
     
    Zeitgeist gefällt das.
  5. Zeitgeist

    Zeitgeist Ehrbarer Bürger

    Danke,hab den Code jetzt eingerückt.


    EDIT

    Hier ist meine Lösung für 4.

    Code:
    begin md_what_time_is_it_script
    
    short state
    short button
    
    if ( OnActivate == 1 ) 
      set state to 1
      Messagebox, "Hallo ^PCName!Es ist %.2f Uhr am %.0f. %.0f. im Jahr 3Ä %.0f.",GameHour, Day, Mouth, Year,"OK"
    endif
    else
      set button to GetButtonPressed
      if ( button == 0 )
      set state to 0
      endif
    end
         
         
     
    Zuletzt bearbeitet: 14. Oktober 2010
  6. Mercarryn

    Mercarryn Ehrbarer Bürger

    Dann will ich hier mal für die erste Lektion meine Lösungen ab Aufgabe 3 präsentieren, es sei denn ihr wollt auch noch für das Rumexperimentieren in 1 und 2 die Lösungen?

    Aufgabe 3:

    Code:
    begin merc_hello_world
    
    short state
    short button
    
    if (state==0)
        if (onActivate==1)
            set state to 1
            MessageBox, "Welchen Geschlechts seid Ihr?", "Mann", "Frau"
        endif
    else
        set button to GetButtonPressed
        if (button ==0)
            [COLOR=Red]set state to 0[/COLOR]
            MessageBox, "Hallo Herr ^PCName."
        elseif (button==1)
            [COLOR=Red]set state to 0[/COLOR]
            MessageBox, "Hallo Frau ^PCName."
        endif
    endif
    
    end
    

    Und gleich mal ne Frage dazu:
    Die von mir rot markierten Zeilen im Script, sollen diese dafür sorgen, dass nach Auswahl der Antwortmöglichkeiten das Script wieder in den Ursprungszustand geht, sprich, wieder auf 0 gesetzt wird? Oder hat dies einen etwas anderen Grund?

    Aufgabe 4:

    Mal das vorläufige Ergebnis, ich feile noch an der genauen Ausgabe der Minuten statt Stundenbruchteilen.

    Code:
    begin merc_greetin_with_clock
    
    
    if (OnActivate==1)
        MessageBox, "Hallo ^PCName, es ist jetzt [COLOR=Red]%.2f.[/COLOR] am %.0f. %.0f. in 3Ä %.0f", gamehour day month year, "OK"
    endif
    end
            
    

    Aufgabe 5:

    Code:
    begin Merc_Journal_Door
    
    if(OnActivate==1)
        if(GetJournalIndex, "blades_rithleen"<1)
        Messagebox, "Euch fehlt der Tagebucheintrag für Rithleen."
    else
        Activate
        Journal,"A1_Sleepers_Assi", 1
        endif
    endif
    
    end
    

    Sehr schöne Aufgaben zur Einführung, klar machbar und doch zum Nachdenken gefordert. So solls sein :)
     
    Zuletzt bearbeitet: 14. Oktober 2010
  7. J2W

    J2W Neuankömmling

    1. Wie ist das deklarieren von state zu verstehen, was nützt es? Wenn state die ganze Zeit auf 0 ist, müsste das Script dann nicht genauso laufen? Da state am Ende wieder zurückgesetzt wird (u.A. im Beispielscript) denke ich dass da keine Endlosschleife entstehen kann.
    2. Ist die Deklaration von Button überhaupt notwendig? kann ich nicht gleich Anstelle von "set Button to GetButtonPressed" nur GetButtonPressed abfragen?

    Danke für die Mühe, das Ganze sieht nach einem Haufen Arbeit für dich aus, ich schätze das wirklich :)
     
  8. Crashtestgoblin

    Crashtestgoblin Freund des Hauses

    Hab mich auch mal daran versucht.

    Aufgabe 3:

    Code:
    begin ctg_hallo_welt_script
    
    short state
    short button
    
    if ( state == 0 )
        if ( OnActivate == 1  )
            set state to 1
            MessageBox, "Hallo, bist du ein Mann oder eine Frau?", "Mann", "Frau"
        endif
    else
        set button to GetButtonPressed
        if ( button == 0 )
            set state to 0
            MessageBox, "Hallo Herr ^PCName."
        elseif ( button == 1 )
            set state to 0
            MessageBox, "Hallo Frau ^PCName."
        endif
    endif
    
    end
    

    Aufgabe 4:


    Code:
    begin ctg_digitaluhr_script
    
    if ( OnActivate == 1 )
        MessageBox, "Hallo ^PCName, beim nächsten Signalton ist es %.2f Uhr. Es ist der %.0f. %.0f. des Jahres 3Ä %.0f.", GameHour, Day, Month, Year, "OK"
    endif
    
    end
    
    Was mich hier stört, ist die Tatsache, dass die beiden Nachkommastellen bei der Zeit bis 100 zählen. Lässt sich das irgendwie auf 60 absenken oder hab ich da was überlesen? :?

    Aufgabe 5:

    Code:
    begin ctg_locked_door_script
    
    short journal
    
    if ( OnActivate == 1 )
        if ( GetJournalIndex, Journal "test_locked_door" == 50 )
            Journal, "test_locked_door", 100
            unlock
            PlaySound, "Open Lock"
        elseif ( GetJournalIndex, Journal "test_locked_door" == 100 )
            activate
        else
            MessageBox, "Du kommst hier net rein!"
            PlaySound, "LockedDoor"
        endif
    endif
    
    end

    Das hab ich aber noch nicht in der Praxis ausprobiert^^ Öhm, muss eigentlich die Tür vorher auch noch wie der Alkoholschrank in der Eisfalter-Festung per Script verschlossen werden?

    //EDIT: So alle Probleme an der Tür gefixt, klappt wunderbar.
     
    Zuletzt bearbeitet: 15. Oktober 2010
  9. Mercarryn

    Mercarryn Ehrbarer Bürger

    @Crashtestgoblin:

    Soweit ich das verstanden habe, braucht bei Aufgabe 5 die Türe nicht extra verschlossen zu werden, da dies durch nicht erfüllte Bedingungen von ganz allein geschieht. Ich hab meine Lösung ingame getestet und sie hat auf jeden Fall so funktioniert, wie es sein sollte.
     
    Crashtestgoblin gefällt das.
  10. Killfetzer

    Killfetzer Super-Moderator Mitarbeiter

    Wir wollen gar nichts. Ihr wollt üben. Aber ich denke den Code der Aufgaben 1 und 2 müsst ihr nicht vergleichen ;)

    Genau, das ist der Sinn dieser Zeilen. Durch diese Zeile kann der Activator seine Nachricht immer wieder abspielen. Außerdem verhindert es, dass die GetButtonPressed-Abfrageimmer wieder neu durchlaufen wird.

    Das erfüllt aber nicht die Anforderungen (und ist auch nicht sehr schön gesetzt). Der Tagebucheintrag sollte ja nur einmal erscheinen und nicht immer.

    Deine Fragen musst du nicht in Spoiler setzen ;)

    1. Normalerweise lässt du ein Script ja etwas mehr machen als eine Messagebox ausgeben. In meinem Beispielscript würde es wahrscheinlich auch ohne state laufen. Aber ich bin mir relativ sicher, dass es zu ungewollten Nebenwirkungen mit anderen Scripten kommen könnte und sowas will man natürlich vermeiden.
      Allgemein empfehle ich dir, es einfach auszuprobieren. Dafür ist der Kurs ja da. Lass es einfach mal weg und schaue was passiert.
    2. Ja, kannst du. Allerdings ist es programmiertechnisch üblich, dass man eine Funktion nur einmal aufruft und das Ergebnis zwischenspeichert. Die Funktion benötigt nämlich mehr Rechenzeit als das Abrufen einer gespeicherten Variable und man ist immer bemüht, die Rechenzeit zu optimieren.

    Genau das ist ja der Knackpunkt an der Aufgabe. Dafür muss man schon ein bisschen rätseln. ;)
     
  11. Zeitgeist

    Zeitgeist Ehrbarer Bürger

    Code:
    begin md_sesam_open_you_script
    
    short state
    short journal                           
    
    if ( state == 0 )
       if ( OnActivate == 1 )
          if ( GetJournalIndex, Journal "test_locked_door" < 50 )
          Messagebox "Der Weg ist euch verwehrt!Habt ihr etwas vergessen?"
          elseif ( GetJournalIndex, Journal "test_locked_door ==50 )
                 Activate
                 Journal, "test_locked_door", 100
                 set state to 1
          endif
        endif
    endif
    
    end


    Was mich stört ist die 3. Aufgabe
    OK,wenn man die Stundenbruchteile weg haben will muss man den Platzhalter in %.0f ändern.Trotzdem fehlen noch die Minuten...
     
  12. Crashtestgoblin

    Crashtestgoblin Freund des Hauses

    Gibt es irgendwie eine Möglichkeit lediglich die Nachkommastellen auf 0 zu setzen? Ich bau andauernd Zeitmaschinen, die die Uhrzeit auf 0.00 zurücksetzen...
    Oder kann ich GetSecondsPassed irgendwie als Variable verwenden? Es ist zum Verzweifeln...
     
  13. £exa

    £exa Freund des Hauses

    Du suchst Funktionen wie ABS(x), DIV(x) und MOD(x)... zu schade, dass es sowas nicht gibt :-D

    Wie heißt es so schön, bei Morrowind Script kann man vieles nur über Umwege machen. Nur wie könnte man dann von einer Dezimalzahl (float) die Dezimalen wegschneiden und nur den ganzzahligen Teil, also einen Integer (Short/Long) behalten... ;)

    Denk ein wenig nach, vielleicht kommst du drauf... es ist nicht so schwer.
     
  14. Killfetzer

    Killfetzer Super-Moderator Mitarbeiter

    Und man kann nicht mal eine math.h einbinden :lol:

    Aber man kann sich alle diese Funktionen sehr einfach selbst basteln. Wartet mal bis wir trigonometrische Funktionen als Reihenentwicklung in Morrowind Script basteln, das wird dann ein bisschen komplizierter ;)
     
  15. IvanDaVile

    IvanDaVile Abenteurer

    Mit strenger Logik würde man kaum darauf kommen, dass eine Zuweisung Gleitkomma -> ganzzahlig sowas wie eine Floor-funktion impliziert oder? Aber für alle die noch nie programmiert haben, speichert einfach mal die Uhrzeit als short ab.

    Und als Zusatzaufgabe: Wie würde man eine Gleitkommazahl dann normal runden?
     
  16. Teridan

    Teridan Mr. Morrowind 2007

    Ich war fleißig und habe meine Hausaufgaben gemacht:

    Code:
    begin teri_geschlecht_script
    
    short Tomate
    short Zucchini
    
    if ( Tomate == 0 )
        if ( OnActivate == 1 )
            set Tomate to 1
            MessageBox "Wer ist's, der vor mir steht? Eine holde Weiblichkeit oder ein Edelmann?", "Frau", "Mann"
        endif
    else
        set Zucchini to GetButtonPressed
        if ( Zucchini == 0 )
            set Tomate to 0
            MessageBox "Guten Tag, edle Dame."
        elseif ( Zucchini == 1 )
            set Tomate to 0
            MessageBox "Guten Tag, edler Herr"
        endif
    endif
    
    end teri_geschlecht_script
    ;Ich wollte es mal unbedingt mit völlig abstrusen Variblen funktionieren und es funktioniert tadellos. ;)

    Code:
    begin Teri_Zeitanzeige_Script
    
    if ( OnActivate == 1 )
        MessageBox, "Guten Tag, ^PCName. Es ist %.2f, am %.0f.%.0f. im Jahr 3Ä %.0f.", Gamehour, Day, Month, Year, "OK"
    endif
    
    end
    ;siehe Frage b)

    Code:
    begin Teri_RavirrTuer_Script
    
    if ( OnActivate == 1 )
        if ( GetJournalIndex, "Teri_ZugangRavirr" < 10 )
            PlaySound, "LockedDoor"
            MessageBox, "Ihr habt nicht die Erlaubnis, das Geschäft von Ra'Virr zu betreten.", "OK"
        elseif ( GetJournalIndex, "Teri_ZugangRavirr" >= 10 )
            Activate
        endif
    endif
    
    end Teri_RavirrTuer_Script
    ;Alles bestens

    Ein Haufen Fragen, die wohl ziemlich dümmlich wirken:

    a) Ich muss das mit dem Else und dem Elseif jetzt ganz genau wissen: Elseif fragt eine festgelegte, also bestimmte Alternative zu If ab, richtig? Und Else dagegen ist die Verneinung zu If und allen Elseifs, also eine unbestimmte Negierung?
    b) Bei Aufgabe 4. zeigt er mir beim Aktivieren die Uhrzeit 15.85, anstatt 15.51 Uhr. Das ist auf eine Art ja auch logisch, die Uhren gehen nicht nach dem Dezimalsystem, welches wiederum Morrowind als einziges kennt. Aber kann man das nicht anders regeln?
    c)
    Wenn ich das richtig verstehe, dann bedeutet dieser Block doch nur, dass das Script nicht die ganze Zeit aktiv ist, sondern nur ab dem Moment, in dem der Spieler das Item mit der Leertaste aktiviert. Nachdem alles ausgeführt wurde, wird State ja wieder auf 0 gesetzt, also das Script deaktiviert. Ist mein Gedankengang richtig?
     
    J2W gefällt das.
  17. Zeitgeist

    Zeitgeist Ehrbarer Bürger

    Antwort b) Das ist doch grade der Witz an der Aufgabe das rauszufinden

    Antwort c) state wird auf 1 gesetzt, ansonsten ist dein Gedankengang richtig,
    wenn ich alles richtig verstanden habe.


    EDIT

    @IvanDaVile

    Meinst du das Runden jetzt im Script oder in der Messagebox?
    Wenn du die Messagebox meinst müsste das doch mit %.0f funktionieren...

    EDIT2

    Code:
    begin md_what_time_is_it_script
    
    short state
    short time
    short button
    
    if ( OnActivate == 1 ) 
      set state to 1
      set GameHour to time
      Messagebox, "Hallo ^PCName!Es ist %.0f Uhr am %.0f. %.0f. im Jahr 3Ä %.0f.",time, Day, Mouth, Year,"OK"
    endif
    else
      set button to GetButtonPressed
      if ( button == 0 )
      set state to 0
      endif
    end
     
    Zuletzt bearbeitet: 15. Oktober 2010
  18. IvanDaVile

    IvanDaVile Abenteurer

    natürlich in Scripts, in den Message Boxen kanns ja schon jeder :)
    alternativ könnt ihr euch auch für das metrische System für die Zeit einsetzten, das einem 8 stunden Tag eine ganz andere Bedeutung verleihen könnte :oops:
     
  19. Tommy

    Tommy Hausvetter

    um das Runden gehts ja ... also wenn es erst 11:30 ist zeigt deine Uhr schon 12 Uhr, was nicht unbedingt gewollt sein muss - glaub zumindest, dass IvanDaVile darauf hinaus wollte

    da das mit den Minuten angefragt wurde: hier eine mögliche Variante, die zwar etwas länglich geraten ist, dafür aber hoffentlich von der Abfolge leicht verständlich ist - Spoiler nur lesen wenn man selber nicht drauf kommt:

    Code:
    float time
    short hours
    short minutes
    
    ; Zeit holen
    set time to GameHour
    
    ; Stunden zählen
    while ( time >= 1 )
       set hours to ( hours + 1 )
       set time to ( time - 1 )
    endwhile
    
    ; Minuten berechnen
    set time to ( 60 * time )
    
    ; Minuten zählen
    while ( time >= 1 )
       set minutes to ( minutes + 1 )
       set time to ( time - 1 )
    endwhile
    
    ; Zeit ausgeben
    if ( minutes < 10 )
       MessageBox, "Zeit: %.0f:0%.0f", hours, minutes
    else
       MessageBox, "Zeit: %.0f:%.0f", hours, minutes
    endif
     
  20. Killfetzer

    Killfetzer Super-Moderator Mitarbeiter

    Da komm ich jetzt nicht ganz mit, hört sich aber eigentlich richtig an :huh:
    Ich formuliere es noch mal anders. elseif wird immer abgefragt, wenn das vorangegangene if falsch war. Aber es muss selber richtig sein, damit es ausgeführt wird. Else wird immer ausgeführt, wenn die vorangegangenen ifs falsch sind.

    Ich hätte nicht erwartet, dass diese Aufgabe solch große Probleme bereitet. Also noch mal ein Tipp: Der Befehl ist kein Einzeiler. Ihr müsst schon mehrere Zeilen verwenden, um die Minuten darzustellen.

    Nicht ganz. State kontrolliert nur, ob man das Objekt aktivieren kann. Nur wenn state gleich 0 ist, wird die Aktivierung mit der Leertaste registriert. Das soll verhindern, dass ein Script durch eine erneute Aktivierung während der Laufzeit auf einen falschen Wert gesetzt wird. Wenn der Status also 0 ist, wird geprüft, ob das Objekt aktiviert wird. In dem Moment wird der Status auf 1 gesetzt und das Script kann, solange es will, seine Arbeit machen (OnActivate wird ja wieder auf 0 gesetzt nach der Aktivierung). Erst wenn die Arbeit fertig ist, wird der Status wieder auf 0 gesetzt und das Script für einen neuen Start wieder freigegeben.
    Im Beispiel ist es relativ egal, da der Effekt des Scripts in einem Durchlauf abgearbeitet ist, bei längeren Scripts wird es aber wichtig, dass man solch eine Fehlbedienung verhindert.

    /EDIT:
    @Tommy: Nette Version, die funktioniert auf jeden Fall und ist formal korrekt. Ich hab ein wenig gecasted. Das funktioniert auch reibungslos und ist nur 3 Zeilen lang ;)
     
    Zuletzt bearbeitet: 15. Oktober 2010
  21. Mercarryn

    Mercarryn Ehrbarer Bürger

    Ich hab mir jetzt nochmal Aufgabe 5 genau durchgelesen.

    Wenn ich die bisherige Reihenfolge der Abfrage in meinem Script einhielt, um die genauen Vorgaben einzuhalten, bekam ich einen Decompression(?)-Fehler im Spiel selbst, sobald ich das Script testen wollte.
    Also die Reihenfolge dann umgestrickt, nur hat es dann noch immer nicht so richtig geklappt. Ich habe mal dann mit den Lösungswegen der anderen verglichen, das von Crashtestgoblin kam meinem sehr nahe.

    Mir ist allerdings bei seiner Lösung auch ein kleiner Fehler aufgefallen:
    Bei seiner jetzigen Reihenfolge wird immer das Tagebuch aktualisiert, sobald der notwendige Eintrag vorhanden ist. Darum müssen die ersten beiden Bedingungen in seinem Script vertauscht werden, dann wird nur beim ersten Betreten mit notwendigem Journal-Eintrag selbiges aktualisiert, danach nicht mehr.

    Und hier dann meine Lösung, aufbauend auf Crashtestsgoblins Script:

    Code:
    begin Merc_Journal_Door
    
    
    
    short journal
    
    if ( OnActivate == 1 )
        if ( GetJournalIndex, Journal "A1_Sleepers_Assi" == 1 )
            activate
        elseif ( GetJournalIndex, Journal "blades_rithleen" == 1 )
            Journal, "A1_Sleepers_Assi", 1
            Activate
            PlaySound, "Open Lock"
        else
            MessageBox, "Euch fehlt der Tagebucheintrag für Rithleen!"
            PlaySound, "LockedDoor"
        endif
    endif
    
    end
    

    Das Problem mit Aufgabe 4 und den blöden Minuten werd ich mich am Sonntag widmen.
     
  22. Werbung (Nur für Gäste)
  1. Diese Seite verwendet Cookies, um Inhalte zu personalisieren, diese deiner Erfahrung anzupassen und dich nach der Registrierung angemeldet zu halten.
    Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden