[FREE][ESX]Hayden's Simple Store Robbery System

THIS IS NO LONGER SUPPORTED OR AVAILABLE

Hello there! Let me introduce myself, my name is Hayden and I’m an 18 year old developer from Australia!

Recently, I’ve noticed that there is a lack of secure resources on the FiveM forums, I’ve noticed a lot of people offering or charging for resources that are either:

  1. Stolen code and resold
  2. Made by the developer, charge $20 and have abusable exploits all within

Today, I bring you my very first release on these forums, and it’s a simplistic ESX Store Robbery script, in which I actually check for things on the server side and leave the client to only do the bare minimum (animations & police alerts)

Showcase
Download Link

Contains Highly configurable settings such as:

  • Ped models
  • Max and Minimum payout
  • Cops Required
  • Cooldown
  • Weapons you can rob with
  • Rob timer
  • Turn blips on/off
  • Language support (Complete with full Locales)

Other features include:

  • Chance of ped fighting back (can be edited)
  • Police being alerted with mugshot being sent

This is my first ever script release, and it’s a basic script.
I plan on working & adjusting this resource as I go, but do keep in mind I offer it completely free, so there is only so much support I can do. This was more or so a learning experience for me rather then anything.

I’ve tried to make this 100% exploit free, please let me know if you believe there are potential exploits and I will patch them ASAP.

I hope you enjoy this release !

Made with :heart: by Hayden

12 Likes

Thats something cool :upside_down_face:

Nice little script.

Use qtarget to avoid doing this. OR have the wait time change depending on distance. There’s no point checking if you’re a job that cannot rob, like police or EMS.

This is within the loop:

            if distance < 3 then
                if IsPedArmed(PlayerPedId(), 7) then               
                    if aiming and not IsPedDeadOrDying(Config.NPC[i]['id']) and GetEntityHealth(Config.NPC[i]['id']) > 0 then 
                        Draw3DText( tL, tL2 , tL3, "Press " .. Config.ContextKey .. " to threaten shop keeper", 4, 0.1, 0.1)
                        if IsControlJustPressed(0, Config.Key) then
                            id = Config.NPC[i]['id']
                            FreezeEntityPosition(Config.NPC[i]['id'], false)
                            SetEntityInvincible(Config.NPC[i]['id'], false)
                            TriggerServerEvent('hayden_store:robClerk', i, id)
                        end 
                    end
                end
            end

I’ve refused to use bt-target/qtarget as I’m classy and prefer the 3D Text, but that’s something I’ll work on adding in just as I know it’s popular.

Would you recommend utilising Polyzones? Or just fetching the ped model and making it any ped model?

1 Like

I’d just use the zone, or the entity. Also its usually a good idea to define the vars, you’re calling “Config.NPC[i][‘id’]” a lot. Replace that with “local ped = Config.NPC[i][‘id’]” at the top of the loop and have it call that instead. You are actually doing that where you define id, but you don’t seem to be re-using it.

EDIT: Here’s a location loop I made a few months ago, you can make it even more optimized than this, but this should make performance better:

Just a reminder, the above code is old.

1 Like

nicee

Have here times the German translation

['de'] = {
        ['robbing'] = "Alarm wurde ausgelöst",
        ['cop_msg'] = "In einem Geschäft wurde Alarm ausgelöst, CCTV hat das Gesicht des Kriminellen erfasst!",
        ['set_waypoint'] = "Wegpunkt zum Store setzen",
        ['hide_box'] = "Schließen Sie dieses Feld",
        ['playerRobbing'] = "Sie rauben jetzt den Laden aus! Halten Sie Ihre Waffe gerichtet!",
        ['robbery'] = "Ladenraub",
        ['no_cop'] = "Nicht genug Polizisten im Dienst, um den Laden auszurauben!",
        ['recent'] = "Dieser Laden wurde vor kurzem ausgeraubt!",
        ['success'] = "Sie haben den Laden erfolgreich ausgeraubt!",
        ['nowep'] = "Es scheint, dass Sie nicht über die entsprechenden Waffen für diese Aufgabe verfügen!",
        ['shotNPC'] = "Du hast den NPC erschossen, der Raub wurde abgesagt!",
    }
1 Like

issue, when the photo comes up for cctv its of the person thats receiving the image any idea for a fix?

also if someone goes too far it does not cancel

Thank you this has been added

1 Like

I’ll fix this & your other issue today.

I apologise for this.

This has been fixed in the latest version

Thank you for this, I’ll clean up this store robbery script and include this into my future releases

Few nitpicks for improvement below. I’ll start with a few minor things, then include some problematic code I see.

  • GetHashKey(‘WEAPON_PISTOL’) (etc)
    Rather than GetHashKey, which will call the native each time, enclose the weapon name in backticks (`) to hash the result during compilation.

  • CreateThread
    You have two of them running on tick - you should only bother having a single one, and work on how often they need to be checked.

-- This is the actual functionality behind counting police
RegisterNetEvent('hayden_store:countPolice')
AddEventHandler('hayden_store:countPolice', function(source)
	local xPlayers = ESX.GetPlayers()
 	pcountPolice = 0

    for i=1, #xPlayers, 1 do
        local Player = ESX.GetPlayerFromId(xPlayers[i])
        if Player.job.name == 'police' then
           pcountPolice = pcountPolice + 1
        end
    end

    if Config.Debug then 
        print("Cop count updated, current cop count is: " .. pcountPolice)
    end

end)

I suppose for older ESX support you can’t specifically use ESX.GetExtendedPlayers(), but you should change the logic for counting police. Traditional xPlayer loops like that start causing server hitches due to the overhead and synchronous nature of game events.

Best option is always event handlers for players connecting, disconnecting, and changing jobs.

RegisterNetEvent('hayden_store:beginRob')
AddEventHandler('hayden_store:beginRob', function(source, i, id)
    local timer = (Server.SetTimer * 1000)
    display = true
    while true do 
        Wait(0)
        ply = source 
        plyPed = GetPlayerPed(ply)
        pCoords = GetEntityCoords(plyPed)

        sX = Config.NPC[i]['Coords'].x
        sY = Config.NPC[i]['Coords'].y
        sZ = Config.NPC[i]['Coords'].z
        sCoords = vector3(sX, sY, sZ)

        if #(pCoords - sCoords) > 5 then 
            tooFar = true 
            print("Too far")
            TriggerEvent('hayden_store:cooldown', i)
            TriggerClientEvent('hayden_store:clearTask', source, i)
            display = false 
            TriggerClientEvent('hayden_store:changeHud', source, display )
            
            TriggerClientEvent('mythic_notify:client:SendAlert', source, { type = 'error', text = Translation[Config.Language]['tooFar'], length = 2500 })

            
            return false 
        else
            timer = timer - 50
            TriggerClientEvent('hayden_store:changeHud', source, timer) 
            if timer <= 0 then
                timer = 0 
                if not tooFar then 
                    TriggerEvent('hayden_store:reward', source, i ) 
                    timer = 0 
                    return false
                end 
            end 
        end 
    end 

end)

I understand wanting to make it unexploitable, but this seems a little excessive since each tick is getting the ped, coords, and distance then sending an event to the client. While it’s true that you generally can’t trust the client, you should run most of this on the client and then confirm with the server once the task is completed, instead.

Overall, not bad - I don’t recall seeing many resources that bother to properly utilise the benefits of OneSync. Better than anything I could do half a year ago. For the job check I mentioned, reference

1 Like

is there anyway to make the alert and the blip only show for cops?

The blip & alert only show for the police

Thank you for this amazing information, I’ll work on optimising this now :pray:

Keep pushing !

1 Like

Nicely done, congrats :clap:

1 Like

To improve resmon you can add a check to your main loop inside client/cl_main.lua. Something I like to do is add a boolean at the beginning of the loop like local closeToNPC = false and then set that to true when the distance is close enough to interact with the npc. Then at the end of the cloop I add this check:

if not closeToNPC then
    Citizen.Wait(1000)
end

Now you can do this directly at the if distance < 3 then check but I suggest you make another check with a bit bigger distance so you won’t have to wait 1 second for the drawtext to pop up.

So for example in your script at line 40:

if distance < 3 then
    ...
end

Add a check like this:

if distance < 5 then
    closeToNPC = true
    if distance < 3 then
        ...
    end
end

You can change it to something higher than 5 if you feel like you still have to wait for the drawtext to pop up.

This should improve resmon when not near any of the NPC’s but remain fully functional when actually near one as the loop will then go back to checking distance and stuff every frame instead of once a second.

1 Like