With OneSync getting more and more features this might actually be planned at some point, still I’d like to hear your opinions and ask for help developing this idea.
There have been quite a few experiments over the last years on the behavior of NPCs with no players nearby. Not much progress has been made, most likely due to the fact that the GTA V-natives are not written with long-range actions in mind. This post and Serpent itself present an idea that WILL work (as I’ve already proven with a few videos which are linked below).
The idea is easiest described like this:
I want an NPC be able to drive around Paleto Bay and act normally even if every player on a server is inside Los Santos.
Disclaimer
I am posting this as several posts due to the length of each.
Dear mods, I hope this is ok as this thread will desperately need some structure…
The first post outlines the general idea of the project. The pictures and code in there might be a little outdated.
The second post outlines what already has been created, what is in a working state and what isn’t.
This will also contain the link to the github-repo with the currently existing code.
The third post describes what needs to be done, what I can offer and what you could do to help this project be realized.
Why would you want this?
You might be familiar with FivePD, the multiplayer police mod released over a year ago. It has gained a lot of traction and is imo a fantastic mod. The callouts however have been quite limited in possibilities the last time I checked the mod. FivePD uses (or atleast - used) a system similar to LSPDFR in that you can accept missions and they are only spawned afterwards which presents a problem regarding the timing of missions.
In single player you don’t need to rely on mission timing (simply hardcode the timing in a proper way). In a multiplayer environment you absolutely need consistent time and space. It would be pretty strange, if a mission in a police mod called out Attack on Paleto Bay PD
and one officer would be like Ehh no? I'm standing inside it
, only to be murdered by five NPCs that spawned as soon as the mission got accepted.
In order to get around that I want to give the NPCs their own agency. I want to make sure that the NPCs can move on their own and do their own decision-making independent of players or even players being near the place (have an attack on Paleto Bay PD triggered while everyone is on Route 69?).
Now you could work around this problem by checking if a player currently is inside Paleto Bay PD and suppress the mission that would result in spawning NPCs running rampage. However imagine this mission:
You could hardcode the vehicle to appear at a specific point when police gets near (this is how every police-mod would do it). But that defeats a in my opinion very important part of police work: Search for the criminal. Without properly simulating the car driving down Great Ocean Highway this will always feel bullshit to an extent (I was at the entrance to Paleto Bay and drove down Great Ocean Highway when the mission triggered. I never saw a dark grey Oracle speeding towards me...
). Simulating NPC movement over the map will actually make this mission playable in the way it is supposed to work. This would be a huge factor for immersion and a fun yet challenging gameplay.
This isn’t possible client side, since the LongRange functions don’t work properly and most of the time the entities simply get deleted upon creation. Trying to force the issue will render non-moving NPCs that do not react to any movement command. This gets exponentially worse with multiple players on the server. While one player on the server will have the ped working sometimes, with multiple players it’s essentially never working.
The main idea for a solution
My suggestion for Serpent should simulate the NPC-movement completely serverside. Relying only on self-created data it wouldn’t need problem-riddled Natives. Instead the server creates and controls these entities. While no player is near the entity is never spawned and exists purely as a bunch of variables. Only when a player gets near the server issues a SpawnCommand to the player in question. It remains in control of the entity in the sense that it sends every action the entity should make to the client that spawned the entity (e.g. move here, attack this, …).
Now am I completely insane? Well, yes, probably. But the system still can work. A possible design would look like this:
PedList = {}
VehicleList = {}
first off initialize the main lists that will carry the data for every single object to be simulated.
Now data for any ped could look like this:
local ExamplePed = {
PedIID = 1, -- Mod-Internal ID: This is the main ID of any entity used in this system. It is persistent and will be used to identify the ped, issue tasks, change its data etc etc
x = x, -- current position: x coord
y = y, -- current position: y coord
z = z, -- current position: z coord
IsSpawnedBool = false, -- checks if the ped currently is available client side
OwnerClientNetID = 0, -- NetID of the client that spawned the ped
PedNetID = 0, -- NetID of the Ped when spawned
PedModel = "a_f_m_beach_01", -- Ped Model
PedVisualData = {}, -- Components and Props of that model
CurrObjective = "DriveToCoord", -- the currently issued task
ObjectiveData = { -- the data of said task
tarx = 2000.0,
tary = 2000.0,
tarz = 2000.0,
},
PathfindingData = {}, -- if the task is a moving-task you'll need pathfinding data. If you need to store this data this is the place
IsInVeh = false, -- bool if the ped currently is in a vehicle
VehIID = 0, -- Mod-Internal ID of the vehicle
. -- possibly a shitload of other variables that need to be saved
.
.
}
Yes, I’m insane, you probably got that by now. Yes, this would be a full-scale entity handler done serverside. Now what code would need to run serverside in order to actually make such a system work?
Player-Position
The position of every player needs to be known to the server. Let every player send their position to the server by using a serverside while loop on a Wait(500) + events.
Entity-Position
The position of every controlled entity needs to be updated. Could be done by using a serverside while loop on a Wait(500) and executing serverside events for every entity (e.g. Event “DriveToCoord” for the above entity). See below for these “action-events”.
“Action-Events”
The actions of the entities get controlled serverside. This is done by using events that simulate the behavior. Let’s assume that we want to send an entity to a specific coordinate, using a “DriveToCoord”-event.
We need to check whether the entity is spawned or not. If the entity is spawned, this is trivial: Let the server send a command (using TriggerClientEvent
) to the client responsible for the entity. That Client event should make the client trigger the Native DriveToCoord
for the respective entity (note that the server got every required variable for that native saved in the above list).
If the entity is not spawned, this is harder, but certainly possible. First of all, we need
The pathfinding algorithm
I am very much certain that GTA V uses A-Star for pathfinding albeit in a very complex way. With 70000 nodes you wouldn’t want to have an algorithm venture through all of them to find the best way.
However for the goal here this massive amount of nodes isn’t necessary at all. GTA V simulates movement up to the specific lane a car is driving on. For DISTANT peds all that is necessary is a broad approximation. For this, a simple implementation of A-Star should suffice. I already implemented A-Star and tested it successfully for Paleto Bay:
This is a picture of Paleto Bay that I put out with path nodes. Neighboring pathnodes are connected, so the system can recognize every single road. Note that I included every by-street and parking lot, and got a total of 72 nodes. Excluding parking lots will bring this number down to approx. 25 nodes.
A single node looks like this:
It has a specific ID, coordinates, and has every possible exit to another node given in a list. The number after behind the id is the speed limit of that piece of road (unit is mph). Also you can use different booleans, e.g. intersection
, highway
, pedestrianOnly
, …, that could later be used to modify the behavior of that pathnode.
Note how these pathnodes have MUCH fewer variables and information than Rockstars’ system.
Yes, you’ll never get me back, now that I showed you that I do not only produce insane ideas but actually do parts of it.
Is creating pathnodes for the rest of the map insane? Yes, but it’s only time intensive, you can very well
create a small ingame script for it.
A result for the A-star algorithm looks like this:
It’s simply a list of the IDs of the pathnodes the entity needs to cross.
Serverside movement
While client-side movement needs to be smooth, you can simulate the serverside movement using a while loop on a Wait(500) and simply assume the paths between two pathnodes to be linear. No one is ever going to see movement that only happens serverside. As soon as you try to get near the entity, Rockstars’ system takes over. That way it shouldn’t be too much of a problem to actually simulate entity movement.
With this base-idea in mind let’s check what I have already published and what I intentionally hid from the public