Ploep Posted November 20, 2013 Share Posted November 20, 2013 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
Moderators IIYAMA Posted November 21, 2013 Moderators Share Posted November 21, 2013 You are wasting to much bandwidth. Use: https://wiki.multitheftauto.com/wiki/GetElementSyncer And set your TriggerClientEvent targets manually in stead of root them, because just 1 player have to check his own synced peds. Too solve your laggy problem. 1 Link to comment
Renkon Posted November 21, 2013 Share Posted November 21, 2013 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
Ploep Posted November 21, 2013 Author Share Posted November 21, 2013 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
Renkon Posted November 21, 2013 Share Posted November 21, 2013 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
Ploep Posted November 21, 2013 Author Share Posted November 21, 2013 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 IIYAMA Posted November 21, 2013 Moderators Share Posted November 21, 2013 (edited) 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 December 27, 2020 by IIYAMA 1 Link to comment
Ploep Posted November 21, 2013 Author Share Posted November 21, 2013 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_settingsPut 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
Moderators IIYAMA Posted November 22, 2013 Moderators Share Posted November 22, 2013 np. Link to comment
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now