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:
Beliebig viele Sektionen [ControlDef]
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 |
Wenn wahr, ist dies eine globale, d.h. keinem Spieler zugeordnete Definition. Siehe Globale Definitionen. |
Hold |
Boolean |
Wenn wahr, wird das Kommando als ein gehaltenes Kommando interpretiert. Ein solches Kommando speichert, ob die Steuerungstaste gedrueckt ist und generiert beim Loslassen ein zusaetzliches Scriptereignis. Siehe Gehaltene Tasten. |
RepeatDelay |
Integer |
Nur gueltig wenn Hold wahr. Wenn groesser 0, generiert die Taste im gehaltenen Zustand im angegebenen Abstand (in Frames) weitere Scriptereignisse. Siehe Tastenwiederholungen. |
InitialRepeatDelay |
Integer |
Wenn angegeben, kann die Wartezeit fuer das erste Tastenwiederholungsereignis geaendert werden. Siehe Tastenwiederholungen. |
DefaultDisabled |
Boolean |
Wenn wahr, ist das Kommando im Normalfall deaktiviert und muss erst per Script aktiviert werden. Nuetzlich fuer Kommandos, die nur in sehr speziellen Situationen benoetigt werden. Siehe Deaktivierte Kommandos. |
ExtraData |
C4ID |
Optionale ID, die an die Scriptfunktion uebergeben wird. Siehe 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:
Wert |
Beschreibung |
None |
Keine Aktion. |
Script |
Ausführung des Scriptbefehls PlayerControl. Siehe Script-Callbacks. |
ZoomIn |
Zoomt eine Einheit rein |
ZoomOut |
Zoomt eine Einheit raus |
Menu |
Oeffnen des Spielermenues (asynchrones Kommando). |
MenuOK |
Bestaetigen des ausgewaehlten Elementes im Spielermenue (asynchrones Kommando). |
MenuCancel |
Schliessen des Spielermenues (asynchrones Kommando). |
MenuLeft / MenuUp / MenuRight / MenuDown |
Navigation im Spielermenu (asynchrones Kommando). |
ObjectMenuOK / ObjectMenuSelect / ObjectMenuOKAll |
Bestätigen des ausgewählten Elements im Spielermenü (synchrones Kommando). |
ObjectMenuCancel |
Schließen des Spielermenüs (synchrones Kommando). |
ObjectMenuLeft / ObjectMenuUp / ObjectMenuRight / ObjectMenuDown |
Navigation im Spielermenü (synchrones Kommando). |
|
Sektion [ControlSets]
Definition von Standard-Steuerungsbelegungen.
Beliebig viele Sektionen [ControlSet]
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. |
Beliebig viele Sektionen [Assignment]
Wert |
Datentyp |
Beschreibung |
Key |
Zeichenkette |
Taste(n) dieser Belegung oder Referenz auf eine andere Belegung. Siehe Tastenbelegungen. |
ComboIsSequence |
Boolean |
Wenn wahr, werden mehrfache Tasten als Sequenz interpretiert. Das heisst, sie muessen nacheinander statt gleichzeitig gedrueckt werden. Siehe Tastenbelegungen. |
Control |
Zeichenkette |
Kommando, das mit dieser Belegung verknuepft wird. Der Name sollte dem Identifier eines in einer [ControlDef] definierten Kommandos entsprechen. |
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:
Wert |
Beschreibung |
Standardwert |
Keine besondere Aktion. |
Hold |
Die Taste versetzt das verlinkte Kommando in den gedrueckten Zustand, selbst wenn die Taste selbst nur angeschlagen wird. Nur gueltig, wenn das Kommando das Hold-Attribut gesetzt hat. Dieser Zustand bleibt erhalten, bis eine entsprechende Belegung mit Ausloesemodus Release gedrueckt wird. Siehe Gehaltene Tasten. |
Release |
Die Taste entfernt den gedrueckten Zustand. Eine Taste kann auch sowohl Hold als auch Release setzen, um zwischen den Zustaenden hin und her zu schalten. Siehe Gehaltene Tasten. |
AlwaysUnhandled |
Der Tastendruck wird immer an die Belegung mit der naechstniedrigen Prioritaet weitergereicht, unabhaengig davon, ob das vorherige Kommando erfolgreich ausgefuehrt wurde. |
ClearRecentKeys |
When the assignment is triggered, all recent keys are deleted and the trigger key is not added to the recent list. This means no future key combos can be triggered with any keys including and preceding the current. |
|
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, bool release)
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, bool release)
{
// Which command has been issued?
// The constant CON_Jump has been declared automatically through the definition in PlayerControls.txt
if (control == CON_Jump && !release)
{
// 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;
}
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, bool release)
{
// Handling of known controls
// [...]
// control with own handling
if (control_extra) return control_extra->PlayerControl(player, control, x, y, strength, repeat, release);
// unkown control
return false;
}
Und im Script der Schaufel:
func PlayerControl(int player, int control, int x, int y, int strength, bool repeated, bool release)
{
// 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.
-
Tastenwiederholungen werden erzeugt.
- Der Haltezustand der Taste kann mit GetPlayerControlState im Script abgefragt werden.
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, bool release)
{
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
...
Sven2, 2009-06