No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-01-20 13:11:41 -05:00
src Initial commit: Adaptive Trigger API v1.0.0 2026-01-20 13:06:20 -05:00
Cargo.toml Update repository URL in Cargo.toml 2026-01-20 13:11:41 -05:00
README.md Update README with correct git repository URL 2026-01-20 13:09:24 -05:00

Adaptive Trigger API

A standardized API for controlling DualSense adaptive triggers from Skyline plugins running in the Citron emulator.

Quick Start

Add the dependency to your plugin's Cargo.toml:

[dependencies]
adaptive_trigger_api = { git = "https://git.citron-emu.org/SylveonDeko/adaptive_trigger_api", branch = "main" }
# Or use a local path during development:
# adaptive_trigger_api = { path = "../adaptive_trigger_api" }

Use the API in your plugin:

use adaptive_trigger_api::{Trigger, set_feedback, set_vibration, set_off};

// Apply resistance to right trigger (like holding a heavy object)
set_feedback(Trigger::Right, 0.2, 0.8);

// Vibrate both triggers (warning/impact feedback)
set_vibration(Trigger::Both, 0.0, 0.7, 20.0);

// Reset trigger to normal
set_off(Trigger::Left);

API Reference

Triggers

pub enum Trigger {
    Left,   // ZL / L2
    Right,  // ZR / R2
    Both,   // Both triggers simultaneously
}

Functions

set_off(trigger: Trigger)

Reset trigger to normal (no effect).

set_feedback(trigger: Trigger, position: f32, strength: f32)

Continuous resistance starting at a position.

  • position: Where resistance starts (0.0 = beginning, 1.0 = fully pressed)
  • strength: How strong the resistance is (0.0 = none, 1.0 = maximum)

Use cases: Holding objects, pressure, tension

set_weapon(trigger: Trigger, start: f32, end: f32, strength: f32)

Weapon-style effect with a click point.

  • start: Where resistance begins (0.0-1.0)
  • end: Where resistance ends/clicks (0.0-1.0)
  • strength: Effect intensity (0.0-1.0)

Use cases: Gun triggers, bow draws, button clicks

set_vibration(trigger: Trigger, position: f32, amplitude: f32, frequency: f32)

Vibration effect on the trigger.

  • position: Where vibration is felt (0.0-1.0)
  • amplitude: Vibration intensity (0.0-1.0)
  • frequency: Speed in Hz (typically 1-40)

Use cases: Warnings, impacts, engine rumble

Convenience Functions

reset_all()                              // Turn off both triggers
set_left_feedback(position, strength)    // Left trigger only
set_right_feedback(position, strength)   // Right trigger only
set_both_vibration(pos, amp, freq)       // Both triggers

Example: Shield Pressure

use adaptive_trigger_api::{Trigger, set_feedback, set_vibration, set_off};

fn update_shield(shield_health: f32, max_shield: f32) {
    if shield_health <= 0.0 {
        // Shield broken - intense vibration
        set_vibration(Trigger::Both, 0.0, 1.0, 40.0);
        return;
    }

    // Calculate resistance (more as shield depletes)
    let normalized = shield_health / max_shield;
    let resistance = 1.0 - normalized;

    // Apply to both triggers
    set_feedback(Trigger::Both, 0.1, resistance);

    // Warning vibration when critical
    if normalized < 0.2 {
        set_vibration(Trigger::Both, 0.3, 0.6, 25.0);
    }
}

How It Works

The API maintains a shared memory region marked with "ADTR" that the Citron emulator scans for. When found, the emulator reads trigger states at 60Hz and applies them to connected DualSense controllers.

┌─────────────────────────────────────────────────┐
│  Your Plugin                                    │
│  set_feedback(Trigger::Right, 0.2, 0.8)         │
│                    │                            │
│                    ▼                            │
│  ┌───────────────────────────────────────────┐  │
│  │ Shared Memory: "ADTR" + trigger states    │  │
│  └───────────────────────────────────────────┘  │
└─────────────────────────────────────────────────┘
                     │
                     ▼ (emulator reads at 60Hz)
┌─────────────────────────────────────────────────┐
│  Citron Emulator → DualSense Controller         │
└─────────────────────────────────────────────────┘

Requirements

  • Citron emulator with DualSense support
  • DualSense controller connected via USB or Bluetooth
  • macOS (currently, other platforms coming soon)

License

GPL-2.0-or-later