Bully Scripting Documentation

website·Indexed 30 days ago

https://bully-scripting.vercel.app/

A technical reference for scripting in Bully, featuring raw dumps of global variables, Lua functions, and game triggers. Includes comprehensive PS2 object model lists for peds, vehicles, weapons, and clothing, as well as scripting enumerations for mission indices, ped stats, and physical states.

Tokens
171.3K
Snippets
646
Records
794
Agent score
72%

What's inside Bully Scripting

  1. Overview of Derpy's Script Loader (DSL)

    Derpy's Script Loader (DSL) is a script loader for Bully: Scholarship Edition (PC) that allows developers to run Lua scripts without manual compilation. Key capabilities include:

    • Loading scripts from folders or zip archives.
    • Bypassing compilation via a patched Lua parser to run scripts from source.
    • Support for an unlimited number of scripts via a custom script manager.
    • Access to the full Lua standard library with optional security settings.
    • Script collections that can be started, stopped, and restarted during gameplay.
    • Ability to save/load arbitrary Lua data within game save files.
    • Integrated console for detailed error reporting and custom scriptable commands.
    • Custom per-frame renderer for low-level drawing functions.
    • Early script execution (e.g., on the main menu or before conventional STimeCycle.lur replacements).
    • Localized text entry replacement and registration.
    • Event-based hooking into base game scripts.
  2. Use mission indices for mission management and debugging

    The mission index is an integer-based alternative to standard string mission codes. While less common and primarily used for debugging, it allows developers to identify, start, and track missions using unique IDs rather than strings. In DSL 10, mission indices can be used to spoof the game into believing a specific mission or minigame is active.
  3. Configure the DSL server settings

    The server is configured via the config.txt file generated upon first run. Key configuration options include:

    • server_name: The name of the server.
    • server_info: Information about the server.
    • server_icon: (Optional) Relative path to a 1:1 PNG file (max 100 KiB).
    • whitelist_instead: Set to true to enable IP whitelisting.
    • whitelist_ip: Used when whitelist_instead is true; duplicate this line to add multiple allowed IPs.
  4. Use Derpy Script Server for network scripting

    Derpy Script Server is the server-side version of DSL. It enables the server to send scripts to players and facilitate communication between players via scripting. Note that DSL and the server do not handle game synchronization. Server capabilities include:

    • Managing script collections via the server console.
    • Sending client scripts and updates to players upon collection restart.
    • Creating server-side scripts with access to most DSL functions.
    • Using network events to exchange arbitrary Lua data between client and server scripts.
  5. Retrieve pool metadata using GetAllPoolInfo

    The GetAllPoolInfo function (introduced in DSL 6) returns a table containing information about individual pools. If a specific pool name is provided as an argument, it returns info for that pool; otherwise, it returns info for all available pools.

    Note: The pool names returned in the table may not directly match the names expected by the GetPoolSize function.

    Each pool info table contains the following fields:

    • name (string): The name of the pool.
    • count (integer): The number of elements currently used in the pool.
    • limit (integer): The current limit of the pool (typically equal to size).
    • size (integer): The maximum number of elements allowed in the pool.
    -- Example: Print all pool info
    for index, pool in pairs(GetAllPoolInfo()) do
      for key, value in pairs(pool) do
        print(key .. ': ' .. value)
      end
      print('---', index)
    end
  6. Understand Bully: Anniversary Edition control codes

    Control codes in Bully: Anniversary Edition (mobile) are tilde-delimited sequences (e.g., ~code~) embedded within game text. They serve as inline instructions for the game engine to handle text formatting and UI rendering—such as inserting line breaks, displaying icons, or triggering contextual buttons—without being visible to the player as raw text. These codes are found within the decompiled XML localization files.
  7. Understand and use the POINTLIST global object

    The POINTLIST global object contains named spatial anchors used for spawn locations, teleport targets, restart positions, and environmental anchors. Unlike TRIGGER (which defines volumes), POINTLIST entries define specific coordinates.

    Key constraints:

    • No Iteration: POINTLIST cannot be iterated with pairs() because it is an engine-managed container where Lua only receives integer handles.
    • Non-stable IDs: Point handles change between sessions; always reference points by their constant name (e.g., POINTLIST._PLAYER_START).
    • Case-Insensitivity: Keys are case-insensitive, though UPPERCASE is the recommended best practice.
    • Loading Requirement: You must load the corresponding .dat file using DATLoad before referencing a point, otherwise the value will be -1.
  8. Understand and use TRIGGER spatial detectors

    Triggers are engine-managed spatial detectors (cuboids or spheres) used to trigger actions when players or NPCs enter or exit a region. They are exposed to Lua as global constants (e.g., TRIGGER._AMB_SCHOOL_AREA) rather than standard Lua tables.

    Critical Requirements:

    • You must load the corresponding .dat file using DATLoad before referencing a trigger. If the file is not loaded, the trigger constant will return -1.
    • Trigger IDs are not stable across sessions; always reference them by their constant name.
    • Keys in the TRIGGER object are case-insensitive, though UPPERCASE is the recommended best practice to match internal game code style.
  9. Example: Register and update a dynamic localized text label

    This example demonstrates how to register a custom label TARGET_PED_NAME, update its content dynamically using ReplaceLocalizedText based on a target ped's name, and display it using TextPrint.
    RegisterLocalizedText('TARGET_PED_NAME', 100)
    
    function main()
      while not SystemIsReady() do
        Wait(0)
      end
      while true do
        local target = PedGetTargetPed(gPlayer)
        if PedIsValid(target) then
          -- Update the registered label with the ped's name
          ReplaceLocalizedText('TARGET_PED_NAME', PedGetName(target))
          -- Print the localized text to the screen
          TextPrint('TARGET_PED_NAME', 0, 1)
        end
        Wait(0)
      end
    end
  10. Create a configuration file for a script collection

    Each script collection can have a config.txt or config.ini file located in the root of its folder or zip archive. Since DSL 10, these files are no longer generated automatically and must be created manually to define settings, scripts, and requirements.
    ; Name and requirements
    require_name: My Awesome Mod
    require_version: 10
    
    ; Startup Behavior
    main_script: scripts/main.lua      # Defaults to "main.lua"
    init_script: scripts/init.lua       # Runs when main menu is first reached
    pre_init_script: scripts/pre-init.lua # Runs very early during game init
    auto_start: true                    # Automatically start the collection
    
    ; Network Settings
    allow_on_server: false              # Allow running when connected to a server
    
    ; Game File Registration (Temporary IMG archive)
    act_file: AI/AI.cat
    cuts_file: Cutscenes/1-01.dat
    trigger_file: Triggers/MisTrig.dat
    ide_file: IDE/default.idb
    scripts_file: Scripts/main.lur
    world_file: World/MG_Biology.nft
    
    ; Custom Mod Settings (Read via GetConfigString, GetConfigNumber, etc.)
    font: Consolas
    scale: 1.5
    vertical_position: top
    horizontal_position: right
  11. Disable controller input using ZeroController

    The ZeroController function zeros all input memory on a specified controller. This is the primary method for disabling all input on an input device. To prevent buttons from misbehaving (such as acting as if they are being repeatedly pressed), this function must be called during both the ControllerUpdating and ControllersUpdated events.

    This function was introduced in DSL 6 (replacing the non-functional DisableController from DSL 5).

    RegisterLocalEventHandler('ControllerUpdating', function(controller)
      if controller == 0 then
        ZeroController(controller)
      end
    end)
    
    RegisterLocalEventHandler('ControllersUpdated', function()
      ZeroController(0)
    end)
  12. Install and run the DSL server on Ubuntu Linux

    The DSL server is a 32-bit application. On 64-bit Ubuntu systems, you must install lib32z1 and libc6-i386 to run the server. The server executable must be granted execution permissions via chmod before it can be run.
    # Create and enter server directory
    mkdir my-dss-server
    cd my-dss-server
    
    # Download and extract server release
    wget -q -O dss.zip https://www.mediafire.com/file_premium/vobshxqcc2kxxa8/derpy_script_server_9_s.zip/file
    unzip dss.zip
    
    # Install required 32-bit packages
    sudo apt-get install lib32z1
    sudo apt-get install libc6-i386
    
    # Make server executable
    chmod +x derpy_script_server
    
    # Run once to generate config.txt
    ./derpy_script_server
    
    # Edit configuration
    nano config.txt
    
    # Run the server
    ./derpy_script_server