# Avatares NPC

Exibir um avatar como uma entidade em uma cena.

{% hint style="info" %}
**💡 Dica**: Experimente o [NPC Toolkit library](https://github.com/decentraland-scenes/dcl-npc-toolkit) para uma experiência mais fácil ao lidar com NPCs, especialmente se você precisar interagir via uma árvore de conversação.
{% endhint %}

## Criar um avatar

O snippet a seguir cria um avatar com wearables e body shape aleatórios, e nome "NPC".

```ts
const myAvatar = engine.addEntity()
AvatarShape.create(myAvatar)

Transform.create(myAvatar, {
	position: Vector3.create(4, 0.25, 5),
})
```

Ao passar dados para gerar um `AvatarShape`, os seguintes campos são obrigatórios:

* `id`: (obrigatório) Identificador interno para o Avatar

Os seguintes campos opcionais também estão disponíveis:

* `name`: Nome a ser exibido sobre a cabeça do Avatar. Padrão: "NPC".
* `bodyShape`: String para definir qual body shape usar. Opções válidas são 'urn:decentraland:off-chain:base-avatars:BaseMale' e 'urn:decentraland:off-chain:base-avatars:BaseFemale'.
* `wearables`: Array com lista de URNs dos wearables que o avatar atualmente está usando. Se wearables entrarem em conflito (como dois sendo chapéus), o último na lista substitui o outro.
* `emotes`: Array com lista de URNs de emotes NFT que o avatar é capaz de reproduzir
* `eyeColor`: *Color3* para a cor dos olhos (qualquer cor é válida)
* `skinColor`: *Color3* para a cor da pele (qualquer cor é válida)
* `hairColor`: *Color3* para a cor do cabelo (qualquer cor é válida)
* `talking`: Se *true*, exibe um conjunto de barras verdes ao lado do nome, como quando jogadores usam chat de voz no mundo.
* <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>💡 Dica</strong>: Veja <a href="../essenciais-de-conteudo-3d/color-types">color types</a> para mais detalhes sobre como definir cores.</p></div>

{% hint style="warning" %}
**📔 Nota**: O `AvatarShape`component must be imported via

> `import { AvatarShape } from "@dcl/sdk/ecs"`

Veja [Imports](https://docs.decentraland.org/creator/content-creator-pt/primeiros-passos/coding-scenes#imports) para como lidar com estes facilmente.
{% endhint %}

{% hint style="warning" %}
**📔 Nota**: Os campos URN devem seguir o mesmo formato usado para [NFTShapes](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/media/display-a-certified-nft): `urn:decentraland:<CHAIN>:<CONTRACT_STANDARD>:<CONTRACT_ADDRESS>:<TOKEN_ID>`
{% endhint %}

## Animações

Avatares reproduzem animações de idle padrão enquanto imóveis.

Para reproduzir animações no avatar, defina o `expressionTriggerId` string para o nome da animação que você quer reproduzir.

```ts
const myAvatar = engine.addEntity()
AvatarShape.create(myAvatar, {
	id: '',
	emotes: [],
	wearables: [],
	expressionTriggerId: 'robot',
})

Transform.create(myAvatar, {
	position: Vector3.create(4, 0.25, 5),
})
```

O `expressionTriggerId` campo suporta todas as [default animations](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/player-avatar#default-animations), bem como animações customizadas [from a scene file](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/player-avatar#custom-animations), e até URNs de emotes que estão publicados no Marketplace.

### Animações em Loop

Animações em um `AvatarShape` reproduzem uma vez; se você quiser que o avatar fique repetindo uma animação, deve criar um sistema que diga para reproduzir a animação novamente a cada alguns segundos.

Use o `expressionTriggerTimestamp` para reproduzir o mesmo emote novamente. O valor deste campo é um [lamport timestamp](https://en.wikipedia.org/wiki/Lamport_timestamp), o que significa que não é um valor de tempo, mas sim um índice que é incrementado em 1 a cada repetição do emote.

Então, na primeira vez que você reproduz um emote, você define `expressionTriggerTimestamp` to *0*. Para reproduzir o emote novamente, você deve atualizar esse valor para 1. É assim que o engine sabe que esta é uma nova instrução, e não uma instrução que já foi executada.

O snippet a seguir cria um sistema que roda o mesmo emote a cada 2 segundos:

```ts
const myAvatar = engine.addEntity()
AvatarShape.create(myAvatar, {
	id: '',
	emotes: [],
	wearables: [],
	expressionTriggerId: 'clap',
    expressionTriggerTimestamp: 0
})

Transform.create(myAvatar, {
	position: Vector3.create(4, 0.25, 5),
})

let clapTimer = 0
let emoteDuration = 2  // 2 segundos

// system
engine.addSystem((dt: number) => {
    clapTimer += dt
      
    if (clapTimer >= emoteDuration) {
        // Trigger the clap emote
        AvatarShape.getMutable(wearable).expressionTriggerTimestamp =+ 1 
        
        clapTimer = 0 // Resetar timer
    }
})
```

{% hint style="info" %}
**💡 Dica**: Você deve saber a duração do emote, e fazer essa a duração do sistema. Se você criar um emote que mantém o avatar imóvel em uma mesma pose, é recomendável fazer a duração do emote maior que a do sistema. Dessa forma, você pode garantir que não haja artefatos ao terminar e resetar a animação.
{% endhint %}

## Copiar wearables do jogador

O snippet a seguir altera os wearables e outras características de um avatar NPC para corresponder aos que o jogador atualmente está usando. Isso pode ser usado em uma cena como um manequim, para exibir um wearable ou emote específico combinado com a roupa atual do jogador.

```ts
import { getPlayer } from '@dcl/sdk/src/players'


export function swapAvatar(avatar: Entity) {

  let userData = getPlayer()
  console.log(userData)

  if (!userData || !userData.wearables) return

  const mutableAvatar = AvatarShape.getMutable(avatar)

  mutableAvatar.wearables = userData.wearables
  mutableAvatar.bodyShape = userData.avatar?.bodyShapeUrn
  mutableAvatar.eyeColor = userData.avatar?.eyesColor
  mutableAvatar.skinColor = userData.avatar?.skinColor
  mutableAvatar.hairColor = userData.avatar?.hairColor
  
}
```

## Exibir apenas wearables

Use o `show_only_wearables` campo para exibir apenas os wearables listados de um avatar. O resto do corpo do avatar ficará invisível.

```ts
const myAvatar = engine.addEntity()
AvatarShape.create(myAvatar, {
	id: '',
	emotes: [],
	wearables: [
    'urn:decentraland:matic:collections-v2:0x90e5cb2d673699be8f28d339c818a0b60144c494:0'
  ],
	showOnlyWearables: true,
})

Transform.create(myAvatar, {
	position: Vector3.create(4, 0.25, 5),
})
```

Isto é útil para exibir wearables, por exemplo em uma loja.

{% hint style="info" %}
**💡 Dica**: Se um wearable for relativamente pequeno, tente definir o `scale` do `Transform` para um valor maior.
{% endhint %}

## Anexar uma entidade a um NPC

Você pode usar o `AvatarAttach` recurso para fixar uma entidade a um dos ossos de um avatar NPC, por exemplo, para que o NPC segure um objeto na mão. A entidade se moverá junto com o avatar quando ele animar.

Para usar este recurso, use a `id` property on the `AvatarShape` para atribuir um id arbitrário a este avatar, e então referenciar esse id no `AvatarAttach`. O id pode ser qualquer string que você quiser.

```ts
// Criar NPC, com um ID
const myAvatar = engine.addEntity()
Transform.create(myAvatar, {
  position: Vector3.create(8, 0.25, 8),
})
AvatarShape.create(myAvatar, {
  id: "my-avatar-id", 
  wearables: [],
  emotes: []
})

// Criar objeto para anexar ao NPC
const attachedEntity = engine.addEntity()
Transform.create(attachedEntity, {
    position: Vector3.create(4, 2, 4),
    scale: Vector3.create(0.15,0.15,0.15)
})
MeshRenderer.setBox(attachedEntity)
Material.setBasicMaterial(attachedEntity, { diffuseColor: Color4.Blue() })
AvatarAttach.create(attachedEntity, {
    avatarId: "my-avatar-id",
    anchorPointId: AvatarAnchorPointType.AAPT_LEFT_HAND
})
```

Saiba mais sobre o `AvatarAttach` component [aqui](https://docs.decentraland.org/creator/content-creator-pt/essenciais-de-conteudo-3d/entity-positioning#attach-an-entity-to-an-avatar).
