Detailed breakdown of my Lua scripting and game development projects
Full job management for 5,000+ concurrent players — salaries, performance metrics, and real-time sync.
A comprehensive job management system designed for gaming servers, featuring dynamic job creation, player employment mechanics, salary systems, and workplace interactions. The system includes real-time job tracking, performance analytics, and administrative controls.
-- Job registration and player assignment
function RegisterJob(jobName, maxPlayers, baseSalary, requirements)
local jobData = {
name = jobName,
maxPlayers = maxPlayers,
currentPlayers = 0,
baseSalary = baseSalary,
requirements = requirements,
activeWorkers = {},
createdAt = os.time()
}
Jobs[jobName] = jobData
TriggerClientEvent('tofu-job:jobCreated', -1, jobData)
print(string.format('[TOFU-JOB] Job "%s" registered with %d max players',
jobName, maxPlayers))
end
-- Player job assignment with validation
function AssignPlayerToJob(playerId, jobName)
local player = GetPlayerPed(playerId)
local job = Jobs[jobName]
if not job then
TriggerClientEvent('tofu-job:notify', playerId, 'Job does not exist', 'error')
return false
end
if job.currentPlayers >= job.maxPlayers then
TriggerClientEvent('tofu-job:notify', playerId, 'Job is full', 'error')
return false
end
-- Add player to job
job.activeWorkers[playerId] = {
startTime = os.time(),
performance = 0,
earnings = 0
}
job.currentPlayers = job.currentPlayers + 1
PlayerJobs[playerId] = jobName
TriggerClientEvent('tofu-job:jobAssigned', playerId, job)
return true
end
-- Dynamic salary calculation based on performance
function CalculateSalary(playerId, workDuration)
local job = Jobs[PlayerJobs[playerId]]
local worker = job.activeWorkers[playerId]
if not job or not worker then return 0 end
local basePay = job.baseSalary
local performanceMultiplier = 1 + (worker.performance / 100)
local timeBonus = math.min(workDuration / 3600, 2.0) -- Max 2x for time
local totalSalary = basePay * performanceMultiplier * timeBonus
-- Add random bonus events
if math.random(1, 100) <= 10 then -- 10% chance
totalSalary = totalSalary * 1.5
TriggerClientEvent('tofu-job:notify', playerId, 'Bonus earned!', 'success')
end
return math.floor(totalSalary)
end
-- Performance tracking system
function UpdatePerformance(playerId, taskCompleted, quality)
local job = Jobs[PlayerJobs[playerId]]
if not job or not job.activeWorkers[playerId] then return end
local performanceGain = quality * 2 -- Quality ranges 1-10
job.activeWorkers[playerId].performance =
math.min(job.activeWorkers[playerId].performance + performanceGain, 100)
TriggerClientEvent('tofu-job:performanceUpdate', playerId,
job.activeWorkers[playerId].performance)
end
Custom race engine with precision lap timing, checkpoint validation, and dynamic leaderboards.
Advanced racing system featuring custom track creation, precise lap timing, competitive leaderboards, and seamless multiplayer support. Includes checkpoint validation, comprehensive race statistics, and tournament management capabilities for competitive gaming environments.
-- Race state management and timing
local RaceManager = {}
RaceManager.activeRaces = {}
RaceManager.playerRaces = {}
function RaceManager:StartRace(raceId, trackId, participants)
local race = {
id = raceId,
trackId = trackId,
participants = participants,
startTime = GetGameTimer(),
status = 'active',
leaderboard = {},
currentLap = {}
}
-- Initialize participant data
for _, playerId in pairs(participants) do
race.currentLap[playerId] = 1
race.leaderboard[playerId] = {
lapTimes = {},
bestLap = 999999,
totalTime = 0,
position = #participants,
checkpoints = 0
}
self.playerRaces[playerId] = raceId
TriggerClientEvent('zendo-racing:raceStart', playerId, race)
end
self.activeRaces[raceId] = race
print(string.format('[RACING] Race %s started with %d participants',
raceId, #participants))
end
-- Checkpoint validation and timing
function RaceManager:ValidateCheckpoint(playerId, checkpointId)
local raceId = self.playerRaces[playerId]
local race = self.activeRaces[raceId]
if not race then return false end
local track = Tracks[race.trackId]
local player = race.leaderboard[playerId]
local expectedCheckpoint = (player.checkpoints % #track.checkpoints) + 1
-- Validate checkpoint sequence
if checkpointId ~= expectedCheckpoint then
TriggerClientEvent('zendo-racing:invalidCheckpoint', playerId)
return false
end
player.checkpoints = player.checkpoints + 1
local currentTime = GetGameTimer() - race.startTime
-- Lap completion detection
if checkpointId == #track.checkpoints then
self:CompleteLap(playerId, currentTime)
end
TriggerClientEvent('zendo-racing:checkpointPassed', playerId, checkpointId)
return true
end
-- Precise lap timing calculation
function RaceManager:CompleteLap(playerId, currentTime)
local raceId = self.playerRaces[playerId]
local race = self.activeRaces[raceId]
local player = race.leaderboard[playerId]
-- Calculate lap time
local lapStartTime = player.lapTimes[race.currentLap[playerId] - 1] or race.startTime
local lapTime = currentTime - lapStartTime
-- Record lap time
table.insert(player.lapTimes, currentTime)
-- Update best lap
if lapTime < player.bestLap then
player.bestLap = lapTime
TriggerClientEvent('zendo-racing:newBestLap', playerId, lapTime)
end
race.currentLap[playerId] = race.currentLap[playerId] + 1
-- Update leaderboard positions
self:UpdateLeaderboard(raceId)
-- Check race completion
local track = Tracks[race.trackId]
if race.currentLap[playerId] > track.totalLaps then
self:PlayerFinished(playerId, currentTime)
end
end
-- Dynamic leaderboard calculation
function RaceManager:UpdateLeaderboard(raceId)
local race = self.activeRaces[raceId]
local sortedPlayers = {}
-- Create sortable player array
for playerId, data in pairs(race.leaderboard) do
table.insert(sortedPlayers, {
id = playerId,
lap = race.currentLap[playerId],
checkpoints = data.checkpoints,
totalTime = #data.lapTimes > 0 and data.lapTimes[#data.lapTimes] or 999999
})
end
-- Sort by lap, then checkpoints, then time
table.sort(sortedPlayers, function(a, b)
if a.lap ~= b.lap then return a.lap > b.lap end
if a.checkpoints ~= b.checkpoints then return a.checkpoints > b.checkpoints end
return a.totalTime < b.totalTime
end)
-- Update positions and broadcast
for position, playerData in ipairs(sortedPlayers) do
race.leaderboard[playerData.id].position = position
TriggerClientEvent('zendo-racing:positionUpdate', playerData.id, position)
end
TriggerClientEvent('zendo-racing:leaderboardUpdate', -1, sortedPlayers)
end
TypeScript speedometer with smooth 60fps animations, RPM tracking, and customizable HUD themes.
Real-time vehicle speedometer built with TypeScript, featuring customizable UI elements, multiple unit support (MPH/KMH), and comprehensive performance metrics display. Features smooth animations, responsive design elements, type-safe implementation, and integration with vehicle systems for accurate speed calculation.
-- Accurate speed calculation and smoothing
local Speedometer = {}
Speedometer.config = {
updateInterval = 50, -- Update every 50ms for smooth animation
smoothingFactor = 0.8,
maxSpeed = 300,
units = 'mph' -- 'mph' or 'kmh'
}
local speedHistory = {}
local currentSpeed = 0
local targetSpeed = 0
-- Calculate vehicle speed with smoothing
function Speedometer:CalculateSpeed(vehicle)
if not DoesEntityExist(vehicle) then return 0 end
local velocity = GetEntityVelocity(vehicle)
local speed = math.sqrt(velocity.x^2 + velocity.y^2 + velocity.z^2)
-- Convert to appropriate units
if self.config.units == 'mph' then
speed = speed * 2.236936 -- m/s to mph
else
speed = speed * 3.6 -- m/s to kmh
end
-- Apply smoothing to prevent jittery display
table.insert(speedHistory, speed)
if #speedHistory > 5 then
table.remove(speedHistory, 1)
end
local smoothedSpeed = 0
for _, historicalSpeed in pairs(speedHistory) do
smoothedSpeed = smoothedSpeed + historicalSpeed
end
return smoothedSpeed / #speedHistory
end
-- Update speedometer display
function Speedometer:UpdateDisplay()
local playerVehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if playerVehicle ~= 0 then
targetSpeed = self:CalculateSpeed(playerVehicle)
-- Get additional vehicle data
local rpm = GetVehicleCurrentRpm(playerVehicle)
local gear = GetVehicleCurrentGear(playerVehicle)
local fuel = GetVehicleFuelLevel(playerVehicle)
local engineHealth = GetVehicleEngineHealth(playerVehicle)
-- Smooth speed transition
currentSpeed = currentSpeed + (targetSpeed - currentSpeed) * self.config.smoothingFactor
-- Send to UI
SendNUIMessage({
type = 'updateSpeed',
speed = math.floor(currentSpeed),
rpm = rpm,
gear = gear,
fuel = fuel,
engineHealth = engineHealth,
maxSpeed = self.config.maxSpeed,
units = self.config.units
})
else
-- Vehicle exited, hide speedometer
SendNUIMessage({
type = 'hideSpeedometer'
})
end
end
// Client-side UI animation and rendering
class SpeedometerUI {
constructor() {
this.canvas = document.getElementById('speedometer-canvas');
this.ctx = this.canvas.getContext('2d');
this.animationFrame = null;
this.currentRotation = 0;
this.targetRotation = 0;
this.setupCanvas();
}
// Smooth needle animation
animateNeedle(speed, maxSpeed) {
const speedPercentage = Math.min(speed / maxSpeed, 1);
this.targetRotation = (speedPercentage * 270) - 135; // 270° range, start at -135°
// Smooth rotation transition
const rotationDiff = this.targetRotation - this.currentRotation;
this.currentRotation += rotationDiff * 0.15;
this.drawSpeedometer();
if (Math.abs(rotationDiff) > 0.5) {
this.animationFrame = requestAnimationFrame(() =>
this.animateNeedle(speed, maxSpeed)
);
}
}
// Draw speedometer with modern styling
drawSpeedometer() {
const centerX = this.canvas.width / 2;
const centerY = this.canvas.height / 2;
const radius = 120;
// Clear canvas
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
// Draw outer ring
this.drawGradientCircle(centerX, centerY, radius + 10, '#6366f1', '#4f46e5');
// Draw speed markings
this.drawSpeedMarkings(centerX, centerY, radius);
// Draw needle
this.drawNeedle(centerX, centerY, radius - 20);
// Draw center hub
this.drawGradientCircle(centerX, centerY, 15, '#1f2937', '#111827');
}
drawGradientCircle(x, y, radius, color1, color2) {
const gradient = this.ctx.createRadialGradient(x, y, 0, x, y, radius);
gradient.addColorStop(0, color1);
gradient.addColorStop(1, color2);
this.ctx.beginPath();
this.ctx.arc(x, y, radius, 0, 2 * Math.PI);
this.ctx.fillStyle = gradient;
this.ctx.fill();
}
}
Get the complete TypeScript-based Speedometer system! Includes full source code and documentation.
Intelligent speed zone system with violation tracking, fine calculation, and enforcement integration.
Intelligent speed zone management system with automatic speed limit detection, comprehensive violation tracking, and configurable enforcement mechanisms. Features dynamic zone creation, administrative controls, and integration with law enforcement systems.
-- Speed zone creation and management
local SpeedZones = {}
SpeedZones.zones = {}
SpeedZones.playerZones = {}
SpeedZones.violations = {}
function SpeedZones:CreateZone(zoneId, coords, radius, speedLimit, zoneType)
local zone = {
id = zoneId,
coords = vector3(coords.x, coords.y, coords.z),
radius = radius,
speedLimit = speedLimit,
type = zoneType, -- 'residential', 'highway', 'school', 'construction'
active = true,
createdAt = os.time(),
violations = 0,
enforcementLevel = 'warning' -- 'warning', 'fine', 'arrest'
}
self.zones[zoneId] = zone
-- Create client-side zone blip
TriggerClientEvent('speed-zones:createZone', -1, zone)
print(string.format('[SPEED-ZONES] Created %s zone %s: %d mph limit',
zoneType, zoneId, speedLimit))
return zone
end
-- Real-time zone detection and speed monitoring
function SpeedZones:MonitorPlayer(playerId)
local playerPed = GetPlayerPed(playerId)
local playerCoords = GetEntityCoords(playerPed)
local vehicle = GetVehiclePedIsIn(playerPed, false)
if vehicle == 0 then
self.playerZones[playerId] = nil
return
end
local speed = GetEntitySpeed(vehicle) * 2.236936 -- Convert to MPH
local currentZone = nil
-- Check all zones for player position
for zoneId, zone in pairs(self.zones) do
if zone.active then
local distance = #(playerCoords - zone.coords)
if distance <= zone.radius then
currentZone = zone
break
end
end
end
-- Handle zone entry/exit
if currentZone then
self:HandleZoneEntry(playerId, currentZone, speed)
else
self:HandleZoneExit(playerId)
end
end
-- Zone entry and speed limit enforcement
function SpeedZones:HandleZoneEntry(playerId, zone, currentSpeed)
local previousZone = self.playerZones[playerId]
-- First entry into this zone
if not previousZone or previousZone.id ~= zone.id then
self.playerZones[playerId] = zone
TriggerClientEvent('speed-zones:enterZone', playerId, zone)
end
-- Check for speed violations
if currentSpeed > zone.speedLimit then
local violation = {
playerId = playerId,
zoneId = zone.id,
speed = currentSpeed,
speedLimit = zone.speedLimit,
excessSpeed = currentSpeed - zone.speedLimit,
timestamp = os.time(),
coords = GetEntityCoords(GetPlayerPed(playerId))
}
self:ProcessViolation(violation, zone)
end
end
-- Comprehensive violation handling
function SpeedZones:ProcessViolation(violation, zone)
local playerId = violation.playerId
local excessSpeed = violation.excessSpeed
-- Initialize player violation history
if not self.violations[playerId] then
self.violations[playerId] = {}
end
table.insert(self.violations[playerId], violation)
zone.violations = zone.violations + 1
-- Determine enforcement action based on excess speed and history
local action = self:DetermineEnforcementAction(playerId, excessSpeed, zone)
-- Execute enforcement action
if action.type == 'warning' then
TriggerClientEvent('speed-zones:warning', playerId, {
message = string.format('Speed limit: %d mph | Your speed: %d mph',
zone.speedLimit, math.floor(violation.speed)),
excessSpeed = excessSpeed
})
elseif action.type == 'fine' then
local fineAmount = self:CalculateFine(excessSpeed, zone.type)
TriggerClientEvent('speed-zones:fine', playerId, {
amount = fineAmount,
reason = 'Speeding violation',
zone = zone.id
})
-- Notify law enforcement if enabled
if zone.enforcementLevel ~= 'warning' then
TriggerEvent('police:speedingViolation', violation, fineAmount)
end
elseif action.type == 'serious' then
-- Serious violation - notify all law enforcement
TriggerEvent('police:seriousSpeedingViolation', violation)
TriggerClientEvent('speed-zones:seriousViolation', playerId, violation)
end
-- Log violation for analytics
self:LogViolation(violation, action)
end
-- Smart fine calculation based on multiple factors
function SpeedZones:CalculateFine(excessSpeed, zoneType)
local baseFine = 50
local speedMultiplier = math.max(1, excessSpeed / 10) -- $5 per mph over
-- Zone type modifiers
local zoneModifiers = {
residential = 1.5,
school = 2.0,
construction = 1.8,
highway = 0.8
}
local modifier = zoneModifiers[zoneType] or 1.0
local totalFine = baseFine * speedMultiplier * modifier
return math.floor(totalFine)
end
-- Administrative zone management
function SpeedZones:AdminUpdateZone(adminId, zoneId, updates)
local zone = self.zones[zoneId]
if not zone then return false end
-- Validate admin permissions
if not self:HasAdminPermission(adminId, 'zone_management') then
TriggerClientEvent('speed-zones:notify', adminId, 'Insufficient permissions', 'error')
return false
end
-- Apply updates
for key, value in pairs(updates) do
if key ~= 'id' and key ~= 'createdAt' then
zone[key] = value
end
end
-- Broadcast updates to all clients
TriggerClientEvent('speed-zones:zoneUpdated', -1, zone)
print(string.format('[SPEED-ZONES] Admin %s updated zone %s', adminId, zoneId))
return true
end
Extensible FiveM interaction framework — 2,500+ downloads across 200+ active servers.
Advanced interaction framework for FiveM servers providing a flexible, extensible system for creating interactive elements. Features multiple interaction types, conditional logic, performance optimization, and a comprehensive API with extensive documentation for developers.
-- Advanced interaction creation system
function InteractionCore:CreateInteraction(data)
local interactionId = data.id or self:GenerateId()
local interaction = {
id = interactionId,
coords = data.coords or vector3(0, 0, 0),
distance = data.distance or self.Config.maxInteractionDistance,
type = data.type or self.Types.SIMPLE,
helpText = data.helpText or 'Press ~INPUT_CONTEXT~ to interact',
callback = data.callback,
conditions = data.conditions or {},
cooldown = data.cooldown or self.Config.cooldownTime,
-- Advanced features
animation = data.animation,
progressBar = data.progressBar,
menu = data.menu,
-- Conditional requirements
job = data.job,
gang = data.gang,
item = data.item,
-- Visual elements
blip = data.blip,
marker = data.marker,
active = true,
lastUsed = 0
}
self.interactions[interactionId] = interaction
-- Create visual elements
if interaction.blip then
self:CreateInteractionBlip(interaction)
end
if interaction.marker then
self:CreateInteractionMarker(interaction)
end
return interactionId
end
-- Intelligent interaction processing
function InteractionCore:ProcessInteraction()
local playerPed = PlayerPedId()
local closestInteraction = self:GetClosestActiveInteraction()
if not closestInteraction then return end
-- Cooldown check
if GetGameTimer() - closestInteraction.lastUsed < closestInteraction.cooldown then
return
end
-- Advanced condition validation
if not self:ValidateConditions(closestInteraction, playerPed) then
return
end
closestInteraction.lastUsed = GetGameTimer()
self:HandleInteractionType(closestInteraction, playerPed)
end
-- Flexible interaction type system
function InteractionCore:HandleInteractionType(interaction, playerPed)
local interactionType = interaction.type
if interactionType == self.Types.SIMPLE then
-- Immediate callback execution
self:HandleSimpleInteraction(interaction)
elseif interactionType == self.Types.ANIMATED then
-- Animation-based interaction
if interaction.animation then
local animDict = interaction.animation.dict
local animName = interaction.animation.name
local duration = interaction.animation.duration or 2000
RequestAnimDict(animDict)
while not HasAnimDictLoaded(animDict) do Wait(100) end
TaskPlayAnim(playerPed, animDict, animName, 8.0, 8.0, duration, 0, 0, false, false, false)
Wait(duration)
ClearPedTasks(playerPed)
RemoveAnimDict(animDict)
end
if interaction.callback then
interaction.callback(interaction.data)
end
elseif interactionType == self.Types.PROGRESSIVE then
-- Progress bar interaction
if interaction.progressBar then
local progressData = {
duration = interaction.progressBar.duration or 5000,
label = interaction.progressBar.label or 'Processing...',
canCancel = interaction.progressBar.canCancel or true,
disableMovement = interaction.progressBar.disableMovement or true
}
self:ShowProgressBar(progressData, function(success)
if success and interaction.callback then
interaction.callback(interaction.data)
end
end)
end
elseif interactionType == self.Types.CONDITIONAL then
-- Advanced conditional logic
self:HandleConditionalInteraction(interaction)
elseif interactionType == self.Types.TIMED then
-- Time-based interaction requiring sustained presence
local timerDuration = interaction.timer or 10000
local startTime = GetGameTimer()
Citizen.CreateThread(function()
while GetGameTimer() - startTime < timerDuration do
local currentCoords = GetEntityCoords(playerPed)
if #(currentCoords - interaction.coords) > interaction.distance then
return -- Player moved away, cancel
end
Wait(100)
end
if interaction.callback then
interaction.callback(interaction.data)
end
end)
end
end
-- Comprehensive condition validation
function InteractionCore:ValidateConditions(interaction, playerPed)
-- Job requirement validation
if interaction.job then
local PlayerData = QBCore.Functions.GetPlayerData()
if PlayerData.job.name ~= interaction.job then
return false
end
end
-- Gang requirement validation
if interaction.gang then
local PlayerData = QBCore.Functions.GetPlayerData()
if PlayerData.gang.name ~= interaction.gang then
return false
end
end
-- Item requirement validation
if interaction.item then
if not self:PlayerHasItem(interaction.item) then
return false
end
end
-- Custom conditions validation
if interaction.conditions and type(interaction.conditions) == 'table' then
for _, condition in pairs(interaction.conditions) do
if type(condition) == 'function' and not condition() then
return false
end
end
end
return true
end
-- Performance-optimized distance checking
function InteractionCore:StartInteractionThread()
Citizen.CreateThread(function()
while true do
local sleep = 500
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
self.activeInteractions = {}
-- Efficient spatial checking
for id, interaction in pairs(self.interactions) do
if self:IsInteractionValid(interaction, playerPed, playerCoords) then
local distance = #(playerCoords - interaction.coords)
if distance <= interaction.distance then
self.activeInteractions[id] = interaction
sleep = 0 -- Active interaction found, reduce sleep
if self.Config.showHelpText and interaction.helpText then
self:ShowHelpText(interaction.helpText)
end
end
end
end
Wait(sleep)
end
end)
end
Get the complete Interaction Core System for free! Includes full source code, documentation, and examples.
Lockpicking job system with skill progression, MySQL persistence, and anti-exploit protection.
Zendo-Lockpick: Complete lockpicking job system for FiveM servers featuring skill progression, dynamic rewards, database integration, and comprehensive administrative controls. Includes anti-exploit protection and extensive customization options. Available as a free download with full source code!
-- Dynamic job creation and player assignment
function StartLockpickJob()
local randomLocation = Config.Locations[math.random(1, #Config.Locations)]
currentJobData = {
location = randomLocation,
startTime = GetGameTimer(),
completed = false
}
isDoingLockpickJob = true
CreateJobBlip(randomLocation.coords)
QBCore.Functions.Notify('New lockpick job available! Check your GPS.', 'success')
TriggerServerEvent('lockpick-job:server:jobStarted', currentJobData)
end
-- Advanced lockpicking minigame with skill-based success rates
function StartLockpickingMinigame(difficulty)
local success = false
local attempts = 3
while attempts > 0 and not success do
QBCore.Functions.Notify(string.format('Lockpicking... Attempt %d/3', 4 - attempts), 'primary')
-- Skill-based success calculation
local skillChance = math.min((lockpickSkill / Config.MaxSkillLevel) * 100, 85)
local difficultyModifier = (1 - (difficulty * 0.15))
local finalChance = skillChance * difficultyModifier
Wait(3000) -- Minigame simulation
local randomRoll = math.random(1, 100)
if randomRoll <= finalChance then
success = true
QBCore.Functions.Notify('Lock picked successfully!', 'success')
else
attempts = attempts - 1
if attempts > 0 then
QBCore.Functions.Notify('Failed! Try again.', 'error')
end
end
end
return success
end
-- Intelligent skill progression and reward calculation
function CompleteLockpickJob(success)
if not isDoingLockpickJob then return end
local reward = 0
local skillGain = 0
if success then
local difficulty = currentJobData.location.difficulty
-- Dynamic reward calculation based on skill and difficulty
reward = Config.BaseReward * difficulty * (1 + (lockpickSkill / Config.MaxSkillLevel))
skillGain = Config.SkillIncrement * difficulty
-- Progressive skill system with diminishing returns
lockpickSkill = math.min(lockpickSkill + skillGain, Config.MaxSkillLevel)
QBCore.Functions.Notify(string.format('Job completed! Earned $%d and %d skill XP',
math.floor(reward), skillGain), 'success')
end
-- Clean up job state
if currentJobData.blip then
RemoveBlip(currentJobData.blip)
end
isDoingLockpickJob = false
currentJobData = {}
-- Server synchronization
TriggerServerEvent('lockpick-job:server:jobCompleted', {
success = success,
reward = reward,
skillGain = skillGain,
newSkillLevel = lockpickSkill
})
end
-- Server-side reward processing and validation
RegisterNetEvent('lockpick-job:server:jobCompleted', function(completionData)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if completionData.success then
-- Update player skill and statistics
playerSkillData[Player.PlayerData.citizenid].skillLevel = completionData.newSkillLevel
playerSkillData[Player.PlayerData.citizenid].jobsCompleted =
playerSkillData[Player.PlayerData.citizenid].jobsCompleted + 1
-- Award money with validation
Player.Functions.AddMoney('cash', completionData.reward, 'lockpick-job-reward')
-- Persistent storage
SavePlayerSkillData(Player.PlayerData.citizenid)
-- Update client
TriggerClientEvent('lockpick-job:client:updateSkill', src, completionData.newSkillLevel)
end
end)
-- Persistent player skill tracking with MySQL
local function LoadPlayerSkillData(citizenid)
MySQL.Async.fetchAll('SELECT * FROM player_lockpick_skills WHERE citizenid = ?', {citizenid},
function(result)
if result[1] then
playerSkillData[citizenid] = {
skillLevel = result[1].skill_level or 0,
jobsCompleted = result[1].jobs_completed or 0,
lastJobTime = result[1].last_job_time
}
else
-- Create new player record
MySQL.Async.execute('INSERT INTO player_lockpick_skills (citizenid) VALUES (?)', {citizenid})
playerSkillData[citizenid] = {skillLevel = 0, jobsCompleted = 0, lastJobTime = nil}
end
-- Sync with client
local Player = QBCore.Functions.GetPlayerByCitizenId(citizenid)
if Player then
TriggerClientEvent('lockpick-job:client:updateSkill', Player.PlayerData.source,
playerSkillData[citizenid].skillLevel)
end
end)
end
-- Administrative commands for server management
QBCore.Commands.Add('setlockpickskill', 'Set a player\'s lockpick skill level (Admin Only)', {
{name = 'id', help = 'Player ID'},
{name = 'skill', help = 'Skill Level (0-100)'}
}, true, function(source, args)
local targetId = tonumber(args[1])
local skillLevel = tonumber(args[2])
if skillLevel < 0 or skillLevel > Config.MaxSkillLevel then
TriggerClientEvent('QBCore:Notify', source,
'Skill level must be between 0 and ' .. Config.MaxSkillLevel, 'error')
return
end
local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
if TargetPlayer then
local citizenid = TargetPlayer.PlayerData.citizenid
if not playerSkillData[citizenid] then
playerSkillData[citizenid] = {skillLevel = 0, jobsCompleted = 0}
end
playerSkillData[citizenid].skillLevel = skillLevel
SavePlayerSkillData(citizenid)
TriggerClientEvent('lockpick-job:client:updateSkill', targetId, skillLevel)
TriggerClientEvent('QBCore:Notify', source,
string.format('Set %s\'s lockpick skill to %d',
TargetPlayer.PlayerData.name, skillLevel), 'success')
end
end, 'admin')
Get the complete Zendo-Lockpick system absolutely free! Includes full source code, documentation, and installation guide.
Download all files with dedicated page and easy access
Full Zendo-Lockpick system with all files and configurations
View individual files and folder structure online
FiveM resource manifest file for easy installation
Complete setup instructions and configuration documentation
Location discovery with fuzzy search, distance sorting, GPS integration, and custom categories.
Advanced world search and discovery system for FiveM servers featuring intelligent location finding, category-based organization, distance calculations, and customizable filters. Perfect for large maps with hundreds of points of interest, enabling players to quickly find businesses, landmarks, and interactive locations. Available as a free download with full source code!
-- Advanced search system with fuzzy matching
local WorldSearch = {}
WorldSearch.locations = {}
WorldSearch.categories = {}
WorldSearch.searchIndex = {}
-- Initialize search system with location data
function WorldSearch:Initialize()
-- Load locations from database
self:LoadLocations()
-- Build search index for performance
self:BuildSearchIndex()
print('[WORLD-SEARCH] Initialized with ' .. #self.locations .. ' locations')
end
-- Intelligent location search with fuzzy matching
function WorldSearch:Search(query, category, maxDistance)
local results = {}
local playerCoords = GetEntityCoords(PlayerPedId())
local lowerQuery = string.lower(query)
for _, location in pairs(self.locations) do
-- Category filter
if category and location.category ~= category then
goto continue
end
-- Distance filter
local distance = #(playerCoords - location.coords)
if maxDistance and distance > maxDistance then
goto continue
end
-- Fuzzy text matching
local nameMatch = self:FuzzyMatch(string.lower(location.name), lowerQuery)
local descMatch = location.description and
self:FuzzyMatch(string.lower(location.description), lowerQuery) or 0
local relevanceScore = math.max(nameMatch, descMatch * 0.7)
if relevanceScore > 0.3 then -- Minimum relevance threshold
table.insert(results, {
location = location,
distance = distance,
relevance = relevanceScore
})
end
::continue::
end
-- Sort by relevance, then distance
table.sort(results, function(a, b)
if math.abs(a.relevance - b.relevance) < 0.1 then
return a.distance < b.distance
end
return a.relevance > b.relevance
end)
return results
end
-- Advanced GPS waypoint system
function WorldSearch:SetWaypoint(locationId)
local location = self:GetLocationById(locationId)
if not location then
return false
end
local coords = location.coords
SetNewWaypoint(coords.x, coords.y)
-- Create visual waypoint marker
local blip = AddBlipForCoord(coords.x, coords.y, coords.z)
SetBlipSprite(blip, 8) -- Waypoint sprite
SetBlipColour(blip, 5) -- Yellow
SetBlipRoute(blip, true)
SetBlipRouteColour(blip, 5)
-- Store active waypoint
self.activeWaypoint = {
location = location,
blip = blip,
startTime = GetGameTimer()
}
-- Notify player
local playerCoords = GetEntityCoords(PlayerPedId())
local distance = #(playerCoords - coords)
TriggerEvent('chat:addMessage', {
template = 'Waypoint set to ' .. location.name,
args = {}
})
return true
end
Get the complete World Search system absolutely free! Includes full source code, documentation, and setup guide.
Full system with all files, UI components, and configurations
View individual files and folder structure online
Realistic transmission simulation — manual/automatic modes and clutch mechanics. Coming soon.
Advanced vehicle transmission system for FiveM servers featuring realistic gear shifting mechanics, manual and automatic transmission modes, clutch system, and performance tuning capabilities. Provides immersive driving experience with customizable shift patterns, engine sounds, and visual indicators. Designed for realistic roleplay servers seeking authentic vehicle behavior.
Note: These are conceptual snippets showing the planned architecture. Final implementation may vary.
-- Advanced transmission management system
local Transmission = {}
Transmission.vehicles = {}
Transmission.config = {
manualMode = false,
clutchEnabled = true,
shiftTime = 200, -- ms
realisticStalling = true
}
-- Initialize vehicle transmission
function Transmission:InitVehicle(vehicle)
local vehicleData = {
vehicle = vehicle,
currentGear = 1,
rpm = 0,
maxRPM = 8000,
mode = 'automatic', -- 'automatic' or 'manual'
clutchEngaged = true,
engineStalled = false,
gearRatios = self:GetGearRatios(vehicle),
shiftPoints = self:CalculateShiftPoints(vehicle)
}
self.vehicles[vehicle] = vehicleData
return vehicleData
end
-- Realistic gear shifting with RPM management
function Transmission:ShiftGear(vehicle, direction)
local vehData = self.vehicles[vehicle]
if not vehData then return false end
-- Check if shifting is allowed
if not vehData.clutchEngaged and self.config.clutchEnabled then
TriggerEvent('transmission:notify', 'Engage clutch to shift!', 'error')
return false
end
local newGear = vehData.currentGear + direction
local maxGear = #vehData.gearRatios
-- Validate gear range
if newGear < 1 or newGear > maxGear then
return false
end
-- Perform shift
vehData.currentGear = newGear
-- Calculate RPM change based on gear ratio
local oldRatio = vehData.gearRatios[vehData.currentGear - direction]
local newRatio = vehData.gearRatios[newGear]
vehData.rpm = vehData.rpm * (oldRatio / newRatio)
-- Visual and audio feedback
self:PlayShiftAnimation(vehicle)
self:PlayShiftSound(vehicle, direction)
return true
end
-- Calculate optimal shift points based on vehicle stats
function Transmission:CalculateShiftPoints(vehicle)
local maxSpeed = GetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fInitialDriveMaxFlatVel')
local acceleration = GetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fInitialDriveForce')
local shiftPoints = {}
local baseShiftRPM = 6500
-- Adjust for vehicle performance
local performanceFactor = (acceleration / 1.0) * (maxSpeed / 150.0)
for gear = 1, 6 do
shiftPoints[gear] = {
upshift = baseShiftRPM * (1 - (gear * 0.05)),
downshift = baseShiftRPM * 0.4
}
end
return shiftPoints
end
-- Realistic clutch mechanics with stalling
function Transmission:UpdateClutch(vehicle, clutchInput)
local vehData = self.vehicles[vehicle]
if not vehData or not self.config.clutchEnabled then return end
-- Clutch is analog (0.0 to 1.0)
local previousState = vehData.clutchEngaged
vehData.clutchEngaged = clutchInput < 0.5
-- Check for stall conditions
if self.config.realisticStalling then
local speed = GetEntitySpeed(vehicle) * 3.6 -- Convert to km/h
-- Stall if releasing clutch too fast in low gear at low speed
if not previousState and vehData.clutchEngaged then
if vehData.currentGear <= 2 and speed < 5 and vehData.rpm < 1500 then
self:StallEngine(vehicle)
return
end
end
end
-- Update power delivery based on clutch engagement
local powerMultiplier = vehData.clutchEngaged and 1.0 or clutchInput
SetVehicleEnginePowerMultiplier(vehicle, powerMultiplier)
end
-- Engine stall handling
function Transmission:StallEngine(vehicle)
local vehData = self.vehicles[vehicle]
if not vehData then return end
vehData.engineStalled = true
vehData.rpm = 0
SetVehicleEngineOn(vehicle, false, true, false)
-- Visual feedback
TriggerEvent('transmission:notify', 'Engine Stalled! Press [IGNITION] to restart', 'warning')
-- Play stall sound
PlaySoundFromEntity(-1, 'Engine_fail', vehicle, 'DLC_PILOT_ENGINE_FAILURE_SOUNDS', true, 0)
end
-- Restart stalled engine
function Transmission:RestartEngine(vehicle)
local vehData = self.vehicles[vehicle]
if not vehData or not vehData.engineStalled then return end
-- Check if conditions are right for restart
if vehData.clutchEngaged or vehData.currentGear == 0 then
SetVehicleEngineOn(vehicle, true, false, true)
vehData.engineStalled = false
vehData.rpm = 1000 -- Idle RPM
TriggerEvent('transmission:notify', 'Engine started', 'success')
else
TriggerEvent('transmission:notify', 'Engage clutch or put in neutral first', 'error')
end
end
-- Intelligent automatic transmission logic
function Transmission:UpdateAutomatic(vehicle, deltaTime)
local vehData = self.vehicles[vehicle]
if not vehData or vehData.mode ~= 'automatic' then return end
local throttle = GetVehicleThrottleOffset(vehicle)
local brake = GetVehicleHandbrake(vehicle)
local currentGear = vehData.currentGear
local shiftPoint = vehData.shiftPoints[currentGear]
-- Upshift logic
if vehData.rpm > shiftPoint.upshift and throttle > 0.3 then
if currentGear < #vehData.gearRatios then
-- Smooth automatic shift
self:AutoShift(vehicle, 1)
end
end
-- Downshift logic
if vehData.rpm < shiftPoint.downshift and currentGear > 1 then
-- Only downshift if throttle is applied or braking
if throttle > 0.1 or brake then
self:AutoShift(vehicle, -1)
end
end
-- Kickdown detection (for quick acceleration)
if throttle > 0.9 and vehData.rpm < shiftPoint.upshift * 0.7 then
if currentGear > 2 then
self:AutoShift(vehicle, -1) -- Downshift for more power
TriggerEvent('transmission:notify', 'Kickdown activated', 'info')
end
end
end
-- Smooth automatic shifting with delay
function Transmission:AutoShift(vehicle, direction)
local vehData = self.vehicles[vehicle]
-- Reduce power during shift
SetVehicleEnginePowerMultiplier(vehicle, 0.3)
Citizen.SetTimeout(self.config.shiftTime, function()
self:ShiftGear(vehicle, direction)
-- Restore power after shift
Citizen.SetTimeout(100, function()
SetVehicleEnginePowerMultiplier(vehicle, 1.0)
end)
end)
end
-- Toggle between automatic and manual
function Transmission:ToggleMode(vehicle)
local vehData = self.vehicles[vehicle]
if not vehData then return end
if vehData.mode == 'automatic' then
vehData.mode = 'manual'
TriggerEvent('transmission:notify', 'Manual mode activated', 'success')
else
vehData.mode = 'automatic'
TriggerEvent('transmission:notify', 'Automatic mode activated', 'success')
end
-- Update UI
SendNUIMessage({
type = 'updateMode',
mode = vehData.mode
})
end
This project is currently in active development. We're working hard to deliver a realistic and immersive transmission system that will enhance your driving experience. The system will be released once it meets our quality standards and includes comprehensive documentation.
Stay tuned! Follow this portfolio for updates on the release. Once available, full source code and installation instructions will be provided for free download.
Automated vertical video editing — 10x faster than manual. TikTok, Shorts, and Reels optimized.
The AI Clip Generator is a powerful automated video editing service designed specifically for content creators who want to maximize their reach on TikTok, YouTube Shorts, Instagram Reels, and other vertical video platforms. Upload your long-form content and let AI handle the heavy lifting—from identifying viral-worthy moments to generating captions and reformatting for mobile viewers.
Ready to transform your content workflow? I offer flexible pricing packages tailored to your needs—whether you're a solo creator or running a content agency.
$75
per video
$250
per month (4 videos)
Custom
Let's talk
All prices are negotiable! I'm happy to create a custom package that fits your budget and needs.
Every content creator has unique needs. Let's chat about your project and find a pricing solution that works for both of us. I'm flexible and open to negotiation!
I respond to all inquiries within 24 hours, usually much faster! Send me an email with your content type, monthly volume, and budget—I'll send you a personalized quote with flexible payment options.