Ergebnis 1 bis 7 von 7

Thema: (RGSS1) Mordechajs Scripting-Fragen

  1. #1

    (RGSS1) Mordechajs Scripting-Fragen

    EDIT: Ich erwarte, immer mal wieder mit Fragen hier anzukommen; es wird wohl unpraktisch sein, dafür jedes Mal ein neues Thema zu eröffnen. Deshalb widme ich diesen Thread einfach mal um.


    Ich teste gerade folgendes Script aus.

    Code:
    # Code by Mobius XVI
    # Based on SirBilly's Player Turn & Move script for VX Ace
    # Requested by Crydsch
    # Causes player to turn before moving
    # (Mord) ++ Waits are decreased from 7 to 4 ++ (Mord)
    class Game_Player < Game_Character  
    #--------------------------------------------------------------------------  
    # * Object Initialization  
    #--------------------------------------------------------------------------
      def initialize
        @wait_time = 0
        super
        end  
    #--------------------------------------------------------------------------  
    # * Frame Update  
    #--------------------------------------------------------------------------  
    # Alias old method
    alias mobius_turn_step_update update  
    # Redefine update
    def update    
    # Decrease wait time
    @wait_time -= 1    
    # Remember whether or not moving in local variables
    last_moving = moving?    
    # If moving, event running, move route forcing, and message window
    # display are all not occurring
    unless moving? or $game_system.map_interpreter.running? or           
      @move_route_forcing or $game_temp.message_window_showing
    # Move player in the direction the directional button is being pressed
    case Input.dir4      
    # When Down
    when 2
      if Input.trigger?(Input::DOWN) and self.direction == 2
        move_down
      elsif Input.trigger?(Input::DOWN)
        @wait_time = 4
        turn_down
      elsif @wait_time <= 0
        move_down
        end      
    # When Left
    when 4
      if Input.trigger?(Input::LEFT) and self.direction == 4
        move_left
      elsif Input.trigger?(Input::LEFT)
        @wait_time = 4
        turn_left
      elsif @wait_time <= 0
        move_left
        end      
    # When right
    when 6
      if Input.trigger?(Input::RIGHT) and self.direction == 6
        move_right
      elsif Input.trigger?(Input::RIGHT)
        @wait_time = 4
        turn_right
      elsif @wait_time <= 0
        move_right
        end      
    # When Up
    when 8
      if Input.trigger?(Input::UP) and self.direction == 8
        move_up
      elsif Input.trigger?(Input::UP)
        @wait_time = 4
        turn_up
      elsif @wait_time <= 0
        move_up
      end
    end
    end    
    # Remember coordinates in local variables
    last_real_x = @real_x
    last_real_y = @real_y
    super    
    # If character moves down and is positioned lower than the center    
    # of the screen
    if @real_y > last_real_y and @real_y - $game_map.display_y > CENTER_Y      
    # Scroll map down
    $game_map.scroll_down(@real_y - last_real_y)
    end    
    # If character moves left and is positioned more let on-screen than    
    # center
    if @real_x < last_real_x and @real_x - $game_map.display_x < CENTER_X      
    # Scroll map left
    $game_map.scroll_left(last_real_x - @real_x)
    end    
    # If character moves right and is positioned more right on-screen than    
    # center
    if @real_x > last_real_x and @real_x - $game_map.display_x > CENTER_X      
    # Scroll map right
    $game_map.scroll_right(@real_x - last_real_x)
    end    
    # If character moves up and is positioned higher than the center    
    # of the screen
    if @real_y < last_real_y and @real_y - $game_map.display_y < CENTER_Y      
    # Scroll map up
    $game_map.scroll_up(last_real_y - @real_y)
    end    
    # If not moving
    unless moving?      
    # If player was moving last time
    if last_moving        
    # Event determinant is via touch of same position event
    result = check_event_trigger_here([1,2])        
    # If event which started does not exist
    if result == false          
    # Disregard if debug mode is ON and ctrl key was pressed
    unless $DEBUG and Input.press?(Input::CTRL)            
    # Encounter countdown
    if @encounter_count > 0
      @encounter_count -= 1
    end
    end
    end
    end      
    # If C button was pressed
    if Input.trigger?(Input::C)        
    # Same position and front event determinant
    check_event_trigger_here([0])
    check_event_trigger_there([0,1,2])
    end
    end
    end
    end
    # Class End
    Was das Script tut, ist bei Antippen der entsprechenden Richtungstaste den Character erst in die entsprechende Richtung zu drehen und erst danach die Bewegung um ein Tile auszuführen. Der dafür notwendige wait-Befehl kommt mir nun aber bei einigen Gameplay-Elementen in die Quere. Ich würde gern eine Bedingung einfügen (Script-Befehl oder Switch), die das Script deaktiviert, bis es wieder aktiviert wird, oder eben umgekehrt. Wie vielleicht schon am Code zu erkennen ist, habe ich das Script nur kopiert und die @wait_time-Werte geändert. Zu viel mehr bin ich coding-mäßig leider auch nicht in der Lage.

    Lässt sich das vielleicht recht einfach umsetzen? Ob mir jemand weiterhelfen könnte?

    Geändert von Mordechaj (23.08.2017 um 20:00 Uhr)

  2. #2
    Ich bin kein Ruby-Experte, aber was du versuchen könntest:

    Code:
    # If moving, event running, move route forcing, and message window
    # display are all not occurring
    unless moving? or $game_system.map_interpreter.running? or           
      @move_route_forcing or $game_temp.message_window_showing
      # Move player in the direction the directional button is being pressed
      if $game_switches[hier die Nummer vom Switch einsetzen]  
        case Input.dir4      
        # When Down
        when 2
          if Input.trigger?(Input::DOWN) and self.direction == 2
            move_down
          elsif Input.trigger?(Input::DOWN)
            @wait_time = 4
            turn_down
          elsif @wait_time <= 0
            move_down
          end      
        # When Left
        when 4
          if Input.trigger?(Input::LEFT) and self.direction == 4
            move_left
          elsif Input.trigger?(Input::LEFT)
            @wait_time = 4
            turn_left
          elsif @wait_time <= 0
            move_left
          end      
        # When right
        when 6
          if Input.trigger?(Input::RIGHT) and self.direction == 6
            move_right
          elsif Input.trigger?(Input::RIGHT)
            @wait_time = 4
            turn_right
          elsif @wait_time <= 0
            move_right
          end      
        # When Up
        when 8
          if Input.trigger?(Input::UP) and self.direction == 8
            move_up
          elsif Input.trigger?(Input::UP)
            @wait_time = 4
            turn_up
          elsif @wait_time <= 0
            move_up
          end
        end
      else
        # Bewegung ohne Drehen
        case Input.dir4
        when 2
          move_down
        when 4
          move_left
        when 6
          move_right
        when 8
          move_up
        end
      end
    end
    # Remember coordinates in local variables
    Mit $game_switches[Nummer] greift man auf die Standard-Switches vom Maker zu. Die Methode fragt ab, ob der Switch an ist und falls ja, wird zuerst die Drehung ausgeführt, falls nein, bewegt sich die Figur ganz normal.

  3. #3
    Vermutlich könnte man auch bei aktiviertem Switch einfach die ursprüngliche update-Methode von Game_Player aufrufen, der Originalautor hat ja ein Alias erstellt.
    Code:
      # Alias old method
      alias mobius_turn_step_update update
      # Redefine update
      def update
        if $game_switches[hier die Nummer vom Switch einsetzen]
          # Run original Game_Player#update instead
          mobius_turn_step_update
          return
        end
        # restlicher Code...

  4. #4
    Ich danke euch beiden sehr, es klappt einwandfrei!

  5. #5
    So. Ich habe mal wieder ein Anliegen, und zwar diesmal ein wahrscheinlich ungleich schwierigeres als zuvor.

    Ich möchte gern, und zwar je nach Event entschieden, Folgen von Show-Message-Befehlen so einrichten, dass der Spieler dabei immer noch Kontrolle über den Char hat, und die Message abbrechen kann, indem er sich zu weit vom Event wegbewegt. (A la Chrono Trigger, sagt man mir.)

    Zum Beispiel also: Der Spieler quatscht irgendnen NPC an, weil ... das macht man halt so. Und der fängt jetzt an seine Lebensgeschichte von der Wiege bis in den Sarg zu erzählen, und den Spieler nervt das. Traditionell muss er jetzt aber Message Box für Message Box einzeln nacheinander wegdrücken und läuft dabei Gefahr, den NPC am Ende nochmal zu aktivieren, der dann wieder seine ganze Lebensgeschichte erzählt. Stattdessen soll der Spieler sich frei bewegen können und einfach ein paar Tiles weiterlaufen, um dem Opi nicht mehr zuhören zu müssen.

    Es gibt bereits ein Script, das das kann, nämlich Wachungas Multiple Message Windows in der Version von Heretic86 (Code von v1.56 im Spoiler).


    Das Problem: Das nutze ich nicht, da fehlt mir zu viel und ist zu viel drin, was ich nicht gebrauchen kann. Ich arbeite stattdessen mit Hermes 0.3c (Code als Zip-Datei; sorry, aber der Code überschreitet die maximale Zeichenzahl). Neuere Versionen verursachen bei mir Kompabilitätsprobleme, bzw. sehe ich nicht ein, für den letter-by-letter speed zwei statt einen Buchstaben zu schreiben. ^^"

    Ich habe nun bereits zwei Tools, die hier, wie ich meine, hilfreich sein könnten; das ist einmal der asynchronous-Tag bei Hermes, ein andermal das Script "Event Range Conditions" von ForeverZer0. Damit -- und mit etwas Variablen- und ID-Rumgeschiebe und einem PP-Event -- kriege ich das, was ich will, für genau eine einzige Message hin und auch das nur, wenn ich am Ende der Message einen close-tag anhänge.

    Was mir jetzt also noch fehlt -- oder was insgesamt vielleicht völlig anders umgesetzt werden müsste, auch weil das Variablen-Rumgeschiebe und das PP-Event etwas aufwendig sind -- ist Folgendes:

    Der Spieler kann sich also frei bewegen, während die Message über dem Event (geschwätziger NPC) angezeigt wird, muss aber am Ende der Message mit Enter die Message schließen, bevor die nächste beginnen kann. Er soll sich aber -- um's zusätzlich kompliziert zu machen -- weiterhin bewegen können, während die Message auf den Tastendruck wartet. Und der Spieler soll weiterhin die ganze Zeit einfach weglaufen können und nach z.B. zwei Tiles Entfernung zum Event soll die Message sich automatisch schließen und das Event in seinen Ausgangszustand zurückkehren.



    Hat jemand eine Idee, wie sich das umsetzen ließe? Oder ist das ganz utopisch?
    Ich kann mit MMW einfach nichts anfangen -- außer mit diesem einen sehr essentiellen Element davon.

    Geändert von Mordechaj (09.12.2017 um 19:19 Uhr)

  6. #6
    Also da du ein Custom Script verwendest sinkt die Wahrscheinlichkeit stark, dass dir jemand helfen kann. Und das mit den "Nach 2 Tiles Entfernng schließen schließen" fällt mir spontan keine Funktion ein die das macht. Man muss vermutlich von Scene_Map aus @window_message.terminate aufrufen., aber das mit "2 Tiles entfernung" muss mal jmd. anderes liefern, zu viel Arbeit. Vermutlich Position des Events das die Message anzeigt ermitteln und dann einfach Distanz zwischen dem Event und dem Helden mit einer Metrik deiner Wahl (euklidisch oder Manhattan) berechnen.

    Damit man noch laufen kann wenn eine Message angezeigt wird, würde bei nem Standard-Message-Script folgendes reichen:
    Eventuell klappts auhc bei dem Custom script.

    In Game_Player update ersetze die unless moving? Zeile mit
    Code:
    unless moving? or ($game_system.map_interpreter.running? and not $game_temp.message_window_showing) or
               @move_route_forcing
    Das "whitelisted" den Fall "interpreter läuft UND message window ist sichtbar".

  7. #7
    Erst einmal vielen Dank! Ich kann mir schon denken und kann auf alle Fälle verstehen, dass das die Wahrscheinlichkeit senkt; vor allem, weil man sich ja da erstmal anschauen muss, was dieses Script eigentlich so gut -- was ich übrigens selbst nur in sehr begrenztem Maße verstehe (wie begrenzt, wird sich gleich noch offenbaren ^^").

    Die Entfernung kann ich beispielsweise mit Event-Scriptbefehlen aus ForeverZer0s Script (Code im Spoiler) abfragen.



    Was ich beispielsweise bisher gebastelt habe, sieht so aus:

    Das ActionButton-Event:
    Code:
    # Variable 4 = ID dieses Events
    
    Script: $game_variables[4] = @event_id
    
    # Aktiviere den dazugehörigen Parallel Process
    # (Befehl aus einem Utility Script)
    
    Script: set_self_switch('A','On',3)
    
    # Message Box über diesem Event, asynchronous
    # (die Message wird angezeigt, ohne die Steuerung zu blockieren).
    # Warte nach dem letzten Zeichen eine Sekunde (\|\|) bevor die Box
    # geschlossen wird (\^)
    
    Text: \p[,async]Tenny mucho mucho Deniro in su trucky-trailer?\|\|\^
    Das dazugehörige Parallel Process Event macht Folgendes:
    Code:
    # Prüfe, ob Player noch in der Nähe ist
    # (X-Achse: Distanz zu Event mit gespeicherter ID = 2?)
    # Wenn nicht, zeige neue Message Box.
    # Deaktiviere Parallel Process.
    
    @>Conditional Branch: Script: x_dist?(2, $game_variables[4])
      @>
     :  Else
       @>Text: \p[kill,async]Lauf nicht weg!\|\|\^
       @>Control Self Switch: A =OFF
     :  Branch End
    
    # Prüfe, ob Player noch in der Nähe ist
    # (Y-Achse: Distanz zu Event mit gespeicherter ID = 2?)
    # Wenn nicht, zeige neue Message Box.
    # Deaktiviere Parallel Process.
    
    @>Conditional Branch: Script: y_dist?(2, $game_variables[4])
      @>
     :  Else
       @>Text: \p[kill,async]Lauf nicht weg!\|\|\^
       @>Control Self Switch: A =OFF
     :  Branch End
    Das Argument "kill" im \p-Tag ruft die Event ID aus Variable 4 ab, sodass die neue Message Box den aktuell über dem entsprechenden Event aktuell angezeigten Text abbricht und ersetzt. Wenn ich nur "\p[kill,async]" angebe, liest das Hermes-Script eine leere Message und löscht nur den über dem entsprechenden Event aktuell angezeigten Text.

    Das läuft also im Prinzip genau so, wie ich es möchte (wobei meine Frage trotzdem noch ist, ob man das nicht galanter lösen könnte). Aber mit einer sehr entscheidenden Einschränkung:

    Ich kann so nur eine einzige Message über dem Event ausgeben, weil der \p[,async]-Tag dazu führt, dass das Event automatisch die darauffolgende Nachricht ebenfalls ausliest, die dann automatisch ihren Vorgänger löscht. Außerdem muss ich die Messages so automatisch enden lassen, der Spieler kann die Message-Box also nicht durch Enter-Tastendruck schließen. Wenn es also bei dieser Lösung bleiben würde -- was nicht schlimm wär --, bräuchte ich die Möglichkeit, in einer async-Message am Ende einen Tastendruck zu verlangen, mit dem dann erst die nächste Message aufgerufen wird.

    Zitat Zitat von Ghabry Beitrag anzeigen
    Damit man noch laufen kann wenn eine Message angezeigt wird, würde bei nem Standard-Message-Script folgendes reichen:
    Eventuell klappts auhc bei dem Custom script.

    In Game_Player update ersetze die unless moving? Zeile mit
    Code:
    unless moving? or ($game_system.map_interpreter.running? and not $game_temp.message_window_showing) or
               @move_route_forcing
    Das "whitelisted" den Fall "interpreter läuft UND message window ist sichtbar".
    Das bedeutet also, ich würde für prinzipiell jede Message sagen, dass sie die Steuerung nicht blockieren soll? Kann ich das auch situativ, also bspw. mit einem Script-Befehl im Event machen?
    Und: Der Effekt wäre dann, dass der Player noch bewegt werden kann; wie ist das mit dem Enter-Drücken am Ende der Nachricht? Könnte ich, als Spieler, rumlaufen und gleichzeitig durch Enterdrücken die Message Box schließen? Ich werde es bei Gelegenheit einfach mal ausprobieren, aber ich erwarte fast, dass das wie immer wird: Ich mach irgendwas kaputt und brauche Stunden, um herauszufinden, wie ich's wieder baue, sodass ich dann erst überhaupt testen kann.

    Du merkst vielleicht, mein Scripting-Wissen ist massiv eingeschränkt; ich bin schon geschmeichelt, dass du mir zutraust zu wissen, was der Unterschied zwischen euklidisch und Manhattan ist. ^^"
    Vor allem auch deshalb schonmal und nochmal: Vielen Dank!

    Geändert von Mordechaj (09.12.2017 um 19:18 Uhr)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •