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 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:
Wert Beschreibung
None Keine Aktion.
Script Execution of the script function PlayerControl. See Script callbacks. (Default value)
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 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:
Wert Beschreibung
Standardwert Keine besondere Aktion.
Hold The key changes the state of the command linked to to be held even if the key itself is pressed only shortly. Only valid if the Hold attribute is set for the command. This state remains until a corresponding mapping with trigger mode Release is being pressed. See Held keys.
Release The key removes the held state. A key can have both Hold and Release set to toggle between the two states. See Held keys.
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, 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:
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

...
Sven2, 2009-06