Spielersteuerung
OC erlaubt die Engine, Steuerungskommandos fuer Spieler komplett frei zu definieren. Eigene Tastaturkommandos koennen hinzugefuegt oder veraendert werden. Alle unterstuetzten Eingabegeraete wie Maus, Tastatur und Gamepads koennen frei belegt werden und Kommandos koennen aus beliebigen Tastenkombinationen oder Sequenzen bestehen.
PlayerControls.txt
All control commands which a player can send to the game are defined in the file PlayerControls.txt. The standard keys as well as their standard mapping for various input devices are contained in the global definition file in the Systems.ocg folder. Object definitions and scenarios can add more keys or overload the parameters of existing commands in their local Systems.ocg folder.
Sektion [ControlDefs]
Definition der moeglichen Spielerkommandos. Dieser Sektion untergeordnet:
Wert | Datentyp | Beschreibung | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Identifier | Zeichenfolge (Max. 96 Zeichen) | Intern benutzter Name zur Identifikation des Kommandos. Das Kommando wird unter diesem Namen in Standardbelegungen referenziert und im Script als CON_Name-Konstante vordefiniert. Der Name sollte folglich im Script gueltig sein, d.h. nur aus Buchstaben, Zahlen sowie _ bestehen. Insbesondere sollten keine Leerzeichen oder deutsche Umlaute verwendet werden. Zur Vermeidung von Konflikten gelten in szenarienlokalen sowie Objektpaketlokalen Definitionen dieselben Benennungsregeln wie zur Vergabe von Objekt-IDs. | ||||||||||||||||||||||||
GUIName | Zeichenkette | Name, der dem Spieler im Steuerungskonfigurationsdialog sowie in den Steuerungstooltips angezeigt wird. Lokalisierte Zeichenketten koennen aus dem zugehoerigen StringTable refeenziert werden ($Name$). | ||||||||||||||||||||||||
GUIDesc | Zeichenkette | Informative description which is displayed to the player in the control configuration dialog. Localized strings from the corresponding string table can be used ($Desc$). | ||||||||||||||||||||||||
Global | Boolean | If true this is a global definition, i.e. not assigned to a particular player. See Global definitions. | ||||||||||||||||||||||||
Hold | Boolean | If true this command is interpreted as a held command. Such a command remembers whether the control key is pressed and generates another scripting event when it is released. See Held keys. | ||||||||||||||||||||||||
RepeatDelay | Integer | Only valid if Hold is true. If greater than 0 then this key generates additional scripting events while pressed every that many number of frames. See Key repeats. | ||||||||||||||||||||||||
InitialRepeatDelay | Integer | If specified then the delay of the first key repeat event can be changed. See Key repeats. | ||||||||||||||||||||||||
DefaultDisabled | Boolean | If true then the command is deactivated in the normal case and needs to be activated by script first. This is useful for commands that are only required in special situations. See Deactivated commands. | ||||||||||||||||||||||||
ExtraData | C4ID | Optional ID that is passed to the script function. See ExtraData. | ||||||||||||||||||||||||
CoordinateSpace | Game, Viewport | For viewport the given coordinates are relative to the players top left corner of the window. Default ist Game. | ||||||||||||||||||||||||
SendCursorPos | Boolean | Wenn wahr, wird mit dem Kommando die GUI-Mausposition zum Zeitpunkt des Ausloesens des Kommandos als separates CON_CursorPos-Kommando gesendet. Ist keine Maus aktiviert, wird die Cursorposition in GUI-Koordinaten uebertragen. | ||||||||||||||||||||||||
Action | Zeichenkette |
Auszufuehrende Aktion bei diesem Kommando. Moegliche Werte:
|
Sektion [ControlSets]
Definition von Standard-Steuerungsbelegungen.
Wert | Datentyp | Beschreibung |
---|---|---|
Name | Zeichenkette | Internal name for identification of otherwise equal control mappings. By using placeholders (*) keys can directly be defined in multiple mappings. |
GUIName | Zeichenkette | Name der Steuerung welche wie sie in den Optionen angezeigt wird. |
Keyboard | Boolean | Ob diese Steuerung die Tastatur benutzt. Default 1. |
Mouse | Boolean | Ob diese Steuerung die Maus benutzt. Default 1. |
Gamepad | Boolean | Ob diese Steuerung ein Gamepad benutzt. Default 0. |
Wert | Datentyp | Beschreibung | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Key | Zeichenkette | Specifies the key(s) of this mapping or a reference to another mapping. See Key mappings. | ||||||||||||
ComboIsSequence | Boolean | If true then multiple keys are taken as a sequence, i.e. they need to be pressed one after the other instead of all at the same time. See Key mappings. | ||||||||||||
Control | Zeichenkette | Command that is combined with this mapping. The name should be equivalent to the Identifier of a command defined in a [ControlDef]. | ||||||||||||
GUIName | Zeichenkette | Name which is shown to the player in the control configuration dialog and in control tooltips. Localized strings from the corresponding string table can be used ($Name$). If unset, GUIName of the control def is used. If set to "None", the control is not displayed in the user customization dialog even if the control def has a name set. | ||||||||||||
GUIDesc | Zeichenkette | Informative description which is displayed to the player in the control configuration dialog. Lokalisierte Zeichenketten koennen aus dem zugehoerigen StringTable refeenziert werden ($Name$). If unset, GUIDesc of the control def is used. | ||||||||||||
GUIGroup | Integer | Tastenbelegungen in der gleichen Gruppe werden in den Optionen zusammen angezeigt. Die Gruppe mit der kleinsten Nummer erscheint ganz oben in der Liste. | ||||||||||||
GUIDisabled | Boolean | Ob diese Tastenbelegung nicht in den Optionen angepasst werden kann. Default 0. | ||||||||||||
Priority | Integer | Prioritaet der Belegung. Nutzen mehrere Belegungen die gleichen Tasten, so wird zunaechst die Taste mit der hoeheren Prioritaet ausgefuehrt, bis ein Kommando als behandelt gilt. | ||||||||||||
TriggerMode | Bitmask |
Auslösemodus dieser Belegung. Bitmaske aus folgenden Werten:
|
||||||||||||
OverrideAssignments | Boolean | Die Zuweisung ueberschreibt alle weiteren Zuweisungen zum gleichen Control mit gleichem Press/Release-Triggermodus. |
Script-Callbacks
Zum Initialisieren der Spielersteuerung wird für jeden gesteuerten Spieler die Funktion InitializePlayerControl aufgerufen. Dieser Aufruf erfolgt gegebenenfalls einige Frames verspätet nach InitializePlayer, da die Initialisierung der Steuerung im Netzwerk übertragen werden muss. Beim Fortsetzen von Spielständen wird InitializePlayerControl wiederholt aufgerufen. Die gewählte Steuerung kann sich hier von der ursprünglichen Steuerung unterscheiden. Gleiches gilt, falls der Spieler mitten im Spiel die Steuerung wechselt.
global func InitializePlayerControl(int player, string control_name, bool has_keyboard, bool has_mouse, bool has_gamepad) { // Here one has the possibility to create special control elements like a gamepad crosshair // or destroy it because the controls have changed from gamepad to another control return true; }
Die meisten Kommandos (abgesehen von asyrnchronen Kommandos im Spielermenue), rufen eine globale Scriptfunktion auf:
global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, int state)
Fuer eine Erlaeuterung der Parameter siehe PlayerControl. Die Funktion erhaelt unter anderem den aufrufenden Spieler in player, sowie das ausgefuehrte Kommando in iControl.
Fuer ein einfaches Beispiel sei in der globalen PlayerControls.txt folgendes Kommando definiert:
[ControlDefs] [ControlDef] Identifier=Jump GUIName=Jump GUIDesc=Hoppin' around Repeat=5 [ControlSets] [ControlSet] Name=Keyboard1 [Assignment] Key=W Control=Jump Priority=50
Dies definiert eine Sprungtaste und die zugehoerige Standardbelegung auf der Tastatur fuer den ersten Spieler. Dazu folgendes Script zur Behandlung:
global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, int state) { // Which command has been issued? // The constant CON_Jump has been declared automatically through the definition in PlayerControls.txt if (control == CON_Jump && state == CONS_Down) { // pressed the jump button. The clonk selected by the player shall jump var player_clonk = GetCursor(player); if (player_clonk && player_clonk->Jump()) { // The command has been processed successfully return true; } } // Unbekanntes Kommando return false; }
ExtraData
Da nicht jede Objektdefinition die globale PlayerControl-Funktion ueberladen kann, gibt es das ExtraData-Feld zum Verteilen von Kommandos. Zum Beispiel fuer folgende Definition:
[ControlDefs] [ControlDef] Identifier=Dig GUIName=Dig GUIDesc=Going underground ExtraData=Shovel
Dabei sei Shovel die ID eines Schaufelobjektes. Im globalen Script kann zum Beispiel folgende, allgemeine Behandlung fuer unbekannte Kommandos stehen:
global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, int state) { // Handling of known controls // [...] // control with own handling if (control_extra) return control_extra->PlayerControl(player, control, x, y, strength, repeat, state); // unkown control return false; }
Und im Script der Schaufel:
func PlayerControl(int player, int control, int x, int y, int strength, bool repeated, int state) { // Handling of known controls // Control dig directly in the shovel if (control == CON_Dig) { // Only if a clonk is selected that can dig var player_clonk = GetCursor(player); if (player_clonk && player_clonk->HasShovel()) { return player_clonk->StartDig(); } } // Unkown control return false; }
Gehaltene Tasten
Wird fuer ein Kommando das Hold-Flag gesetzt, so speichert die Engine den gegenwaertigen Tastenzustand fuer diese Taste. Solche Tasten haben einige Besonderheiten:
- Sie generieren auch beim Loslassen PlayerControl-Aufrufe mit gesetztem Release-Flag im Script.
- Belegungen koennen mit den Hold/Release-Flags dauerhafte Tastendruecke emulieren.
- Key repeats are generated.
- Der Haltezustand der Taste kann mit GetPlayerControlState im Script abgefragt werden.
- If the command is bound to an analog stick or trigger on a controller, every change in position causes in a call to PlayerControl() with state = CONS_Moved.
Bestes Beispiel hierfuer ist ein Richtungskommando:
[ControlDef] Identifier=Left GUIName=Left GUIDesc=Walk left Hold=1
Im Script wird die Richtung dann auf den Clonk uebertragen:
global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, int state) { if (control == CON_Left) return UpdateControlDir(player); // ... } global func UpdateControlDir(int player) { // Clonk is selected? var player_clonk = GetCursor(player); if (player_clonk) { // update control dir var new_comdir = COMD_Stop; if (GetPlayerControlState(player, CON_Left)) new_comdir = COMD_Left; player_clonk->SetComDir(new_comdir); // control handled return true; } // control handled return false; }
Um klassisches Steuerungsverhalten zu erreichen, kann eine Tastenbelegung den Hold-Zustand emulieren:
[Assignment] Key=A Control=Left TriggerMode=Hold [Assignment] Key=S Control=Left TriggerMode=Release | AlwaysUnhandled
Globale Definitionen
...
Tastenwiederholungen
Hat ein Kommando ein RepeatDelay definiert, so werden wiederholte Kommandos beim Halten der Taste erzeugt. Zum Beispiel fuer ein Wurkommando:
[ControlDef] Identifier=Throw GUIName=Throw GUIDesc=Get rid of your selected inventory Hold=1 RepeatDelay=5 InitialRepeatDelay=35
Im Beispiel koennte man die Wurftaste nach einmal Druecken auch halten. Das Wurfkommando wuerde dann nach 35 Frames (ca. eine Sekunde) halten alle 5 Frames automatisch wiederholt.
Wiederholungen werden nur erzeugt, wenn das Kommando ebenfalls das Hold-Flag gesetzt hat.
Deaktivierte Kommandos**
...
Tastenbelegungen
...
Prioritäten
...