Redscript
HomeGitHubDiscord
  • Home
  • Getting Started
    • Downloads
    • Setup for VSCode
    • Setup for JetBrains IDEs
    • How to start REDscripting
      • Step 1: Mod structure
      • Step 2: Finding the right class
  • Language
    • Intro
      • REDscript in 2 minutes
      • How to create a hook
        • Things to hook
    • Language Features
      • Intrinsics
      • Loops
      • Strings
      • Modules
      • Annotations
      • Conditional compilation
      • Configurable user hints
    • Built-in Types
    • Built-in Functions
      • Math
      • Random
      • Utilities
  • References and examples
    • Common Patterns
      • Safe downcasting
      • Class constructors
      • Hash maps
      • Heterogeneous array literals
      • Scriptable systems (singletons)
      • DelaySystem and DelayCallback
      • Generic callbacks
      • Persistence
    • Logging
    • UI Scripting
      • Logging Widget Trees
      • Popups
    • Vehicle system
    • Weapons
    • Codeware callbacks
      • Scriptables comparison
    • Libraries
    • Gameplay
      • Sleeping and Skipping Time
  • Help
    • Community
    • Troubleshooting
Powered by GitBook
On this page
  1. References and examples

Logging

This guide describes how you can write logs while debugging your scripts. It can be helpful too to get feedback from players when they find bugs.

PreviousPersistenceNextUI Scripting

Last updated 1 year ago

Was this helpful?

CtrlK
  • Logging and tracing functions
  • Example usage
  • Where does it go?
  • Improve logging

Was this helpful?

Logging and tracing functions

With Cyberpunk >= 2.01, you need to paste the snippet below into e.g. r6\scripts\Logs.reds if you want to avoid UNRESOLVED_FN errors at compile time.

This will give access to these functions to all scripts (including yours):

native func Log(const text: script_ref<String>) -> Void
native func LogWarning(const text: script_ref<String>) -> Void
native func LogError(const text: script_ref<String>) -> Void

// output goes to CET window
native func LogChannel(channel: CName, const text: script_ref<String>)
native func LogChannelWarning(channel: CName, const text: script_ref<String>) -> Void
native func LogChannelError(channel: CName, const text: script_ref<String>) -> Void

native func FTLog(const value: script_ref<String>) -> Void
native func FTLogWarning(const value: script_ref<String>) -> Void
native func FTLogError(const value: script_ref<String>) -> Void

native func Trace() -> Void
native func TraceToString() -> String

Do not package this file with your mod though because that would lead to conflicts with other scripts.

Example usage

@wrapMethod(EquipmentSystemPlayerData)
func OnRestored() -> Void {
    wrappedMethod(); // call the original function
    LogChannel(n"DEBUG", "Player Initialized"); // create a log output
}

Where does it go?

You can see the output on your CET console, or in the scripting.log inside the CET folder.

Improve logging

You can use the function FTLog to create logs with your mod's name as a prefix. It will make it easier for you to go over your logs and filter them:

module MyMod.Logger

public static func MyLog(value: script_ref<String>) -> Void {
  FTLog(s"[MyMod] \(value)");
}

public static func MyLogWarn(value: script_ref<String>) -> Void {
  FTLogWarning(s"[MyMod] \(value)");
}

public static func MyLogError(value: script_ref<String>) -> Void {
  FTLogError(s"[MyMod] \(value)");
}

You can use it like this:

import Codeware.*
import MyMod.Logger.*

class CrazyService extends ScriptableService {
  private cb func OnLoad() {
    MyLog("Psycho stuff!");
    MyLogWarn("Psycho stuff!");
    MyLogError("Psycho stuff!");
  }
}

// It will log something like:
// ... [MyMod] Psycho stuff!
// ... [MyMod] Psycho stuff!      // Colored in Game Log
// ... [MyMod] Psycho stuff!      // Colored in Game Log

We can even improve on this with Codeware. It provides the function GetStackTrace so we can deduce the class and function where our logging function is executed:

module MyMod.Logger

public static func MyLog(value: script_ref<String>) -> Void {
  let entries = GetStackTrace(1, true);
  let entry = entries[0];
  let trace = "";

  if IsDefined(entry.object) {
    trace = s"[\(entry.class)][\(entry.function)]";
  } else {
    trace = s"[\(entry.function)]";
  }
  FTLog(s"[MyMod] \(trace) \(value)");
}

// Same with MyLogWarn / MyLogError and FTLogWarning / FTLogError.

You can use it the same way, this time it will log something like:

// ... [MyMod] [CrazyService][OnLoad] Psycho stuff!

This is convenient as you don't have to worry when you copy/paste this line in another function. The class and function name will be deduced for you. It also works when using a global function.

You can improve this function to list more entries of the stack trace. This is up to you to implement it if you want. An other alternative worth checking is to use redscript-dap, a debugger which integrates with VS Code.