Jump to content

Sync peds


Ploep

Recommended Posts

Hi,

I'm trying to create a little AI for some peds in my mod. I used the AI traffic generator from CrystalMV to create a lot of nodes in an area and connect them (thanks for the tool) and apply Dijkstra's algorithm to move all the spawned peds to a specific location. I'm having problems with syncing the peds. When another player joins the syncing is still pretty well, but sometimes 1 out of 6 peds is almost invincible, it's very hard to hit the ped and it won't die.

Almost everything is done server-side which may be te source of my problem. But I think it is still strange that most of the peds are synced excellent and sometimes one is completely out of sync. Is this a bug? Will this problem be solved if I handle the control-states on the client side and only keep the location, rotation, etc. on the server?

Some snippets of my code:

Server script handling the spawn of the zombies

  
-- spawns a zombie on a random zombie spawn point and walks to the target 
function spawnZombie(thePlayer) 
    local zombieSpawn = getElementsByType("zombiespawn", mapRoot) 
    local x, y, z, rot 
     
    local key = math.random(1, #zombieSpawn) 
    x = getElementData(zombieSpawn[key], "posX") 
    y = getElementData(zombieSpawn[key], "posY") 
    z = getElementData(zombieSpawn[key], "posZ") 
     
    -- @TODO: different skins 
    local zombie = Zombie.new(createPed(264, x, y, z, 0.0, true), thePlayer) 
     
    giveWeapon(zombie:getPed(), 4, 0, true) 
             
    -- add to the table 
    zombies[#zombies+1] = zombie 
     
    -- update client graphics 
    triggerClientEvent("createZombie", getRootElement(), zombie:getPed()) 
end 
  
-- handle zombie logic, tick every 1000 msec 
function zombieLogic() 
    for i = 1, #zombies do       
        -- update sight of the zombie 
        triggerClientEvent("checkZombie", getRootElement(), zombies[i]:getPed(), zombies[i]:getTarget()) 
        -- @TODO: Clear zombie array after wave 
        if not zombies[i]:isDead() then      
            if(isPedDead(zombies[i]:getPed())) then 
                triggerClientEvent("destroyZombie", getRootElement(), zombies[i]:getPed()) 
                zombies[i]:setDead(true) 
            else 
                local x, y, z = getElementPosition(zombies[i]:getPed()) 
                local tx, ty, tz = getElementPosition(zombies[i]:getTarget()) 
                local distance = calculateDistanceBetweenLocations(x, y, z, tx, ty, tz) 
                 
                -- can we see the target? 
                if(canSeeTarget[zombies[i]:getPed()]) then 
                    zombies[i]:followTarget() 
                    if distance <= 2 then 
                        -- ATTACK! 
                        zombies[i]:followTarget() 
                        setPedAnimation(zombies[i]:getPed()) 
                        triggerClientEvent("attackZombie", getRootElement(), zombies[i]:getPed(), zombies[i]:getTarget()) 
                    else 
                        setPedAnimation(zombies[i]:getPed(), "ped", "WOMAN_runsexy", -1, true, true, true, false) 
                    end 
                else 
                    -- cannot see target, plan route 
                    local completedRoute = zombies[i]:walkPath() 
                    local path = zombies[i]:getPath() 
                     
                    if path[#path] ~= calculateClosestNode(tx, ty, tz) then 
                        zombies[i]:setPath(calculatePath(x, y, z, tx, ty, tz))      -- target moved, need recalculation              
                    end      
                     
                    setPedAnimation(zombies[i]:getPed(), "ped", "WOMAN_runsexy", -1, true, true, true, false) 
                end 
            end 
        end 
    end 
end 
  

Client side is only for updating the state of the ped, if the ped can see the player without obstacles it will just run without pathfinding.

  
function attackTarget(theZombie, target) 
    local x, y, z = getElementPosition(theZombie) 
    local tx, ty, tz = getElementPosition(target) 
     
    setPedAimTarget(theZombie, x, y, z) 
  
    if getElementHealth(target) > 1 then 
        setPedControlState(theZombie, "fire", pedAttack[theZombie])              
        pedAttack[theZombie] = false 
    else 
        killTimer(theZombie) 
    end 
end 
  
-- attack the target ped/player 
function attackZombie(theZombie, target)     
    if not isTimer(zombieTimer[theZombie]) then      
        pedAttack[theZombie] = true 
        zombieTimer[theZombie] = setTimer(attackTarget, 300, 2, theZombie, target) 
    end 
end 
  
-- check if the zombie can see the player, if so just run to it and don't do any path planning 
function checkZombie(theZombie, targetZombie) 
    local x, y, z = getElementPosition(theZombie) 
    local tx, ty, tz = getElementPosition(targetZombie) 
  
    if isLineOfSightClear(x, y, z, tx, ty, tz, true, true, false, true, false, false) then 
        triggerServerEvent("onZombieSee", getLocalPlayer(), theZombie, true)  
    else 
        triggerServerEvent("onZombieSee", getLocalPlayer(), theZombie, false)  
    end 
end 
  

P.S. If I comment out the zombie-logic such that the peds will stand still ... I still keep the problem.

Link to comment

Exactly, as the guy above said, you gotta use setElementSyncer, and you can make it work with no syncer maybe, as it may become laggy if a lagger is syncing the peds.

Question, why Dijkstra? Shouldn't it be way better to use A*? Just got that doubt (although I may not be able to explain the reason in English as its not my mother tongue)

Link to comment

Thanks, but even when I shutdown the zombielogic (sending no client events) and simplifying my program alot by just creating 20 peds on different locations with:

  
createPed(264, x, y, z, 0.0, true) 
  

There are some invincible peds, I think the only way to solve this is to create peds like this:

  
createPed(264, x, y, z, 0.0, false) 
  

Disabling the syncing automatically and trigger client events to the syncer of the objects telling him to update the ped position. That will take a while ...

@Renkon:

I used Dijkstra because it is an easy implementation of A* (heuristics = 0).

Link to comment
Thanks, but even when I shutdown the zombielogic (sending no client events) and simplifying my program alot by just creating 20 peds on different locations with:

  
createPed(264, x, y, z, 0.0, true) 
  

There are some invincible peds, I think the only way to solve this is to create peds like this:

  
createPed(264, x, y, z, 0.0, false) 
  

Disabling the syncing automatically and trigger client events to the syncer of the objects telling him to update the ped position. That will take a while ...

@Renkon:

I used Dijkstra because it is an easy implementation of A* (heuristics = 0).

Doing that ,wouldn't peds kind of jump every x ms? Wouldn't that be like the same way SAMP players move (havent played since 2010, but at least by that time it was like that)?

Link to comment
Thanks, but even when I shutdown the zombielogic (sending no client events) and simplifying my program alot by just creating 20 peds on different locations with:

  
createPed(264, x, y, z, 0.0, true) 
  

There are some invincible peds, I think the only way to solve this is to create peds like this:

  
createPed(264, x, y, z, 0.0, false) 
  

Disabling the syncing automatically and trigger client events to the syncer of the objects telling him to update the ped position. That will take a while ...

@Renkon:

I used Dijkstra because it is an easy implementation of A* (heuristics = 0).

Doing that ,wouldn't peds kind of jump every x ms? Wouldn't that be like the same way SAMP players move (havent played since 2010, but at least by that time it was like that)?

I don't really know, I'm new to scripting for MTASA. I also found this bug report on Mantis http://bugs.mtasa.com/view.php?id=4921 describing this problem. Also having issues with invincible peds.

Link to comment
  • Moderators

Peds/vehicles/players have automatic de-sync functions when they got streamed out. They will go over to light sync updates(slow updates). You can set up some of those settings with this: https://wiki.multitheftauto.com/wiki/Sy ... l_settings

Put ped_sync_interval at around 150/200.

Trigger events are using much more data then streamed in elements.

I don't run a zombie server, but I will recommend you to limit the zombies or try to set them in differed dimensions or what every you can try.

For finding the best data result, use: /shownetstat

This will show you how many packets will be send, the less packets the better.

Also note:

Uploading cost much more bandwidth than download.

So script as manys thing that have to be with sync at serverside.

Make sure the server and the client knows "which player sync which ped".

So you make sure that I know all peds that are synced by me, etc. (but other players don't have to know that)

Good luck,

Edited by IIYAMA
  • Thanks 1
Link to comment
Peds/vehicles/players have automatic de-sync functions when they got streamed out. They will go over to light sync updates(slow updates). You can set up some of those settings with this: https://wiki.multitheftauto.com/wiki/Sy ... l_settings

Put ped_sync_interval at around 150/200.

Trigger events are using much more data then streamed in elements.

I don't run a zombie server, but I will recommend you to limit the zombies or try to set them in differed dimensions or what every you can try.

For finding the best data result, use: /shownetstat

This will show you how many packets will be send, the less packets the better.

Also note:

Uploading cost much more bandwidth then download.

So script as manys thing that have to be with sync at serverside.

Make sure the server and the client knows "which player sync which ped".

So you make sure that I know all peds that are synced by me, etc. (but other players don't have to know that)

Good luck,

Thanks! I already changed the ped_sync_interval but it only helped a little. I'm doing all the movement server-side but even when the peds aren't moving (disabling the logic) and sending no trigger events there is always one ped being invincible. But I think it's playable because when i'm not spawning too much at the same time it only lasts for a couple of seconds. Thanks for the tips!!

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...