In diesem Tutorial geht es darum, wie man das Zahlenschloss so umbaut, dass es jede Runde einen neuen Code hat. Die aufwandsfreiere Methode ist, ein logic_case in die Konstruktion des Zahlenschlosses zu implementieren. Wer jedoch das Maximum ausreizen will, muss sich nun durch dieses Tut quälen. Freilich werde ich auch gleich eine Möglichkeit erklären, den Code in der Map darzustellen zu können.
Vorneweg empfehle ich folgende Tutorials durchzuarbeiten:
(Anmerkung: Die ersten beiden Tutorials werden benötigt, um die Zahlen darstellen zu können. Das Zahlenschloss-Tutorial sollte komplett verstanden worden sein. Btw. sollte man genügend Interesse und Vorstellungsvermögen mitbringen, weil es in diesem Tut keine Bilder, dafür aber jede Menge Text gibt. Damit das ganze anschaulicher wird, stelle ich unter Downloads noch eine Beispielmap, sowie zwei vorgefertigte Materials zur Verfügung.)
Im Groben kann man die Konstruktion so beschreiben: Ein math_counter bekommt einen Wert, den er zu einem logic_case sendet, welches ein Ereignis triggert und zu einem logic_compare, welches entscheidet, ob der math_counter ein weiteres Mal getriggert und eine weitere Zahl ermittelt wird. Zudem wird der zufällig ausgewählte Wert des Computers zu einem math_counter geschickt, welcher seinen Wert zu den env_texturetoggles überträgt, welche dann wiederum eine Textur verändern, die die Zahl/das Symbol zeigt. Für dieses Tutorial habe ich eine Textur verwendet, welche die Zahlen von 0-9 (wobei der Zahlenwert dem Frame entspricht) auf durchschaltbaren Einzelbildern anzeigt. Soch, nun wollen wir aber mal loslegen.
Wir brauchen:
Neben dem Entity steht jeweils der Name, den ich für dieses genommen habe.
Es setzt die Maschinerie in Gang, wodurch der Computer den zufälligen Code bestimmt.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OnMapSpawn | cp_math | SetValue | 4 | 0.00 |
Sie stellen die Tasten 1-9 dar. Wahlweise kann man auch einen 10. für die Zahl 0 erstellen (Problematiken) oder einen zum Resetten (der Code wird in diesem Tutorial automatisch zurückgesetzt). Die Einstellungen sind egal, ich empfehle jedoch in den Flags nur „Use Activates“ zu markieren, damit durch eventuelles Berühren nicht ungewollte Eingaben getätigt werden. Namen brauchen die Buttons nicht.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OnPressed | p_math | add 1 | 0 | 0.00 |
| OnPressed | p_math | multiply 10 | 0 | 0.05 |
Das sind die Outputs für die Taste mit der 1. Für die weiteren Tasten (2-9) muss dann beim Add-Output jeweils die zugehörige Nummer des Buttons eingesetzt werden.
Er nimmt den zufälligen Codewert des Computers auf. Als Werte bekommt er überall eine 0.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OutValue | cp_compare | SetCompareValue | 0.00 |
Achtet hier unbedingt darauf, dass ihr den richtigen Input erwischt!
Er zählt den Eingabewert des Spielers. Als Werte bekommt er überall eine 0.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OutValue | cp_compare | SetValueCompare | 0.00 | |
| OutValue | r_math | Add | 1 | 0.00 |
Hier bitte ebenfalls darauf achten, dass ihr den richtigen Input nehmt! Beachtet auch, dass wir zu diesem Zeitpunkt den logic_branch (r_branch) noch gar nicht erstellt haben. Er wird erst ziemlich gegen Ende des Tuts erstellt.
Dieser ist primär zuständig für die Länge des Codes. Seine Werte sollten ebenfalls alle 0 sein. Sein „Initial Value“ wird später ingame automatisch geändert.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OutValue | cp_compare2 | SetValureCompare | 0.00 | |
| OutValue | c_case2 | InValue | 0.05 |
In diesem Case stehen die zufälligen Werte, welche c_math aufnimmt.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OnCase01 | m_* | SetValue | 1 | 0.00 |
| OnCase01 | c_math | add | 1 | 0.01 |
| OnCase01 | c_math | multiply | 10 | 0.05 |
Die Outputs werden für jedes Case (wie auch schon bei den Buttons) sinngemäß weitergeführt. Dabei entsprechen die ersten beiden Outputs dem jeweiligen Zahlenwert (z. B. bei der 2 hieße es dann: OnCase02, m_*; SetValue, 2, 0.00). Beachtet hier bitte den speziellen Entitynamen, welcher gleich mehrere Entities anspricht (m_1000 - m_0001). Der Multiply-Output bleibt bei jedem Case gleich. Wie die einzelnen Cases genannt werden ist egal.
Falls der Wert, den es erhält, größer ist als 0 (in diesem Fall), wird cp_math erneut getriggert.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OnGreaterThan | c_case1 | Pickrandom | 0.00 | |
| OnGreaterThan | cp_math | Subtract | 1 | 0.25 |
Es vergleicht den Zufallscode vom Computer mit den Eingaben des Spielers und setzt dementsprechend ein logic_branch auf True oder False.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OnEqualTo | r_branch | SetValue | 1 | 0.00 |
| OnNotEqualTo | r_branch | SetValue | 0 | 0.00 |
Den logic_branch (r_branch) haben wir zu diesem Zeitpunkt noch nicht erstellt.
Sie nehmen den zufällig gewählten Zahlenwert des Computers auf und übertragen ihn zu den env_texturetoggle. Alle Werte sollten 0 sein.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OutValue | tt_1000 | SetTextureIndex | 0.00 |
Die anderen 3 math_counter (m_0001, m_0010, m_0100) haben ebenfalls dementsprechende Outputs.
Dies ist dafür zuständig, dass die math_counter nacheinander deaktiviert werden. Wichtig ist, dass es als Cases die Zahlen 1-4 bekommt (also Case01 = 1, Case02 = 2,…).
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OnCase01 | m_0001 | Disable | 0.05 | |
| OnCase02 | m_0010 | Disable | 0.05 | |
| OnCase03 | m_0100 | Disable | 0.05 | |
| OnCase04 | m_1000 | Disable | 0.05 |
Es ermittelt, wie oft der Spieler bereits eine Eingabe getätigt hat. Wenn das Maximum erreicht ist, sendet es einen Test-Output zum r_branch, welcher dann entsprechend triggert. Als „Maximum Legal Value“ erhält er die doppelte länge des Codes, also in diesem Fall 8. Das ist aus dem Grunde so, weil durch die Buttons der p_math, von dem er seinen Input erhält doppelt getriggert wird (Addition und Multiplikation), wodurch der r_math dann jeweils +2 pro gedrücktem Knopf erhält.
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OnHitMax | r_branch | Test | 1.00 |
Hier wird verglichen, ob die Eingabewerte des Spielers mit dem Zufallswert des Computers übereinstimmen. Je nachdem wird entweder die Eingabe zurückgesetzt (wenn False) oder es wird ein Ereignis getriggert (wie z. B. das Öffnen einer Tür, wenn True).
| Output | Target Entity | Target Input | Parameter | Delay |
|---|---|---|---|---|
| OnFalse | p_math | SetValueNoFire | 0 | 0.01 |
| OnFalse | r_math | SetValueNoFire | 0 | 0.01 |
| OnTrue | <Entity> | <MachDies> | 0 | 0.05 |
Sie dienen dazu, den Code mithilfe der durchschaltbaren Textur darzustellen. Was für Zeichen/Zahlen ihr nehmt ist euch überlassen. Natürlich könnt ihr die Overlays auch durch andere Entities, wie z. B. einem func_brush ersetzen. Wichtig ist, dass jedes einen eigenen Namen erhält. Ich habe sie tt_1000, tt_0100, tt_0010 und tt_0001 genannt.
Sie sind dazu da, die Textur der Overlays zu ändern. Als „Target Brush“ wird der Name des jeweiligen Overlays (bzw. des Entities, welches ihr benutzt habt) eingetragen.
Die Konstruktion braucht nicht gerade wenig Entities, deswegen solltet ihr euch gut überlegen ob ihr sie wirklich in eure Map einbauen wollt. Falls ihr sie einbaut, sollte sie auch sinnvoll genutzt werden.
In der Beispielmap gibt es ein paar In- und Outputs, sowie ein paar Entites mehr, welche jedoch nicht direkt dafür benötigt werden, dass die Konstruktion funktioniert. Sie dienen viel mehr der Veranschaulichung, damit klarer wird, wo wie etwas letztendlich getriggert wird dadurch.
Alternativ zu der Möglichkeit den Code mithilfe von Texturen darzustellen, kann man ihn auch mit Klängen darstellen. Dabei solltet ihr darauf achten, dass der Code nicht durch das logic_auto generiert wird, weil ansonsten eine falsche Eingabe getätigt werden müsste um ihn zu erhalten, was Spieletechnisch unschick ist.
Wenn ihr ein logic_case für die simplere Auswahl an bereits festgelegten Codes benutzt, dann könnte der Code auch einfach mit einem game_text angezeigt werden.
Eine Einsatzmöglichkeit wäre z. B. bei TF2, wo ein Scout sich flott in die feindliche Basis begibt, um den Code für das Öffnen der Tür zur feindlichen Basis zu stehlen, während der Rest des Teams einen wichtigen Kontrollpunkt, etc. verteidigt.
Eine weitere Einsatzmöglichkeit wäre in einem DM-Spiel, wo der Code für eine Superrüstung/Waffe auf einem Display erscheint und er sich kurz vor jedem Respawn des Ausrüstungsgegenstandes neu generiert. Sich einen Code merken, während man von allen Seiten beballert wird und dann noch schnell zur Rüstung sprinten und unter Beschuss den Code eingeben (und ein anderer huscht stattdessen dann durch die geöffnete Tür) stelle ich mir besonders ulkig vor.
Seid kreativ. ;)