Steamworks

Documentação do Steamworks
Ficheiro de ações do jogo (IGA)

Vista geral


Os developers têm de fornecer um ficheiro de ações do jogo (IGA), que define as ações, conjuntos de ações e estrutura básica da configuração de input do respetivo jogo. O presente artigo descreve a estrutura geral deste ficheiro e inclui vários exemplos concretos de alguns jogos.

Ficheiros de exemplo


Como criar manualmente um ficheiro de ações do jogo

Comece por fazer download de um dos ficheiros IGA de exemplo acima. De seguida, crie um diretório denominado "controller_config" dentro da pasta do Steam (normalmente C:/Program Files (x86)/Steam/controller_config) e guarde o ficheiro nesse diretório. Como a pasta Steam já terá uma pasta com um nome parecido, certifique-se de que guarda o ficheiro na pasta "controller_config" e não na pasta "controller_base". Mude o nome do ficheiro para: "game_actions_X.vdf", sendo X o AppID do seu jogo no Steam. Se não souber o AppID do seu jogo, pode encontrá-lo no site de parceiros Steamworks.

Abra o ficheiro no seu editor de texto preferido. O ficheiro está num formato padrão da Valve chamado KeyValues, que é um formato simples e fácil de ler. Talvez também lhe seja útil fazer download de um dos nossos modelos de ficheiros IGA ou do ficheiro IGA do Portal 2 para referência.

Como gerar um ficheiro IGA a partir de um jogo existente que use a API do Steam Input


Ao guardar uma configuração para qualquer jogo no Steam como "local", poderá encontrar o ficheiro correspondente no diretório:
[Diretório do Steam]\UserData\[ID do utilizador]\241100\remote\controller_config\[AppID]\[nome do ficheiro].vdf

Segue-se um exemplo de onde as configurações locais do jogo Defender's Quest são guardadas num computador com Windows 10:

whereisvgf.png

(Estes ficheiros não são réplicas exatas do ficheiro IGA mestre enviado pelo developer, mas pode ter uma ideia da estrutura original ao olhar para os blocos "actions" e "localization", que são extraídos diretamente do ficheiro mestre.)

Aqui está um link para o ficheiro #library_controllersavedefaulttitle_0.vdf mostrado na imagem acima. Pode ser útil compará-lo com o ficheiro IGA mestre do Defender's Quest.

Formato do ficheiro IGA


O ficheiro IGA usa o formato de um documento VDF, que se trata do formato de dados da Valve usado para criar dados de objetos estruturados com pares de strings chave/valor.

Estrutura


A estrutura básica do ficheiro é um objeto wrapper com o nome "In Game Actions" e dois subobjetos denominados "actions" e "localization", respetivamente:

"In Game Actions" { "actions" { } "localization" { } }

Conjuntos de ações

Comecemos pelo objeto "actions". Este objeto irá conter os conjuntos de ações. A estrutura de um objeto "actions" tem o seguinte aspeto:
"actions" { "Nome_personalizado_do_conjunto" { "title" "#Título_personalizado" "StickPadGyro" { } "AnalogTrigger" { } "Button" { } } }

As strings "Nome_personalizado_do_conjunto" e "#Título_personalizado" são as únicas strings no exemplo acima que o utilizador deve substituir, as restantes são palavras-chave reservadas.

O valor que substituir "Nome_personalizado_do_conjunto" será o nome do conjunto de ações usado na API do Steam Input e o valor que substituir "#Título_personalizado" será o token de tradução usado na secção "localization" mais à frente no ficheiro. Tenha em mente que o símbolo # é obrigatório.

Cada conjunto de ações deve ter um nome diferente e é possível adicionar mais ao criar novos objetos dentro do objeto "actions" Não é necessário usar vírgulas ou parênteses retos, pois este formato é VDF e não JSON.

Existem três subobjetos possíveis para cada objeto de conjunto de ações: "StickPadGyro", "AnalogTrigger" e "Button". Estes são os únicos objetos que pode definir e que irão conter as definições de cada ação individual. Porém, não é obrigatório definir todas as três categorias.

Por exemplo, a seguinte estrutura é perfeitamente válida:
"actions" { "Nome_de_conjunto_1" { "title" "#Título1" "AnalogTrigger" { } "Button" { } } "Nome_de_conjunto_2" { "title" "#Título2" "StickPadGyro" { } } "Nome_de_conjunto_3" { "title" "#Título3" "Button" { } } }

StickPadGyro

Este bloco do conjunto de ações é para ações analógicas com até dois eixos de movimento, que normalmente são associadas a um joystick, um trackpad ou um giroscópio (daí o nome). Além disso, tudo o que pretenda controlar com um rato ou algo semelhante deve ser incluído aqui.

AnalogTrigger

Este bloco do conjunto de ações é para ações analógicas com apenas um eixo de movimento, que normalmente são associadas a um gatilho analógico.

Button

Este bloco do conjunto de ações é para ações puramente digitais, que só indicam se estão num estado ativo ou inativo. Embora o nome deste bloco seja "button,", ações digitais podem ser associadas a qualquer input físico, incluindo aqueles pensados para dados analógicos (como joysticks, trackpads, etc.).

Ações


Como um ficheiro IGA não fará nada até que tenha algumas ações definidas, vamos adicionar algumas!

Ações StickPadGyro

Vamos começar por adicionar algumas ações do tipo StickPadGyro (analógicas com 2 eixos). A título de exemplo, pode ser algo para mover a personagem (usaremos o nome "Move") e algo para controlar a câmara ("Camera").

"actions" { "FPSControls" { "title" "#Set_FPSControls" "StickPadGyro" { "Move" { "title" "#Action_Move" "input_mode" "joystick_move" } "Camera" { "title" "#Action_Camera" "input_mode" "absolute_mouse" } } } }

Como pode ver, a estrutura abstrata de uma ação do tipo StickPadGyro é:
"Nome_da_ação" { "title" "#Título_da_ação" "input_mode" "<analog_mode>" }

Os únicos valores editáveis pelo utilizador nesta estrutura serão "Nome_da_ação", "#Título_da_ação" e "<analog_mode>". Respetivamente, correspondem ao nome da ação usada na API do Steam Input, a chave de tradução usada na secção de tradução deste ficheiro e o modo de fonte de input que rege como os dados analógicos são processados e interpretados.

A propriedade "input_mode" tem dois valores possíveis para ações do tipo StickPadGyro:

  • "joystick_move"
  • "absolute_mouse"

Use "joystick_move" para uma ação cujos valores são interpretados como um joystick (deflexão constante a partir de um ponto central) e use "absolute_mouse" para uma ação analógica mais flexível e genérica. Se estiver na dúvida, use "absolute_mouse".

"joystick_move" vs. "absolute_mouse"

Temos de salientar que, ao criar um input de câmara para um jogo na primeira/terceira pessoa ou para qualquer ação que use o cursor, deve sempre usar o tipo "absolute_mouse" e reagir a deltas como se fosse um rato.

A API fará automaticamente o correto para inputs baseados no stick, logo terá um input de stick ajustável se a câmara for aplicada a um stick analógico (estilo PS4/Xbox) com características que pode especificar na configuração predefinida, como zonas mortas, curvas de resposta, etc. Este mesmo input irá funcionar com joysticks, trackpads ou giroscópios (Comando Steam/PS4) e futuramente com ratos.

Não deve usar o método de input "joystick_move" para a câmara, uma vez que não é possível mapear na direção oposta para obter dados 1:1 úteis de um trackpad/giroscópio/rato/controlos de movimento.

Esta advertência também se aplica a inputs baseados no cursor: "absolute_mouse" como cursor irá funcionar corretamente para inputs baseados no stick, logo não é um problema se criar um cursor baseado no stick.

Também é possível enviar eventos de rato de baixo nível com os dados analógicos. O seu jogo não poderá distinguir estes eventos daqueles gerados pelo sistema operativo. Para tal, adicione o parâmetro "os_mouse" com o valor de 1.

Por exemplo:
"StickPadGyro" { "Mouse" { "title" "#Action_Mouse" "input_mode" "absolute_mouse" "os_mouse" "1" } }


Ações AnalogTrigger
Ações do tipo AnalogTrigger são ações analógicas unidimensionais que podem ser associadas a gatilhos. Se pretender usar o gatilho para uma ação simples, como disparar ou ativar o modo de mira, recomendamos que use uma ação do tipo Button em vez de AnalogTrigger para que os utilizadores tenham uma maior flexibilidade na configuração dos controlos.

As ações do tipo AnalogTrigger têm uma zona morta configurável na interface de configuração de controlos e são ajustadas de 0 a 1.0f entre esses valores. Comandos com gatilhos digitais, como o comando Pro da Nintendo Switch, irão enviar ou 0 ou 1.0. Por isso, certifique-se de que não tem código para mecânicas do jogo que dependa de alterações graduais no gatilho.

Ações deste tipo têm um formato simples, com o nome da ação como a chave e o token de tradução como o valor. Por exemplo:
"AnalogTrigger" { "AccelerationAxis" "#Action_Accelerate" "BreakingAxis" "#Action_Brake" }

Ações Button

Ações do tipo Button também têm um formato semelhante, com o nome da ação e o token de tradução:
"Button" { "nome_da_primeira_ação_digital" "#TítuloDaPrimeiraAçãoDigital" "nome_da_segunda_ação_digital" "#TítuloDaSegundaAçãoDigital" }

Caso necessário, pode definir um evento de input de hardware de baixo nível (como um clique nativo do rato) que é ativado com a ação. Isto é útil em alguns casos especiais se o seu jogo depende de uma pilha de input complexa que nunca trata eventos do rato simulados vindos da camada da aplicação da mesma forma que eventos gerados diretamente pelo sistema operativo.

"Button" { "clique_simples" "#clique_simples" "clique_especial" "#clique_especial, mouse_button LEFT" }

Isto faz com que o jogo emita um evento genuíno do botão esquerdo do rato a nível de sistema operativo sempre que a ação "clique_especial" for ativada.

Atenção!

Nunca use este truque como um método de forçar inputs específicos para ações. Se o fizer, estará a contrariar o paradigma de "ações, não inputs" e a impedir que o utilizador tenha um controlo absoluto sobre a configuração. Se reparar que está a usar esta funcionalidade para mais do que resolver casos especiais e raros, provavelmente estará a abusar.

Layers de conjuntos de ações

Para além de usar apenas conjuntos de ações, também pode usar uma layer de conjunto de ações para sobrepor alterações graduais no conjunto de ações ativo. Este processo pode ser útil para especializações no modo geral (como, por exemplo, uma layer para controlos de sniper sobreposta nos controlos usados para andar) ou para lidar com casos em que um menu aparece à frente do jogo, como menus de votação. As layers são declaradas numa secção própria. Por exemplo:
"action_layers" { "IngameModalLayer" { "title" "#Layer_IngameModal" "legacy_set" "0" "set_layer" "1" "parent_set_name" "InGame" "AnalogTrigger" { } "Button" { "Modal_Accept" "#Action_Modal_Accept" "Modal_Decline" "#Action_Modal_Decline" } } }

Tradução


O ficheiro IGA mestre deve conter uma secção de tradução (denominada "localization") junto das definições de conjuntos de ações. Cada objeto derivado do objeto de tradução será uma string de um dos idiomas disponíveis no Steam. Não se esqueça de incluir, pelo menos, um bloco com títulos de ações em inglês.

"localization" { "english" { "move" "Move" "camera" "Camera" } }

Tenha em mente que os nomes das propriedades devem corresponder às chaves de tradução especificadas nas secções anteriores, mas sem o símbolo "#".

Para adicionar mais idiomas, basta adicionar mais blocos de idioma com texto traduzido para cada entrada:

"localization" { "english" { "move" "Move" "camera" "Camera" } "portuguese" { "move" "Andar" "camera" "Câmara" } "norwegian" { "move" "Bevege" "camera" "Kamera" } }
O token de cada idioma deve usar o respetivo "código de idioma na API" (por exemplo, "schinese" para chinês simplificado). A lista completa dos idiomas suportados está disponível aqui.

Como o Steam usa o ficheiro IGA


O ficheiro IGA mestre que criar só será usado durante o desenvolvimento (mas deverá ser guardado, mantido, armazenado no seu sistema de controlo de versões, etc.). Quando criar uma configuração oficial de input para o seu jogo durante o desenvolvimento, a aplicação Steam usa o ficheiro IGA mestre para gerar um modelo inicial.