-- CONFIGURATION VARIABLES FOR YOU TO EDIT --local weaponID = 39 local teamLock = false local teams = {"LS ~ STAFF", "Police", "Admin"} local guns = {30,31} local nadeModel = nil local launchV = 0.8 local inheritMomentum = true local consumeNades = true local fireKey = "e" local explodeOnContact = false local contactThreshold = 0.1 local reloadTime = 2 local debugMode = false -- END OF CONFIGURATION VARIABLES -- DO NOT TOUCH THESE, initializing variables local reloaded = true local reloadstarted = false local bombs = {} local differences = {} -- This is for debugging purposes -- We invert the teams and guns thingies here for faster access later local allowedTeams = {} for i,v in ipairs(teams) do allowedTeams[v] = false end local allowedGuns = {} for i,v in ipairs(guns) do allowedGuns[v] = true end -- Derived Aiming Check Function, credits to the 2012-Funstein (Thanks, my past self!) function isPedAiming ( thePedToCheck ) if isElement(thePedToCheck) then if getElementType(thePedToCheck) == "player" or getElementType(thePedToCheck) == "ped" then if getPedTask(thePedToCheck, "secondary", 0) == "TASK_SIMPLE_USE_GUN" then return true end end end return false end -- Function that checks whether the player should be able to fire or not. function canHeFire(player) local weaponID = getPedWeapon(player, 8) if not isPedAiming(player) then return false end if isPedDead(player) or isPedInVehicle(player) then return false end if teamLock and not (getPlayerTeam(player) and allowedTeams[getTeamName(getPlayerTeam(player))]) then return false end if consumeNades and not ((getPedWeapon(player, 8) == weaponID) and (getPedTotalAmmo(player, 8) > 0)) then return false end if not (getPedWeapon(player) and allowedGuns[getPedWeapon(player)]) then return false end return true end -- This is the actual firing function function fireNade() if canHeFire(localPlayer) then if not reloadStarted then if reloaded then -- Get position of weapon muzzle and target local mx, my, mz = getPedWeaponMuzzlePosition(localPlayer) local tx, ty, tz = getPedTargetCollision(localPlayer) if not (tx and ty and tz) then tx, ty, tz = getPedTargetEnd(localPlayer) end if mx and my and mz and tx and ty and tz then -- Calculate the launch velocity of the grenade local speed = getDistanceBetweenPoints3D(mx, my, mz, tx, ty, tz) local coef = launchV / speed local nx, ny, nz = (tx-mx) * coef, (ty-my) * coef, ((tz-mz)* coef) + 0.1 -- Momentum inheritance is performed here if inheritMomentum then local pvx, pvy, pvz = getElementVelocity(localPlayer) nx, ny, nz = nx + pvx, ny + pvy, nz + pvz end local weaponID = getPedWeapon(localPlayer, 8) -- Create the grenade! local nade = createProjectile(localPlayer, weaponID, mx, my, mz, 0, nil, 0, 0, 0, nx, ny, nz, nadeModel) if nade then -- Fixing some weird issue that happens for who knows what reason setElementVelocity(nade, nx, ny, nz) -- Inserting the projectile to the list of tracked projectiles if explodeOnContact then table.insert(bombs, {false, false, false, nade}) addEventHandler("onClientElementDestroy", nade, function() unlistBomb(source) end) end -- Reduce ammo and require player to reload if consumeNades then triggerServerEvent("glauncher.fired", localPlayer) end reloaded = false end end else outputChatBox("Debes recargar para usar el Lanza Granadas!", 255, 0, 0) end else outputChatBox("No puedes disparar mientras recarga!", 255, 0, 0) end end end bindKey(fireKey, "down", fireNade) -- The function that checks velocity differences for contact-explosion function trackBombs() if debugMode then for i,v in ipairs(differences) do local textHeight = dxGetFontHeight() dxDrawText(v, 500, 500 + ((i - 1) * (textHeight + 2)), 500, 500 + (i * (textHeight + 2))) end end for i,v in ipairs(bombs) do local bomb = v[4] if isElement(bomb) then -- Compare previous and current velocities of the bomb local vx, vy, vz = getElementVelocity(bomb) local ox, oy, oz = unpack(v) local diff = 0 if ox and oy and oz then diff = math.abs(getDistanceBetweenPoints3D(vx, vy, vz, ox, oy, oz)) end -- DEBUGGER if debugMode then table.insert(differences, diff) while #differences > 10 do table.remove(differences, 1) end end -- END OF DEBUGGER if diff > contactThreshold or isElementInWater(bomb) then -- Detonate bomb if change in velocity is over the threshold setElementVelocity(bomb, 0, 0, 0) destroyElement(bomb) if debugmode then table.insert(differences, "-----KABOOM!-----") end else -- Store the current velocity of the bomb bombs[i] = {vx, vy, vz, bomb} end else -- Remove bomb from list if it exists no more unlistBomb(v) end end end if explodeOnContact then addEventHandler("onClientRender", root, trackBombs) end function unlistBomb(bomb) for i,v in ipairs(bombs) do if v == bomb then table.remove(bombs, i) return end end end function endReload() if reloadStarted then reloaded = true reloadStarted = false end end addEventHandler("onClientPlayerSpawn", localPlayer, endReload) function beginReload() if not (getPedWeapon(localPlayer) and allowedGuns[getPedWeapon(localPlayer)]) then return false end if isTimer(antispam) then outputChatBox("#ff0000Espere 2 segundos para recargar el projectil!",255,0,0,true) return else end if (not reloadStarted) or (not isPedInVehicle(localPlayer)) then reloadStarted = true setTimer(function() endReload() end, reloadTime * 1000, 1) antispam = setTimer ( function() end, 2000, 1) end end --addCommandHandler("reload",beginReload) bindKey("r","down", beginReload)--"reload") -- the sound has been started function granadaLauncher(x, y, z) local theSound = playSound3D( "granada.mp3", x, y, z) setSoundMaxDistance( theSound, 20) end addEvent("onGranadaLauncher", true) addEventHandler("onGranadaLauncher", getRootElement(), granadaLauncher)