The EV Hookers System provides an immersive feature allowing players to interact with NPCs for specific services. It includes customizable payment systems, localized prompts, and detailed animations for a realistic experience.
Configuration
The configuration defines parameters for interactions, payments, and NPC behaviors.
General Settings
System Features
Hooker Interaction
Initiating Interaction:
Players honk their vehicle horn near a valid NPC to start interaction.
Prompts appear if conditions are met (e.g., vehicle suitability, seat availability).
Secluded Area Requirement:
Players must move to a secluded area for services to proceed.
A timer ensures players act within a reasonable time.
Service Options:
Players choose from a menu of services (e.g., "Blow Job," "Sex").
Services are limited to Config.MaxServices.
Payment Handling:
Payments are handled based on the selected framework.
If the player cannot afford the service, interaction ends.
Animations:
NPCs and players engage in synchronized animations during services.
Animations vary by selected service.
Client-Side Details
Hooker Interaction Logic
The system continuously scans for nearby NPCs and checks for eligibility.
Secluded Area Check
To proceed with services, the player must park in a secluded area.
Service Menu
A custom menu allows players to select services.
Server-Side Details
Payment Handling
The server validates and deducts payments based on the configured framework.
Example Scenarios
Scenario 1: Successful Interaction
A player honks near an eligible NPC.
The NPC enters the vehicle if conditions are met.
The player drives to a secluded area.
The player selects a service and pays.
The NPC and player engage in synchronized animations.
Scenario 2: Failed Interaction
A player honks near an NPC but uses a blacklisted vehicle.
A prompt appears: "You cannot pick up hookers in this vehicle."
Interaction ends.
Notes
Customization:
Adjust Config.Prices and Config.MaxServices to fit your design.
Add or remove NPC models in Config.HookerPedModels.
Framework Integration:
The script adapts seamlessly to configured frameworks.
Vehicle Constraints:
Certain vehicle classes are blacklisted to maintain realism.
Config = {
MaxDistance = 7.5, -- Maximum distance from a hooker to pick them up.
MaxServices = 3, -- Maximum services a hooker will provide.
MaxVehicleSpeed = 0.1, -- Maximum vehicle speed allowed for interactions.
PaymentEnabled = true, -- Enable or disable payments.
Framework = "qbcore", -- Framework used: "qbcore", "esx", "ndcore", "standalone".
Prices = { -- Service prices.
SERVICE_BLOWJOB = 50,
SERVICE_SEX = 100
},
Localization = { -- Localization for interaction prompts.
InviteHooker = "Press ~INPUT_VEH_HORN~ or honk your horn to invite the prostitute into the vehicle.",
FindSecludedArea = "Go somewhere more secluded.",
FindSecludedAreaFailed = "You did not find a secluded area in time.",
VehicleUnsuitable = "You cannot pick up hookers in this vehicle.",
FrontSeatOccupied = "The front seat needs to be empty to invite a hooker.",
NotEnoughMoney = "You don't have enough money!"
},
HookerPedModels = { -- NPCs considered hookers.
[`s_f_y_hooker_01`] = true,
[`s_f_y_hooker_02`] = true,
[`s_f_y_hooker_03`] = true
},
BlackListedVehicleClasses = { -- Vehicle classes that cannot pick up hookers.
[8] = true, -- Motorcycles
[13] = true, -- Cycles
[14] = true, -- Boats
[15] = true, -- Helicopters
[16] = true, -- Planes
[18] = true, -- Emergency
[19] = true, -- Military
[21] = true, -- Trains
[22] = true, -- Open Wheel
}
}
local function IsPedEligibleHooker(ped)
local pedModel = GetEntityModel(ped)
if not Config.HookerPedModels[pedModel] then
return false
end
if IsPedInjured(ped) or IsPedAPlayer(ped) or IsPedInAnyVehicle(ped, true) then
return false
end
return true
end
local function IsInSecludedArea(hooker, vehicle)
local vehicleSpeed = GetEntitySpeed(vehicle)
if vehicleSpeed >= Config.MaxVehicleSpeed then
return false
end
local coords = GetEntityCoords(PlayerPedId())
for _, ped in pairs(GetNearbyPeds()) do
if #(coords - GetEntityCoords(ped)) < 75.0 and HasEntityClearLosToEntity(ped, vehicle, 17) then
return false
end
end
return true
end
local servicesMenu = {
Title = "Services Available",
Buttons = {
{ service = "SERVICE_BLOWJOB", label = "Blow Job", price = Config.Prices.SERVICE_BLOWJOB },
{ service = "SERVICE_SEX", label = "Sex", price = Config.Prices.SERVICE_SEX },
{ service = "SERVICE_DECLINE", label = "Decline Service" },
},
OnButtonSelected = function(button)
serviceSelected = button.service
end
}
RegisterServerEvent('hookers:moneyCheck')
AddEventHandler('hookers:moneyCheck', function(service)
local cost = Config.Prices[service]
if Config.Framework == "qbcore" then
local Player = QBCore.Functions.GetPlayer(source)
if Player.Functions.GetMoney('cash') >= cost then
Player.Functions.RemoveMoney('cash', cost, "Hooker")
TriggerClientEvent('hookser:paymentReturn', source, true)
else
TriggerClientEvent('hookser:paymentReturn', source, false)
end
elseif Config.Framework == "esx" then
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer.getMoney() >= cost then
xPlayer.removeMoney(cost)
TriggerClientEvent('hookser:paymentReturn', source, true)
else
TriggerClientEvent('hookser:paymentReturn', source, false)
end
end
end)