Mitsch93

Kriegsherr

  • »Mitsch93« ist der Autor dieses Themas

Motto: Aufgeben ist es, was den Menschen tötet. Nur der Mensch, der sich weigert aufzugeben, hat sich das Recht verdient, auf dem glanzvollen Pfad der Menschheit zu wandeln.

  • Nachricht senden

1

Mittwoch, 2. August 2017, 15:30

[OFFEN] Mitschs KS-Baustelle

Ahoi,

es ist mal wieder soweit; das KS braucht ein Update.
Der Grund: Das ATB geht mir gehörig auf die Nerven.

Im Grunde genommen ist es ein ganz schickes Addon, wären da nicht
die vielen Bugs, die es auslöst. Einige davon wurden zwar bereits behoben (Battle Event, Force Action)
trotzdem gibt es noch welche. Was mir beim jüngsten Testen dann noch aufgefallen ist,
sprengt den Rahmen und ich bekomm es auch nicht hin, das zu fixen.
Deshalb ist nun mein Plan, dass ATB komplett aus dem Spiel zu entfernen.

ZB erst neu gefundener Bug:
Ein State soll den Spieler 5 Runden lang heilen. Teilweise macht der States das aber
nur 2 oder 3 Runden, je nachdem wie schnell er Actor ist. Da 90% der States auf
diesem Muster basieren (Mache X Runde das und das), ist es ganz schön ,,breaking the
game mechanics". Aus diesem Grund will ich mich vom ATB verabschieden
und wieder mit dem Standard (mit einigen Veränderungen) Tankentai arbeiten.

Aber was geht mir auch dabei gegen den Strich?
  • Alle Spieler wähen zuerst ihre Aktion aus, danach tätigen sie die Aktion dann:
    Sehr zum Nachteil des Spielers (vor Allem in Bossfights), dass der Spieler schon
    eine Runde komplett durchplanen muss am Anfang, obwohl er noch nicht weiß, was in
    dieser Runde passiert. Kritisch wird das ganze vorallem dann, wenn der Boss enrage geht,
    Schildzauber oder fiese DoTs castet (wie beim Wasserlementar).
  • Der Spieler hat keinerlei Informationen über die Reihenfolge der Aktionen, wer
    wann welche Aktion tätigt. Auch das ist ein sehr großer Nachteil für Bossfights.


Was soll also gemacht werden?


1. Aktionen

Zuerst einmal, müsste die Reihenfolge im Kampf verändert werden.
Konkret soll das heißen, dass man immer nur die Aktion des aktuellen (schnellsten)
Battlers (Actors) auswählen kann. Danach wird die Aktion durchgeführt und der
nächste Actor ist an der Reihe.
Zur Veranschaulichung mal ein Bild dazu:
Links: alt, Standard, bäh! Rechts: meine Vorstellung

Bild

Zudem habe ich mal versucht, im Standard-KS einen Actor eine
weitere Aktion zu gewähren (im ATB macht man das ja einfach mit
battler.atb = atb_max). Ich habe es mit den Force-Action Befehlen versucht,
dabei kam aber raus, dass der Spieler keine vom Grund auf neue (freie) Aktion hat,
sondern einfach die letzte Aktion wiederholte. Das ist natürlich Käse.
Entweder hab ich es total falsch gemacht, oder es ist evtl. nicht ohne neue
Methode möglich. Wenn das so ist, müsste noch eine entsprechende Methode implementiert
werden.


2. Spieler-Reihenfolge und Anzeige

Kommen wir zum zweiten angesprochenen Punkt: der Spieler-Reihenfolge.
Beim ATB wird die ja auf der ATB-Leiste angezeigt. Mit dem Wegfallen des
ATB müsste eine andere Lösung her.
Mein Favourit ist eine Leiste wie in Herr der Ringe - das Dritte Zeitalter.

Dort gibt es einen Balken, mit einer symbolischen Anzeige aller Spieler (Actors+Enemies).
Der oberste in der Anzeige ist als erstes/aktuell dran, der unterste entsprechend als letztes.

Theoretisch und praktisch ist die Anzeige für mich relativ leicht zu implementieren,
im KS gibt es ja ein Array @action_battlers, das eben diese Reihenfolge beinhaltet.

Schwieriger hierbei ist aber eine vernüpftige Umsetzung des Ganzen.

Würde ich nur über das @action_battlers Array gehen, würde die Anzeige immer weiter schrumpfen,
denn nach einer getätigten Aktion, wird der Battler aus dem Array geschmissen.
Ich würde das gerne in einer Art Schlange machen, sprich: Wenn ein Actor gerade eine Aktion getätigt hat,
wird er wieder an das Array hintendran gehängt.

Hinzu kommt noch ein weiteres Problem: Aktuell ist es so, dass sich die Reihenfolge
während einer Runde nicht ändert, sondern nur zu Beginn einer Runde.
Das ist natürlich vollkommen blöd.
Beispiel:
Vareesa (sehr schneller Charakter) ist als erstes dran. Gibt Artih (sehr langsam) einen
Beweglichkeitstrank, um das Tempo zu erhöhen. Effekt: Bringt in dieser Runde rein gar nichts,
da die Reihenfolge nicht mehr verändert wird. Sprich, Arith wir erst in der kommenden Runde schneller sein.


Für das Problem habe ich schon eine Methode geschrieben, die einfach die Reihenfolge updatet.

Ruby Quellcode

1
2
3
4
5
6
7
8
9
  #--------------------------------------------------------------------------
  # * Refesh Action Order
  #--------------------------------------------------------------------------
  def refresh_action_order
    for battler in @action_battlers
      battler.make_action_speed
    end
    @action_battlers.sort! {|a,b|b.current_action.speed - a.current_action.speed }
  end


Diese Methode müsste dann aufgerufen werden, wenn:
  • Ein BattleEvent (Battle Event Page) ausgelöst wird
  • Beim "Result" (Attack, Skill, Item)

Das konnte ich auch schon gut einfügen, nur besteht das Problem beim Skill:
Skill wird ausgeführt -> Action Order Refresh -> CE Aufruf durch Skill.
Eigentlich müsste man mit dem Refresh noch warten, bis das CE aufgerufen wurde,
das habe ich aber noch nicht hinbekommen können.

So, jetzt springe ich nochmal zurück zum Thema Anzeige bzw. generelle Reihenfolge.
Hierbei müssen auch Fälle abgefangen werden wie "Gegner verschwindet" der "Gegner taucht auf" (hidden).

Die Anzeige würde ich so realisieren:
Es gibt das @action_battlers Array und danach soll sich auch einfach im Kampf orientiert werden.
Für die Anzeige würde ich noch ein Hilfs-Array basteln, dass die gelöschten Battler aus dem
@action_battlers Array einfach hinten dranhängt.
Beide Arrays zusammen würden dann bei der Anzeige den Eindruck einer Schleife erwecken.





So ich hoffe es ist soweit klar, was gemeint ist.
Ich habe mich teilweise schon selbst dran versucht, bin aber gescheitert
(habe es an einem neuen Projekt am Standard-KS probiert).

Da ich mich mit der Grund-KS-Mechanik auch noch nicht so gut auskenne, muss ich da ein wenig
an die Hand genommen werden :D
Vorallem wo man am besten bei sowas anfängt - hätte jetzt bei Punkte 1) angefangen, aber
wie gesagt; alleine gescheitert^^.

Alle verwendeten, relavanten Skripte befinden sich als .txt im Anhang.
»Mitsch93« hat folgende Dateien angehängt:

2

Mittwoch, 2. August 2017, 23:59

tl;dr


Ist denn schon zehnjähriges Jubiläum? Ich hab's euch gesagt! :3

@refresh_action_order: Warum benutzt Du Minus statt <=>?

Zitat

Da ich mich mit der Grund-KS-Mechanik auch noch nicht so gut auskenne, muss ich da ein wenig
an die Hand genommen werden :D
Im Prinzip hast Du erstmal eine Statemachine (realisiert über die @phase-Variable). Die ist für alle Kämpfer die gleiche, also eigentlich sind im StandardKS immer alle Kämpfer in der selben Phase. Das willst Du ja scheinbar aufbrechen. Das ist möglich, aber dann müsste man halt eine saubere neue Statemachine definieren. Da Du am besten weißt, was Du alles im Kampf hast und möchtest, wäre es am besten Du schreibst die auf mit allen Zuständen und Zustandsübergängen. Und wenn das geplant ist, dann programmiert man das ganze. ;) Aber ja - das wird einiges an Zeit kosten, sowas zu machen einfach weil der Umfang groß ist, aber könnte man sich mal dransetzen. Siehe auch diesen Beitrag 16 letzter Absatz.

Mitsch93

Kriegsherr

  • »Mitsch93« ist der Autor dieses Themas

Motto: Aufgeben ist es, was den Menschen tötet. Nur der Mensch, der sich weigert aufzugeben, hat sich das Recht verdient, auf dem glanzvollen Pfad der Menschheit zu wandeln.

  • Nachricht senden

3

Freitag, 4. August 2017, 23:49

Zitat

@refresh_action_order: Warum benutzt Du Minus statt <=>?

Wenn ich den Operator richtig gegoogelt habe, dann sollte der doch eigentlich nicht
dafür geeignet sein oder nicht?
a <=> b ; a > b : 1, a = b : 0, a <b : -1

Damit hätte man ja nur 3 Geschwindigkeiten und keine richtige Differenz, über die dann
der schnellste Actor ermittelt wird, oder sehe ich das gerade falsch?
Im Standard-KS wird das ja auch mit einem Minus gemacht.

Zitat

Und wenn das geplant ist, dann programmiert man das ganze.

Mein Plan war es eigentlich, erstmal das Standard-KS zu verändern, uind wenn das einwandfrei läuft,
Code vom Tankentai zu "klauen" und copy-paste durchzuheizen (das war zumindest meine Hoffnung) :D

Zum KS:
Ich habe deinen Rat befolgt und mal ein Zustandsdiagramm erstellt.
Bild

Voller Motivation habe ich mich dann nochmal ans Standard-KS gesetzt. Mit dem Zustandsgraphen im
Nacken ging es dann auch wesentlich besser. Dachte wirklich anfangs, mit ein bisschen hier und da editieren wäre
es erledigt, aber man muss ja wirklich den Großteil umschreiben^^.

Habe es dann auch soweit zum laufen bekommen. Einige Kleinigkeiten fehlen noch (z.B. Battle End).

Allerdings taucht folgender Bug auf:
In der ersten Runde (Nullte Runde) können nur Actors eine Aktion auswählen, Enemies nicht.
Keine Ahnung, wie ich das hingebekommen habe^^, kurz davor ging es noch einwandfrei.

Das Projekt ist mal im Anhang.
Nicht von den 9 teiligen Skript erschrecken lassen. Habe es wirklich versucht ganz Schritt für
Schritt hinzubekommen. Und für den Anfang heißt es : Je mehr Phasen, desto besser.
Das hilft mir Zwecks Übersichtlichkeit. Bisher ist auch Battle_ActionEnd mit noch nichts
belegt, evtl. ändern sich da ja noch Sachen, also werde ich erstmal diese größere Strukur weiter benutzen.

Und ich habe mal eine Frage zum folgenden Codeausschnitt:

Ruby Quellcode

1
2
3
4
5
6
7
8
9
    # If an action forcing battler doesn't exist
    if $game_temp.forcing_battler == nil
      # Set up battle event
      setup_battle_event
      # If battle event is running
      if $game_system.battle_interpreter.running?
        return
      end
    end


Eigentlich sitzt das in Scene_Battle 4 Zeile 98, bei mir in Battle_6 Zeile 54.
Mir ist der Sinn hiervon nicht ganz klar. Ist das ein Trigger, falls im Battle Event als Auslöser
Actor.hp <= 0 oder sowas steht?

Edit

Konnte noch ein wenig dran basteln. Die Anzeige der Kampfreihenfolge habe ich eingefügt
und die scheint auch gut zu funktionieren (zumindest bis jetzt ohne Fehler).
Sie wird immer geupdatet und sollte sich die Agi eines Battlers ändern, ändert sich evtl.
die Kampfreihenfolge (wie es auch sein soll).
Es funktioniert auch alles korrekt, wenn Battler sterben / verschwinden / sich verwandeln.

Was immer noch buggy ist, dass in der ersten Runde die Enemies keine Aktion tätigen.
Aktuellste Version im Anhang.

PS: Bei einem Codeabend wäre ich am start, evtl. bin ich sogar dieses WE Freitag/Samstag abends online.


Edit
PPS:
Was noch gar nicht funktioniert ist der Force-Action-Befehl. Mir war zwar klar, dass durch
die ganzen Änderungen der Eventbefehl nicht mehr funktioniert, aber ich kriege es auch per Skript
nicht zum Laufen. Da bräuchte ich auch mal faschmännische Beratung.

Ebenso die Programmierung für eine zusätzliche freie Aktion.
Hingekriegt :love:

Aktuelle Version mit freier Aktion hinzugefügt (Anhang).
Aluxes Standardskill löst zusätzliche Aktion aus. Ist gerade noch bisschen hardcoded,
werde ich morgen erst verbessern.
»Mitsch93« hat folgende Dateien angehängt:

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Mitsch93« (4. August 2017, 23:20)


4

Samstag, 5. August 2017, 00:36

Hier mal der Auszug aus der Ruby-Dokumentation, wie sort funktioniert. Der Block ist nur für die paarweisen Vergleiche nötig:
Array#sort → an_array
Array#sort {| a,b | block } → an_array


Returns a new array created by sorting self. Comparisons for the sort will be done using the <=> operator or using an optional code block. The block implements a comparison between a and b, returning -1, 0, or +1. See also Enumerable#sort_by.

Ruby Quellcode

1
2
3
a = [ "d", "a", "e", "c", "b" ]
a.sort                    #=> ["a", "b", "c", "d", "e"]
a.sort {|x,y| y <=> x }   #=> ["e", "d", "c", "b", "a"]

Tatsächlich, scheint man aber auch Minus benutzen zu können. Interessant!

Zitat

Bei einem Codeabend wäre ich am start, evtl. bin ich sogar dieses WE Freitag/Samstag abends online.

Zitat von »Chat«

(19:46:08) Steve: Mitsch93 betritt den Raum.
(23:35:35) Steve: Mitsch93 + Chat = #ERROR (timeout)
(23:35:39) Steve: Playm betritt den Raum.
(23:35:46) Playm: Ah
(23:35:50) Playm: Knapp den Mitsch verpasst
"abends online" :hm: Samstagabend bin ich leider nicht da. :(

Zitat

Eigentlich sitzt das in Scene_Battle 4 Zeile 98, bei mir in Battle_6 Zeile 54.
Mir ist der Sinn hiervon nicht ganz klar. Ist das ein Trigger, falls im Battle Event als Auslöser
Actor.hp <= 0 oder sowas steht?

An dieser Stelle im Kampfverlauf starten alle BattleEvents. (Ausgenommen die, die als Condition haben vor dem Kampf ausgeführt zu werden. Diese starten in Phase1 schon.)
Im Standard-KS kann man das ganz gut nachvollziehen. Wenn in der Main-Phase kein ForceAction gibt, dann wird das erste Event gestartet, dessen Conditions erfüllt sind und returned. Im Scene_Battle#update wird dann geguckt: Läuft der Eventinterpreter gerade? Wenn ja, arbeite den ab und starte danach die restlichen BattleEvents die noch von der Condition her passen. Danach geht das Update wieder in update_phase4 rein und die restliche Mainphase läuft an. Stelle gerne noch Detailfragen, Mitsch.

@Zwei Dateien angehangen: Noch nicht runtergeladen. :x Vielleicht gucke ich da am Wochenende mal drauf. Mal sehen.

Mitsch93

Kriegsherr

  • »Mitsch93« ist der Autor dieses Themas

Motto: Aufgeben ist es, was den Menschen tötet. Nur der Mensch, der sich weigert aufzugeben, hat sich das Recht verdient, auf dem glanzvollen Pfad der Menschheit zu wandeln.

  • Nachricht senden

5

Samstag, 5. August 2017, 18:43

Musste gestern abend noch meine Freundin abholen^^.

Wäre auf jeden Fall sehr edel von dir, wenn du mal drübergucken könntest.
So richtig habe ich es noch nicht raus, wie ich richtig die BattleEvent Pages trigger.

Habe es mal getestet mit Span: Moment, wenn ein Gegner tot ist. Das BattleEvent wird nicht
nur falsch ausgelöst (Gegner stirbt -> nächster Battler ist dran, erst nachdem dann dieser eine
Aktion tätigt wird Event getriggert. Evtl den oben geposteten Ausschnitt in"Main" verlagern? Aktuell
ist der Abschnitt von in "Action"), sondern wiederholt sich dann auch in Endlossschleife.

Werde das mal noch mit anderen Conditions durchtesten. Span Battle und Span Turn
scheint jedenfalls korrekt zu funktionieren.

Und wie gesagt - woran es liegt, dass in der ersten Runde die Enemies keine Aktion ausführen,
weiß ich immer noch nicht.

Achso, in die erste Version braucht du eigtl nicht mehr reingucken, die aktuellste ist:
New Battle - mit freier Aktion.exe

Irrlicht

Leuchtendes Irgendwas

Motto: Keep shining!

  • Nachricht senden

6

Samstag, 5. August 2017, 21:30

Huhu,

Ich erinnere mich dass ich irgendwann mal vorhatte eine eigene Interpretation vom ATB-Addon zu schreiben, mittlerweile weiß ich leider nichtmal mehr was ich damals alles ändern wollte... Aber so wie es aussieht kannst du diese Arbeit ja ohnehin bald übernehmen. :)

Zitat

Und wie gesagt - woran es liegt, dass in der ersten Runde die Enemies keine Aktion ausführen,
weiß ich immer noch nicht.
Ohne es selbst getestet zu haben würde ich vermuten dass das an der Methode liegt die die Aktionen der Gegner auswürfelt (Game_Enemy#make_action). Soweit ich weiß war die so geschrieben dass in Runde 0 nur Aktionen gewählt wurden bei denen als Bedingung "Turn 0+0x" eingestellt war.

Im Standardkampfsystem wird ja zu Beginn der Hauptphase (Scene_Battle#start_phase4) ja erst der Rundenzähler erhöht und dann die Aktionen der Gegner festgelegt sodass keine Probleme auftauchen.


Unabhängig davon könntest du evtl. battler.hp > 0 an einigen Stellen durch battler.movable? bzw. battler.inputable? ersetzen. Im Moment kann ein betäubter Actor immernoch Aktionen auswählen und der Kampf hängt sich zwischen update_phase6_step1 und update_phase6_step2 auf (in "step1" wäre im Standardkampfsystem ja der nächste Battler ausgewählt worden).


(Leider ein etwas unvollständiger Beitrag... mal wieder. Aber viel Erfolg dir mit deinem Vorhaben :) )

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Irrlicht« (5. August 2017, 22:16)


Mitsch93

Kriegsherr

  • »Mitsch93« ist der Autor dieses Themas

Motto: Aufgeben ist es, was den Menschen tötet. Nur der Mensch, der sich weigert aufzugeben, hat sich das Recht verdient, auf dem glanzvollen Pfad der Menschheit zu wandeln.

  • Nachricht senden

7

Montag, 7. August 2017, 20:34

Ah danke, jap, wenn ich alle Enemy Actions auf "Turn 0+0X" stelle funktioniert es wie gewollt.

Und danke für den Tipp mit moveable und inputable.
Unterschied scheint ja nur zu sein:
moveable = false => Battler kann gar nichts machen
inputable = false => Battler kann Aktionen duchführen, aber nicht auswählen (zB bei "Always attack allies")

Wenn ich es jetzt noch hinkriege, alle BattleEvents korrekt zu triggern,
steht das Grundgerüst eigentlich schon.
War ja gar nicht so kompliziert wie gedacht^^. Aber wird vermutlich
nochmal ein Brocken Arbeit das Tankentai in das Grundgerüst zu kriegen.


Edit
Soho Freunde der Sonne, das KS ist fertig.

Runden:
Eine Runde ist erst zuende, nachdem alle noch agierenden Battler (als nicht tot, bewegungsunfähig usw) eine AKtion getätigt haben (so wie im Standard-KS).
Am Ende jeder Runde kommen Befehle wie SlipDamage und RemoveStateAuto -> Damit sollte das so funktionieren,
wie ich es mir gewünscht haben.

Reihenfolge:
Die angezeigte Reihenfolge besteht aus zwei Arrays. Im ersten Array (@order_array_now) befinden sich alle Battler die noch an der Reihe sind,
in @order_array_next alle Battler, die bereits eine Aktion getätigt haben. Sobald ein Battler eine Aktion tätigt, wird er an das Ende des @order_array_next
verschoben, sodass das ganze sich wie eine Art Warteschlange verhält.

Einmalig wird am Anfang einer jeden Runde die Kampfreihenfolge entschieden. Per update_action_speed wird weiterhin überprüft, ob sich die
AGI eines Battlers ändert, und er somit schneller agieren kann -> dadurch kann sich die Reihenfolge ändern.
Das update muss geschehen, wenn:
  • Nachdem ein CE aufgerufen wurde
  • Am Ende einer Aktion
  • Am Anfang einer Runde

Das sind alles Möglichkeiten, wann die AGI eines Actors verändert werden könnte, daher die relativ häufigen Aufrufe.

Anzeige der Reihenfolge
Battler die tot oder hidden sind, werden nicht in der Liste angezeigt.

Force Action und New Action
Force Action (das Erwzingen einer bestimmten Aktion) sowie New Action (Auswahl einer komplett neuen, freien Aktion) wurden erfolgreich implementiert.
Zusätzlich kann bei Force Action ausgewählt werden, ob die Aktion, die dadurch ausgelöst wurde, als eine Aktion zählt oder nicht.
Wenn es bpsweise als Action zählt, dann kann der betroffene Battler in der aktuellen Runde keine freie Aktion mehr tätigen.

Ebenso sollten auch die von Irrlicht angesprochenen Bugs behoben sein.
Bisher konnte ich noch keine Fehler ermitteln und es läuft wie es soll.

Deshalb werde ich mich dann in den kommenden Tagen darum kümmern, dass das Sideview in diese Struktur
irgendwie eingebraucht wird. Tipps hierfür? Denke, dass ich da große Hilfe brauchen werde^^.



»Mitsch93« hat folgende Datei angehängt:
  • New Battle.exe (1,03 MB - 1 mal heruntergeladen - zuletzt: 8. August 2017, 00:18)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Mitsch93« (7. August 2017, 20:34)


Social Bookmarks