Jump to content

Exceeding limit even though there's a check


Recommended Posts

Hi i got this zombie script from the community by dutchman, even though the max zombies is set to 5

 

and the spawnZombie function has a check as well

if #zombiesChasingMe >= maxZombies 

it still exceeds the limit, more zombies are still spawning than the maxZombies value.

 

local maxZombies = 5 --Max zombies to chase local player
local minDistance = 10 --Minium distance from player to keep zombies spawning
local maxDistance = 30 --Maximum distance to spawn zombies
local minInterval = 2000 --Minium time between spawning zombies
local maxInterval = 5000 --Maximum time between spawning zombies

local zombieData = {skins={10, 11, 12, 13, 14, 15}}
local zombiesChasingMe = {}
local playersDoomed = {}
local timesExecuted = 0
local playersEatable = {}
local playerEated = {}
local colshapes = {}
local mySteps = {}

local function rot( x1, y1, x2, y2 )
    local t = -math.deg( math.atan2( x2 - x1, y2 - y1 ) )
    return t < 0 and t + 360 or t
end

local function getZombieCalculatedPathDistance(zombie)

	local currentIndex = zombieData[zombie].positions

	local distance = 0
	if currentIndex < #zombieData[zombie].paths then
		for index = currentIndex,#zombieData[zombie].paths do
			if zombieData[zombie].paths[index] and zombieData[zombie].paths[index+1] then
				local ox,oy = unpack(zombieData[zombie].paths[index])
				local nx,ny = unpack(zombieData[zombie].paths[index+1])
				distance = distance + getDistanceBetweenPoints2D(ox,oy,nx,ny)
			end
		end
	else
		local zVector = zombie.position
		local npVector = zombieData[zombie].paths[currentIndex]+1
		distance = getDistanceBetweenPoints2D(zVector.x,zVector.y,npVector.x,npVector.y)
	end

	return distance
	
end

local function isZombieChasingMe(zombieToCheck,removeIt)

	for index,zombie in ipairs(zombiesChasingMe) do
		if zombie == zombieToCheck then
			if removeIt then table.remove(zombiesChasingMe,index) end
			return zombie
		end
	end

end

local function onDamage(attacker,weapon,bodypart,loss)

	if attacker and isElement(attacker) and attacker == localPlayer then
		triggerServerEvent("Zday:damageZombie",source,attacker,weapon,bodypart,loss)
	end

end

local function onWasted(killer)

	if zombieData[source].doomed then return end
	zombieData[source].doomed = true
	triggerServerEvent("Zday:delayDestroyZombie",source)

end

local function onDestroy()

	isZombieChasingMe(source,true)
	if zombieData[source].syncCol and isElement(zombieData[source].syncCol) then destroyElement(zombieData[source].syncCol) end
	zombieData[source] = nil

end

local function resetPlayer()

	playersDoomed[source] = nil
	playersEatable[source] = nil
	playerEated[source] = nil

end

local function setPlayerEatable(player)

	playersEatable[player] = true

end

local function murderPlayerByZombie(player,zombie)
	
	if not getElementData(zombie, "groaning") == true then 
		playSound3D("sounds/mgroan"..tostring(math.random(1,10))..".ogg",zombie.position)
		setElementData(zombie, "groaning", true)
		setTimer(setElementData, 3000, 1, zombie, "groaning", false)
	end 
	if player == localPlayer then triggerServerEvent("Zday:murderPlayer",localPlayer,zombie) end

end

local function arePedLegsBlocked(zombie)

	local upperTorsoVec = Vector3(getPedBonePosition(zombie,4))
	local legVec = Vector3(getPedBonePosition(zombie,54))
	local forwardVec = zombie.matrix.position + (zombie.matrix.forward/2)
	
	local x,y = upperTorsoVec.x,upperTorsoVec.y
	local x2,y2 = forwardVec.x,forwardVec.y
	local notClear = false
	for z=legVec.z,upperTorsoVec.z,0.05 do
		if not isLineOfSightClear(x,y,z,x2,y2,z,true,true,false,true,false,true,true,zombie) then
			notClear=true
			break
		end
	end
	
	return notClear

end

local function checkPlayer(player,col)

	if not isElement(player) then return false end
	if not isElement(col) then return end
	if not colshapes[col] then return false end
	if player.type ~= "player" then return false end
	if player.dimension ~= col.dimension then return false end
	if player.interior ~= col.interior then return false end

	return true,colshapes[col]
	
end

local function comp(w1,w2)

	if w1[2] < w2[2] then
		return true
	end
	
	return false

end

local function getNewTarget(zombie,excludedTarget)

	local col = zombieData[zombie].syncCol
	local players = getElementsWithinColShape(col,"player")
	local possibleTargets = {}
	local alternativeReturn = false
	local isClear = false
	for index,player in ipairs(players) do
		if checkPlayer(player,col) and player ~= excludedTarget and player ~= zombieData[zombie].target then
			local distance = getDistanceBetweenPoints2D(zombie.position,player.position)
			if distance < 80 then
				table.insert(possibleTargets,{player,distance})
				isClear = isLineOfSightClear(zombie.position,player.position,true,false,false,true,false,true,true,zombie)
				alternativeReturn=true
			end
		end
	end
	
	if not alternativeReturn then return false end
	
	table.sort(possibleTargets,comp)
	local target,distance2 = unpack(possibleTargets[1])
	return target,isClear,distance2

end

local function resetZombieAnimation(zombie)

	if zombie and isElement(zombie) then
		setPedAnimation(zombie)
		zombieData[zombie].eating = nil
	end

end

local function findNewTarget(player)

	local valid,zombie = checkPlayer(player,source)
	if not valid then return end
	if player ~= zombieData[zombie].target then return end
	if player ~= localPlayer then return end
	local newTarget = getNewTarget(zombie)
	
	if newTarget and newTarget ~= localPlayer and newTarget ~= zombieData[zombie].target then
		triggerServerEvent("Zday:setZombieNewTarget",zombie,newTarget)
	elseif not zombieData[zombie].doomed then
		zombieData[zombie].doomed = true
		triggerLatentServerEvent("Zday:destroyZombie",5000,true,zombie)
	end

end

local function trackMe()
	
	local zombies = getElementsByType("ped",resourceRoot,true)
	
	for index,zombie in ipairs(zombies) do
		if math.random(1,40) == 5 and isPedDead(zombie) == false then playSound3D("sounds/mgroan"..tostring(math.random(1,10))..".ogg",zombie.position) end
		local zombieTarget = zombieData[zombie].target
		if zombieTarget and isElement(zombieTarget) then
			local lx,ly,lz = getElementPosition(zombieTarget)
			local lVector = Vector3(lx,ly,lz)
			local hVector = Vector3(getPedBonePosition(zombie,6))
			local zVector = Vector3(getElementPosition(zombie))
			local doesZombieSeePlayer = isLineOfSightClear(hVector,lVector,true,false,false,true,false,true,true,zombie)
			local distanceToPlayer = getDistanceBetweenPoints2D(zVector.x,zVector.y,lVector.x,lVector.y)
			if timesExecuted%5 == 0 and zombieData[zombie].target == localPlayer then
				local newTarget,doesSee,distance = getNewTarget(zombie)
				if newTarget and doesSee and distance < distanceToPlayer and newTarget ~= zombieData[zombie].target then
					triggerServerEvent("Zday:setZombieNewTarget",zombie,newTarget)
				end
			end
			if zombieData[zombie].target == localPlayer and doesZombieSeePlayer == false and isPedDead(zombieTarget)==false then
				local newTarget,doesSee = getNewTarget(zombie,localPlayer)
				if newTarget and doesSee and newTarget ~= zombieData[zombie].target then
					triggerServerEvent("Zday:setZombieNewTarget",zombie,newTarget)
				end
			end
			if zombieData[zombie].hunting then
				if not zombieData[zombie].positions then zombieData[zombie].positions = 0 end
				if not zombieData[zombie].paths then zombieData[zombie].paths = {} end
				local dist = false
				if #zombieData[zombie].paths > 1 then
					local llx,lly,llz = unpack(zombieData[zombie].paths[#zombieData[zombie].paths-1])
					dist = getDistanceBetweenPoints3D(llx,lly,llz,lx,ly,lz)
				end
				if dist and dist > 0.7 then
					table.insert(zombieData[zombie].paths,{lx,ly,lz,getPedControlState(zombieTarget,"jump"),getPedControlState(zombieTarget,"sprint")})
				elseif not dist then
					table.insert(zombieData[zombie].paths,{lx,ly,lz,getPedControlState(zombieTarget,"jump"),getPedControlState(zombieTarget,"sprint")})
				end
				if zombieData[zombie].paths[zombieData[zombie].positions+1] and not zombieData[zombie].eating then
					local nx,ny,nz,jump,sprint = unpack(zombieData[zombie].paths[zombieData[zombie].positions+1])
					local nVector = Vector3(nx,ny,nz)
					local isClear = isLineOfSightClear(zVector,nVector,true,true,false,true,false,true,true,zombie)
					local notMoving = false
					if zombieData[zombie].lastPosition then
						local dist = getDistanceBetweenPoints3D(zombieData[zombie].lastPosition,zVector)
						if dist < 0.01 then
							local action = math.random(1,2)
							if action == 1 then
								setPedControlState(zombie,"fire",true)
							elseif action == 2 then
								notMoving = true
							end
						else
							setPedControlState(zombie,"fire",false)
						end
					end
					local needToJump = (jump or getPedSimplestTask(zombie) == "TASK_SIMPLE_CLIMB" or arePedLegsBlocked(zombie) or notMoving)
					if needToJump then
						if (getPedMoveState(zombie) ~= "jump" or getPedMoveState(zombie) ~= "climb") then setPedControlState(zombie,"forwards",false) end
						if sprint then setPedControlState(zombie,"sprint",true) end
						setPedControlState(zombie,"jump",true)
					else
						setPedControlState(zombie,"sprint",false)
						setPedControlState(zombie,"jump",false)
					end
					local dist = getDistanceBetweenPoints2D(zVector.x,zVector.y,nVector.x,nVector.y)
					local pathDistance = getZombieCalculatedPathDistance(zombie)
					local diff = pathDistance/distanceToPlayer
					if pathDistance > distanceToPlayer and diff > 1.1 and doesZombieSeePlayer then
						zombieData[zombie].paths = {}
						zombieData[zombie].positions = 0
						zombieData[zombie].changingPath = true
						zombieData[zombie].changePathTick = getTickCount()
					end
					if zombieData[zombie].changingPath then
						if (getTickCount() - zombieData[zombie].changePathTick) > 500 then
							zombieData[zombie].changingPath = nil
							zombieData[zombie].changePathTick = nil
						end
					end
					local angle = rot(zVector.x,zVector.y,nVector.x,nVector.y)
					setPedCameraRotation(zombie,-angle)
					setPedControlState(zombie,"forwards",true)
					if zombie.inWater then
						setElementRotation(zombie,0,0,angle)
						setPedControlState(zombie,"sprint",true)
					elseif not sprint then
						setPedControlState(zombie,"sprint",false)
					end
					zombieData[zombie].lastPosition = Vector3(getElementPosition(zombie))
					if isClear and dist < 1 then
						zombieData[zombie].positions = zombieData[zombie].positions + 1
					end
				else
					if isPedDead(zombie) == false and getDistanceBetweenPoints3D(zVector,lVector) < 1 and not playersDoomed[zombieTarget] then
						murderPlayerByZombie(zombieTarget,zombie)
						if isPedDead(zombieTarget) then 
							playersDoomed[zombieTarget] = true
						end 
					elseif getDistanceBetweenPoints3D(zVector,lVector) < 1 and ((isPedDead(zombieTarget) or zombieTarget.health<1) and playersEatable[zombieTarget] and not playerEated[zombieTarget]) then
						playerEated[zombieTarget] = true
						zombieData[zombie].eating = true
						setPedAnimation(zombie,"MEDIC","cpr",-1,false,true,false)
						setTimer(resetZombieAnimation,10000,1,zombie)
					end
					setPedControlState(zombie,"forwards",false)
				end
			else
				if doesZombieSeePlayer and not zombieData[zombie].hunting then
					zombieData[zombie].hunting = true
					zombieData[zombie].positions = 0
				elseif not zombieData[zombie].hunting then
					local newTarget = getNewTarget(zombie,localPlayer),doesSee
					if newTarget and doesSee and not zombieData[zombie].changingTarget then
						triggerServerEvent("Zday:setZombieNewTarget",zombie,newTarget)
						zombieData[zombie].changingTarget = true
					end
				end
				if not zombieData[zombie].changingPath then
					setPedControlState(zombie,"forwards",false)
				end
			end
		else
			setPedControlState(zombie,"forwards",false)
		end
	end
	
	timesExecuted=timesExecuted+1

end

local function getPointFromDistanceRotation(x, y, dist, angle)

    local a = math.rad(90 - angle);

    local dx = math.cos(a) * dist;
    local dy = math.sin(a) * dist;

    return x+dx, y+dy;

end

local function spawnZombie()

	if #zombiesChasingMe >= maxZombies then
		setTimer(spawnZombie,math.random(minInterval,maxInterval),1)
		return
	end

	local x,y,z = getElementPosition(localPlayer)
	local dist = math.random(minDistance,maxDistance)
	local _,_,_,_,_,_,_,fov = getCameraMatrix()
	local cr = getPedCameraRotation(localPlayer)+(getPedControlState(localPlayer,"look_behind") and 0 or 180)
	if cr > 360 then cr = cr-360 end
	local r = math.random(cr-fov,cr+fov)
	local zx,zy = getPointFromDistanceRotation(x,y,dist,r)
	local zz = false
	for tz = z,550 do
		local newZ = getGroundPosition(zx,zy,tz)
		if newZ and newZ ~= 0 then
			zz = newZ+1
			break
		end
	end
	if not zz then zz = z+3 end
	if not isLineOfSightClear(x,y,z,zx,zy,zz,true,false,false,true,false,true,true,localPlayer) then return setTimer(spawnZombie,500,1) end
	local zr = rot(x,y,zx,zy)
	local s = zombieData.skins[math.random(1,#zombieData.skins)]
	triggerServerEvent("Zday:spawnZombie",localPlayer,s,zx,zy,zz,zr)
	setTimer(spawnZombie,math.random(minInterval,maxInterval),1)

end

local function lookForNewTarget(excludedTarget)

	local newTarget = getNewTarget(source,excludedTarget,true)
	
	if isElement(newTarget) and not zombieData[source].target ~= newTarget then
		triggerServerEvent("Zday:setZombieNewTarget",zombie,newTarget)
	elseif not zombieData[source].doomed then
		zombieData[source].doomed = true
		triggerLatentServerEvent("Zday:destroyZombie",5000,true,source)
	end

end

local function setZombieTarget(zombie,targett)

	if not zombieData[zombie] then zombieData[zombie] = {} end
	if not zombieData[zombie].handled then
		addEventHandler("onClientPedDamage",zombie,onDamage)
		addEventHandler("onClientPedWasted",zombie,onWasted)
		addEventHandler("onClientElementDestroy",zombie,onDestroy)
		addEventHandler("Zday:askForNewTarget",zombie,lookForNewTarget)
		zombieData[zombie].handled = true
	end
	
	if not zombieData[zombie].syncCol then
		zombieData[zombie].syncCol = createColSphere(zombie.position,80)
		colshapes[zombieData[zombie].syncCol] = zombie
		attachElements(zombieData[zombie].syncCol,zombie)
		addEventHandler("onClientColShapeLeave",zombieData[zombie].syncCol,findNewTarget)
	end
	
	zombieData[zombie].target = targett

	isZombieChasingMe(zombie,true)
	if target == localPlayer then
		table.insert(zombiesChasingMe,zombie)
	end

end

local function getZombiesInfo(zombiesReceived)

	for zombie,target in pairs(zombiesReceived) do
		setZombieTarget(zombie,target)
	end

end

local function initScript()

	for _,id in ipairs(zombieData.skins) do
		local txd = engineLoadTXD("skins/"..tostring(id)..".txd")
		engineImportTXD(txd,id)
		local dff = engineLoadDFF("skins/"..tostring(id)..".dff")
		engineReplaceModel(dff,id)
	end
	
	for _,zombie in ipairs(getElementsByType("ped",resourceRoot)) do
		zombieData[zombie] = {}
		addEventHandler("onClientPedDamage",zombie,onDamage)
		addEventHandler("onClientPedWasted",zombie,onWasted)
		addEventHandler("onClientElementDestroy",zombie,onDestroy)
		addEventHandler("Zday:askForNewTarget",zombie,lookForNewTarget)
		zombieData[zombie].handled = true
		zombieData[zombie].syncCol = createColSphere(zombie.position,80)
		colshapes[zombieData[zombie].syncCol] = zombie
		attachElements(zombieData[zombie].syncCol,zombie)
		addEventHandler("onClientColShapeLeave",zombieData[zombie].syncCol,findNewTarget)
	end

	addEvent("Zday:askForNewTarget",true)
	addEvent("Zday:setZombieTarget",true)
	addEvent("Zday:sendZombiesInfo",true)
	
	addEventHandler("Zday:sendZombiesInfo",localPlayer,getZombiesInfo)
	addEventHandler("Zday:setZombieTarget",resourceRoot,setZombieTarget)
	addEventHandler("onClientPlayerSpawn",root,resetPlayer)
	
	setTimer(trackMe,100,0)
	setTimer(spawnZombie,math.random(minInterval,maxInterval),1)
	triggerServerEvent("Zday:getZombiesInfo",localPlayer)
	
end

addEventHandler("onClientResourceStart",resourceRoot,initScript)

--MAKES A ZOMBIE PUNCH

addEvent( "ZOMB_PUNCH", true )
function Zpunch ( zombie )
	if (isElement(zombie)) then
		setPedControlState( zombie, "fire", true )
		setTimer ( function (zombie) if ( isElement ( zombie ) ) then setPedControlState ( zombie, "fire", false) end end, 500, 1, zombie )
	end
end
addEventHandler( "ZOMB_PUNCH", root, Zpunch )

--STFU ZOMBIE

addEvent( "Zomb_STFU", true )
function Zstfu ( zombie )
	if (isElement(zombie)) then
		setPedVoice(zombie, "PED_TYPE_DISABLED")
	end
end
addEventHandler( "Zomb_STFU", root, Zstfu )


-- More damage ZOMBIE

function zombieattack ( attacker, weapon, bodypart )
	if (attacker) then
		if getElementType ( attacker ) == "ped" then
			if (getElementData (attacker, "zombie") == true) then
				if getElementData(source, "threat") == "high" then 
					local timehour, timeminute = getTime()
					if timehour == 21 or timehour == 22 or timehour == 23 or timehour == 0 or timehour == 1 or timehour == 2 or timehour == 3 or timehour == 4 then
						if not getElementData(attacker, "zombieSpecial") then 
							setElementHealth(source, getElementHealth(getLocalPlayer())-10)
						end 
					end 
				end
				local playerHealth = getElementHealth ( getLocalPlayer() )
				local mutatedZombie = getElementData(attacker, "mutatedZombie")
				local zombieSpecial = getElementData(attacker, "zombieSpecial")
				local model = getElementModel(attacker)
				if playerHealth > 15 then
					if mutatedZombie == "Armored" or mutatedZombie == "Brute" or mutatedZombie == "Mutated" then 
						setElementHealth ( source, playerHealth - 40 )
					elseif mutatedZombie == "Abomination" then 
						setElementHealth ( source, playerHealth - 80 )
					elseif model == 49 then 
						setElementHealth ( source, playerHealth - 40 )
					elseif zombieSpecial then 
						setElementHealth ( source, playerHealth - 30 )
					elseif getElementData(attacker, "zombie") then 
						setElementHealth ( source, playerHealth - 10 )
					end 
				end
			end
		end
	end
end
addEventHandler ( "onClientPlayerDamage", getLocalPlayer(), zombieattack )

 

Link to post

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...