The Lua API docs for protohook
Go to file
2025-01-26 04:48:35 +00:00
README.md Update README.md 2025-01-26 04:48:35 +00:00

Table of Contents

  1. Overview
  2. Engine Table
  3. Renderer Table
  4. Utility Functions
  5. Example Lua Scripts
  6. Best Practices
  7. Troubleshooting

Overview

This documentation outlines the Lua API exposed by your C++ application, allowing Lua scripts to interact with the engine's functionalities and perform rendering operations using ImGui. The API is organized into two primary tables:

  • Engine: Provides utility functions related to logging, coordinate transformations, and settings management.
  • Renderer: Offers a suite of drawing functions to render shapes, images, and text on the screen.

Additionally, utility functions like GetPlayers facilitate data retrieval from the C++ side to Lua.


Engine Table

The Engine table encapsulates functions related to debugging, coordinate transformations, screen information, and settings management. These functions are accessible in Lua as Engine.<FunctionName>.

1. Engine.LogDebug

Description: Logs a debug message to the engine's logging system.

Usage:

Engine.LogDebug(message)

Parameters:

  • message (string): The debug message to log.

Example:

Engine.LogDebug("This is a debug message.")

Notes:

  • Primarily used for development and debugging purposes.
  • Depending on your logging configuration, debug messages may be visible only in development builds.

2. Engine.LogError

Description: Logs an error message to the engine's logging system.

Usage:

Engine.LogError(message)

Parameters:

  • message (string): The error message to log.

Example:

Engine.LogError("An error has occurred in the script.")

Notes:

  • Use this function to report errors that should be visible to users or developers.
  • Errors are typically more prominent in logs and may trigger alerting mechanisms if implemented.

3. Engine.WorldToScreen

Description: Transforms world coordinates (x, y, z) to screen coordinates (screenX, screenY).

Usage:

success, screenX, screenY = Engine.WorldToScreen(x, y, z)

Parameters:

  • x (number): The X-coordinate in the world space.
  • y (number): The Y-coordinate in the world space.
  • z (number): The Z-coordinate in the world space.

Returns:

  • success (boolean): true if the transformation was successful; false otherwise.
  • screenX (number): The resulting X-coordinate on the screen (valid if success is true).
  • screenY (number): The resulting Y-coordinate on the screen (valid if success is true).

Example:

local success, sx, sy = Engine.WorldToScreen(100.0, 200.0, 50.0)
if success then
    Renderer.DrawCircle(sx, sy, 10, 255, 0, 0, 255) -- Draw a red circle at the screen position
else
    Engine.LogError("WorldToScreen transformation failed.")
end

Notes:

  • Ensure that the provided world coordinates are valid and within the visible range.
  • The function relies on an external view matrix (g_ViewMatrix) for the transformation.

4. Engine.GetScreenSize

Description: Retrieves the current screen's width and height.

Usage:

width, height = Engine.GetScreenSize()

Returns:

  • width (number): The width of the screen in pixels.
  • height (number): The height of the screen in pixels.

Example:

local screenWidth, screenHeight = Engine.GetScreenSize()
Renderer.DrawBox(screenWidth - 100, screenHeight - 50, 90, 40, 0, 255, 0, 255) -- Draw a green box near the bottom-right corner

Notes:

  • Useful for positioning UI elements relative to the screen dimensions.
  • Reflects the current display size; changes due to window resizing are updated accordingly.

5. Engine.Settings.Set

Description: Sets the value of a specified engine setting, particularly color configurations.

Usage:

Engine.Settings.Set(identifier, colorTable)

Parameters:

  • identifier (string): The name of the color setting to modify (e.g., "g_GlobalColor").
  • colorTable (table): A table containing four numerical values representing RGBA components, each ranging from 0 to 255.

Color Identifiers:

  • "g_GlobalColor"
  • "g_RectangleColor"
  • "g_SkeletonColor"
  • "g_HealthColorLow"
  • "g_HealthColorHigh"
  • "g_GlowColor"
  • "g_OffscreenArrowColor"
  • "g_BombCircleColor"
  • "g_CircleColor"
  • "g_NameColor"
  • "g_FlagsColor"

Example:

-- Set the global color to blue with full opacity
Engine.Settings.Set("g_GlobalColor", {0, 0, 255, 255})

-- Set the health color low threshold to red with half opacity
Engine.Settings.Set("g_HealthColorLow", {255, 0, 0, 128})

Notes:

  • The colorTable must contain exactly four numerical values corresponding to red (r), green (g), blue (b), and alpha (a) channels.
  • Values must be within the range [0, 255]. Out-of-range values will result in an error.
  • Changing these settings may immediately affect rendering elements that rely on these color configurations.

Renderer Table

The Renderer table provides a collection of functions to draw various shapes, images, and text on the screen. These functions leverage ImGui's drawing capabilities and are accessible in Lua as Renderer.<FunctionName>.

1. Renderer.DrawBox

Description: Draws a filled rectangle (box) on the screen.

Usage:

Renderer.DrawBox(x, y, width, height, r, g, b, a)

Parameters:

  • x (number): The X-coordinate of the top-left corner.
  • y (number): The Y-coordinate of the top-left corner.
  • width (number): The width of the box in pixels.
  • height (number): The height of the box in pixels.
  • r (number): Red component of the color (0-255).
  • g (number): Green component of the color (0-255).
  • b (number): Blue component of the color (0-255).
  • a (number): Alpha (opacity) component of the color (0-255).

Example:

-- Draw a semi-transparent blue box at (50, 50) with size 100x150
Renderer.DrawBox(50, 50, 100, 150, 0, 0, 255, 128)

Notes:

  • The box is drawn relative to the screen's coordinate system.
  • Alpha (a) controls the transparency; 0 is fully transparent, and 255 is fully opaque.

2. Renderer.DrawCircle

Description: Draws a filled circle on the screen.

Usage:

Renderer.DrawCircle(x, y, radius, r, g, b, a)

Parameters:

  • x (number): The X-coordinate of the circle's center.
  • y (number): The Y-coordinate of the circle's center.
  • radius (number): The radius of the circle in pixels.
  • r (number): Red component of the color (0-255).
  • g (number): Green component of the color (0-255).
  • b (number): Blue component of the color (0-255).
  • a (number): Alpha (opacity) component of the color (0-255).

Example:

-- Draw a solid red circle at (200, 200) with a radius of 50
Renderer.DrawCircle(200, 200, 50, 255, 0, 0, 255)

Notes:

  • The circle is filled with the specified color and opacity.
  • The number of segments (24 in the C++ code) determines the smoothness of the circle.

3. Renderer.DrawLine

Description: Draws a straight line between two points on the screen.

Usage:

Renderer.DrawLine(x1, y1, x2, y2, r, g, b, a)

Parameters:

  • x1 (number): The X-coordinate of the starting point.
  • y1 (number): The Y-coordinate of the starting point.
  • x2 (number): The X-coordinate of the ending point.
  • y2 (number): The Y-coordinate of the ending point.
  • r (number): Red component of the line color (0-255).
  • g (number): Green component of the line color (0-255).
  • b (number): Blue component of the line color (0-255).
  • a (number): Alpha (opacity) component of the line color (0-255).

Example:

-- Draw a green line from (300, 300) to (400, 400)
Renderer.DrawLine(300, 300, 400, 400, 0, 255, 0, 255)

Notes:

  • Lines are drawn with a default thickness (2.0f in the C++ code).
  • The color's alpha value affects the line's transparency.

4. Renderer.DrawText

Description: Renders text at a specified position on the screen.

Usage:

Renderer.DrawText(x, y, text, r, g, b, a)

Parameters:

  • x (number): The X-coordinate where the text begins.
  • y (number): The Y-coordinate where the text begins.
  • text (string): The text string to render.
  • r (number): Red component of the text color (0-255).
  • g (number): Green component of the text color (0-255).
  • b (number): Blue component of the text color (0-255).
  • a (number): Alpha (opacity) component of the text color (0-255).

Example:

-- Draw white text at (500, 500)
Renderer.DrawText(500, 500, "Hello, World!", 255, 255, 255, 255)

Notes:

  • The text uses ImGui's current font and font size.
  • Ensure that the text parameter is a valid string to avoid rendering issues.

5. Renderer.DrawEllipse

Description: Draws a filled ellipse on the screen.

Usage:

Renderer.DrawEllipse(x, y, rx, ry, r, g, b, a)

Parameters:

  • x (number): The X-coordinate of the ellipse's center.
  • y (number): The Y-coordinate of the ellipse's center.
  • rx (number): The horizontal radius of the ellipse.
  • ry (number): The vertical radius of the ellipse.
  • r (number): Red component of the ellipse color (0-255).
  • g (number): Green component of the ellipse color (0-255).
  • b (number): Blue component of the ellipse color (0-255).
  • a (number): Alpha (opacity) component of the ellipse color (0-255).

Example:

-- Draw a semi-transparent yellow ellipse at (600, 600) with radii 80 and 40
Renderer.DrawEllipse(600, 600, 80, 40, 255, 255, 0, 128)

Notes:

  • The number of segments (24 in the C++ code) determines the smoothness of the ellipse.
  • Similar to DrawCircle, the alpha value controls transparency.

6. Renderer.DrawPolygon

Description: Draws a filled convex polygon with a specified number of vertices.

Usage:

Renderer.DrawPolygon(n, x1, y1, x2, y2, ..., r, g, b, a)

Parameters:

  • n (number): The number of vertices (must be at least 3).
  • x1, y1 (number): Coordinates of the first vertex.
  • x2, y2 (number): Coordinates of the second vertex.
  • ... (number): Coordinates of subsequent vertices (x3, y3, etc.).
  • r (number): Red component of the polygon color (0-255).
  • g (number): Green component of the polygon color (0-255).
  • b (number): Blue component of the polygon color (0-255).
  • a (number): Alpha (opacity) component of the polygon color (0-255).

Example:

-- Draw a green rectangle as a polygon
Renderer.DrawPolygon(4, 700, 700, 800, 700, 800, 800, 700, 800, 0, 255, 0, 255)

Notes:

  • The polygon must be convex. Non-convex polygons may not render correctly.
  • Ensure that the number of coordinates matches n * 2.
  • Alpha (a) controls the transparency of the polygon.

7. Renderer.DrawArc

Description: Draws an arc between two angles around a center point.

Usage:

Renderer.DrawArc(x, y, radius, start_angle, end_angle, r, g, b, a)

Parameters:

  • x (number): The X-coordinate of the arc's center.
  • y (number): The Y-coordinate of the arc's center.
  • radius (number): The radius of the arc.
  • start_angle (number): The starting angle of the arc in degrees.
  • end_angle (number): The ending angle of the arc in degrees.
  • r (number): Red component of the arc color (0-255).
  • g (number): Green component of the arc color (0-255).
  • b (number): Blue component of the arc color (0-255).
  • a (number): Alpha (opacity) component of the arc color (0-255).

Example:

-- Draw a blue arc from 0 to 180 degrees at (900, 900) with radius 100
Renderer.DrawArc(900, 900, 100, 0, 180, 0, 0, 255, 255)

Notes:

  • Angles are specified in degrees. Ensure correct angle calculations when scripting.
  • The arc is drawn as an outline with a default thickness (2.0f in the C++ code).
  • Alpha (a) controls the transparency of the arc.

8. Renderer.DrawBezierCurve

Description: Draws a cubic Bezier curve between two points with two control points.

Usage:

Renderer.DrawBezierCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, r, g, b, a)

Parameters:

  • x1, y1 (number): Coordinates of the starting point.
  • cx1, cy1 (number): Coordinates of the first control point.
  • cx2, cy2 (number): Coordinates of the second control point.
  • x2, y2 (number): Coordinates of the ending point.
  • r (number): Red component of the curve color (0-255).
  • g (number): Green component of the curve color (0-255).
  • b (number): Blue component of the curve color (0-255).
  • a (number): Alpha (opacity) component of the curve color (0-255).

Example:

-- Draw a yellow Bezier curve from (1000, 1000) to (1100, 1100) with control points
Renderer.DrawBezierCurve(1000, 1000, 1050, 950, 1150, 1150, 1100, 1100, 255, 255, 0, 255)

Notes:

  • The curve is drawn with a default thickness (2.0f in the C++ code).
  • Control points influence the curvature; adjusting them alters the shape of the curve.
  • Alpha (a) controls the transparency of the curve.

9. Renderer.DrawTriangle

Description: Draws a filled triangle defined by three vertices.

Usage:

Renderer.DrawTriangle(x1, y1, x2, y2, x3, y3, r, g, b, a)

Parameters:

  • x1, y1 (number): Coordinates of the first vertex.
  • x2, y2 (number): Coordinates of the second vertex.
  • x3, y3 (number): Coordinates of the third vertex.
  • r (number): Red component of the triangle color (0-255).
  • g (number): Green component of the triangle color (0-255).
  • b (number): Blue component of the triangle color (0-255).
  • a (number): Alpha (opacity) component of the triangle color (0-255).

Example:

-- Draw a purple triangle
Renderer.DrawTriangle(1200, 1200, 1250, 1250, 1200, 1300, 128, 0, 128, 255)

Notes:

  • The triangle is filled with the specified color and opacity.
  • Ensure that the three points do not lie on a straight line to form a valid triangle.

10. Renderer.DrawPolyline

Description: Draws a series of connected lines (polyline) between multiple points.

Usage:

Renderer.DrawPolyline(n, x1, y1, x2, y2, ..., r, g, b, a)

Parameters:

  • n (number): The number of points (must be at least 2).
  • x1, y1 (number): Coordinates of the first point.
  • x2, y2 (number): Coordinates of the second point.
  • ... (number): Coordinates of subsequent points (x3, y3, etc.).
  • r (number): Red component of the polyline color (0-255).
  • g (number): Green component of the polyline color (0-255).
  • b (number): Blue component of the polyline color (0-255).
  • a (number): Alpha (opacity) component of the polyline color (0-255).

Example:

-- Draw a cyan polyline forming a V shape
Renderer.DrawPolyline(3, 1300, 1300, 1350, 1350, 1400, 1300, 0, 255, 255, 255)

Notes:

  • The polyline is not closed; it connects each point sequentially without forming a loop.
  • The line thickness is set to 2.0f in the C++ code.
  • Alpha (a) controls the transparency of the polyline.

Utility Functions

GetPlayers

Description: Retrieves a table of player information from the C++ side. This function is exposed globally to Lua as GetPlayers.

Usage:

players, error = GetPlayers()

Returns:

  • players (table): A table containing player data. Each entry corresponds to a player with various attributes.
  • error (string, optional): An error message if the retrieval fails. nil if successful.

Player Attributes: Each player table includes the following fields:

  • name (string): Player's name.
  • ping (number): Player's ping in milliseconds.
  • health (number): Player's health points.
  • armor (number): Player's armor points.
  • team (number): Player's team identifier.
  • distance (number): Distance from the player to a reference point.
  • hasDefuser (boolean): Indicates if the player has a defuser.
  • hasHelmet (boolean): Indicates if the player has a helmet.
  • position (table): Player's current position with x, y, z coordinates.
  • headPosition (table): Player's head position with x, y, z coordinates.

Example:

local players, err = GetPlayers()
if not players then
    Engine.LogError("Failed to retrieve players: " .. err)
else
    for i, player in ipairs(players) do
        Renderer.DrawText(player.position.x, player.position.y, player.name, 255, 255, 255, 255)
        Renderer.DrawCircle(player.position.x, player.position.y, 10, 0, 255, 0, 255) -- Green circle for each player
    end
end

Notes:

  • The function returns nil and an error message if the players' data pointer is invalid.
  • Ensure that the players pointer is valid and that player data is populated on the C++ side.

Example Lua Scripts

Below are example Lua scripts demonstrating how to utilize the Engine and Renderer APIs to perform various tasks.

Example 1: Simple Debug Logging and Drawing

-- Log a debug message
Engine.LogDebug("Script initialized successfully.")

-- Get screen size
local width, height = Engine.GetScreenSize()

-- Draw a red box at the center of the screen
Renderer.DrawBox(width / 2 - 50, height / 2 - 50, 100, 100, 255, 0, 0, 255)

-- Draw a blue circle at the top-left corner
Renderer.DrawCircle(50, 50, 30, 0, 0, 255, 255)

-- Draw white text inside the box
Renderer.DrawText(width / 2 - 40, height / 2 - 20, "Hello!", 255, 255, 255, 255)

Example 2: Dynamic Player Indicators

function onTick()
    local players, err = GetPlayers()
    if not players then
        Engine.LogError("Error retrieving players: " .. err)
        return
    end

    for _, player in ipairs(players) do
        if player.health > 0 then
            Renderer.DrawCircle(player.position.x, player.position.y, 15, 0, 255, 0, 255) -- Green circle for alive players
            Renderer.DrawText(player.position.x + 20, player.position.y, player.name, 255, 255, 255, 255)
        else
            Renderer.DrawCircle(player.position.x, player.position.y, 15, 255, 0, 0, 255) -- Red circle for dead players
            Renderer.DrawText(player.position.x + 20, player.position.y, player.name, 255, 255, 255, 255)
        end
    end
end

Example 3: Drawing Complex Shapes

-- Draw an ellipse with semi-transparent purple color
Renderer.DrawEllipse(400, 400, 80, 40, 128, 0, 128, 128)

-- Draw a polygon (triangle) with yellow color
Renderer.DrawPolygon(3, 500, 500, 550, 500, 525, 550, 255, 255, 0, 255)

-- Draw an arc representing a 90-degree section
Renderer.DrawArc(600, 600, 60, 0, 90, 0, 255, 255, 255)

-- Draw a Bezier curve for a smooth path
Renderer.DrawBezierCurve(700, 700, 750, 650, 850, 750, 900, 700, 0, 255, 255, 255)

-- Draw a filled triangle
Renderer.DrawTriangle(1000, 1000, 1050, 1050, 1000, 1100, 255, 0, 255, 255)

-- Draw a polyline forming a zig-zag pattern
Renderer.DrawPolyline(4, 1100, 1100, 1150, 1150, 1200, 1100, 1250, 1150, 0, 255, 255, 255)

Best Practices

To ensure optimal performance, maintainability, and stability when using the Lua API, adhere to the following best practices:

  1. Validate Inputs:

    • Always provide the correct number and type of arguments when calling API functions.
    • Utilize error handling (e.g., checking return values) to manage unexpected scenarios.
  2. Optimize Drawing Calls:

    • Minimize the number of drawing calls within high-frequency functions like onTick to prevent performance degradation.
    • Batch multiple drawing operations where possible.
  3. Manage Resources Wisely:

    • Ensure that any resources (e.g., textures) used in drawing functions are properly loaded and managed on the C++ side.
    • Avoid memory leaks by adhering to proper ownership and lifecycle management of objects.
  4. Use Meaningful Logging:

    • Leverage Engine.LogDebug and Engine.LogError to trace script execution and debug issues.
    • Provide clear and concise log messages to facilitate troubleshooting.
  5. Coordinate Systems Awareness:

    • Understand the screen coordinate system where (0,0) typically represents the top-left corner.
    • Account for screen resizing by dynamically retrieving screen dimensions using Engine.GetScreenSize.
  6. Thread Safety:

    • If interacting with shared resources or multi-threaded systems, ensure that proper synchronization mechanisms are in place to prevent race conditions.
  7. Consistent Style and Naming:

    • Follow consistent naming conventions for variables and functions to enhance code readability.
    • Structure your scripts logically, grouping related operations together.
  8. Documentation and Comments:

    • Comment your Lua scripts to explain complex logic or drawing sequences.
    • Refer to this documentation as needed to understand the API functions and their usages.

Troubleshooting

Common Issues and Solutions

  1. Error: "Invalid color identifier: "

    Cause: The provided identifier string does not match any recognized color settings.

    Solution:

    • Verify that the identifier matches one of the predefined color identifiers exactly (case-sensitive).
    • Refer to the Engine.Settings.Set documentation for available identifiers.

    Example:

    -- Correct identifier
    Engine.Settings.Set("g_GlobalColor", {255, 255, 255, 255})
    
    -- Incorrect identifier (case-sensitive)
    Engine.Settings.Set("G_GlobalColor", {255, 255, 255, 255}) -- This will cause an error
    
  2. Error: "Renderer. expects numerical arguments at position "

    Cause: One or more arguments provided to a drawing function are not numbers.

    Solution:

    • Ensure all positional arguments are of type number.
    • Check the order and count of arguments as per the function's documentation.

    Example:

    -- Correct usage
    Renderer.DrawBox(100, 100, 50, 50, 0, 0, 255, 255)
    
    -- Incorrect usage (non-number argument)
    Renderer.DrawBox(100, "100", 50, 50, 0, 0, 255, 255) -- Second argument should be a number
    
  3. Error: "Renderer. expects a lightuserdata for textureID"

    Cause: The textureID provided to Renderer.DrawImage is not a light userdata.

    Solution:

    • Ensure that textureID is a valid ImTextureID passed as light userdata from the C++ side.
    • Confirm that the texture is properly loaded and accessible.

    Example:

    -- Correct usage (assuming 'texture' is a valid ImTextureID)
    Renderer.DrawImage(texture, 300, 300, 100, 100, 255, 255, 255, 255)
    
    -- Incorrect usage
    Renderer.DrawImage("invalid_texture", 300, 300, 100, 100, 255, 255, 255, 255) -- Should be lightuserdata, not string
    
  4. Text Not Rendering or Positioned Incorrectly

    Cause: The text position may be outside the visible screen area or the text string is empty.

    Solution:

    • Verify that the x and y coordinates are within the screen bounds.
    • Ensure that the text parameter contains a valid string.

    Example:

    -- Correct usage
    Renderer.DrawText(500, 500, "Player Name", 255, 255, 255, 255)
    
    -- Incorrect usage (out-of-bounds coordinates)
    Renderer.DrawText(-10, -10, "Hidden Text", 255, 255, 255, 255)
    
  5. No Visible Drawings Despite Correct Function Calls

    Cause: The drawing functions rely on ImGui's drawing system, which may not be initialized or may have rendering issues.

    Solution:

    • Ensure that ImGui is properly initialized in your C++ application.
    • Verify that the drawing occurs within a valid rendering loop.
    • Check for any ImGui-related errors in the C++ logs.

    Example:

    // Ensure ImGui is initialized before running scripts
    ImGui::CreateContext();
    // ... other ImGui setup code
    

Additional Information

Extending the API

You can further enhance the Lua API by adding more functions to both the Engine and Renderer tables. Follow the established patterns for consistency and maintainability. Ensure that each new function includes thorough argument validation and adheres to best practices outlined above.

Security Considerations

  • Sandboxing: If Lua scripts are sourced from untrusted inputs, consider sandboxing the environment to prevent malicious operations.
  • Resource Limits: Implement limits on script execution time and resource usage to prevent scripts from degrading application performance.

Performance Optimization

  • Minimize Drawing Calls: Reduce the number of drawing calls within high-frequency loops to enhance performance.
  • Batch Rendering: Where possible, batch multiple drawing operations into a single call.
  • Profile Scripts: Use profiling tools to identify and optimize slow-performing scripts.