Blood, Carnage, and Unexpected AI
-
So I had this very simple script.
Spawn the girl, spawn the car, give the girl a task to drive to the airport while I sit back, as the player (my hands off the keyboard), and enjoy the drive. Not using Rockstar Editor, never do, but I have the drive on cinematic mode (R key).
Nothing unusual until the girl, who is a terrible driver, rams into something. No big deal right? Well the other driver takes exception, he has a gun, and all hell breaks loose as his buddies and other scumbags join in. I'm just sitting in the car watching as my ped girl gets out of the car and starts to engage these criminals. At this point I turn on OBS which is open in the background and record the mayhem, while tossing grenades just for fun.
I figure the drive is over, that the script will terminate, ....but no...she gets back into the car to finish the drive! Too funny.
-
Dynamically adjusting the drivers maximum speed based on the type of road node at the vehicles velocity position can improve the standard driving AI a hell of alot.
static void DriverSpeed(Ped p, Vehicle v) // This is run every tick { if (v != null && p != null && v.Driver.Handle == p.Handle) { float roadSpeed = GetRoadSpeed(v.Position + v.Velocity); if (roadSpeed != Speed) { float increment = 0.01f; Speed = roadSpeed; if (v.Speed > Speed) { p.MaxDrivingSpeed = v.Speed - (increment * Game.LastFrameTime); p.DrivingSpeed = v.Speed - (increment * Game.LastFrameTime); } else { p.MaxDrivingSpeed = Speed; p.DrivingSpeed = Speed; } } } } public static float GetRoadSpeed(Vector3 pos) { OutputArgument outArgA = new OutputArgument(); OutputArgument outArgB = new OutputArgument(); if (Function.Call<bool>(Hash.GET_VEHICLE_NODE_PROPERTIES, pos.X, pos.Y, pos.Z, outArgA, outArgB)) { int busy = outArgA.GetResult<int>(); int flags = outArgB.GetResult<int>(); float speed = 8; foreach (int flag in Enum.GetValues(typeof(PathnodeFlags)).Cast<PathnodeFlags>()) { if ((flag & flags) != 0) { switch ((PathnodeFlags)flag) { case PathnodeFlags.Two: speed = 16; break; case PathnodeFlags.Freeway: speed = 35; break; case PathnodeFlags.Slow: speed = 9; break; case PathnodeFlags.Eight: speed = 16; break; case PathnodeFlags.SlowTraffic: speed = 14; break; case PathnodeFlags.FourWayIntersection: speed = 11; break; case PathnodeFlags.Intersection: speed = 11; break; default: speed = 8; break; } } } int NodeID = Function.Call<int>(Hash.GET_NTH_CLOSEST_VEHICLE_NODE_ID, pos.X, pos.Y, pos.Z, 1, 1, 200f, 200f); if (Function.Call<bool>(Hash._GET_IS_SLOW_ROAD_FLAG, NodeID)) { if (speed > 9) { speed *= 0.7f; } } return speed; } return 5; }
-
@mcal9909 Hi. I wasn't trying to figure out why the ped was such a bad driver, on the contrary I find that amusing. What surprised me is that after killing dozens of people and blowing up vehicles (my part) the ped resumed the script - I would have bet money the script would terminate. The speed was set at 95 on purpose and the driving style set to default. What is equally as funny is that this was supposed to be a casual drive, never expected a firefight.
Having said that, thank you for your code. Looks quite detailed and interesting. Could be very useful for a script in the future.
-
@JohnFromGWN Indeed it was entertaining, Not behaviour i have seen yet as such a ped in any script i have made will not react to events happening around them
Ped.BlockPermanentEvents = true;
, from my understanding certain tasks can be layered ontop of each other with primary and secondary tasks. It would be interesting to know what else a ped can do while still keeping the underlying drive task.Did the ped drive to the correct location? I wonder if the game gave the ped a new drive task or if the original task was still active.
-
@mcal9909 Yes the ped will drive correctly to the location, although any obstacles can cause changes in the route - or worst case back and forth movements. The peds, scripted or not, will often do stuff that will make you say WTF???
Not sure how you would implement a secondary task. I know for example some task sequences, animations for example, will require a wait statement - if not the animations are triggered differently than expected.
-
@JohnFromGWN My guess is reacting to events is a secondary task in its self. Some reactions are permanent. If your driver was unarmed she would run away and never come back.
Come to think of it i have seen this bevior in my script, i have peds that run a patrol task on foot. They have weapons and events are not blocked. They will attack if provoked and carry on with there assigned task after all enemies are dead. Just never thought to try it with driving.
-
@mcal9909 Funniest one, strangest, and only happened once, while testing a driving script which i had run 100s of times without incident, suddenly a car stops in front of my vehicle (which is auto driving through script). My vehicle rear ends the vehicle and a couple occupants get out and start a firefight with another vehicle, completely random.
But it gets better. After the occupants of the car are killed, a jogger running by (NPC) stops, looks at the car, gets in and drives away. Too funny again.
P.S. You have to admit the ped in my video, well she's one badass.