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.