> For the complete documentation index, see [llms.txt](https://wiki.redmodding.org/scripting-cyberpunk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.redmodding.org/scripting-cyberpunk/scripting/snippets-and-examples/user-interface/notification-prompts.md).

# Notification Prompts

How to use simple notification prompts with different types of responses to ask for.

{% hint style="info" %}
This requires [Codeware](/scripting-cyberpunk/introduction/tools-and-frameworks/codeware.md)
{% endhint %}

This snippet requires [Codeware](/scripting-cyberpunk/introduction/tools-and-frameworks/codeware.md) as it gives us access to the game's ink system on demand, which lets us get a reference to the respective [game controller](/scripting-cyberpunk/scripting/game-systems/ui-scripting/ink-controllers.md#inkgamecontroller) for the [menu layer](https://wiki.redmodding.org/scripting-cyberpunk/scripting/snippets-and-examples/user-interface/pages/k81UnWc76dSM5ndnBewU#ink-layers-as-of-2.12_a) which is needed to give the player a prompt.

In order to show a prompt, we'll need a game controller as mentioned and we'll also need to define a callback method to call when the player answers the prompt. There's different types of prompts you can show the player that depends on what you want to prompt for.

## Snippet

This example shows the player a [confirm/cancel](https://nativedb.red4ext.com/e/7973911300251480) prompt which gives the player a prompt with the option to either confirm or cancel. The prompt is shown whenever the player jumps, which is a silly use-case but feel free to take the code and implement it for your mod purposes.

For an actual use-case, look at how it's done in EquipmentEx: <https://github.com/psiberx/cp2077-equipment-ex/blob/master/scripts/UI/ConflictsPopup.reds>

{% tabs %}
{% tab title="Redscript" %}

```swift
@addField(PlayerPuppet)
public let m_token: ref<inkGameNotificationToken>;

@wrapMethod(PlayerPuppet)
protected cb func OnAction(action: ListenerAction, consumer: ListenerActionConsumer) -> Bool {
  wrappedMethod(action, consumer);

  if !IsDefined(this.m_token) && action.IsAction(n"Jump") && action.IsButtonJustReleased() {
    let controller = GameInstance.GetInkSystem().GetLayer(n"inkMenuLayer").GetGameController() as inkGameController;
    this.m_token = GenericMessageNotification.Show(controller, "Title", "Body", GenericMessageNotificationType.ConfirmCancel);
    this.m_token.RegisterListener(this, n"OnPromptClose");
  }
}

@addMethod(PlayerPuppet)
protected cb func OnPromptClose(data: ref<inkGameNotificationData>) {
  let resultData: ref<GenericMessageNotificationCloseData> = data as GenericMessageNotificationCloseData;

  this.m_token = null;

  if IsDefined(resultData) {
    FTLog(s"picked: \(resultData.result)");
  }
}
```

{% endtab %}

{% tab title="Lua" %}

```lua
registerForEvent('onInit', function()
  local token

  local callback = NewProxy({
    OnPromptClose = {
      args = {"handle:inkGameNotificationData"},
      callback = function(data)
        if IsDefined(data) and data:IsA("GenericMessageNotificationCloseData") then
          local result = data.result

          print("picked: " .. data.result.value)
        end

        token = nil
        collectgarbage()
      end
    }
  })

  ---@param this PlayerPuppet
  ---@param action ListenerAction
  ---@param consumer ListenerActionConsumer
  Observe("PlayerPuppet", "OnAction", function(this, action, consumer)
    if not IsDefined(token) and action:IsAction("Jump") and action:IsButtonJustReleased() then
      local controller = Game.GetInkSystem():GetLayer("inkMenuLayer"):GetGameController()
      token = GenericMessageNotification.Show(controller, "Title", "Body", GenericMessageNotificationType.ConfirmCancel);
      token:RegisterListener(callback:Target(), callback:Function("OnPromptClose"))
    end
  end)
end)
```

{% endtab %}
{% endtabs %}

## Different Types of Notifications

### `GenericMessageNotificationType.OK`

<figure><img src="https://1927068511-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Ffwsaoju1TBAUvMpI6NIw%2Fuploads%2FiwM1JKkDyG54lQR4Nmyk%2FUI_NotificationPrompt_OK.png?alt=media&amp;token=5433a7a0-6f69-45ff-af86-1d63c6275749" alt=""><figcaption></figcaption></figure>

### `GenericMessageNotificationType.Confirm`

<figure><img src="https://1927068511-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Ffwsaoju1TBAUvMpI6NIw%2Fuploads%2F1LYVkWOsvGvnE3GZYeiY%2FUI_NotificationPrompt_Confirm.png?alt=media&amp;token=26b1bf2c-9a3e-4dc9-8ee0-f0071f550170" alt=""><figcaption></figcaption></figure>

### `GenericMessageNotificationType.Cancel`

<figure><img src="https://1927068511-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Ffwsaoju1TBAUvMpI6NIw%2Fuploads%2FTjoDYVryD1mZMwrQ2Snt%2FUI_NotificationPrompt_Cancel.png?alt=media&amp;token=46e8e091-c7fd-467e-ace3-39ae26b1171e" alt=""><figcaption></figcaption></figure>

### `GenericMessageNotificationType.ConfirmCancel`

<figure><img src="https://1927068511-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Ffwsaoju1TBAUvMpI6NIw%2Fuploads%2FY2Kv5jBmFKaBRBu6QQMx%2FUI_NotificationPrompt_ConfirmCancel.png?alt=media&amp;token=565da74c-437e-40e0-8b3c-668f0650a8a4" alt=""><figcaption></figcaption></figure>

### `GenericMessageNotificationType.YesNo`

<figure><img src="https://1927068511-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Ffwsaoju1TBAUvMpI6NIw%2Fuploads%2FqGSP1A0MvTWZ2MFmUd3G%2FUI_NotificationPrompt_YesNo.png?alt=media&amp;token=bf1eb97b-99ed-4637-abce-6ca2bea35b52" alt=""><figcaption></figcaption></figure>
