> ## Documentation Index
> Fetch the complete documentation index at: https://docs.humalike.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Akcje zdefiniowane przez serwer

> Deklaruj akcje wykonywane przez Twój własny skrypt, warunkowane faktami, które zgłasza.

Dostawca akcji deklaruje akcje obok obserwacji, które
[zgłasza](/pl/ai-npc/integrations/world-events#obserwacje-serwerowe). Model
wybiera zadeklarowaną akcję jak każdą akcję z katalogu, Humalike przyjmuje tag
dopiero po zgłoszeniu wymaganych obserwacji, a Twoje `RunAction` wykonuje akcję.
Jak brama i lada sklepowa zachowują się w grze, opisano w sekcji
[Systemy rozgrywki](/pl/ai-npc/gameplay#akcje-zdefiniowane-przez-serwer).

```lua theme={null}
exports.humalike:RegisterProvider('actions', {
    name = 'my_actions', apiVersion = 1, priority = 100,
    SupportedActions = {},
    Namespace = 'myserver',
    Observations = {
        item_given = {
            fields = { item = 'string', quantity = 'integer' },
            template = { en = 'the character handed you {quantity} x {item}' },
        },
    },
    Actions = {
        give_map = {
            name = 'Give the treasure map',
            description = 'Hand the player the map to the hidden chest.',
            params = { copies = { type = 'integer', enum = { 1, 2 } } },
            fixed = { item = 'treasure_map' },
            requires = {
                { observation = 'item_given', where = { item = 'amulet' }, consume = true },
            },
            locked_hint = { en = 'Only once the amulet is in your hands.' },
        },
    },
    RunAction = function(action, source, npcCoords, params)
        if action ~= 'give_map' then return false end
        return exports.ox_inventory:AddItem(source, params.item, params.copies or 1)
    end,
})
```

Włącz `myserver:give_map` w panelu na tych NPC, które mają ją mieć. Klucze są
poprzedzone przestrzenią nazw po sieci (`myserver:give_map`) i lokalne w
`RunAction` (`give_map`). `RunAction` otrzymuje `params` modelu scalone z
`fixed` oraz `player_id`:

```lua theme={null}
-- Tag: [myserver:give_map copies=2]
-- RunAction receives ('give_map', source, npcCoords, { player_id = 12, copies = 2, item = 'treasure_map' })
```

Akcje są deklarowane ponownie przy każdym raporcie możliwości. Zmieniona lub
usunięta akcja zaczyna obowiązywać przy następnym uruchomieniu zasobu.

## Deklaracja

| Pole          | Opis                                                                                                                                                                              |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`        | Wyświetlane w panelu. Do 80 znaków.                                                                                                                                               |
| `description` | Linia, którą model czyta w ramach swoich reguł ACTIONS. Do 400 znaków, bez nawiasów kwadratowych.                                                                                 |
| `params`      | Do 4 wartości, które uzupełnia model. Zobacz [Parametry](#parametry).                                                                                                             |
| `fixed`       | Do 16 wartości, o których decyduje Twój skrypt. Nigdy nie są wysyłane do Humalike; scalane pod wartościami modelu przed `RunAction` i zawsze wygrywają.                           |
| `requires`    | Do 4 warunków na zgłoszonych obserwacjach, z których wszystkie muszą być spełnione. Zobacz [Warunki](#warunki).                                                                   |
| `locked_hint` | Co NPC słyszy, per kod języka (dowolny z oferowanych w panelu; gdy język NPC nie ma tekstu, czytany jest angielski), dopóki warunek nie jest spełniony.                           |
| `limit`       | `{ per_player = 1, every_s = 86400, hint = { en = '...' } }`. Liczba akcji na gracza w dowolnym oknie `every_s` sekund (do 7 dni). Brak limitu, jeśli nie zadeklarowano.          |
| `auto`        | `true`: Humalike wykonuje akcję przy następnej odpowiedzi NPC, gdy tylko jej warunki są spełnione, niezależnie od tego, czy model napisze tag. Wymaga warunku z `consume = true`. |
| `params_from` | `{ amount = 'item_given.quantity' }`. Wartości brane z faktów odblokowujących, nigdy od modelu. Zobacz [Parametry z faktów](#parametry-z-faktów).                                 |
| `uses_stock`  | `{ item = 'map', quantity = 1 }`. Akcja pobiera z zapasów NPC i blokuje się przy zerze. Zobacz [Zapasy](#zapasy).                                                                 |

### Parametry

```lua theme={null}
params = {
    copies = { type = 'integer', enum = { 1, 2 }, required = true, description = 'How many copies.' },
}
```

* Typy to `string`, `integer` lub `boolean`.
* `enum` zawiera do 16 pojedynczych słów lub liczb całkowitych.
* `required` i `description` są opcjonalne.
* `player_id` jest zawsze dodawane przez Humalike.
* Tag, którego wartości nie pasują do deklaracji, jest odrzucany, zanim zostanie
  wypowiedziany lub zapamiętany.

### Warunki

```lua theme={null}
requires = {
    { observation = 'item_given', where = { item = 'cash', quantity = { gte = 500 } },
      within_s = 600, consume = true },
}
```

| Pole          | Opis                                                                                 |
| ------------- | ------------------------------------------------------------------------------------ |
| `observation` | Zadeklarowany klucz obserwacji, zgłoszonej dla tego NPC i gracza, któremu odpowiada. |
| `where`       | Warunki na zadeklarowanych polach. Wszystkie muszą pasować.                          |
| `within_s`    | Maksymalny wiek liczonych faktów w sekundach. Od 5 do 3600, domyślnie 600.           |
| `consume`     | `true` zużywa każdy fakt policzony przez warunek po wykonaniu akcji.                 |

| Forma `where`                | Dopasowuje                                       |
| ---------------------------- | ------------------------------------------------ |
| `item = 'amulet'`            | Równość skalarna. `1` i `1.0` to ta sama liczba. |
| `quantity = { gte = 500 }`   | Dolna granica pola liczbowego.                   |
| `quantity = { lte = 3 }`     | Górna granica. `gte` i `lte` można łączyć.       |
| `quantity = { sum_gte = 2 }` | Suma po wszystkich liczonych faktach.            |

Zużyte fakty znikają dla każdej akcji i dla lady sklepowej.

### Parametry z faktów

```lua theme={null}
refund_deposit = {
    name = 'Give the deposit back',
    description = 'Return the deposit the player put on the counter.',
    requires = { { observation = 'item_given', where = { item = 'cash' }, consume = true } },
    params_from = { amount = 'item_given.quantity' },
},
-- RunAction receives { player_id, amount = <what was actually handed over> }
```

* Wartości pochodzą z faktów policzonych przez **pierwszy** wpis `requires` na
  tej obserwacji.
* Liczby są sumowane po tych faktach. Wszystko inne to najnowsza wartość.

## Zapasy

```lua theme={null}
local result = exports.humalike:SetNpcStock(npcId, { map = 50, bread = 'unlimited' })
```

Zastępuje całe zapasy NPC. Przedmiot niewymieniony to taki, którego NPC nie ma
wcale. Panel pokazuje zapasy tylko do odczytu na stronie NPC.

* Do 32 przedmiotów na NPC.
* Nazwy przedmiotów pasują do `^[a-z][a-z0-9_]*$`, co najwyżej 48 znaków.
* Liczby to liczby całkowite od 0 do 1 000 000 lub `'unlimited'`.

Zwraca `{ ok = true, value = { stock } }` lub `{ ok = false, error = code }`:

| Błąd                             | Znaczenie                                                      |
| -------------------------------- | -------------------------------------------------------------- |
| `invalid_npc`                    | `npcId` nie jest ciągiem UUID.                                 |
| `npc_not_found`, `npc_not_bound` | Tak samo jak w `ReportObservation`.                            |
| `invalid_stock`                  | `stock` nie jest tabelą.                                       |
| `invalid_item:<name>`            | Nazwa łamie wzorzec lub długość.                               |
| `invalid_count:<name>`           | Liczba nie jest liczbą całkowitą w zakresie ani `'unlimited'`. |
| `too_many_items`                 | Więcej niż 32 przedmioty.                                      |
| `runtime_not_ready`              | Brak jeszcze poświadczeń. Nic nie wysłano.                     |

## Lada sklepowa

Dla NPC, które sprzedają, zadeklaruj `Catalog` zamiast jednej akcji na produkt.
Humalike przyjmuje zamówienie, wycenia je i pobiera płatność, a następnie
wywołuje `deliver` i `refund` na Twoim `RunAction`.

```lua theme={null}
Catalog = {
    currency = 'cash',
    payment = 'item_given',
    items = {
        water = { price = 5 },
        bread = { price = 3 },
        pistol = { price = 150, limit = { per_player = 1, every_s = 86400 } },
    },
},
```

| Pole       | Opis                                                                                                                                                               |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `currency` | Wartość `item` obserwacji `payment`, która liczy się jako pieniądze.                                                                                               |
| `payment`  | Zadeklarowana obserwacja zgłaszana przez Twój hook ekwipunku. Jej `quantity` musi być typu `integer`.                                                              |
| `items`    | Od 1 do 64 produktów, nazwanych według reguły zapasów, każdy z całkowitą `price` od 0 do 10 000 000 i opcjonalnym `limit` (tego samego kształtu co `limit` akcji). |

NPC sprzedaje przedmioty z katalogu, które Twój skrypt [dodał do zapasów](#zapasy).

### `deliver` i `refund`

Obie są deklarowane za Ciebie wraz z `Catalog`. Nie wymieniaj ich w `Actions`.

| Akcja     | `params`                                                                          | Zwrot                                                                                                                                    |
| --------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `deliver` | `items` (przedmiot do ilości), `total`, `paid`, `change`, `currency`, `player_id` | `true` tylko wtedy, gdy każda pozycja i reszta są w ekwipunku gracza. Przy dowolnym niepowodzeniu cofnij to, co dodano, i zwróć `false`. |
| `refund`  | `amount`, `currency`, `player_id`                                                 | `true` po tym, jak kwota wróciła do ekwipunku gracza.                                                                                    |

```lua theme={null}
RunAction = function(action, source, npcCoords, params)
    if action == 'deliver' then
        return giveAllOrNothing(source, params.items, params.currency, params.change)
    elseif action == 'refund' then
        return exports.ox_inventory:AddItem(source, params.currency, params.amount) == true
    end
    return false
end
```

### Zamówienia z menu

```lua theme={null}
local result = exports.humalike:PlaceOrder(npcId, playerId, { water = 2 })
```

Wysyła pozycje wybrane w Twoim własnym menu sklepu. Do 16 pozycji, każda w
ilości od 1 do 1000. Zwraca `{ ok = true, value = { lines } }` lub
`{ ok = false, error = code }`:

| Błąd                                                                       | Znaczenie                               |
| -------------------------------------------------------------------------- | --------------------------------------- |
| `invalid_player`, `character_not_loaded`, `npc_not_found`, `npc_not_bound` | Tak samo jak w `ReportObservation`.     |
| `no_catalog`                                                               | Dostawca akcji nie deklaruje `Catalog`. |
| `invalid_lines`                                                            | `lines` nie jest niepustą tabelą.       |
| `unknown_item:<name>`                                                      | Nie ma w katalogu.                      |
| `invalid_quantity:<name>`                                                  | Nie jest liczbą całkowitą od 1 do 1000. |
| `too_many_lines`                                                           | Więcej niż 16 pozycji.                  |

### Klucze zarezerwowane

* `order`, `cancel_order`, `order_placed`, `order_refused`: nie można ich
  deklarować jako akcji ani obserwacji.
* `deliver`, `refund`: nie można ich deklarować jako obserwacji.
* Żaden klucz nie może być jednocześnie akcją i obserwacją.
* `spent` jest zarezerwowanym polem obserwacji.

## Kontrakt RunAction

* Zwróć dokładnie `true`, gdy akcja została wykonana. `false` odrzuca wywołanie
  i nie jest ponawiane.
* Odpowiedz w ciągu 5 sekund. Utracona odpowiedź (timeout, zerwane połączenie,
  HTTP 5xx) jest ponawiana od razu, do trzech prób, pod tym samym id wywołania.
* Zachowuj przyjęte id i odpowiadaj na powtórzenie z tego zapisu, aby utracona
  odpowiedź nigdy nie wykonała akcji dwukrotnie.

## Debugowanie

* Odrzuconą deklarację wypisuje `RegisterProvider` wraz z wadliwym polem. Nic
  nie zostaje zarejestrowane.
* Strona NPC w panelu wymienia zadeklarowane akcje z ich warunkami. Widok
  transkrypcji pokazuje obserwacje i akcje.
* `humalike_debug 1` loguje każdy przychodzący push i jego wynik.

## Dalej

* [Jak zachowują się brama i lada sklepowa](/pl/ai-npc/gameplay#akcje-zdefiniowane-przez-serwer).
* [Zgłaszaj obserwacje, od których zależą te akcje](/pl/ai-npc/integrations/world-events#obserwacje-serwerowe).
* [Przejrzyj kontrakt dostawcy](/pl/ai-npc/integrations/provider-api).
