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;
}

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, 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:
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