From f345ba5d3e2bc2d299c8b3d7677bac844dbc046b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 8 Dec 2025 16:47:40 +0000
Subject: [PATCH 01/27] Initial plan
From 2393e7c2c2767b1d98c669623202dc6bff3429c6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 8 Dec 2025 16:55:00 +0000
Subject: [PATCH 02/27] Add GTA V ScriptHookDotNet integration with MSAgent-AI
Co-authored-by: ExtCan <60326708+ExtCan@users.noreply.github.com>
---
GTAVScripts/MSAgentGTAV.cs | 478 ++++++++++++++++++++++++++++++++
GTAVScripts/MSAgentGTAV.csproj | 64 +++++
GTAVScripts/QUICKSTART.md | 180 ++++++++++++
GTAVScripts/README.md | 338 ++++++++++++++++++++++
GTAVScripts/build.bat | 100 +++++++
GTAVScripts/config.example.json | 45 +++
README.md | 27 ++
7 files changed, 1232 insertions(+)
create mode 100644 GTAVScripts/MSAgentGTAV.cs
create mode 100644 GTAVScripts/MSAgentGTAV.csproj
create mode 100644 GTAVScripts/QUICKSTART.md
create mode 100644 GTAVScripts/README.md
create mode 100644 GTAVScripts/build.bat
create mode 100644 GTAVScripts/config.example.json
diff --git a/GTAVScripts/MSAgentGTAV.cs b/GTAVScripts/MSAgentGTAV.cs
new file mode 100644
index 0000000..aa5cd85
--- /dev/null
+++ b/GTAVScripts/MSAgentGTAV.cs
@@ -0,0 +1,478 @@
+using System;
+using System.IO;
+using System.IO.Pipes;
+using System.Text;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Linq;
+using GTA;
+using GTA.UI;
+using GTA.Math;
+using GTA.Native;
+
+namespace MSAgentGTAV
+{
+ ///
+ /// MSAgent-AI integration for GTA V
+ /// Live commentary and reactions to in-game events via Named Pipe communication
+ ///
+ public class MSAgentGTAV : Script
+ {
+ // Configuration
+ private const string PIPE_NAME = "MSAgentAI";
+ private const int COOLDOWN_MS = 10000; // 10 second cooldown between reactions
+ private const int FAST_COOLDOWN_MS = 3000; // 3 second cooldown for frequent events
+
+ // Menu system
+ private UIMenu mainMenu;
+ private MenuPool menuPool;
+ private bool menuEnabled = true;
+
+ // Toggle switches for different reaction types
+ private bool reactToVehicles = true;
+ private bool reactToMissions = true;
+ private bool reactToWeather = true;
+ private bool reactToTime = true;
+ private bool reactToLocation = true;
+ private bool reactToPlayerState = true;
+ private bool reactToCharacterSwitch = true;
+ private bool reactToVehicleValue = true;
+
+ // State tracking
+ private Vehicle lastVehicle;
+ private Weather lastWeather;
+ private int lastHour = -1;
+ private string lastZone = "";
+ private int lastWantedLevel = 0;
+ private DateTime lastReactionTime = DateTime.MinValue;
+ private DateTime lastVehicleReactionTime = DateTime.MinValue;
+ private DateTime lastLocationReactionTime = DateTime.MinValue;
+ private DateTime lastWeatherReactionTime = DateTime.MinValue;
+ private Model lastCharacterModel;
+ private bool playerWasDead = false;
+ private Hash lastMissionHash = 0;
+
+ // Vehicle value tracking
+ private Dictionary vehicleValues = new Dictionary();
+
+ public MSAgentGTAV()
+ {
+ InitializeVehicleValues();
+ SetupMenu();
+
+ // Event handlers
+ Tick += OnTick;
+ Aborted += OnAborted;
+
+ SendToAgent("SPEAK:GTA V integration loaded! I'm ready to commentate!");
+ }
+
+ private void InitializeVehicleValues()
+ {
+ // Approximate vehicle values in GTA$ (these are rough estimates)
+ // Super cars
+ vehicleValues[VehicleHash.Adder] = 1000000;
+ vehicleValues[VehicleHash.Zentorno] = 725000;
+ vehicleValues[VehicleHash.Osiris] = 1950000;
+ vehicleValues[VehicleHash.T20] = 2200000;
+ vehicleValues[VehicleHash.Turismor] = 500000;
+ vehicleValues[VehicleHash.Entityxf] = 795000;
+ vehicleValues[VehicleHash.Infernus] = 440000;
+ vehicleValues[VehicleHash.Vacca] = 240000;
+ vehicleValues[VehicleHash.Bullet] = 155000;
+ vehicleValues[VehicleHash.Cheetah] = 650000;
+ vehicleValues[VehicleHash.Voltic] = 150000;
+ vehicleValues[VehicleHash.Banshee] = 105000;
+
+ // Sports cars
+ vehicleValues[VehicleHash.Carbonizzare] = 195000;
+ vehicleValues[VehicleHash.Coquette] = 138000;
+ vehicleValues[VehicleHash.Elegy2] = 0; // Free
+ vehicleValues[VehicleHash.Feltzer2] = 145000;
+ vehicleValues[VehicleHash.Ninef] = 130000;
+
+ // Motorcycles
+ vehicleValues[VehicleHash.Akuma] = 9000;
+ vehicleValues[VehicleHash.Bati] = 15000;
+ vehicleValues[VehicleHash.Hakuchou] = 82000;
+ vehicleValues[VehicleHash.Pcj] = 9000;
+
+ // Helicopters
+ vehicleValues[VehicleHash.Buzzard2] = 1750000;
+ vehicleValues[VehicleHash.Frogger] = 1300000;
+ vehicleValues[VehicleHash.Maverick] = 780000;
+
+ // Planes
+ vehicleValues[VehicleHash.Luxor] = 1500000;
+ vehicleValues[VehicleHash.Shamal] = 1150000;
+ vehicleValues[VehicleHash.Velum] = 450000;
+
+ // Boats
+ vehicleValues[VehicleHash.Jetmax] = 299000;
+ vehicleValues[VehicleHash.Marquis] = 413000;
+ vehicleValues[VehicleHash.Seashark] = 16000;
+ }
+
+ private void SetupMenu()
+ {
+ menuPool = new MenuPool();
+ mainMenu = new UIMenu("MSAgent-AI", "~b~GTA V Integration Settings");
+ menuPool.Add(mainMenu);
+
+ // Add toggle items
+ var vehicleToggle = new UIMenuCheckboxItem("React to Vehicles", reactToVehicles,
+ "Enable/disable reactions when entering vehicles");
+ mainMenu.AddItem(vehicleToggle);
+
+ var missionToggle = new UIMenuCheckboxItem("React to Missions", reactToMissions,
+ "Enable/disable reactions to mission events");
+ mainMenu.AddItem(missionToggle);
+
+ var weatherToggle = new UIMenuCheckboxItem("React to Weather", reactToWeather,
+ "Enable/disable reactions to weather changes");
+ mainMenu.AddItem(weatherToggle);
+
+ var timeToggle = new UIMenuCheckboxItem("React to Time", reactToTime,
+ "Enable/disable reactions to time of day");
+ mainMenu.AddItem(timeToggle);
+
+ var locationToggle = new UIMenuCheckboxItem("React to Location", reactToLocation,
+ "Enable/disable reactions when entering new areas");
+ mainMenu.AddItem(locationToggle);
+
+ var playerStateToggle = new UIMenuCheckboxItem("React to Player State", reactToPlayerState,
+ "Enable/disable reactions to health, wanted level, etc.");
+ mainMenu.AddItem(playerStateToggle);
+
+ var characterToggle = new UIMenuCheckboxItem("React to Character Switch", reactToCharacterSwitch,
+ "Enable/disable reactions when switching characters");
+ mainMenu.AddItem(characterToggle);
+
+ var vehicleValueToggle = new UIMenuCheckboxItem("React to Vehicle Value", reactToVehicleValue,
+ "Enable/disable reactions based on vehicle worth");
+ mainMenu.AddItem(vehicleValueToggle);
+
+ // Handle checkbox changes
+ mainMenu.OnCheckboxChange += (sender, item, checked_) =>
+ {
+ if (item == vehicleToggle) reactToVehicles = checked_;
+ else if (item == missionToggle) reactToMissions = checked_;
+ else if (item == weatherToggle) reactToWeather = checked_;
+ else if (item == timeToggle) reactToTime = checked_;
+ else if (item == locationToggle) reactToLocation = checked_;
+ else if (item == playerStateToggle) reactToPlayerState = checked_;
+ else if (item == characterToggle) reactToCharacterSwitch = checked_;
+ else if (item == vehicleValueToggle) reactToVehicleValue = checked_;
+
+ Notification.Show($"~g~MSAgent: {item.Text} " + (checked_ ? "enabled" : "disabled"));
+ };
+
+ mainMenu.RefreshIndex();
+ }
+
+ private void OnTick(object sender, EventArgs e)
+ {
+ // Process menu
+ menuPool.ProcessMenus();
+
+ // Toggle menu with F9 key (can be changed)
+ if (Game.IsKeyPressed(System.Windows.Forms.Keys.F9))
+ {
+ if (mainMenu.Visible)
+ mainMenu.Visible = false;
+ else
+ mainMenu.Visible = true;
+
+ Wait(200); // Debounce
+ }
+
+ Ped player = Game.Player.Character;
+ if (player == null || !player.IsAlive)
+ {
+ if (!playerWasDead && reactToPlayerState)
+ {
+ playerWasDead = true;
+ SendChatPrompt("The player just died! React to their death with sympathy or humor.");
+ }
+ return;
+ }
+
+ if (playerWasDead)
+ {
+ playerWasDead = false;
+ if (reactToPlayerState)
+ {
+ SendChatPrompt("The player respawned. Welcome them back.");
+ }
+ }
+
+ // Check vehicle changes
+ CheckVehicleChange(player);
+
+ // Check weather changes
+ CheckWeatherChange();
+
+ // Check time changes
+ CheckTimeChange();
+
+ // Check location changes
+ CheckLocationChange(player);
+
+ // Check wanted level changes
+ CheckWantedLevel(player);
+
+ // Check character switch
+ CheckCharacterSwitch(player);
+
+ // Check mission state
+ CheckMissionState();
+ }
+
+ private void CheckVehicleChange(Ped player)
+ {
+ if (!reactToVehicles) return;
+
+ Vehicle currentVehicle = player.CurrentVehicle;
+
+ if (currentVehicle != null && currentVehicle != lastVehicle)
+ {
+ if (CanReact(ref lastVehicleReactionTime, FAST_COOLDOWN_MS))
+ {
+ lastVehicle = currentVehicle;
+
+ string vehicleType = GetVehicleTypeString(currentVehicle);
+ string vehicleName = currentVehicle.FriendlyName;
+ string valueInfo = "";
+
+ if (reactToVehicleValue && vehicleValues.ContainsKey((VehicleHash)currentVehicle.Model.Hash))
+ {
+ int value = vehicleValues[(VehicleHash)currentVehicle.Model.Hash];
+ valueInfo = $" worth ${value:N0}";
+ }
+
+ SendChatPrompt($"The player just entered a {vehicleType} called {vehicleName}{valueInfo}. React to this vehicle!");
+ }
+ }
+ else if (currentVehicle == null && lastVehicle != null)
+ {
+ if (CanReact(ref lastVehicleReactionTime, FAST_COOLDOWN_MS))
+ {
+ lastVehicle = null;
+ SendChatPrompt("The player just exited their vehicle. Comment on it.");
+ }
+ }
+ }
+
+ private void CheckWeatherChange()
+ {
+ if (!reactToWeather) return;
+
+ Weather currentWeather = World.Weather;
+ if (currentWeather != lastWeather)
+ {
+ if (CanReact(ref lastWeatherReactionTime, COOLDOWN_MS))
+ {
+ lastWeather = currentWeather;
+ string weatherName = currentWeather.ToString();
+ SendChatPrompt($"The weather changed to {weatherName}. Comment on the weather!");
+ }
+ }
+ }
+
+ private void CheckTimeChange()
+ {
+ if (!reactToTime) return;
+
+ int currentHour = World.CurrentDayTime.Hours;
+
+ // React to major time transitions
+ if (lastHour != -1 && lastHour != currentHour)
+ {
+ bool shouldReact = false;
+ string timeDescription = "";
+
+ if (currentHour == 0 && lastHour == 23)
+ {
+ shouldReact = true;
+ timeDescription = "midnight";
+ }
+ else if (currentHour == 6 && lastHour == 5)
+ {
+ shouldReact = true;
+ timeDescription = "sunrise/morning";
+ }
+ else if (currentHour == 12 && lastHour == 11)
+ {
+ shouldReact = true;
+ timeDescription = "noon";
+ }
+ else if (currentHour == 18 && lastHour == 17)
+ {
+ shouldReact = true;
+ timeDescription = "sunset/evening";
+ }
+
+ if (shouldReact && CanReact(ref lastReactionTime, COOLDOWN_MS))
+ {
+ SendChatPrompt($"It's now {timeDescription} in the game. Comment on the time!");
+ }
+ }
+
+ lastHour = currentHour;
+ }
+
+ private void CheckLocationChange(Ped player)
+ {
+ if (!reactToLocation) return;
+
+ string currentZone = World.GetZoneLocalizedName(player.Position);
+
+ if (!string.IsNullOrEmpty(currentZone) && currentZone != lastZone)
+ {
+ if (CanReact(ref lastLocationReactionTime, COOLDOWN_MS))
+ {
+ lastZone = currentZone;
+ SendChatPrompt($"The player entered {currentZone}. Comment on this location!");
+ }
+ }
+ }
+
+ private void CheckWantedLevel(Ped player)
+ {
+ if (!reactToPlayerState) return;
+
+ int currentWantedLevel = Game.Player.WantedLevel;
+
+ if (currentWantedLevel != lastWantedLevel)
+ {
+ if (CanReact(ref lastReactionTime, FAST_COOLDOWN_MS))
+ {
+ lastWantedLevel = currentWantedLevel;
+
+ if (currentWantedLevel > 0)
+ {
+ SendChatPrompt($"The player now has {currentWantedLevel} wanted stars! React to the police chase!");
+ }
+ else
+ {
+ SendChatPrompt("The player escaped the police! Congratulate them!");
+ }
+ }
+ }
+ }
+
+ private void CheckCharacterSwitch(Ped player)
+ {
+ if (!reactToCharacterSwitch) return;
+
+ Model currentModel = player.Model;
+
+ if (lastCharacterModel.Hash != 0 && currentModel.Hash != lastCharacterModel.Hash)
+ {
+ if (CanReact(ref lastReactionTime, COOLDOWN_MS))
+ {
+ string characterName = GetCharacterName(currentModel);
+ SendChatPrompt($"The player switched to {characterName}. React to this character!");
+ }
+ }
+
+ lastCharacterModel = currentModel;
+ }
+
+ private void CheckMissionState()
+ {
+ if (!reactToMissions) return;
+
+ // Check if player is in a mission
+ if (Function.Call(Hash.GET_MISSION_FLAG))
+ {
+ // Get current mission (this is simplified - actual mission detection is complex)
+ Hash currentMission = (Hash)Function.Call(Hash._GET_LABEL_TEXT, "CELL_1");
+
+ if (currentMission != lastMissionHash && currentMission != 0)
+ {
+ if (CanReact(ref lastReactionTime, COOLDOWN_MS))
+ {
+ lastMissionHash = currentMission;
+ SendChatPrompt("A mission started or progressed. Comment on the mission action!");
+ }
+ }
+ }
+ }
+
+ private string GetVehicleTypeString(Vehicle vehicle)
+ {
+ if (vehicle.Model.IsHelicopter) return "helicopter";
+ if (vehicle.Model.IsPlane) return "plane";
+ if (vehicle.Model.IsBoat) return "boat";
+ if (vehicle.Model.IsBike || vehicle.Model.IsBicycle) return "motorcycle";
+ if (vehicle.Model.IsCar) return "car";
+ return "vehicle";
+ }
+
+ private string GetCharacterName(Model model)
+ {
+ // GTA V protagonists
+ if (model.Hash == PedHash.Michael.GetHashCode()) return "Michael De Santa";
+ if (model.Hash == PedHash.Franklin.GetHashCode()) return "Franklin Clinton";
+ if (model.Hash == PedHash.Trevor.GetHashCode()) return "Trevor Philips";
+
+ return "a different character";
+ }
+
+ private bool CanReact(ref DateTime lastTime, int cooldownMs)
+ {
+ TimeSpan elapsed = DateTime.Now - lastTime;
+ if (elapsed.TotalMilliseconds >= cooldownMs)
+ {
+ lastTime = DateTime.Now;
+ return true;
+ }
+ return false;
+ }
+
+ private void SendToAgent(string command)
+ {
+ Task.Run(() =>
+ {
+ try
+ {
+ using (var client = new NamedPipeClientStream(".", PIPE_NAME, PipeDirection.InOut))
+ {
+ client.Connect(1000); // 1 second timeout
+
+ using (var reader = new StreamReader(client))
+ using (var writer = new StreamWriter(client) { AutoFlush = true })
+ {
+ writer.WriteLine(command);
+ string response = reader.ReadLine();
+
+ if (response != null && response.StartsWith("ERROR"))
+ {
+ GTA.UI.Notification.Show($"~r~MSAgent Error: {response}");
+ }
+ }
+ }
+ }
+ catch (TimeoutException)
+ {
+ // MSAgent not running, silently ignore
+ }
+ catch (Exception ex)
+ {
+ GTA.UI.Notification.Show($"~r~MSAgent connection error: {ex.Message}");
+ }
+ });
+ }
+
+ private void SendChatPrompt(string prompt)
+ {
+ SendToAgent($"CHAT:{prompt}");
+ }
+
+ private void OnAborted(object sender, EventArgs e)
+ {
+ SendToAgent("SPEAK:GTA V integration stopped. See you later!");
+ }
+ }
+}
diff --git a/GTAVScripts/MSAgentGTAV.csproj b/GTAVScripts/MSAgentGTAV.csproj
new file mode 100644
index 0000000..b7278cf
--- /dev/null
+++ b/GTAVScripts/MSAgentGTAV.csproj
@@ -0,0 +1,64 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {12345678-ABCD-1234-ABCD-123456789ABC}
+ Library
+ Properties
+ MSAgentGTAV
+ MSAgentGTAV
+ v4.8
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(GTAV_DIR)\ScriptHookVDotNet3.dll
+ False
+
+
+
+
+
+
+
+
+
+ if defined GTAV_DIR (
+ if not exist "$(GTAV_DIR)\scripts" mkdir "$(GTAV_DIR)\scripts"
+ copy "$(TargetPath)" "$(GTAV_DIR)\scripts\"
+ )
+
+
+
diff --git a/GTAVScripts/QUICKSTART.md b/GTAVScripts/QUICKSTART.md
new file mode 100644
index 0000000..ee790c6
--- /dev/null
+++ b/GTAVScripts/QUICKSTART.md
@@ -0,0 +1,180 @@
+# Quick Start Guide - MSAgent-AI GTA V Integration
+
+Get MSAgent commentating on your GTA V gameplay in 5 minutes!
+
+## Prerequisites Checklist
+
+Before you begin, download and install these in order:
+
+- [ ] **GTA V** - Obviously you need the game
+- [ ] **MSAgent-AI** - The main application from this repository
+- [ ] **DoubleAgent** - https://doubleagent.sourceforge.net/
+- [ ] **ScriptHookV** - http://www.dev-c.com/gtav/scripthookv/
+- [ ] **ScriptHookVDotNet** - https://github.com/scripthookvdotnet/scripthookvdotnet/releases
+- [ ] **(Optional) Ollama** - https://ollama.ai for AI-powered responses
+
+## Step-by-Step Installation
+
+### 1. Install MSAgent-AI (5 minutes)
+
+```bash
+# Build the main application
+cd src
+dotnet restore
+dotnet build --configuration Release
+```
+
+Or download a pre-built release from GitHub.
+
+### 2. Install Game Mods (5 minutes)
+
+1. **Install ScriptHookV:**
+ - Download from http://www.dev-c.com/gtav/scripthookv/
+ - Extract `ScriptHookV.dll` and `dinput8.dll`
+ - Copy both to your GTA V folder (where `GTA5.exe` is)
+
+2. **Install ScriptHookVDotNet:**
+ - Download from https://github.com/scripthookvdotnet/scripthookvdotnet/releases
+ - Extract ALL files to your GTA V folder
+ - This creates a `scripts` folder automatically
+
+### 3. Install the MSAgent Script (2 minutes)
+
+**Option A: Use Pre-built DLL (Easier)**
+
+1. Download `MSAgentGTAV.dll` from the releases
+2. Copy it to `[GTA V]\scripts\MSAgentGTAV.dll`
+3. Done!
+
+**Option B: Build from Source**
+
+1. Set your GTA V directory:
+ ```cmd
+ setx GTAV_DIR "C:\Program Files\Rockstar Games\Grand Theft Auto V"
+ ```
+
+2. Close and reopen your command prompt, then:
+ ```cmd
+ cd GTAVScripts
+ build.bat
+ ```
+
+### 4. First Launch (1 minute)
+
+1. **Start MSAgent-AI first:**
+ - Run `MSAgentAI.exe`
+ - Wait for the agent to appear
+ - Configure your character if needed
+
+2. **Launch GTA V:**
+ - Start the game normally
+ - Load into story mode
+ - Wait for "GTA V integration loaded!" notification
+
+3. **Test it:**
+ - Press **F9** to open the menu
+ - Get in a car - MSAgent should react!
+ - Try changing weather with a trainer
+ - Switch characters (Story Mode)
+
+## Quick Test
+
+To verify everything works:
+
+1. **Start MSAgent-AI** - You should see the agent on your desktop
+2. **Launch GTA V** - Load into story mode
+3. **Look for the notification** - "GTA V integration loaded!"
+4. **Press F9** - The menu should appear
+5. **Get in any vehicle** - Within 3 seconds, MSAgent should comment
+
+If MSAgent doesn't react, see the Troubleshooting section in README.md.
+
+## Configuration
+
+### MSAgent-AI Settings
+
+Open MSAgent-AI settings and configure:
+
+- **Character**: Choose your favorite MS Agent character
+- **Voice**: Select a SAPI4 voice
+- **Ollama**: (Optional) Enable for AI responses
+ - Install Ollama: https://ollama.ai
+ - Run: `ollama pull llama3.2`
+ - Set URL to `http://localhost:11434`
+ - Enable "Enable Chat"
+
+### Script Settings (In-Game)
+
+Press **F9** in GTA V to access the menu:
+
+- ✅ React to Vehicles - Comments on cars, bikes, boats, planes
+- ✅ React to Missions - Comments on mission events
+- ✅ React to Weather - Comments on weather changes
+- ✅ React to Time - Comments on sunrise, sunset, etc.
+- ✅ React to Location - Comments when entering areas
+- ✅ React to Player State - Comments on health, wanted level
+- ✅ React to Character Switch - Comments when switching
+- ✅ React to Vehicle Value - Mentions vehicle prices
+
+Toggle any off if they're too chatty!
+
+## Common Issues
+
+### "Script not loading"
+- Check that ScriptHookV version matches your game version
+- Update ScriptHookV after GTA V updates
+- Check `ScriptHookV.log` in GTA V folder
+
+### "MSAgent not responding"
+- Make sure MSAgent-AI is running BEFORE you start GTA V
+- Check system tray for MSAgent icon
+- Check `MSAgentAI.log` for errors
+
+### "Too many reactions"
+- Press F9 and disable some reaction types
+- Or edit cooldown times in the source code
+
+### "Game crashes on startup"
+- Remove ScriptHookV temporarily to test
+- Update all mods to latest versions
+- Check game file integrity in Social Club/Steam
+
+## Tips for Best Experience
+
+1. **Enable Ollama AI** - Much better responses than static text
+2. **Start MSAgent first** - Always launch it before GTA V
+3. **Adjust reaction toggles** - Find what works for you
+4. **Use a personality prompt** - Make MSAgent funny/serious/etc.
+5. **Watch the logs** - `MSAgentAI.log` shows all communication
+
+## Example Reactions
+
+With Ollama AI enabled, you might hear:
+
+**Getting in an expensive car:**
+> "Whoa! A Zentorno worth $725,000? Someone's living large! Try not to scratch it!"
+
+**3-star wanted level:**
+> "Uh oh! Three stars! The cops are NOT happy with you! Floor it!"
+
+**Switching to Trevor:**
+> "Oh great, Trevor's here. Time for some chaos, I suppose!"
+
+**Sunset in Los Santos:**
+> "Beautiful sunset over Los Santos. Almost makes you forget about all the crime!"
+
+## What's Next?
+
+- Explore all the reaction types
+- Customize the prompts in the source code
+- Add new vehicle values
+- Share your favorite reactions!
+
+## Need Help?
+
+- Check the full [README.md](README.md)
+- Read the [PIPELINE.md](../PIPELINE.md) documentation
+- Review MSAgent logs
+- Open an issue on GitHub
+
+Have fun!
diff --git a/GTAVScripts/README.md b/GTAVScripts/README.md
new file mode 100644
index 0000000..f31e5e0
--- /dev/null
+++ b/GTAVScripts/README.md
@@ -0,0 +1,338 @@
+# MSAgent-AI GTA V Integration
+
+This script integrates MSAgent-AI with Grand Theft Auto V to provide live commentary and reactions to in-game events using the Microsoft Agent character.
+
+## Features
+
+### Live Commentary On:
+- **Vehicles**: Cars, motorcycles, boats, planes, and helicopters
+- **Vehicle Value**: Reactions based on how expensive the vehicle is
+- **Missions**: Mission starts and progression
+- **Weather**: Weather changes (sunny, rainy, foggy, etc.)
+- **Time of Day**: Sunrise, noon, sunset, midnight transitions
+- **Locations**: Entering new areas and zones
+- **Player State**: Health changes, wanted level, death/respawn
+- **Character Switching**: Switching between Michael, Franklin, and Trevor
+
+### Interactive Menu
+- Press **F9** to open/close the in-game menu
+- Toggle individual reaction types on/off
+- Real-time configuration without restarting the game
+
+## Requirements
+
+### 1. MSAgent-AI Application
+The main MSAgent-AI desktop application must be running for the script to work.
+
+**Download and Setup:**
+1. Build or download MSAgent-AI from the main repository
+2. Install DoubleAgent: https://doubleagent.sourceforge.net/
+3. Install SAPI 4.0a SDK for voices
+4. (Optional) Install Ollama for AI-powered responses: https://ollama.ai
+5. Run MSAgentAI.exe before starting GTA V
+
+### 2. ScriptHookV
+Required for running scripts in GTA V.
+
+**Download:** http://www.dev-c.com/gtav/scripthookv/
+
+**Installation:**
+1. Download ScriptHookV
+2. Extract `ScriptHookV.dll` and `dinput8.dll` to your GTA V root folder
+3. The root folder contains `GTA5.exe`
+
+### 3. ScriptHookVDotNet
+Required for running .NET scripts in GTA V.
+
+**Download:** https://github.com/scripthookvdotnet/scripthookvdotnet/releases
+
+**Installation:**
+1. Download the latest version (v3.x recommended)
+2. Extract all files to your GTA V root folder
+3. This will create a `scripts` folder if it doesn't exist
+
+## Installation
+
+### Quick Install
+
+1. **Ensure MSAgent-AI is running** before launching GTA V
+2. Copy `MSAgentGTAV.dll` to your GTA V `scripts` folder
+ - Usually: `C:\Program Files\Rockstar Games\Grand Theft Auto V\scripts\`
+3. Launch GTA V
+4. Once in-game, you should see a notification: "GTA V integration loaded!"
+
+### Building from Source
+
+If you want to build the script yourself:
+
+#### Prerequisites
+- Visual Studio 2019 or later
+- .NET Framework 4.8 SDK
+- ScriptHookVDotNet3.dll (from ScriptHookVDotNet installation)
+
+#### Build Steps
+
+1. **Set GTA V directory environment variable** (optional, for auto-copy):
+ ```cmd
+ setx GTAV_DIR "C:\Program Files\Rockstar Games\Grand Theft Auto V"
+ ```
+
+2. **Open project in Visual Studio:**
+ ```cmd
+ cd GTAVScripts
+ # Open MSAgentGTAV.csproj in Visual Studio
+ ```
+
+3. **Add ScriptHookVDotNet reference:**
+ - If you didn't set GTAV_DIR, manually add reference to `ScriptHookVDotNet3.dll`
+ - Right-click project → Add → Reference → Browse
+ - Navigate to your GTA V folder and select `ScriptHookVDotNet3.dll`
+
+4. **Build the project:**
+ - Build → Build Solution (or press F6)
+ - The DLL will be in `bin\Release\MSAgentGTAV.dll`
+
+5. **Copy to GTA V:**
+ - If GTAV_DIR was set, the post-build event copies automatically
+ - Otherwise, manually copy `MSAgentGTAV.dll` to `GTA V\scripts\`
+
+#### Alternative: Command Line Build
+
+```cmd
+cd GTAVScripts
+
+# Set reference path to your GTA V directory
+set GTAV_DIR=C:\Program Files\Rockstar Games\Grand Theft Auto V
+
+# Build using MSBuild
+msbuild MSAgentGTAV.csproj /p:Configuration=Release
+
+# Copy to GTA V scripts folder
+copy bin\Release\MSAgentGTAV.dll "%GTAV_DIR%\scripts\"
+```
+
+## Usage
+
+### First Launch
+
+1. **Start MSAgent-AI** - The desktop application must be running first
+2. **Configure MSAgent-AI** (optional):
+ - Set your preferred character
+ - Configure voice settings
+ - Enable Ollama chat for AI-powered responses
+3. **Launch GTA V**
+4. Wait for the game to load
+5. You should see: "GTA V integration loaded!" notification
+6. MSAgent should say: "GTA V integration loaded! I'm ready to commentate!"
+
+### In-Game Controls
+
+**F9** - Open/Close the MSAgent menu
+
+### Menu Options
+
+The in-game menu allows you to toggle different reaction types:
+
+- **React to Vehicles** - Comments when entering/exiting vehicles
+- **React to Missions** - Comments on mission events
+- **React to Weather** - Comments on weather changes
+- **React to Time** - Comments on time of day transitions
+- **React to Location** - Comments when entering new areas
+- **React to Player State** - Comments on health, wanted level, death
+- **React to Character Switch** - Comments when switching protagonists
+- **React to Vehicle Value** - Includes vehicle price in reactions
+
+Each option can be toggled on/off independently without restarting the game.
+
+### Customizing the Key Binding
+
+To change the menu key from F9 to something else:
+
+1. Open `MSAgentGTAV.cs` in a text editor
+2. Find the line: `if (Game.IsKeyPressed(System.Windows.Forms.Keys.F9))`
+3. Replace `F9` with your preferred key (e.g., `F8`, `F10`, `Insert`, etc.)
+4. Rebuild the script
+
+Available keys: F1-F12, Insert, Delete, Home, End, PageUp, PageDown, etc.
+
+## How It Works
+
+The script monitors various game events and sends them to MSAgent-AI through a Named Pipe connection (`\\.\pipe\MSAgentAI`).
+
+### Communication Protocol
+
+The script uses these pipe commands:
+
+- `SPEAK:text` - Make MSAgent speak directly
+- `CHAT:prompt` - Send a prompt to Ollama AI for intelligent responses
+
+### Examples of Reactions
+
+**Vehicle Entry:**
+```
+CHAT:The player just entered a car called Zentorno worth $725,000. React to this vehicle!
+```
+
+**Weather Change:**
+```
+CHAT:The weather changed to Rainy. Comment on the weather!
+```
+
+**Wanted Level:**
+```
+CHAT:The player now has 3 wanted stars! React to the police chase!
+```
+
+**Character Switch:**
+```
+CHAT:The player switched to Trevor Philips. React to this character!
+```
+
+### Cooldown System
+
+To prevent spam, the script implements cooldowns:
+- **Standard cooldown**: 10 seconds between most reactions
+- **Fast cooldown**: 3 seconds for frequent events (vehicles, wanted level)
+- **Location cooldown**: 10 seconds between location changes
+
+## Troubleshooting
+
+### Script Not Loading
+
+1. **Check ScriptHookV is installed:**
+ - `ScriptHookV.dll` in GTA V root folder
+ - `dinput8.dll` in GTA V root folder
+
+2. **Check ScriptHookVDotNet is installed:**
+ - `ScriptHookVDotNet.asi` in GTA V root folder
+ - `ScriptHookVDotNet3.dll` in GTA V root folder
+
+3. **Check MSAgentGTAV.dll location:**
+ - Must be in `GTA V\scripts\` folder
+ - Create the folder if it doesn't exist
+
+4. **Check game version:**
+ - ScriptHookV must match your GTA V version
+ - Update ScriptHookV after game updates
+
+### MSAgent Not Responding
+
+1. **Verify MSAgent-AI is running:**
+ - Check system tray for MSAgent icon
+ - Open MSAgent settings to confirm it's active
+
+2. **Check pipe communication:**
+ - MSAgent-AI starts a pipe server on launch
+ - Look for "Pipeline server started" in MSAgent logs
+ - Log location: `MSAgentAI.log` (same folder as executable)
+
+3. **Test the pipe manually:**
+ - Use PowerShell to test the connection (see PIPELINE.md)
+
+### No Reactions In Game
+
+1. **Check menu settings:**
+ - Press F9 to open menu
+ - Ensure reaction types are enabled (checkboxes)
+
+2. **Check cooldowns:**
+ - Reactions have 3-10 second cooldowns
+ - Wait a bit between events
+
+3. **Check MSAgent chat settings:**
+ - If using Ollama, ensure it's running
+ - Check Ollama URL in MSAgent settings
+ - Verify a model is loaded (e.g., `ollama pull llama3.2`)
+
+### Performance Issues
+
+If the game lags:
+
+1. **Disable unused reactions:**
+ - Open menu (F9)
+ - Disable reaction types you don't need
+
+2. **Increase cooldown times:**
+ - Edit `MSAgentGTAV.cs`
+ - Increase `COOLDOWN_MS` and `FAST_COOLDOWN_MS` values
+ - Rebuild the script
+
+## Known Limitations
+
+1. **Mission Detection**: Full mission dialog detection is limited by game API access
+2. **Online Mode**: Script is designed for single-player mode only
+3. **Pipe Communication**: One-way communication (game → MSAgent only)
+4. **AI Response Time**: CHAT commands may take a few seconds depending on Ollama model
+
+## Customization
+
+### Adding New Vehicle Values
+
+Edit the `InitializeVehicleValues()` method in `MSAgentGTAV.cs`:
+
+```csharp
+vehicleValues[VehicleHash.YourVehicle] = 500000;
+```
+
+### Changing Reaction Messages
+
+Modify the `SendChatPrompt()` calls throughout the script to customize what prompts are sent to MSAgent.
+
+### Adding New Events
+
+Add new event checks in the `OnTick()` method:
+
+```csharp
+private void CheckYourEvent()
+{
+ if (!reactToYourEvent) return;
+
+ if (/* your condition */)
+ {
+ if (CanReact(ref lastYourEventTime, COOLDOWN_MS))
+ {
+ SendChatPrompt("Your custom prompt here!");
+ }
+ }
+}
+```
+
+## Version History
+
+### v1.0.0 (Initial Release)
+- Full vehicle detection (cars, bikes, boats, planes, helicopters)
+- Vehicle value tracking and reactions
+- Weather and time of day monitoring
+- Location/zone change detection
+- Player state tracking (health, wanted level, death)
+- Character switching detection
+- Mission state monitoring
+- In-game menu with F9 hotkey
+- Toggleable reaction categories
+- Cooldown system to prevent spam
+- Named Pipe integration with MSAgent-AI
+
+## Credits
+
+- **MSAgent-AI**: Desktop agent application
+- **ScriptHookV**: By Alexander Blade
+- **ScriptHookVDotNet**: By crosire and contributors
+- **GTA V**: Rockstar Games
+
+## License
+
+MIT License - Same as MSAgent-AI project
+
+## Support
+
+For issues or questions:
+1. Check the troubleshooting section above
+2. Review MSAgent-AI logs: `MSAgentAI.log`
+3. Review ScriptHookV logs: `ScriptHookV.log` (in GTA V folder)
+4. Open an issue on the MSAgent-AI repository
+
+## Related Documentation
+
+- [MSAgent-AI Main README](../README.md)
+- [Pipeline Documentation](../PIPELINE.md)
+- [ScriptHookVDotNet Documentation](https://github.com/scripthookvdotnet/scripthookvdotnet)
diff --git a/GTAVScripts/build.bat b/GTAVScripts/build.bat
new file mode 100644
index 0000000..779fc1a
--- /dev/null
+++ b/GTAVScripts/build.bat
@@ -0,0 +1,100 @@
+@echo off
+REM MSAgent-AI GTA V Script Builder
+REM This script builds the MSAgentGTAV.dll and copies it to your GTA V scripts folder
+
+echo ================================
+echo MSAgent-AI GTA V Script Builder
+echo ================================
+echo.
+
+REM Check if GTAV_DIR is set
+if not defined GTAV_DIR (
+ echo ERROR: GTAV_DIR environment variable is not set!
+ echo.
+ echo Please set it to your GTA V installation directory:
+ echo Example: setx GTAV_DIR "C:\Program Files\Rockstar Games\Grand Theft Auto V"
+ echo.
+ echo After setting it, restart this command prompt and try again.
+ echo.
+ pause
+ exit /b 1
+)
+
+echo GTA V Directory: %GTAV_DIR%
+echo.
+
+REM Check if GTA V directory exists
+if not exist "%GTAV_DIR%\GTA5.exe" (
+ echo ERROR: GTA5.exe not found in %GTAV_DIR%
+ echo Please check your GTAV_DIR environment variable.
+ echo.
+ pause
+ exit /b 1
+)
+
+REM Check if ScriptHookVDotNet3.dll exists
+if not exist "%GTAV_DIR%\ScriptHookVDotNet3.dll" (
+ echo ERROR: ScriptHookVDotNet3.dll not found in %GTAV_DIR%
+ echo.
+ echo Please install ScriptHookVDotNet first:
+ echo https://github.com/scripthookvdotnet/scripthookvdotnet/releases
+ echo.
+ pause
+ exit /b 1
+)
+
+echo Building MSAgentGTAV.dll...
+echo.
+
+REM Build the project
+msbuild MSAgentGTAV.csproj /p:Configuration=Release /v:minimal
+
+if errorlevel 1 (
+ echo.
+ echo ERROR: Build failed!
+ echo.
+ echo Make sure you have:
+ echo - .NET Framework 4.8 SDK installed
+ echo - MSBuild in your PATH
+ echo.
+ pause
+ exit /b 1
+)
+
+echo.
+echo Build successful!
+echo.
+
+REM Create scripts folder if it doesn't exist
+if not exist "%GTAV_DIR%\scripts" (
+ echo Creating scripts folder...
+ mkdir "%GTAV_DIR%\scripts"
+)
+
+REM Copy the DLL
+echo Copying MSAgentGTAV.dll to GTA V scripts folder...
+copy /Y "bin\Release\MSAgentGTAV.dll" "%GTAV_DIR%\scripts\"
+
+if errorlevel 1 (
+ echo.
+ echo ERROR: Failed to copy DLL to scripts folder.
+ echo Please check permissions and try again.
+ echo.
+ pause
+ exit /b 1
+)
+
+echo.
+echo ================================
+echo SUCCESS!
+echo ================================
+echo.
+echo MSAgentGTAV.dll has been installed to:
+echo %GTAV_DIR%\scripts\MSAgentGTAV.dll
+echo.
+echo Next steps:
+echo 1. Make sure MSAgent-AI application is running
+echo 2. Launch GTA V
+echo 3. Press F9 in-game to open the menu
+echo.
+pause
diff --git a/GTAVScripts/config.example.json b/GTAVScripts/config.example.json
new file mode 100644
index 0000000..f28947a
--- /dev/null
+++ b/GTAVScripts/config.example.json
@@ -0,0 +1,45 @@
+{
+ "MSAgentGTAV": {
+ "Description": "Configuration template for MSAgentGTAV script",
+ "MenuKey": "F9",
+ "Cooldowns": {
+ "StandardCooldownMs": 10000,
+ "FastCooldownMs": 3000,
+ "Description": "Cooldown times in milliseconds between reactions"
+ },
+ "DefaultToggles": {
+ "ReactToVehicles": true,
+ "ReactToMissions": true,
+ "ReactToWeather": true,
+ "ReactToTime": true,
+ "ReactToLocation": true,
+ "ReactToPlayerState": true,
+ "ReactToCharacterSwitch": true,
+ "ReactToVehicleValue": true
+ },
+ "PipeSettings": {
+ "PipeName": "MSAgentAI",
+ "ConnectionTimeoutMs": 1000,
+ "Description": "Named pipe connection settings for MSAgent-AI communication"
+ },
+ "CustomPrompts": {
+ "Description": "You can customize these prompts in the source code (MSAgentGTAV.cs)",
+ "Examples": {
+ "VehicleEntry": "The player just entered a {vehicleType} called {vehicleName}{valueInfo}. React to this vehicle!",
+ "VehicleExit": "The player just exited their vehicle. Comment on it.",
+ "WeatherChange": "The weather changed to {weatherName}. Comment on the weather!",
+ "WantedLevel": "The player now has {stars} wanted stars! React to the police chase!",
+ "WantedLevelCleared": "The player escaped the police! Congratulate them!",
+ "PlayerDeath": "The player just died! React to their death with sympathy or humor.",
+ "PlayerRespawn": "The player respawned. Welcome them back.",
+ "CharacterSwitch": "The player switched to {characterName}. React to this character!",
+ "LocationChange": "The player entered {locationName}. Comment on this location!",
+ "TimeOfDay": "It's now {timeDescription} in the game. Comment on the time!"
+ }
+ },
+ "VehicleValues": {
+ "Description": "Vehicle values are defined in InitializeVehicleValues() method",
+ "Note": "Add your own vehicle values by editing the MSAgentGTAV.cs source code"
+ }
+ }
+}
diff --git a/README.md b/README.md
index 2150e98..bde2923 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,8 @@ A Windows desktop friend application inspired by BonziBUDDY and CyberBuddy, usin
- **Ollama AI Integration**: Connect to Ollama for dynamic AI-powered conversations with personality prompting
- **Random Dialog**: Configurable random dialog feature (1 in 9000 chance per second by default) that sends custom prompts to Ollama
- **User-Friendly GUI**: System tray application with comprehensive settings panel
+- **Named Pipe API**: External applications can communicate with the agent (see [PIPELINE.md](PIPELINE.md))
+- **GTA V Integration**: Live commentary script for Grand Theft Auto V (see [GTAVScripts/](GTAVScripts/))
## Requirements
@@ -84,6 +86,22 @@ dotnet build
3. Use Chat to have conversations with the agent (requires Ollama)
4. Use Speak menu to make the agent tell jokes, share thoughts, or say custom text
+## Integrations
+
+### GTA V Live Commentary
+
+Want MSAgent to commentate on your GTA V gameplay? Check out the **[GTA V Integration](GTAVScripts/README.md)**!
+
+The script provides live reactions to:
+- Vehicles (cars, bikes, boats, planes, helicopters)
+- Missions and events
+- Weather and time changes
+- Locations and zones
+- Player state (health, wanted level, death)
+- Character switching
+
+See **[GTAVScripts/QUICKSTART.md](GTAVScripts/QUICKSTART.md)** for quick installation guide.
+
## Project Structure
```
@@ -102,7 +120,16 @@ src/
│ ├── SettingsForm.cs # Settings dialog
│ ├── ChatForm.cs # AI chat dialog
│ └── InputDialog.cs # Simple input dialog
+├── Pipeline/
+│ └── PipelineServer.cs # Named pipe server for external apps
└── Program.cs # Application entry point
+
+GTAVScripts/
+├── MSAgentGTAV.cs # GTA V ScriptHookDotNet integration
+├── MSAgentGTAV.csproj # Project file
+├── README.md # Full documentation
+├── QUICKSTART.md # Quick start guide
+└── build.bat # Build script
```
## License
From 926fdf975f098972720306d452b7f2e9fbfdc87c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 8 Dec 2025 16:57:54 +0000
Subject: [PATCH 03/27] Add comprehensive documentation for GTA V integration
Co-authored-by: ExtCan <60326708+ExtCan@users.noreply.github.com>
---
GTAVScripts/.gitignore | 13 +
GTAVScripts/ADVANCED.md | 565 +++++++++++++++++++++++++++++++++
GTAVScripts/TROUBLESHOOTING.md | 364 +++++++++++++++++++++
3 files changed, 942 insertions(+)
create mode 100644 GTAVScripts/.gitignore
create mode 100644 GTAVScripts/ADVANCED.md
create mode 100644 GTAVScripts/TROUBLESHOOTING.md
diff --git a/GTAVScripts/.gitignore b/GTAVScripts/.gitignore
new file mode 100644
index 0000000..cf32726
--- /dev/null
+++ b/GTAVScripts/.gitignore
@@ -0,0 +1,13 @@
+# Build results
+bin/
+obj/
+*.dll
+*.pdb
+
+# Visual Studio
+.vs/
+*.user
+*.suo
+
+# Build artifacts
+*.log
diff --git a/GTAVScripts/ADVANCED.md b/GTAVScripts/ADVANCED.md
new file mode 100644
index 0000000..9b07176
--- /dev/null
+++ b/GTAVScripts/ADVANCED.md
@@ -0,0 +1,565 @@
+# Advanced Features & Customization
+
+This guide covers advanced features and customization options for power users.
+
+## Customizing Prompts
+
+All prompts sent to MSAgent-AI can be customized by editing `MSAgentGTAV.cs`.
+
+### Vehicle Entry Prompt
+
+**Location:** `CheckVehicleChange()` method
+
+**Default:**
+```csharp
+SendChatPrompt($"The player just entered a {vehicleType} called {vehicleName}{valueInfo}. React to this vehicle!");
+```
+
+**Custom Example:**
+```csharp
+// More excited reactions
+SendChatPrompt($"OH WOW! The player is now driving a {vehicleName}! That's a {vehicleType}{valueInfo}! Say something cool!");
+
+// Roleplay as a car enthusiast
+SendChatPrompt($"Vehicle spotted: {vehicleName}. Give a detailed review of this {vehicleType} like a car enthusiast!");
+
+// Humorous reactions
+SendChatPrompt($"The player just stole a {vehicleName}. Make a joke about their choice of vehicle!");
+```
+
+### Weather Change Prompt
+
+**Location:** `CheckWeatherChange()` method
+
+**Custom Examples:**
+```csharp
+// Weather forecaster style
+SendChatPrompt($"Weather update: We're now experiencing {weatherName} conditions. Provide a weather report!");
+
+// Poetic reactions
+SendChatPrompt($"The sky turns to {weatherName}. Describe it poetically!");
+
+// Concerned friend
+SendChatPrompt($"Oh no, it's {weatherName}! Express concern about the player driving in this weather.");
+```
+
+### Death Prompt
+
+**Location:** `OnTick()` method, player death check
+
+**Custom Examples:**
+```csharp
+// Dark humor
+SendChatPrompt("The player died AGAIN! Mock them gently about their driving skills.");
+
+// Supportive
+SendChatPrompt("The player died. Offer encouraging words and tell them they'll do better next time.");
+
+// Statistics tracking
+SendChatPrompt($"Player death #{deathCount}! Keep track and comment on how many times they've died.");
+```
+
+## Adding New Reaction Types
+
+### Example: Speed Tracking
+
+Add speed-based reactions:
+
+```csharp
+// Add to class variables
+private float lastSpeed = 0;
+private DateTime lastSpeedReactionTime = DateTime.MinValue;
+private bool reactToSpeed = true;
+
+// Add to menu setup
+var speedToggle = new UIMenuCheckboxItem("React to Speed", reactToSpeed,
+ "Enable/disable reactions to high speeds");
+mainMenu.AddItem(speedToggle);
+
+// Add to OnCheckboxChange handler
+else if (item == speedToggle) reactToSpeed = checked_;
+
+// Add new method
+private void CheckSpeed(Ped player)
+{
+ if (!reactToSpeed) return;
+
+ Vehicle vehicle = player.CurrentVehicle;
+ if (vehicle == null) return;
+
+ float currentSpeed = vehicle.Speed * 2.23694f; // Convert to MPH
+
+ // React to high speed
+ if (currentSpeed > 100 && lastSpeed <= 100)
+ {
+ if (CanReact(ref lastSpeedReactionTime, COOLDOWN_MS))
+ {
+ SendChatPrompt($"The player is going {currentSpeed:F0} MPH! React to their high speed!");
+ }
+ }
+
+ lastSpeed = currentSpeed;
+}
+
+// Call in OnTick
+CheckSpeed(player);
+```
+
+### Example: Combat Tracking
+
+Track when player shoots weapons:
+
+```csharp
+// Add to class variables
+private bool reactToCombat = true;
+private DateTime lastCombatReactionTime = DateTime.MinValue;
+private bool wasInCombat = false;
+
+// Add method
+private void CheckCombat(Ped player)
+{
+ if (!reactToCombat) return;
+
+ bool isInCombat = player.IsInCombat;
+
+ if (isInCombat && !wasInCombat)
+ {
+ if (CanReact(ref lastCombatReactionTime, COOLDOWN_MS))
+ {
+ SendChatPrompt("The player just started shooting! React to the combat!");
+ }
+ }
+ else if (!isInCombat && wasInCombat)
+ {
+ if (CanReact(ref lastCombatReactionTime, COOLDOWN_MS))
+ {
+ SendChatPrompt("The combat ended. Comment on how it went.");
+ }
+ }
+
+ wasInCombat = isInCombat;
+}
+```
+
+### Example: Money Tracking
+
+React to changes in player money:
+
+```csharp
+private bool reactToMoney = true;
+private int lastMoney = 0;
+private DateTime lastMoneyReactionTime = DateTime.MinValue;
+
+private void CheckMoney(Ped player)
+{
+ if (!reactToMoney) return;
+
+ int currentMoney = Game.Player.Money;
+
+ if (lastMoney > 0 && currentMoney != lastMoney)
+ {
+ int difference = currentMoney - lastMoney;
+
+ if (Math.Abs(difference) > 1000) // Only react to significant changes
+ {
+ if (CanReact(ref lastMoneyReactionTime, COOLDOWN_MS))
+ {
+ if (difference > 0)
+ {
+ SendChatPrompt($"The player earned ${difference:N0}! Congratulate them!");
+ }
+ else
+ {
+ SendChatPrompt($"The player lost ${Math.Abs(difference):N0}! React to their loss!");
+ }
+ }
+ }
+ }
+
+ lastMoney = currentMoney;
+}
+```
+
+## Advanced Menu Features
+
+### Adding Submenus
+
+Create organized submenus for different settings:
+
+```csharp
+private void SetupAdvancedMenu()
+{
+ menuPool = new MenuPool();
+ mainMenu = new UIMenu("MSAgent-AI", "~b~GTA V Integration");
+ menuPool.Add(mainMenu);
+
+ // Create submenus
+ var vehicleMenu = menuPool.AddSubMenu(mainMenu, "Vehicle Settings");
+ var environmentMenu = menuPool.AddSubMenu(mainMenu, "Environment Settings");
+ var playerMenu = menuPool.AddSubMenu(mainMenu, "Player Settings");
+
+ // Add items to vehicle submenu
+ vehicleMenu.AddItem(new UIMenuCheckboxItem("React to Entry", reactToVehicles));
+ vehicleMenu.AddItem(new UIMenuCheckboxItem("React to Value", reactToVehicleValue));
+ vehicleMenu.AddItem(new UIMenuCheckboxItem("React to Speed", reactToSpeed));
+
+ // Add items to environment submenu
+ environmentMenu.AddItem(new UIMenuCheckboxItem("React to Weather", reactToWeather));
+ environmentMenu.AddItem(new UIMenuCheckboxItem("React to Time", reactToTime));
+ environmentMenu.AddItem(new UIMenuCheckboxItem("React to Location", reactToLocation));
+
+ // Add items to player submenu
+ playerMenu.AddItem(new UIMenuCheckboxItem("React to Health", reactToPlayerState));
+ playerMenu.AddItem(new UIMenuCheckboxItem("React to Death", reactToPlayerState));
+ playerMenu.AddItem(new UIMenuCheckboxItem("React to Wanted Level", reactToPlayerState));
+}
+```
+
+### Adding Sliders for Cooldowns
+
+Allow in-game adjustment of cooldown times:
+
+```csharp
+// Add to menu setup
+var cooldownSlider = new UIMenuSliderItem("Reaction Cooldown (seconds)",
+ new List