Documentação do Steamworks
Estatísticas e conquistas

Visão geral

Estatísticas e conquistas Steam oferecem uma forma fácil para o seu jogo disponibilizar um acompanhamento de conquistas e estatísticas persistente e disponível em qualquer lugar. Os dados do usuário são associados à conta Steam, e as conquistas e estatísticas de cada usuário podem ser formatadas para exibição no perfil da Comunidade Steam.

Para que servem

Além de oferecerem recompensas valiosas a jogadores dos seus jogos, conquistas são úteis para encorajar e recompensar trabalho em equipe e interação entre jogadores, oferecendo uma dimensionalidade a mais aos objetivos do jogo e recompensando jogadores por passarem mais tempo jogando.

Estatísticas contabilizam dados detalhados, como tempo de jogo, quantidade de poderes usados etc. É possível usá-las simplesmente para contabilizar dados internos do jogo — para, por exemplo, atrelar uma conquista com base em estatísticas que abrangem várias sessões, coletadas do usuário de diversos computadores.

Visão geral da implementação

Defina as estatísticas e conquistas do jogo

Conquistas são separadas por jogo e são configuradas na página de administração de aplicativo do site de parceiros Steamworks.

Há três tipos de estatísticas que podem ser armazenadas pelo jogo:
  • INT — Um número inteiro (com sinal) de 32 bits (ex.: partidas jogadas);
  • FLOAT — Um número em ponto flutuante de 32 bits (ex.: quilômetros dirigidos);
  • AVGRATE — Uma média móvel. Consulte: Estatística do tipo AVGRATE

O site de parceiros Steamworks oferece uma interface para definição e atualização das estatísticas e conquistas do jogo. Por meio dela, é possível:
  • Definir as estatísticas e conquistas iniciais;
  • Adicionar mais estatísticas e conquistas;
  • Atualizar nomes, descrições e ícones de conquistas;
  • Atualizar parâmetros e limites de estatísticas (valores máximos e mínimos, tamanho dos intervalos de valores para médias móveis, etc).
Estatísticas têm as seguintes propriedades:
  • ID — Um ID numérico gerado automaticamente para cada estatística;
  • Type — O tipo da estatística — INT, FLOAT ou AVGRATE;
  • Nome na API — A string usada para acessar a estatística por meio da API;
  • Definida por — Define quem pode alterar a estatística. O valor padrão é Cliente. Para mais informações, consulte Estatísticas de servidores;
  • Apenas incrementos? — Se verdadeiro, o valor da estatística não pode ser alterado para um valor menor que o atual;
  • Diferença máx. — Se definido, será o limite de diferença no valor da estatística entre chamadas SetStat;
  • Valor mínimo — Se definido, será o valor numérico mínimo permitido para a estatística. O valor padrão é o mínimo do tipo numérico em uso (INT_MIN ou -FLT_MAX);
  • Valor máximo — Se definido, será o valor numérico máximo permitido para a estatística. O valor padrão é o máximo do tipo numérico em uso (INT_MAX ou FLT_MAX);
  • Valor padrão — Se definido, será o valor padrão da estatística para um usuário novo. Caso contrário, o valor padrão é zero;
  • Agregada — Se verdadeiro, o Steam contabilizará um total global para a estatística. Consulte a seção de estatísticas globais abaixo para mais informações;
  • Nome de exibição — O nome da estatística quando exibida no aplicativo.
AVGRATE faz uso das seguintes propriedades adicionais:
  • Intervalo — O tamanho do "intervalo de valores" usado para calcular a média dos dados.
Uma estatística do tipo AVGRATE tem a média calculada automaticamente pelo Steam. Consulte a seção AVGRATE abaixo para mais informações.

Conquistas têm as seguintes propriedades:
  • ID — Um ID numérico gerado automaticamente para cada conquista.
  • Nome na API — A string usada para acessar a conquista por meio da API;
  • Estatística de progresso — Especifica uma estatística a ser usada como um medidor de progresso na Comunidade Steam para a conquista. A conquista também será alcançada automaticamente quando alcançar o valor de meta;
  • Nome de exibição — O nome da conquista em pop-ups de notificação no cliente e na Comunidade Steam. Pode ser localizado;
  • Descrição — Uma descrição da conquista para exibição na Comunidade Steam. Pode ser localizada;
  • Definida por — Define quem pode alcançar a conquista. O valor padrão é Cliente. Para mais informações, consulte Estatísticas de servidores;
  • Oculta? — Se verdadeiro, uma conquista "oculta" não é exibida (de forma alguma) na página do usuário na Comunidade Steam até ser alcançada;
  • Ícone de alcançada — O ícone para exibição quando alcançada;
  • Ícone de não alcançada — O ícone para exibição quando não alcançada.

Confira abaixo a lista de conquistas do Aplicativo de exemplo da API do Steamworks (SpaceWar):
achievements_spacewar.png

Considerações especiais

  • Os nomes e os ícones das conquistas devem ser apropriados para todas as idades.
  • Por padrão, os jogos são limitados a 100 conquistas no início. Once your app reaches the threshold for Recursos do perfil, you will be able to add more achievements.

Como usá-las

Como acessar estatísticas e conquistas pelo jogo:

Estatística do tipo AVGRATE

Esse tipo de estatística oferece um recurso único e bem útil, mas requer uma explicação mais detalhada.

Considere um caso em que você deseja contabilizar uma estatística de média, como "Pontos marcados por hora". Uma abordagem seria definir duas estatísticas: uma, "TotalPontos", do tipo INT e outra, "TotalHorasJogadas", do tipo FLOAT, e dividir os pontos pelas horas para obter a quantidade de pontos por hora.

A desvantagem dessa implementação é que, quando o usuário acumular muitas horas de jogo, demorará muito para a alteração da média calculada. De fato, quanto mais o usuário jogar, menos a média se moverá. Se o usuário tem 100 horas acumuladas no jogo, a média calculada ficará "atrasada" cerca de 50 horas. Portanto, mesmo se aprimorando no jogo, o aumento na estatística "Pontos marcados por hora" pode ser menor que o esperado.

O tipo de estatística AVGRATE permite implementar uma média móvel. Por exemplo, você pode considerar apenas as últimas horas de jogo, assim a estatística refletirá com uma maior precisão o nível de habilidade atual do usuário.

Vamos configurar uma estatística AVGRATE para implementar "Pontos marcados por hora", na qual apenas as últimas 20 horas de jogo afetam o valor. Para tal, você deverá:
  • Considerar as unidades envolvidas. Neste caso, como a média será calculada "por hora", a unidade de todos os parâmetros temporais associados à estatísticas será "hora". Isso se aplica à propriedade de "Intervalo" na estatística em si, assim como o valor passado para o parâmetro "dSessionLength" da função UpdateAvgRateStat abaixo.
  • Crie uma estatística AVGRATE de nome "MediaPontosPorHora" e um intervalo com valor 20.0 (lembre-se de que o valor é em "horas" — e use ponto para separar valores decimais).
  • Em pontos apropriados no jogo, chame a função ISteamUserStats::UpdateAvgRateStat com os seguintes parâmetros:
    • pchName — "MediaPontosPorHora".
    • flCountThisSession — Quantos pontos foram marcados pelo usuário desde a última vez que a função foi chamada.
    • dSessionLength — O tempo de jogo desde a última vez que a função foi chamada. A unidade deve ser a mesma usada no intervalo da estatística. Neste caso, "hora".
  • Por exemplo, se o usuário marcou 77 pontos na última rodada, que durou 0,225 hora (13 minutos e meio), a chamada ficaria assim: SteamUserStats()->UpdateAvgRateStat( "MediaPontosPorHora", 77, 0.225 )
No exemplo acima, o Steam pegará a média atual de 342,2 pontos por hora (77 dividido por 0,225) e a combinará com o valor anterior. O resultado refletirá a média total nas últimas 20 horas de jogo do usuário. Se essa for a primeira vez que a estatística é definida para o usuário atual, então o novo valor seria 342,2.

Esse exemplo usa a unidade "hora", mas você pode usar a unidade de tempo que preferir. Só tenha em mente que você deve usar a mesma unidade no parâmetro "dSessionLength" e na propriedade de intervalo.

Recuperação de estatísticas de outros usuários

Use a função ISteamUserStats::RequestUserStats para recuperar as estatísticas de outro usuário. Depois, use as funções ISteamUserStats::GetUserStat, ISteamUserStats::GetUserAchievement e ISteamUserStats::GetUserAchievementAndUnlockTime para recuperar os dados desse usuário. Esses dados não são atualizados automaticamente se o outro usuário enviar estatísticas novas. Para atualizá-los, basta chamar a função ISteamUserStats::RequestUserStats novamente.

Para evitar o uso demasiado de memória, um cache LRU (do inglês Least Recently Used, i.é., removendo os dados menos recentemente utilizados) é mantido e estatísticas de outros usuários serão desalocadas ocasionalmente. Quando isso ocorrer, um retorno de chamada ISteamUserStats::UserStatsUnloaded_t será disparado automaticamente, indicando que as estatísticas do usuário informado não estarão mais disponíveis até chamar a função ISteamUserStats::RequestUserStats novamente.

Modo off-line

O Steam mantém um cache local dos dados de estatísticas e conquistas para que as APIs possam ser usadas normalmente no modo off-line. Quaisquer estatísticas que não puderem ser enviadas aos servidores ficarão salvas até a próxima vez que o usuário ficar on-line. Caso haja modificações em mais de uma máquina, o Steam combinará as conquistas automaticamente e escolherá o conjunto de estatísticas com maior progresso. Como o Steam mantém um cache local dos dados de estatísticas, o jogo não precisa manter um cache local dos dados em disco. É provável que ocorra conflitos entre os caches e, quando isso ocorre, o usuário pode pensar que o progresso foi revertido, o que é uma experiência frustrante.

Estatísticas de servidores

A interface ISteamGameServerStats é equivalente à interface ISteamUserStats, mas para uso em servidores. Ela pode ser usada para recuperar as estatísticas de usuários da mesma forma que clientes (como descrito acima). Também podem definir estatísticas e conceder conquistas, mas apenas as cuja configuração "Definida por" esteja como "Servidores" ou "Servidores oficiais". A diferença entre "Servidores" e "Servidores oficiais" é que servidores oficiais são aqueles que você hospeda e controla. O uso de servidores oficiais para a definição de estatísticas oferece uma maior segurança contra trapaças, já que usuários podem modificar os seus servidores próprios ou fingirem ser um servidor. Para definir quais são os servidores oficiais, informe os intervalos de endereços IPs usados por eles aqui.

Estatísticas e conquistas definidas por servidores não podem ser definidas por clientes. Servidores só podem definir estatísticas e conquistas de usuários que estão jogando no servidor. Se um usuário deixar o servidor, há um pequeno período em que o servidor poderá definir quaisquer estatísticas finais, mas, depois, novos envios serão negados. Isso serve para garantir a consistência e evitar a possibilidade de um servidor mal-intencionado definir as estatísticas de qualquer um a qualquer momento. Considerando essa restrição, é importante não esperar até o fim de uma rodada para definir as estatísticas — faça-o continuamente, para poder registrá-las quando o usuário sair.

Os clientes receberão atualizações automáticas quando um servidor alterar as suas estatísticas. Contudo, assim como com clientes, as estatísticas de outros usuários que foram carregadas pelo servidor não são atualizadas automaticamente e podem ser desalocadas.

Redefinição de estatísticas

Durante o desenvolvimento, é comum ser necessário, para testes, redefinir todas as estatísticas e conquistas de uma conta ou de todas as contas. Para redefinir as estatísticas de uma conta, chame a função ISteamUserStats::ResetAllStats. Passe true no parâmetro bAchievementsToo para também redefinir as conquistas. Uma vez chamada, lembre-se de reiterar as estatísticas e conquistas e redefinir o estado do jogo em memória. Não há como redefinir as estatísticas e as conquistas de todos os usuários de uma vez. Um dos motivos para isso é que, mesmo se houvesse uma forma, partidas em andamento poderiam não notar a redefinição e enviar os valores em memória para o Steam. Felizmente, há uma forma fácil de implementar um sistema automático de limpeza para todos os usuários no jogo:
  • Defina uma estatística com um nome como "Versao".
  • Defina um número de versão das estatísticas no jogo em si.
  • Depois que as estatísticas forem carregadas, compare a estatística "Versao" com o número de versão definido no jogo.
  • Se não forem iguais, chame a função ISteamUserStats::ResetAllStats e depois defina a estatística "Versao" com o número de versão definido no jogo.
Dessa forma, sempre que quiser redefinir as estatísticas de todos os usuários, basta alterar o número de versão das estatísticas no jogo. A redefinição ocorrerá conforme os usuários baixarem a nova versão do jogo.

Consistência das estatísticas

É uma boa prática pensar em como estatísticas relacionadas podem ficar inconsistentes entre si. Por exemplo, você pode definir três estatísticas: "Vitorias", "Derrotas" e "PartidasJogadas". Apesar das melhores intenções, as estatísticas podem ficar (cedo ou tarde, elas ficam) inconsistentes entre si. Nesse caso, a soma das vitórias e derrotas pode não ser igual ao total de partidas jogadas. Se isso fosse resolvido ao remover a estatística "Derrotas" e calculá-la usando a equação "PartidasJogadas" - "Vitorias", uma inconsistência resultaria em um valor negativo de "Derrotas". Nesse caso, o melhor é remover a estatística "PartidasJogadas" e calculá-la como "Vitorias" + "Derrotas".

Estatísticas globais

Estatísticas podem ser marcadas como agregadas na página de administração para solicitar ao Steam que mantenha um total global dos valores da estatística para todos os usuários. Isso pode ser usado para obter o total de dinheiro na economia, total de vítimas, armas favoritas, mapas favoritos e qual equipe costuma se sair melhor. Por outro lado, não faz sentido usar essa opção em estatísticas como "RecordeVitimas". Como as estatísticas estão nas mãos dos usuários, esses dados estão sujeitos a manipulação. Portanto, ao usar estatísticas agregadas, é vital definir bons limites de valor mínimo, valor máximo, se apenas incrementos podem ser feitos (se apropriados) e a diferença máxima. O valor de diferença máxima tem um significado especial para estatísticas agregadas: quando um novo valor for enviado, a diferença dos valores globais anterior e posterior não será maior que a diferença máxima. Assim, limita-se a velocidade que um trapaceiro pode influenciar o total global.

Para acessar os totais globais, chame a função ISteamUserStats::RequestGlobalStats e, em seguida, ISteamUserStats::GetGlobalStat para cada estatística global. Você também pode chamar a função ISteamUserStats::RequestGlobalStats pedindo uma quantidade específica de dias de histórico. O histórico é a diferença no valor da estatística para cada dia. Para acessar o histórico, chame a função ISteamUserStats::GetGlobalStatHistory.

Você também pode recuperar, pelo cliente, a porcentagem de usuários que alcançaram cada conquista. Para tal, primeiro chame a função ISteamUserStats::RequestGlobalAchievementPercentages. Depois, itere as conquistas (em ordem decrescente de porcentagem de usuários que alcançaram) usando as funções ISteamUserStats::GetMostAchievedAchievementInfo e ISteamUserStats::GetNextMostAchievedAchievementInfo. Você também pode recuperar essa porcentagem para uma conquista específica por meio da função ISteamUserStats::GetAchievementAchievedPercent.

Testes


Antes de lançar o aplicativo, não será possível ver quais conquistas foram alcançadas pela Comunidade Steam ou na Biblioteca Steam. O aplicativo precisará de uma forma de exibir quais conquistas foram alcançadas pelo usuário.

Para redefinir uma conquista ou estatística sem adicionar código ao jogo, use o console do cliente Steam. Inicie o cliente Steam por meio do comando "steam.exe -console" e então execute os seguintes comandos no console:
  • achievement_clear <AppID> <nome da conquista> (para definir a conquista como não alcançada)
  • reset_all_stats <AppID> (para redefinir todas as estatísticas)

A Comunidade Steam

Após o lançamento do jogo, os dados individuais e globais das conquistas são exibidos na Comunidade Steam. Cada usuário terá um link no seu perfil da Comunidade Steam para acessar uma página listando as conquistas alcançadas e ainda não alcançadas.
AVISO: as conquistas não serão exibidas até que o aplicativo tenha algum tipo de visibilidade na comunidade.

Cada conquista é exibida com o ícone, o nome e a descrição definidos no site de parceiros Steamworks. Se os nomes e as descrições foram traduzidos no idioma selecionado pelo usuário, então eles serão exibidos nesse idioma.

Também haverá um link nessa página (e na página do jogo na Loja Steam) para ver as estatísticas globais de conquistas do jogo. Essa página exibirá a porcentagem de usuários Steam que jogaram o jogo e alcançaram cada uma delas, ordenadas da mais comum à mais rara. Os usuários adoram analisar essas listas, além de serem um ótimo recurso para você, desenvolvedor: os seus desafios especiais são mesmo difíceis? Ou são difíceis demais? (Esses dados também estão disponíveis no site de relatórios de vendas e ativações).

Alguma dúvida?

Tire as suas dúvidas no fórum de discussões de estatísticas e conquistas.