[SALE] [ESX / QBCore] [PAID] Aquiver Animal Farm System (Job, Property)

About

This is a release of our standalone Animal Farm System which got outdated.
Now with our npm module it is easier to setup our resources with the compatible frameworks.

You can still use the script on a fully custom framework, but it will be harder to set up than in the previous version. See: Custom framework export functions
We wanted to cater to those who are not so familiar with development.
Most of the servers are running QBCore and ESX thats why these to main frameworks was our decision to be compatible with our resource(s).

Links

Dependencies

  • Mysql (npm will automatically install it for you and will be packed.)
  • NodeJS (for installing with npm.)
  • Server version atleast 4752. (to support lua54 & escrow)
  • OneSync ON (For serverside player teleporting/distancing, etc. You can easily make the script to non onesyne if you sync the player-position to server, etc.)
  • Aquiver module supported framework & mysql resource. See: Aquiver module compatibles

Features

We have made a custom modelled interior shell for the Animal Farm which is basically a Barn, so the interior is always in one fixed position, so i had to make a custom dimensional system which handles the object and every other entities.

Comes from the Dimension system, you can create as many farms as you want, it will eat up more memory and usage on the serverside, but on the clientside, the farm objects and other necessary things only loading when you enter the farm, so the script idling is around 0.02-0.04ms.

If you are inside the farm it will cost more performance, because everything is in a ‘small’ modelled interior, and need to render many things, but the render tickers are editable if you want to reduce the CPU usage, but i do not recommend it. We had around 170-180 fps inside the interior.

  • Custom dimensional manager for Objects / Players / Particles / Peds, etc.
  • Custom attachment handler.
  • Raycast on objects / peds.
  • Upgrading system
  • Animal buying
  • Available animals:
    • Chicken (generating Egg [passively])
    • Cow (Milk [gather])
    • Pig (Meal [gather])
  • Every math is configable if you want to mess with the numbers.
  • Our modelled/edited props (Blender):
    • Animal Farm base shell (Barn)
    • Chicken paddock
    • Basic paddock
    • Composter
    • Chicken feeder
    • Chicken drinker
    • Rabbit cages
    • Bucket with states (Milk, Water, Empty)
    • And other props modified. (Shovel made for hand, etc.)
  • I could write a bunch of many things, but everything is shown in the Video, its easier if you watch it.
More images





Code is accessible Yes
Subscription-based Yes & No (explained above)
Lines (approximately) Typescript ~7000
Requirements Explained above with more information.
Support Yes
24 Likes

Please include the required paid release template you removed during topic creation

2 Likes

Another great release. Good work.

1 Like

Are the pigs more equal than others?

2 Likes

When you ‘gather’ the pigs you are basically butcher them, so they gets deleted upon gathering. That is why the pig products (meal) worth more.

We calculated average times:
Pig(s) live around 15-20 days (if everything is kept good, health, etc.)
Pig(s) reach the maximum weight state after 5-6 days.

These are just averages, can not really rely on them!

Chickens are the cheapest ones, they are just passively producing eggs for you which can be sold, but you also need to keep them fed, etc.

won’t work with QB will it?

1 Like

As usual, an amazing release. Very creative, unique, and visually looks appealing :heart_eyes:

1 Like

Nice release and original job :+1:

1 Like

It works with it.
You just need to modify the export functions. (Banking, and others) These are all inside a config.lua file, here you can import your framework.

config.lua file:

Summary
-- Add your getBank function here. (Framework)
exports('getBank', function(source)
    return 200000
end)

-- Add your setBank function here. (Framework)
exports('setBank', function(source, amount)
    print(amount)
end)
-- Add your roleplay name getter here. (Framework)
exports('getRoleplayName', function(source)
    return GetPlayerName(source)
end)

-- If you are using custom Multicharacter resource, you can add your identifier handler here. 
exports('getIdentifier', function(source)
    for k, v in ipairs(GetPlayerIdentifiers(source)) do
        if string.match(v, "license:") then
            return v
        end
        end
end)

-- Add your admin getter here. (Framework)
exports('isAdmin', function(source)
    return true
end)

-- Do not modify this vdist export function please.
exports('vdist', function(x, y, z, rx, ry, rz)
    return #(vector3(x,y,z) - vector3(rx,ry,rz))
end)

Can the final product be sold elsewhere? Don’t want to sell on the farm

1 Like

Really nice work

1 Like

Yeah sure, you can easily modify the clickmenu which is opening when you click the lootbox.
You need to just modify the event, to not basically sell the boxes, but give it to you as items.

Yeah these are Typescript functions, but you can delete the lines and simply add your inventory export function or triggerevent simply server-to-server to give the player the item(s).

This is how the functions are:

Clicking
        Object.interactionPress = (Player) =>
        {
            Player.OpenClickMenu({
                header: TSL.list.egg,
                buttons: [
                    {
                        event: 'sell-loot',
                        eventArgs: {
                            type: 'egg',
                            all: false
                        },
                        icon: 'fa-solid fa-dollar-sign',
                        name: TSL.list.menu_sell_one_box,
                        closeAfterClick: true,
                    },
                    {
                        event: 'sell-loot',
                        icon: 'fa-solid fa-sack-dollar',
                        eventArgs: {
                            type: 'egg',
                            all: true
                        },
                        name: TSL.list.menu_sell_all_box,
                        closeAfterClick: true
                    }
                ]
            });
        }
sell-loot event trigger, which is triggered by the clickmenu.
onNet('sell-loot', (d: { all: boolean, type: 'meal' | 'milk' | 'egg' }) =>
{
    const { all, type } = d;

    const Player = sdk.players.at(global.source);
    if (!Player) return;

    if (!Player.isPlayerInOwnedFarm())
        return Player.Notification(TSL.list.farm_player_not_owner);

    const farmLoots = sdk.loots.getFarmLoots(Player.dimension);
    if (!farmLoots) return;

    if (all)
    {
        let price: number;
        let msg: string;

        switch (type)
        {
            case "egg": {
                if (farmLoots.eggLoot < 1) return;

                // @ts-ignore
                const boxAmount = parseInt(farmLoots.eggLoot / LOOT_POSITIONS.EGG.boxPerAmount);
                if (boxAmount > 0)
                {
                    price = sdk.methods.ChanceSdk.integer(
                        {
                            min: SharedConfig.Loot.EggPricePerBox.min,
                            max: SharedConfig.Loot.EggPricePerBox.max
                        }
                    ) * boxAmount;
                    msg = TSL.format(TSL.list.eggs_sold_all_notification, [boxAmount, price]);
                    farmLoots.eggLoot = 0;
                }
                break;
            }
            case "meal": {
                if (farmLoots.mealLoot < 1) return;

                // @ts-ignore
                const boxAmount = parseInt(farmLoots.mealLoot / LOOT_POSITIONS.MEAL.boxPerAmount);
                if (boxAmount > 0)
                {
                    price = sdk.methods.ChanceSdk.integer(
                        {
                            min: SharedConfig.Loot.MealPricePerBox.min,
                            max: SharedConfig.Loot.MealPricePerBox.max
                        }
                    ) * boxAmount;
                    msg = TSL.format(TSL.list.meal_sold_all_notification, [boxAmount, price]);
                    farmLoots.mealLoot = 0;
                }
                break;
            }
            case "milk": {
                if (farmLoots.milkLoot < 1) return;

                // @ts-ignore
                const boxAmount = parseInt(farmLoots.milkLoot / LOOT_POSITIONS.MILK.boxPerAmount);
                if (boxAmount > 0)
                {
                    price = sdk.methods.ChanceSdk.integer(
                        {
                            min: SharedConfig.Loot.MilkPricePerBox.min,
                            max: SharedConfig.Loot.MilkPricePerBox.max
                        }
                    ) * boxAmount;
                    msg = TSL.format(TSL.list.milk_sold_all_notification, [boxAmount, price]);
                    farmLoots.milkLoot = 0;
                }
                break;
            }
        }

        if (typeof price === 'number' && price > 0)
        {
            Player.bank += price;
            Player.Notification(msg);
        }
    }
    else
    {
        let msg: string;

        switch (type)
        {
            case "egg": {
                if (farmLoots.eggLoot < 1) return;

                let price = sdk.methods.ChanceSdk.integer(
                    {
                        min: SharedConfig.Loot.EggPricePerBox.min,
                        max: SharedConfig.Loot.EggPricePerBox.max
                    }
                );
                Player.bank += price;
                msg = TSL.format(TSL.list.egg_sold_notification, [price]);
                farmLoots.eggLoot -= LOOT_POSITIONS.EGG.boxPerAmount;
                break;
            }
            case "meal": {
                if (farmLoots.mealLoot < 1) return;

                let price = sdk.methods.ChanceSdk.integer(
                    {
                        min: SharedConfig.Loot.MealPricePerBox.min,
                        max: SharedConfig.Loot.MealPricePerBox.max
                    }
                );
                Player.bank += price;
                msg = TSL.format(TSL.list.meal_sold_notification, [price]);
                farmLoots.mealLoot -= LOOT_POSITIONS.MEAL.boxPerAmount;
                break;
            }
            case "milk": {
                if (farmLoots.milkLoot < 1) return;

                let price = sdk.methods.ChanceSdk.integer(
                    {
                        min: SharedConfig.Loot.MilkPricePerBox.min,
                        max: SharedConfig.Loot.MilkPricePerBox.max
                    }
                );
                Player.bank += price;
                msg = TSL.format(TSL.list.milk_sold_notification, [price]);
                farmLoots.milkLoot -= LOOT_POSITIONS.MILK.boxPerAmount;
                break;
            }
        }

        Player.Notification(msg);
    }
});

all this is configurable? the days etc.?
Is it possible when he sells gives you items? It can?

1 Like

You just need to modify the clickmenu event, and remove the lines which are giving the money instantly.
I can help you with that if needed.

I like it now I see it, and we buy it

2 Likes

Very clean looking release :slight_smile: Nice job yet again !

1 Like

Sir please add some install instructions for ESX, I have been trying to figure this out and it has been extremely difficult. I wish I had known this before purchasing to be honest, I overestimated my skill I guess.

I have been working on a module which will help developers to setup the script more easily with frameworks.
Couple of days and it will be done, and you will just have to set the desired framework.

everyone can come into my camp and collect all the boars i lost all

They can collect, but can not sell the items at the end.