JRS COREالوثائق
مرجع الـ API

lib

JRS Lib مكتبة برمجة مقسّمة لـ RedM تسهّل تطوير اللعبة بمكوّنات قابلة لإعادة الاستخدام مبنية على النسخ مع تنظيف تلقائي. مصممة خصيصاً لفريمورك JRS Core، وتساعد المطورين يكتبون سكربتات أنظف وأكفأ وتمنع مشاكل شائعة مثل تسريب الذاكرة وتلويث المتغيرات العامة

Note

هذا التوثيق للمطورين اللي يسوون سكربتات لـ redm، وانتبه إن هذا شغل مستمر وأي شي ممكن يتغير في أي وقت لين الإصدار النهائي.

Warning

ما تقدر تستورد ملفات مشفّرة مثل escrow وغيرها، بس الملفات الغير مشفّرة تنستورد.

استخدام المكتبة

عشان تستورد موديولات لسكربتك لازم تضيف التالي لملف fxmanifest.lua حق السكربت

lua
   shared_script "@jrs_core/lib/import.lua"

استيراد الموديولات

Note

بس ملفات Lua تنستورد

قائمة الموديولات

الموديولات (كلاينت)#
entities (موديول)#

هذا الموديول فيه دوال تخليك تنشئ كيانات مثل الشخصيات والمركبات والأغراض وغيرها

blips (موديول)#

هذا الموديول فيه دوال تخليك تنشئ أنواع مختلفة من علامات الخريطة وأشياء تخص الخريطة

inputs (موديول)#

هذا الموديول فيه دوال تخليك تنشئ أزرار تحكم

raycast (موديول)#

هذا الموديول فيه دوال تخليك تسوي raycast من الكاميرا أو من كيان

prompts (موديول)#

هذا الموديول فيه دوال تخليك تنشئ prompts

commands (موديول) (كلاينت)#

هذا الموديول فيه دوال تخليك تسجّل أوامر

points (موديول)#

هذا الموديول فيه دوال تخليك تنشئ نقاط دخول/خروج مع خيارات تصحيح

polyzones (موديول)#

هذا الموديول فيه دوال تخليك تنشئ مناطق كشف مضلعة أو دائرية أو مربعة مع callbacks وأدوات تصحيح

events (موديول)#

هذا الموديول فيه دوال تخليك تسجّل أحداث اللعبة

dataview (موديول)#

هذا الموديول فيه دوال تخليك تستخدم dataview في lua

streaming (موديول)#

هذا الموديول فيه دوال تخليك تحمّل ملفات اللعبة مثل قواميس الأنيميشن والموديلات وغيرها

الموديولات (سيرفر)#
commands (موديول)#

هذا الموديول فيه دوال تخليك تسجّل أوامر للسيرفر مع خيارات صلاحيات وأكثر

الموديولات (مشتركة)#
class (موديول)#

هذا الموديول فيه دوال تخليك تنشئ كلاسات مع وراثة وأكثر

functions (موديول)#

هذا الموديول فيه دوال مثل switch و setInterval وغيرها

logger (موديول)#

هذا الموديول فيه دوال تخليك تنشئ سجلات منسّقة فيها الوقت والمستوى والبادئة وبيانات السياق

استيراد الموديولات

Import#
modulestringrequired

يخليك تستورد أي موديول من المكتبة، وتلقى قائمة الموديولات المتاحة هنا

lua
local module = Import "modulename" -- no symbols

local prompts = Import("prompts").Prompts -- every module has a table with the module name as the key for readability

local Lib = Import "prompts"
local Prompts = Lib.Prompts -- [[@as PROMPTS]] -- for intellisense
Import#
modulestringrequired

يخليك تستورد أي ملف من السكربت اللي أنت فيه، ولازم يبدأ دائماً بـ . أو / عشان توصل لمسار الملف

lua
local module = Import "/filename"
local module = Import "/folder/filename"
Import#
modulestringrequired

يخليك تستورد ملفات من سكربتات ثانية، ولازم يبدأ دائماً بـ @ وبعدها الرموز الخاصة / أو . عشان توصل لمسار الملف

lua
local module = Import "@script_name/filename"
local module = Import "@script_name/folder/filename"

طريقة الاستيراد

Single#
modulestringrequired

اسم الموديول المراد استيراده

lua
local module = Import "module"
Multiple#
modulearrayrequired

اسم الموديول المراد استيراده

lua
local module = Import ({"module", "module2", "module3"})
local prompts = module.Prompts
Mixed#
modulearrayrequired

أسماء الموديولات المراد استيرادها

lua
local module = Import ({"module", "/internal/filename", "@script_name/external/filename"})
local prompts = module.Prompts
local commands = module.Commands

استخدام الموديولات

الموديولات التالية متاحة في المكتبة، تقدر تستوردها بدالة Import، وتوثيق كل موديول موجود تحت

الكيانات

هذا الموديول ينستخدم لإنشاء كيانات مثل الشخصيات والمركبات والأغراض وغيرها، وفيه كلاس أساسي لكل الكيانات وكلاسات فرعية لكل نوع كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف الكيانات عشان يسهل التطوير

فيه متتبّع كيانات إذا تبي تتبع الكيانات من سكربتات ثانية (شوف ملف collector) للـ exports

Shared#

هذا الكلاس الأساسي للكلاسات الفرعية (الشخصيات، المركبات، الأغراض)، تقدر تستخدم الدوال تحت أو الـ natives مباشرة

GetHandle#
returnstring

جلب الـ handle للكيان، وهو معرّف فريد للكيان

GetModel#
returnstring

جلب موديل الكيان

GetPosition#
returnvector3

جلب موقع الكيان

GetHeading#
returnnumber

جلب اتجاه الكيان

GetRotation#
returnvector3

جلب دوران الكيان

GetNetId#
returnnumber

جلب الرقم الشبكي (network id) للكيان إذا انسوى بـ IsNetworked = true

SetPosition#
vectorvectorrequired

تقدر تستخدم vector3 أو vector4 عشان تضبط الاتجاه بس بتمرير جدول فيه w {w = 0.0}

Delete#
returnnil

حذف الكيان

Ped#
  • هذا الكلاس الفرعي ينستخدم لإنشاء شخصيات (يرث من الكلاس الأساسي Entity)، وهي كائنات مستقلة وكل إنشاء له نسخته الخاصة
  • تحت الدوال المتاحة لكلاس ped
Create#

إنشاء ped

Modelintegerrequired

موديل الـ ped

Posvector3required

موقع الـ ped

IsNetworkedboolean

إذا الـ ped شبكي

ScriptHostPedboolean

إذا الـ ped تابع لمستضيف السكربت

P7boolean

غير معروف

P8boolean

غير معروف

Optionstable

هذي معاملات اختيارية

PlaceOnGround = boolean, OutfitPreset = integer

OnCreatefunction

الدالة اللي تتشغّل لما ينسوى الـ ped

OnDeletefunction

الدالة اللي تتشغّل لما ينحذف الـ ped

lua
    -- Example
    -- Import the entities module
    local Entity = Import 'entities' --[[@as ENTITY]]

    local ped = Entity.Ped:Create({
        Model = 'A_C_COW',
        Pos = vector4(0, 0, 0, 0),
        IsNetworked = true,
        Options = {
            PlaceOnGround = true,
            OutfitPreset = 0,
        },
       
            print('Ped created use your own logic here, handle: ', self:GetHandle())
        end,

        netid)
            print('Ped deleted use your own logic here, handle: ', handle, 'netid: ', netid)
        end
    })
    -- methods you can use
   local handle = ped:GetHandle()
   ped:Delete()
Vehicle#
  • هذا الكلاس الفرعي ينستخدم لإنشاء مركبات (يرث من الكلاس الأساسي Entity)، وهي كائنات مستقلة وكل إنشاء له نسخته الخاصة
  • تحت الدوال المتاحة لكلاس المركبة
Create#
Modelstringrequired

موديل المركبة

Posvectorrequired

موقع المركبة

IsNetworkedboolean

إذا المركبة شبكية

ScriptHostVehboolean

إذا المركبة تابعة لمستضيف السكربت

DontAutoCreateDraftAnimalsboolean

ينشئ حيوانات الجر إذا true

P8boolean

غير معروف

Optionstable

PlaceOnGround, Seat = { Ped = ped, Index = -1}

OnCreatefunction

الدالة اللي تتشغّل لما تنسوى المركبة

OnDeletefunction

الدالة اللي تتشغّل لما تنحذف المركبة

lua
-- Example
-- Import the entities module
local Entity = Import 'entities' --[[@as ENTITY]]

local vehicle = Entity.Vehicle:Create({
    Model = 'wagon01x',
    Pos = vector4(0, 0, 0, 0),
    IsNetworked = true,
    Options = {
        PlaceOnGround = true,
        Seat = { -- optional
            Ped = ped, -- entity
            Index = -1, -- -1 for driver, 0 for passenger, 1 for passenger, 2 for passenger, etc
        }
    },
   
        print('Vehicle created use your own logic here, handle: ', self:GetHandle())
    end,

   
        print('Vehicle deleted use your own logic here, handle: ', self:GetHandle())
    end
})

local handle = vehicle:GetHandle()
vehicle:Delete()
Object#
  • هذا الكلاس الفرعي ينستخدم لإنشاء أغراض (يرث من الكلاس الأساسي Entity)، وهي كائنات مستقلة وكل إنشاء له نسخته الخاصة
  • تحت الدوال المتاحة لكلاس الغرض
Create#
Modelintegerrequired

موديل الغرض

Posvector3required

موقع الغرض

IsNetworkedboolean

إذا الغرض شبكي

ScriptHostObjboolean

إذا الغرض تابع لمستضيف السكربت

Dynamicboolean

إذا الغرض ديناميكي

Optionstable

PlaceOnGround = boolean, Rot = vector3,Rot.Order = integer, Rot.P5 = boolean

OnCreatefunction

الدالة اللي تتشغّل لما ينسوى الغرض

OnDeletefunction

الدالة اللي تتشغّل لما ينحذف الغرض

lua
-- Example
-- Import the entities module
local Entity = Import 'entities' --[[@as ENTITY]]

local object = Entity.Object:Create({
    Model = 'prop_paper_bag_01',
    Pos = vector4(0, 0, 0, 0),
    IsNetworked = true,
    Options = { -- optional
        PlaceOnGround = true,
        Rot = {
            Pos = vector3(0, 0, 0),
            Order = 2,
            P5 = true,
        }
    },

   
        print('Object created use your own logic here, handle: ', self:GetHandle())
    end,

   
        print('Object deleted use your own logic here, handle: ', self:GetHandle())
    end
})

local handle = object:GetHandle()
object:Delete()

الخريطة

موديول الخريطة ينستخدم حالياً لإنشاء علامات الخريطة، وراح يتوسع ويشمل ميزات خريطة أكثر لما تعيد تشغيل الريسورس تنحذف علامات الخريطة عشان يسهل التطوير

Blip#

هذا الكلاس الأساسي لعلامات الخريطة، تقدر تستخدم الدوال تحت أو الـ natives مباشرة

GetHandle#
returninteger

جلب handle لعلامة الخريطة

GetBlipColor#
colorstring|tablerequired

جلب color value's لألوان العلامة، ممكن يكون single color string أو table of color strings

returninteger

يرجع color value's المقابل لـ color name's

lua
    -- single string or multiple colors can be requested just for ease of use
    local blue, red, yellow = Map.Blips:GetBlipColor({ 'blue', 'red', 'yellow' })
    blip:AddModifierColor(blue) -- or string  "blue"
Remove#
returnnil

إزالة/حذف علامة الخريطة

SetName#
namestringrequired

تعيين اسم علامة الخريطة

SetCoords#
posvector3required

تعيين إحداثيات علامة الخريطة (pos.x, pos.y, pos.z)

SetStyle#
styleinteger|stringrequired

تعيين ستايل علامة الخريطة، شوف blip style

SetSprite#
spriteinteger|stringrequired

تعيين أيقونة علامة الخريطة. شوف blip sprite

AddModifier#
modifierinteger|stringrequired

إضافة modifier لعلامة الخريطة، شوف blip modifier

RemoveModifier#
modifierinteger|stringrequired

إزالة modifier من علامة الخريطة، شوف blip modifier

AddModifierColor#
colorstring|integerrequired

إضافة modifier لون لعلامة الخريطة، استخدم دالة GetBlipColor عشان تجيب قيم الألوان إذا احتجت

Create#

إنشاء علامة خريطة

BlipTypestringrequired

نوع العلامة: entity، coords، area، radius وكل نوع له معاملات خاصة

Blipinteger|stringrequired

أيقونة/hash العلامة، شوف blip sprite hash

Entityinteger

مطلوب لنوع 'entity' - الكيان اللي تنربط فيه العلامة

Posvector3

مطلوب لأنواع 'coords' و 'area' و 'radius' - موقع العلامة

Scalevector3

مطلوب لنوع 'area' - أبعاد الحجم (x, y, z)

Radiusnumber

مطلوب لنوع 'radius' - حجم النطاق (الافتراضي 0.5)

P7integer

معامل اختياري لنوع 'area' (الافتراضي 0)

Optionstable

معاملات اختيارية لشكل العلامة:

sprite = integer|string, name = string, style = integer|string, modifier = integer|string, color = string

OnCreatefunction

الدالة اللي تتشغّل لما تنسوى العلامة

lua
    -- Example
    -- Import the blips module
    local Map = Import 'blips' --[[@as BLIPS]]

    local blip = Map.Blips:Create('radius', { -- type can be entity, coords, area, radius
        Entity = ped, -- if type is entity, you need to provide a handle
        Pos = vector3(2865.88, 475.38, 66.09), -- position
        Radius = 50.0,                         -- if type is radius or area
        P7 = 0,                                -- optional default is 0
        Blip = 1673015813,                     -- blip hash the style of the blip
        Scale = vector3(1.0, 1.0, 1.0),        -- for type area only
        Options = {                            -- optional
            sprite = 1,                        --string or integer if type is entity or coords
            name = 'Test',
            modifier = 'BLIP_MODIFIER_MP_COLOR_1', -- int or string
            color = 'blue', -- internal color name
        },
       
            print('Created', self:GetHandle())
            local blue, red, yellow = self:GetBlipColor({ 'blue', 'red', 'yellow' })
            self:AddModifier(red)
        end
    })

    local handle = blip:GetHandle()
    blip:Remove()

المدخلات (Inputs)

هذا الموديول ينستخدم لإنشاء أزرار تحكم لريسورسك، وحدة أو أكثر، بدون ما تحتاج تسوي حلقات وكود كثير كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف المدخلات عشان يسهل التطوير

Input#

استخدم الدوال تحت لإدارة أزرار التحكم

Destroy#
returnnil

حذف نسخة المدخل وإيقاف كل المعالجة

RemoveKey#
keystringrequired

إزالة زر معيّن من مدخلات متعددة، أو إذا مدخل واحد يحذفه

Pause#
returnnil

إيقاف معالجة المدخل مؤقتاً بدون حذف النسخة

Resume#
returnnil

استئناف معالجة المدخل بعد إيقافه

Update#
datatablerequired

تحديث المعاملات المخصصة للمدخل إذا احتجت

keystring|integerrequired

مطلوب إذا تستخدم مدخلات متعددة - يحدد أي مدخل يتحدث

Start#
returnnil

بدء معالجة المدخل إذا ما كان شغّال، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته

Register#

تسجيل مدخل أو أكثر

inputTypestringrequired

نوع المدخل: Press، Hold، Release

keystring|integerrequired

الزر اللي ينراقب (مثلاً E، W) هذي أزرار معرّفة مسبقاً، وتقدر تستخدم أي hash أو نص controls

callbackfunctionrequired

دالة تتشغّل لما ينضغط المدخل - تستقبل (instance, customParams)

stateboolean

إذا true، المدخل يبدأ تلقائياً بعد التسجيل، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته

lua
    -- Example
    -- Import the inputs module
    local controls = Import 'inputs' --[[@as INPUTS]]

    -- Multiple input support
    local inputs = {
        { inputType = "Press",   key = "E" },
        { inputType = "Hold",    key = "W" },
        { inputType = "Release", key = "S" },
    }

    local input = controls.Inputs:Register(inputs,function(input, customParams)
        if input.key == "E" then
            print("E was pressed")
        elseif input.key == "W" then
            print("W is being held")
        elseif input.key == "S" then
            print("S was released")
        end
    end, true) -- auto start on register

    input:Destroy()

Raycast#

هذا الموديول ينستخدم لفحص خط الرؤية من كاميرا اللعب أو من كيان يقبل قيم vector3 أو جداول { x, y, z } للإحداثيات ويرجع جدول نتيجة منظم فيه بيانات الإصابة إذا الـ flag ناقص أو غلط، الموديول يرجع لـ World

Import#
lua
local Raycast = Import('raycast').Raycast --[[@as RAYCAST]]
Flags#

أسماء الـ flags المتاحة:

  • World
  • Vehicles
  • Peds
  • Ragdolls
  • Objects
  • Pickups
  • Glass
  • Rivers
  • Foliage
  • All
FromCamera#

إطلاق شعاع من كاميرا اللعب للأمام

distancenumber

مسافة الـ raycast، الافتراضي 10.0

flagsstring

اسم الـ flag لفحص الشكل، القيم الغلط أو الناقصة ترجع لـ World

ignoreEntityinteger

الكيان اللي يتجاهله، الافتراضي PlayerPedId()

options.offsetvector3 | table

إزاحة اختيارية تنضاف لإحداثيات الكاميرا

options.traceTypeinteger

نوع تتبّع فحص الشكل، الافتراضي 7

options.timeoutinteger

أقصى وقت انتظار للنتيجة بالملي ثانية، الافتراضي 1000

options.waitinteger

التأخير بين محاولات الفحص، الافتراضي 0

returnRAYCAST_RESULT

ترجع جدول نتيجة فيه hit وcoords وnormal وentity وmaterial وstate وdidHit وhandle

lua
local Raycast = Import('raycast').Raycast --[[@as RAYCAST]]

local result = Raycast:FromCamera(15.0, 'World')

if result.hit then
    print('Hit coords:', result.coords)
    print('Hit entity:', result.entity)
end
FromEntity#

إطلاق شعاع من كيان للأمام باستخدام اتجاهه الحالي

entityintegerrequired

الكيان اللي ينطلق منه الشعاع، ولازم يكون موجود

distancenumber

مسافة الـ raycast، الافتراضي 10.0

flagsstring

اسم الـ flag لفحص الشكل، القيم الغلط أو الناقصة ترجع لـ World

ignoreEntityinteger

الكيان اللي يتجاهله، الافتراضي نفس الكيان المعطى

options.offsetvector3 | table

إزاحة اختيارية تنضاف لإحداثيات الكيان قبل الإطلاق

options.traceTypeinteger

نوع تتبّع فحص الشكل، الافتراضي 7

options.timeoutinteger

أقصى وقت انتظار للنتيجة بالملي ثانية، الافتراضي 1000

options.waitinteger

التأخير بين محاولات الفحص، الافتراضي 0

returnRAYCAST_RESULT

ترجع جدول نتيجة فيه hit وcoords وnormal وentity وmaterial وstate وdidHit وhandle

lua
local Raycast = Import('raycast').Raycast --[[@as RAYCAST]]

local horse = GetMount(PlayerPedId())
if horse ~= 0 then
    local result = Raycast:FromEntity(horse, 8.0, 'Peds', horse)

    if result.hit then
        print('Entity raycast hit:', result.entity)
    end
end
RAYCAST_RESULT#

حقول النتيجة اللي ترجعها FromCamera و FromEntity

hitboolean

True لما الفحص يصيب شي

stateinteger

حالة فحص الشكل الأصلية

handleinteger

رقم فحص الشكل اللي يرجعه الـ native

didHitinteger

نتيجة الإصابة الخام من الـ native

coordsvector3

إحداثيات الإصابة

normalvector3

اتجاه السطح (normal)

entityinteger

الكيان المصاب، أو 0 إذا ما انصاب كيان

materialinteger

hash المادة اللي يرجعه GetShapeTestResultIncludingMaterial

الـ Prompts

هذا الموديول ينستخدم لإنشاء prompts تتفعّل حسب الإحداثيات، وتقدر تجمع أكثر من prompt وتديرها كوحدة وحدة كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف الـ prompts عشان يسهل التطوير

Prompt#

استخدم الدوال تحت لإدارة الـ prompts

GetHandle#
keystring|integerrequired

معرّف الـ prompt المحدد، وهو نفس اللي حطيته عند التسجيل

returninteger

جلب handle prompt معيّن بالمفتاح

GetPromptGroup#
keystring|integerrequired

معرّف الـ prompt المحدد، وهو نفس اللي حطيته عند التسجيل

returninteger

جلب رقم المجموعة لـ prompt معيّن

GetGroupLabel#
keystring|integerrequired

معرّف الـ prompt المحدد، وهو نفس اللي حطيته عند التسجيل

returnstring

جلب اسم المجموعة لـ prompt معيّن

IsRunning#
returnboolean

فحص إذا الـ prompt اللي سجّلته شغّال حالياً

SetLabel#
labelstringrequired

نص جديد للـ prompt

keystring|integerrequired

معرّف الـ prompt المراد تحديثه، وهو نفس اللي حطيته عند التسجيل

SetEnabled#
enabledbooleanrequired

هل الـ prompt مفعّل أو معطّل

keystring|integerrequired

معرّف الـ prompt المراد تحديثه، وهو نفس اللي حطيته عند التسجيل

SetVisible#
visiblebooleanrequired

هل الـ prompt ظاهر أو مخفي

keystring|integerrequired

معرّف الـ prompt المراد تحديثه، وهو نفس اللي حطيته عند التسجيل

SetMashMode#
mashCountintegerrequired

عدد مرات الضغط المتكرر المطلوبة

keystring|integerrequired

معرّف الـ prompt المراد تحديثه، وهو نفس اللي حطيته عند التسجيل

SetMashIndefinitelyMode#
keystring|integerrequired

معرّف الـ prompt اللي تحطه على وضع ضغط متكرر بلا حد، وهو نفس اللي حطيته عند التسجيل

Start#
returnnil

بدء نظام الـ prompts إذا ما كان شغّال، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته

Pause#
returnnil

إيقاف نظام الـ prompts مؤقتاً بدون حذفه

Resume#
returnnil

استئناف نظام الـ prompts بعد إيقافه

Remove#
keystringrequired

معرّف الـ prompt المراد إزالته إذا متعدد، وإذا واحد ينحذف

Destroy#
returnnil

حذف نظام الـ prompts بالكامل

Register#

تسجيل prompts

coordsvector3required

إحداثيات المركز اللي تكون فيها الـ prompts نشطة

distancenumber

نطاق التفعيل من الإحداثيات (الافتراضي 2.0)

labelstringrequired

اسم المجموعة اللي يظهر فوق مجموعة الـ prompts

sleepinteger

وقت الانتظار لما تكون برا النطاق (الافتراضي 700ms)

markertable

إعدادات marker اختيارية: type، color = {r,g,b,a}، distance، scale = {x,y,z} وتنفع للتصحيح كمان

promptsarrayrequired

مصفوفة prompts فيها: type، key، label، mode، ومعاملات خاصة بكل وضع

الأنواع: Press، Hold، Release، Standard، Pressed، Released، Mash

الأوضاع: Hold (holdTime)، Timed (timedMode)، Mash (mashCount)، Standard (releaseMode)، Standardized (eventHash)

callbackfunctionrequired

دالة تتشغّل لما ينضغط أي prompt - تستقبل (prompt, index, instance, value). value هو العنصر الحالي من جدول locations، عشان ما تحتاج تدوّر عليه مرة ثانية يدوياً.

stateboolean

إذا true، الـ prompts تبدأ تلقائياً بعد التسجيل (الافتراضي false)، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته

lua
    -- Example
    -- Import the prompts module
    local Game = Import 'prompts' --[[@as PROMPTS]]

    local data = {
        locations = {
            { -- index 1
                coords = vector3(2868.43, 480.19, 65.02), -- distance based prompts
                label = 'group label', -- group label
                distance = 2.0, -- distance from coords
                marker = { -- optional marker
                    type = 0x94FDAE17,
                    color = { r = 0, g = 255, b = 0, a = 96 },
                    distance = 4.0,
                    scale = { x = 2.0, y = 2.0, z = 0.5 },
                }
            }
        },
        sleep = 700, -- sleep time when not in range
        prompts = { -- group prompts or single prompt
            { type = 'Press', key = 'G', label = 'press', mode = 'Standard' },
            { type = 'Hold',  key = 'E', label = 'hold',  mode = 'Hold', holdTime = 3000 }
        }
    }

    local prompt = Game.Prompts:Register(data, function(prompt, index, self, location)
        -- location is the current entry from data.locations[index]
        if index == 1 and location.label == 'group label' then
            if prompt.key == 'G' then
                print('G pressed')
            elseif prompt.key == 'E' then
                print('E held for 3 seconds')
            end
        end
    end, true) -- auto start on register

    prompt:Destroy() -- the lib it self will destroy any prompt on script restart

الأوامر

هذا الموديول ينستخدم لتسجيل أوامر للكلاينت/السيرفر مع صلاحيات واقتراحات وفحص للمعاملات كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف الأوامر عشان يسهل التطوير، وإذا الأمر نشط والاقتراح ما انحدد يضاف عند التسجيل، راح ينضاف تلقائياً لما تنختار الشخصية

Command#

استخدم الدوال تحت لإدارة الأوامر

Remove#
returnnil

يحذف الأمر واقتراحه من الشات

AddSuggestion#
returnnil

يضيف اقتراح الأمر للشات

RemoveSuggestion#
returnnil

يحذف اقتراح الأمر من الشات

Pause#
returnnil

إيقاف الأمر مؤقتاً بدون حذفه (يعطّل الأمر مؤقتاً)

Resume#
returnnil

استئناف الأمر بعد إيقافه

Destroy#
returnnil

حذف نسخة الأمر بالكامل وتنظيفها

Start#
addSuggestionboolean

هل يضاف اقتراح الشات عند تسجيل الأمر، استخدمه وقت التشغيل بس، لأن الاقتراح افتراضياً ينضاف تلقائياً لما اللاعب يختار شخصيته

returnnil

بدء/تفعيل الأمر

OnExecute#
callbackfunctionrequired

تتشغّل لما يتنفذ الأمر

OnError#
callbackfunction

تتشغّل لما يكون في الأمر أخطاء

Register#

تسجيل أمر

namestringrequired

اسم الأمر (بدون /)

Suggestiontable

إعدادات اقتراح الشات مع Description ومصفوفة Arguments

Permissionstable

إعدادات الصلاحيات مع مجموعات Ace

OnExecutefunctionrequired

دالة تتشغّل لما يتنفذ الأمر - تستقبل (args, rawCommand, instance)

OnErrorfunction

دالة تتشغّل عند أخطاء الأمر - تستقبل نوع الخطأ كنص

stateboolean

إذا true، الأمر يبدأ تلقائياً بعد التسجيل، مفيد لما تحط state على false وتشغّله لما اللاعب يقرّب من شي أو يختار شخصيته

lua
    -- Example
    -- Import the commands module
    local Commands = Import 'commands' --[[@as COMMANDS]]

    local command = Commands.Command:Register("mycommand", {
        Suggestion = { -- optional
            Description = "My custom command description",
            Arguments = {
                -- if type is number or integer, it will be converted to a number
                -- if type is message, it will give it as a message
                { name = "playerId", help = "Target player ID", type = "integer", required = true },
                { name = "amount", help = "Amount value", type = "number", required = true },
                { name = "message", help = "Optional message", type = "message"}
            }
        },

        Permissions = { -- optional
            Ace = "group.admin" -- Restrict to admin group, or remove for public command
        },

        rawCommand, instance)
            print("Command executed with args:", json.encode(args))
            print("Player ID:", args[1]) -- integer type
            print("Amount:", args[2])     -- number type
            print("Message:", args[3])    -- message type (remaining args combined)
        end,

       
            if errorType == 'missing_arguments' then
                print('Usage: /mycommand <playerId> <amount> [message]')
            elseif errorType == 'missing_permission' then
                print('You do not have permission to use this command')
            elseif errorType == 'command_active' then
                print('Command is currently paused')
            end
        end
    }, true) -- Auto-start

    -- Control methods
    command:Start(true)       -- Start and add suggestion if not have been added yet
    command:Destroy()         -- Clean up completely

    -- Argument types:
    -- "integer" - converts to number (whole numbers)
    -- "number" - converts to number (decimals allowed)
    -- "message" - combines remaining arguments into string
    -- (no type) - keeps as string

    -- Error types:
    -- "missing_arguments" - Required argument not provided
    -- "missing_permission" - User lacks required permissions
    -- "command_active" - Command is paused
    -- "missing_target" - Target not found (if applicable)
Command#

استخدم الدوال تحت لإدارة أوامر السيرفر

Remove#
returnnil

حذف الأمر واقتراحه من كل اللاعبين وصلاحيات ACE

AddSuggestion#
targetintegerrequired

رقم اللاعب اللي ينرسل له الاقتراح

returnnil

إضافة اقتراح الأمر لشات لاعب معيّن

RemoveSuggestion#
targetintegerrequired

رقم اللاعب اللي ينحذف منه الاقتراح

returnnil

حذف اقتراح الأمر من شات لاعب معيّن

Pause#
returnnil

إيقاف الأمر مؤقتاً بدون حذفه (تعطيل مؤقت)

Resume#
returnnil

استئناف الأمر بعد إيقافه

Destroy#
returnnil

حذف نسخة الأمر بالكامل وتنظيفها

Start#
returnnil

بدء/تفعيل الأمر وتسجيل صلاحيات ACE إذا محددة

OnExecute#
callbackfunctionrequired

تعيين أو تحديث دالة الـ callback اللي تتشغّل لما يتنفذ الأمر

OnError#
callbackfunctionrequired

تعيين أو تحديث دالة الـ callback اللي تتشغّل لما يكون في الأمر أخطاء

Register#

تسجيل أمر للسيرفر

namestringrequired

اسم الأمر (بدون /)

Suggestiontable

إعدادات اقتراح الشات مع Description ومصفوفة Arguments

  • Description: وصف الأمر
  • Arguments: معاملات الأمر
  • name: اسم المعامل
  • help: شرح المعامل
  • type: نوع المعامل، إذا number أو integer يتحوّل لرقم، وإذا message ينعطى كرسالة
  • required: هل المعامل مطلوب
lua
    Suggestion = { -- optional
        Description = "Admin command with complex permissions",
        Arguments = {
            { name = "playerId", help = "Target player ID", type = "integer", required = true },
            { name = "amount", help = "Amount value", type = "number", required = true },
            { name = "message", help = "Optional message", type = "message" }
        }
    }
Permissionstable

إعدادات صلاحيات متقدمة مع Ace والوظايف والمجموعات و CharIds

  • Ace: صلاحية ACE (تتغلب على الباقي)، خلها false إذا ما تبي تستخدم صلاحيات ace
  • Groups: صلاحيات المجموعات مع قسم users (جدول المستخدمين) وقسم characters (جدول الشخصيات)
  • Jobs: صلاحيات حسب الوظيفة مع تقييد اختياري بالرتبة
  • CharIds: صلاحيات حسب أرقام شخصيات معيّنة
lua
Permissions = { -- optional
    Ace = "group.admin", -- ACE permission (overrides others) leave false if you dont want to use ace permissions
    Groups = { -- optional
        users = {
            admin = true,
            moderator = true
        },
        characters = {
            gang_leader = true
        }
    },

    Jobs = { -- optional
        Police = { -- jobname
            [0] = false,
            [1] = true
        },
        Sheriff = true -- All ranks allowed
    },

    CharIds = { -- optional
        [123] = true, -- Specific character ID
        [456] = true
    },
}
OnExecutefunctionrequired

دالة تتشغّل لما يتنفذ الأمر - تستقبل (source, args, rawCommand, instance)

OnErrorfunction

دالة تتشغّل عند أخطاء الأمر - تستقبل نوع الخطأ كنص

stateboolean

إذا true، الأمر يبدأ تلقائياً بعد التسجيل (الافتراضي false)

lua
    -- Example
    -- Import the server commands module
    local LIB = Import 'commands' --[[@as COMMANDS]]

    local command = LIB.Command:Register("commandName", {
        Suggestion = { -- optional
            Description = "Admin command with complex permissions",
            Arguments = {
                { name = "playerId", help = "Target player ID", type = "integer", required = true },
                { name = "amount", help = "Amount value", type = "number", required = true },
                { name = "message", help = "Optional message", type = "message" }
            }
        },

        Permissions = { -- optional
            Ace = "group.admin", -- ACE permission (overrides others) leave false if you dont want to use ace permissions

            Jobs = { -- optional
                Police = { -- jobname
                    [0] = false, -- Rank 0 not allowed
                    [1] = true,  -- Rank 1+ allowed
                },
                Sheriff = true -- All ranks allowed
            },

            Groups = { -- optional
                users = {
                    admin = true,
                    moderator = true
                },
                characters = {
                    gang_leader = true
                }
            },

            CharIds = { -- optional
                [123] = true, -- Specific character ID
                [456] = true
            }
        },

        args, rawCommand, instance)
            print("Command executed by source:", source)
            print("Player ID:", args[1]) -- player type (validated)
            print("Amount:", args[2])    -- number type
            print("Message:", args[3])   -- message type

        end,

       
            if errorType == 'missing_arguments' then
                print('Usage: /admincommand <playerId> <amount> [message]')
            elseif errorType == 'missing_permission' then
                print('You do not have permission to use this command')
            elseif errorType == 'missing_job' then
                print('You do not have the required job')
            elseif errorType == 'missing_grade' then
                print('You do not have the required job rank')
            elseif errorType == 'missing_group' then
                print('You do not have the required group')
            elseif errorType == 'missing_character' then
                print('Your character is not authorized')
            elseif errorType == 'missing_user' then
                print('User not found or console command not supported')
            elseif errorType == 'command_active' then
                print('Command is currently paused')
            end
        end
    }, true) -- Auto-start

    -- Control methods
    command:Destroy()                  -- Clean up completely

    -- Server-specific features:
    -- - Automatic ACE permission management
    -- - Complex job/grade validation
    -- - Character and user group permissions
    -- - Per-player suggestion management
    -- - Console command restriction (source = 0)

    -- Error types (additional server-side):
    -- "missing_user" - User not found or console command
    -- "missing_job" - Player doesn't have required job
    -- "missing_grade" - Player doesn't have required job rank
    -- "missing_group" - Player doesn't have required group
    -- "missing_character" - Character not authorized
    -- "missing_state" - State validation failed

    -- Permission priority:
    -- 1. ACE permissions (highest) all others will be ignored
    -- 2. Job permissions
    -- 3. Group permissions
    -- 4. Character ID permissions

النقاط

هذا الموديول ينستخدم لإنشاء مناطق دخول/خروج حسب الإحداثيات مع كشف النطاق، وتقدر تسجّل أكثر من نقطة وتديرها كل وحدة لحالها كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف النقاط عشان يسهل التطوير

Point#

استخدم الدوال تحت لإدارة النقاط

IsPointActive#
idstring|integerrequired

المعرّف الفريد للنقطة المراد فحصها

returnboolean

ترجع true إذا النقطة نشطة ومو معطّلة

IsPointInside#
idstring|integerrequired

المعرّف الفريد للنقطة المراد فحصها

returnboolean

ترجع true إذا اللاعب حالياً داخل نطاق النقطة

IsPointOutside#
idstring|integerrequired

المعرّف الفريد للنقطة المراد فحصها

returnboolean

ترجع true إذا اللاعب حالياً برا نطاق النقطة

UpdatePoint#
idstring|integerrequired

المعرّف الفريد للنقطة المراد تحديثها

datatablerequired

بيانات نقطة جديدة تستبدل إعدادات النقطة الحالية

RemovePoint#
idstring|integerrequired

المعرّف الفريد للنقطة المراد إزالتها

returnnil

يزيل النقطة المحددة من النسخة

PausePoint#
idstring|integerrequired

المعرّف الفريد للنقطة المراد إيقافها مؤقتاً

returnnil

يعطّل النقطة المحددة بدون ما يزيلها

ResumePoint#
idstring|integerrequired

المعرّف الفريد للنقطة المراد استئنافها

returnnil

يعيد تفعيل نقطة كانت موقفة

Start#
returnnil

بدء نظام النقاط إذا ما كان شغّال، ويبدأ يراقب موقع اللاعب

Pause#
returnnil

إيقاف نظام النقاط كامل مؤقتاً بدون حذفه

Resume#
returnnil

استئناف نظام النقاط بعد إيقافه

Destroy#
returnnil

حذف نسخة النقاط بالكامل وتنظيف كل النقاط

DebugPoints#
returnnil

تفعيل علامات التصحيح المرئية للنقاط اللي مفعّل فيها debug

Register#

تسجيل نقاط حسب الإحداثيات لكشف الدخول/الخروج

Argumentsarrayrequired

مصفوفة إعدادات النقاط، كل نقطة لازم يكون لها id فريد وإحداثيات مركز ونطاق

  • id: معرّف فريد للنقطة (نص/رقم)
  • center: إحداثيات مركز النقطة (vector3)
  • radius: نطاق الكشف حول المركز (رقم)
  • wait: فترة الفحص بالملي ثانية (اختياري، الافتراضي 500)
  • debug: تفعيل علامة تصحيح مرئية (اختياري، boolean)
  • deActivate: إذا true، النقطة تبدأ معطّلة ولازم تفعّلها يدوياً (اختياري، boolean)
lua
    -- supports multiple points
    Arguments = {
        {
            id = 'bank_entrance',
            center = vector3(2843.49, 474.49, 64.03),
            radius = 15.0,
            wait = 500,
            debug = true,
            deActivate = false,
        }
    }
OnEnterfunctionrequired

دالة تتشغّل لما يدخل اللاعب أي نقطة - تستقبل (point, distance)

OnExitfunctionrequired

دالة تتشغّل لما يطلع اللاعب من أي نقطة - تستقبل (point, distance)

stateboolean

إذا true، نظام النقاط يبدأ تلقائياً بعد التسجيل، وإلا استخدم دالة Start عشان تشغّله

lua
    -- Example
    -- Import the points module
    local GamePoints = Import 'points' --[[@as POINTS]]

    local points = GamePoints.Points:Register({
        Arguments = {
            {
                id = 'bank_entrance',                        -- unique identifier
                center = vector3(2843.49, 474.49, 64.03), -- center coordinates
                radius = 15.0,                             -- detection radius
                wait = 500,                                -- check interval (ms)
                debug = true,                              -- show debug marker
                deActivate = true,                        -- start active? remove to start active
            },
            {
                id = 'shop_door',
                center = vector3(2884.03, 484.19, 66.73),
                radius = 10.0,
                wait = 300,
                debug = true,
            },
        },

        distance)
            print("Entered point:", point.id, "Distance:", distance)
            if point.id == 'bank_entrance' then
                print("Welcome to the bank!")
            elseif point.id == 'shop_door' then
                print("Welcome to the shop!")
            end
        end,

        distance)
            print("Exited point:", point.id, "Distance:", distance)
            if point.id == 'bank_entrance' then
                print("Left the bank area")
            elseif point.id == 'shop_door' then
                print("Left the shop area")
            end
        end
    }, true) -- Auto-start

    -- Control methods
    points:PausePoint('shop_door')        -- Pause specific point
    points:ResumePoint('shop_door')       -- Resume specific point
    points:RemovePoint('bank_entrance')   -- Remove specific point

    -- Check point status
    local isActive = points:IsPointActive('shop_door')
    local isInside = points:IsPointInside('shop_door')
    local isOutside = points:IsPointOutside('shop_door')

    -- System control
    points:Pause()   -- Pause entire system
    points:Resume()  -- Resume entire system
    points:Destroy() -- Clean up completely

PolyZones#

هذا الموديول ينستخدم لإنشاء مناطق كشف بشكل مضلع أو دائرة أو مربع مع فلترة بالارتفاع، رسم للتصحيح، و callbacks للدخول/الوجود داخلها/الخروج كل شي تنشئه كائن مستقل: كل نسخة منطقة خاصة بالسكربت اللي استوردها وتنحذف تلقائياً لما يعيد الريسورس التشغيل

PolyZone#

استخدم الدوال تحت لتسجيل وإدارة أشكال المناطق المتقدمة

GetId#
returnstring|integer

ترجع المعرّف الفريد للمنطقة (يتولّد تلقائياً إذا ما انعطى)

GetType#
returnstring

ترجع نوع المنطقة poly أو circle أو box

IsRunning#
returnboolean

ترجع true لما تكون حلقة فحص المنطقة شغّالة حالياً

IsInside#
returnboolean

ترجع true إذا اللاعب المحلي حالياً داخل المنطقة

SetCallbacks#
cbEnterfunction

تستبدل الـ callback onEnter (تستقبل نسخة المنطقة وإحداثيات اللاعب)

cbExitfunction

تستبدل الـ callback onExit (تستقبل نسخة المنطقة وإحداثيات اللاعب)

cbInsidefunction

تستبدل الـ callback onInside اللي يتشغّل كل tick وأنت داخل المنطقة

UpdatePolygon#
pointsarray

تحدّث نقاط المضلع (قائمة vector3) وتعيد حساب الحدود، للمناطق المضلعة فقط

UpdateCircle#
centervector3

تحدّث موقع مركز الدائرة

radiusnumber

تحدّث نصف قطر الدائرة، للمناطق الدائرية فقط

UpdateBox#
centervector3

تحدّث موقع مركز المربع

lengthnumber

تحدّث طول المربع، للمناطق المربعة فقط

widthnumber

تحدّث عرض المربع، للمناطق المربعة فقط

headingnumber

اتجاه جديد اختياري بالدرجات للمنطقة المربعة

SetHeight#
minZnumber

تحدد أقل ارتفاع Z مسموح قبل ما تعتبر المنطقة اللاعب برّاها

maxZnumber

تحدد أعلى ارتفاع Z مسموح قبل ما تعتبر المنطقة اللاعب برّاها

SetDebug#
enabledboolean

تفعّل أو تعطّل رسم التصحيح (تبدأ حلقة التصحيح تلقائياً لما تكون المنطقة شغّالة)

SetTickRates#
outsideMsnumber

تحدد فترة الفحص بالملي ثانية وقت ما اللاعب برا المنطقة (الافتراضي 200)

insideMsnumber

تحدد فترة الفحص بالملي ثانية وقت ما اللاعب داخلها (الافتراضي 1)

Start#
returnnil

تبدأ الخيط الخلفي اللي يفحص المنطقة، وتشغّل رسم التصحيح تلقائياً إذا مفعّل

Pause#
returnnil

توقف المنطقة مؤقتاً بدون مسح الـ callbacks أو بيانات الشكل

Resume#
returnnil

تعيد تشغيل منطقة موقفة وترجع للكشف

Destroy#
returnnil

تعطّل المنطقة وتمسح إعداداتها (المفروض تتخلص من النسخة بعدها)

Register#

تسجيل مناطق مضلعة أو دائرية أو مربعة مع callbacks وتشغيل تلقائي اختياري

datatablerequired

جدول إعدادات المنطقة:

  • id: معرّف فريد اختياري نص أو رقم (polyzone_<timestamp> إذا ما انحط)
  • type: نوع المنطقة poly أو circle أو box (الافتراضي poly، ما يفرق بين الأحرف الكبيرة والصغيرة)
  • sleep: الفترة بالملي ثانية وقت ما تكون برا المنطقة (الافتراضي 200)
  • sleepInside: الفترة بالملي ثانية وقت ما تكون داخل المنطقة (الافتراضي 1)
  • padding: أمتار إضافية تنضاف لنصف قطر الحدود للرفض المبكر (الافتراضي 1.5)
  • debug: تفعيل رسم التصحيح للمنطقة (boolean)
  • minZ / maxZ: حدود ارتفاع اختيارية تقيّد الكشف
  • onEnter(zone, coords): callback يتشغّل لما يدخل اللاعب المنطقة
  • onInside(zone, coords): callback اختياري يتشغّل كل tick وقت ما اللاعب داخلها
  • onExit(zone, coords): callback يتشغّل لما يطلع اللاعب من المنطقة
  • المضلع: أعطِ points فيه 3 قيم vector3 على الأقل و center اختياري
  • الدائرة: أعطِ center vector3 و radius رقم (أو جدول size بنفس القيم)
  • المربع: أعطِ center vector3، و length و width أرقام، و heading اختياري (درجات) أو جدول size { x, y }
stateboolean

إذا true المنطقة تبدأ مباشرة بعد التسجيل (الافتراضي false، وإلا استدعِ Start() يدوياً)

returnPolyZone

ترجع نسخة المنطقة عشان تتحكم فيها بالدوال اللي فوق

lua
    local PolyZones = Import('polyzones').PolyZones

    local stables = PolyZones:Register({
        id = 'valentine_stables',
        type = 'poly',
        points = {
            vector3(-546.83, -600.65, 42.23),
            vector3(-548.62, -607.16, 42.32),
            vector3(-554.35, -605.86, 42.31),
            vector3(-552.20, -599.25, 42.27),
            vector3(-554.13, -594.14, 42.19),
        },
        minZ = 41.8,
        maxZ = 45.0,
        debug = true,
        coords)
            print(('Entered %s at %.2f %.2f'):format(zone:GetId(), coords.x, coords.y))
        end,
       
            print('Left zone', zone:GetId())
        end,
    }, true)
lua
    local PolyZones = Import('polyzones').PolyZones

    local campfire = PolyZones:Register({
        id = 'campfire_radius',
        type = 'circle',
        center = vector3(-567.97, -594.54, 42.51),
        radius = 2.5,
        debug = true,
        sleepInside = 250,
        coords)
            print(('Warming up at %.2f %.2f'):format(coords.x, coords.y))
        end,
       
            print('Leaving the fire')
        end,
    }, true)
lua
    local PolyZones = Import('polyzones').PolyZones

    local jailCell = PolyZones:Register({
        id = 'jail_cell_a',
        type = 'box',
        center = vector3(-565.68, -605.77, 42.31),
        length = 4.0,
        width = 3.0,
        heading = 90.0,
        minZ = 41.5,
        maxZ = 44.0,
    }, true)

    jailCell:SetDebug(true)
    jailCell:SetTickRates(100, 10)
Destroy#
instancePolyZone

نسخة المنطقة اللي ترجعها Register

returnnil

توقف المنطقة وتشيلها من المدير وتنظّفها

lua
    local PolyZones = Import('polyzones').PolyZones
    local zone = PolyZones:Register({
        id = 'temp_zone',
        type = 'circle',
        center = vector3(-100.0, 120.0, 40.0),
        radius = 3.0,
    }, true)

    PolyZones:Destroy(zone)

الأحداث (Events)

هذا الموديول ينستخدم لتسجيل مستمعي أحداث اللعبة اللي يلتقطون أحداث اللعبة الأصلية ويعالجونها مع تحليل تلقائي للبيانات كل شي تنشئه يكون كائن مستقل (instance): كل إنشاء له نسخته الخاصة وما يتشارك مع سكربتات ثانية لأنه مستورد داخل سكربتك لما تعيد تشغيل الريسورس تنحذف مستمعات الأحداث عشان يسهل التطوير

Event#

استخدم الدوال تحت لإدارة مستمعي الأحداث

Start#
returnnil

بدء مستمع الحدث ومراقبة الحدث المسجّل

Pause#
returnnil

إيقاف مستمع الحدث مؤقتاً بدون حذف النسخة

Resume#
returnnil

استئناف مستمع الحدث بعد إيقافه

Destroy#
returnnil

حذف نسخة مستمع الحدث وتنظيفها

DevMode#
enabledbooleanrequired

تفعيل أو تعطيل وضع المطوّر لتصحيح الأحداث

eventsToIgnorestring|array

أحداث اختيارية يتجاهلها في وضع المطوّر (اسم الحدث كنص أو hash)

returnnil

لما يكون مفعّل يسجّل كل الأحداث في المجموعة. استخدم eventsToIgnore عشان تفلتر الإزعاج.

lua
    -- Enable dev mode and ignore specific events
    event:DevMode(true, {"EVENT_PED_CREATED", "EVENT_PED_DESTROYED"})

    -- Enable dev mode for all events
    event:DevMode(true)

    -- Disable dev mode
    event:DevMode(false)
Register#

تسجيل مستمع لحدث في اللعبة

eventNamestring|integerrequired

اسم حدث اللعبة (نص) أو الـ hash (رقم) المراد الاستماع له

groupintegerrequired

مجموعة الأحداث المراقبة: 0 لـ SCRIPT_EVENT_QUEUE_AI أو 1 لـ SCRIPT_EVENT_QUEUE_NETWORK

  • SCRIPT_EVENT_QUEUE_AI (0): للأحداث المتعلقة بالذكاء الاصطناعي والـ NPC
  • SCRIPT_EVENT_QUEUE_NETWORK (1): للأحداث المتعلقة بالشبكة واللاعبين
callbackfunctionrequired

دالة تتشغّل لما يحصل الحدث - تستقبل بيانات الحدث بعد التحليل أو ولا شي إذا الحدث ما فيه بيانات

stateboolean

إذا true، مستمع الحدث يبدأ تلقائياً بعد التسجيل، وإلا استخدم دالة Start

lua
    -- Example
    -- Import the events module
    local Game = Import 'events' --[[@as EVENTS]]

    -- Register event with automatic data parsing
    local event = Game.Events:Register('EVENT_PED_CREATED', 0, function(data)
        print("Ped created with data:", json.encode(data, {indent = true}))
    end, true) -- Auto-start

    -- Developer mode for debugging, dont fire this events when in dev mode
    event:DevMode(true, {"EVENT_PED_CREATED","EVENT_VEHICLE_CREATED"}) -- Enable dev mode, ignore these events
    -- dev mode enables all events to be triggered

    -- Clean up
    event:Destroy()

DataView#

هذا الموديول يعطي وظائف DataView مثل JavaScript للتعامل مع البيانات الثنائية في Lua مع دعم أنواع بيانات مختلفة وترتيب البايتات هذا الموديول مبني على تطبيق DataView من gottfriedleibniz ويعطي تعامل فعّال مع البيانات الثنائية

DataView#

استخدم الدوال تحت لإدارة البيانات الثنائية

Buffer#
returnstring

جلب الـ buffer الثنائي كنص

ByteLength#
returninteger

جلب طول الـ buffer بالبايت

ByteOffset#
returninteger

جلب موقع الإزاحة الحالي داخل الـ buffer

دوال قراءة أنواع البيانات#

دوال القراءة المتاحة لقراءة أنواع بيانات مختلفة:

  • GetInt8(offset, endian) - قراءة عدد صحيح 8-بت بإشارة
  • GetUint8(offset, endian) - قراءة عدد صحيح 8-بت بدون إشارة
  • GetInt16(offset, endian) - قراءة عدد صحيح 16-بت بإشارة
  • GetUint16(offset, endian) - قراءة عدد صحيح 16-بت بدون إشارة
  • GetInt32(offset, endian) - قراءة عدد صحيح 32-بت بإشارة
  • GetUint32(offset, endian) - قراءة عدد صحيح 32-بت بدون إشارة
  • GetInt64(offset, endian) - قراءة عدد صحيح 64-بت بإشارة
  • GetUint64(offset, endian) - قراءة عدد صحيح 64-بت بدون إشارة
  • GetFloat32(offset, endian) - قراءة عدد عشري 32-بت
  • GetFloat64(offset, endian) - قراءة عدد double 64-بت
  • GetString(offset, endian) - قراءة نص ينتهي بـ null
  • GetLuaInt(offset, endian) - قراءة عدد صحيح Lua
  • GetLuaNum(offset, endian) - قراءة رقم Lua
offsetintegerrequired

إزاحة البايت من بداية الـ buffer للقراءة منها

endianboolean

ترتيب البايتات: true لـ big-endian، و false/nil لـ little-endian

returnnumber|string|nil

القيمة المقروءة، أو nil إذا الإزاحة برا الحدود

دوال قراءة بحجم ثابت#
  • GetFixedString(offset, length, endian) - قراءة نص بطول ثابت
  • GetFixedInt(offset, length, endian) - قراءة عدد صحيح بإشارة بحجم ثابت
  • GetFixedUint(offset, length, endian) - قراءة عدد صحيح بدون إشارة بحجم ثابت
offsetintegerrequired

إزاحة البايت من بداية الـ buffer

lengthintegerrequired

عدد البايتات المراد قراءتها

endianboolean

ترتيب البايتات: true لـ big-endian، و false/nil لـ little-endian

SubView#
offsetintegerrequired

إزاحة البايت اللي ينسوى منها العرض الفرعي

returnDataView

إنشاء DataView جديد يشارك نفس الـ buffer بس بإزاحة مختلفة

دوال كتابة أنواع البيانات#

دوال الكتابة المتاحة لكتابة أنواع بيانات مختلفة:

  • SetInt8(offset, value, endian) - كتابة عدد صحيح 8-بت بإشارة
  • SetUint8(offset, value, endian) - كتابة عدد صحيح 8-بت بدون إشارة
  • SetInt16(offset, value, endian) - كتابة عدد صحيح 16-بت بإشارة
  • SetUint16(offset, value, endian) - كتابة عدد صحيح 16-بت بدون إشارة
  • SetInt32(offset, value, endian) - كتابة عدد صحيح 32-بت بإشارة
  • SetUint32(offset, value, endian) - كتابة عدد صحيح 32-بت بدون إشارة
  • SetInt64(offset, value, endian) - كتابة عدد صحيح 64-بت بإشارة
  • SetUint64(offset, value, endian) - كتابة عدد صحيح 64-بت بدون إشارة
  • SetFloat32(offset, value, endian) - كتابة عدد عشري 32-بت
  • SetFloat64(offset, value, endian) - كتابة عدد double 64-بت
  • SetString(offset, value, endian) - كتابة نص ينتهي بـ null
  • SetLuaInt(offset, value, endian) - كتابة عدد صحيح Lua
  • SetLuaNum(offset, value, endian) - كتابة رقم Lua
offsetintegerrequired

إزاحة البايت من بداية الـ buffer للكتابة فيها

valuenumber|stringrequired

القيمة المراد كتابتها

endianboolean

ترتيب البايتات: true لـ big-endian، و false/nil لـ little-endian

returnDataView

ترجع نفسها عشان تقدر تسلسل الدوال

دوال كتابة بحجم ثابت#
  • SetFixedString(offset, length, value, endian) - كتابة نص بطول ثابت
  • SetFixedInt(offset, length, value, endian) - كتابة عدد صحيح بإشارة بحجم ثابت
  • SetFixedUint(offset, length, value, endian) - كتابة عدد صحيح بدون إشارة بحجم ثابت
offsetintegerrequired

إزاحة البايت من بداية الـ buffer

lengthintegerrequired

عدد البايتات لنوع البيانات

valuenumber|stringrequired

القيمة المراد كتابتها

endianboolean

ترتيب البايتات: true لـ big-endian، و false/nil لـ little-endian

ArrayBuffer#

إنشاء buffer ثنائي جديد

lengthintegerrequired

حجم الـ buffer المراد حجزه بالبايت

returnDataView

ترجع نسخة DataView جديدة مع buffer محجوز

lua
    -- Import the dataview module
    local Data = Import 'dataview' --[[@as DATAVIEW]]

    -- Create a 64-byte buffer
    local buffer = Data.DataView.ArrayBuffer(64)

    -- Write different data types
    buffer:SetInt32(0, 42)           -- Write integer at offset 0
    buffer:SetFloat32(4, 3.14159)    -- Write float at offset 4
    buffer:SetString(8, "Hello")     -- Write string at offset 8

    -- Read the data back
    local intValue = buffer:GetInt32(0)       -- 42
    local floatValue = buffer:GetFloat32(4)   -- 3.14159
    local stringValue = buffer:GetString(8)   -- "Hello"

    print("Buffer length:", buffer:ByteLength()) -- 64
    print("Values:", intValue, floatValue, stringValue)
Wrap#

تغليف بيانات ثنائية موجودة

binaryDatastringrequired

نص البيانات الثنائية الموجودة المراد تغليفه

returnDataView

ترجع نسخة DataView تغلّف البيانات الموجودة

lua
    -- Wrap existing binary data
    local existingData = string.pack("i4f", 100, 2.718)
    local wrappedView = Data.DataView.Wrap(existingData)

    -- Read from wrapped data
    local intVal = wrappedView:GetInt32(0)    -- 100
    local floatVal = wrappedView:GetFloat32(4) -- 2.718
DataStream#

إنشاء قارئ بيانات متسلسل

dataViewDataViewrequired

نسخة DataView اللي ينسوى منها الـ stream

returnDataStream

ترجع DataStream للقراءة المتسلسلة

دوال DataStream المتاحة (تقدّم الإزاحة تلقائياً):

  • Int8(endian, align), Uint8(endian, align)
  • Int16(endian, align), Uint16(endian, align)
  • Int32(endian, align), Uint32(endian, align)
  • Int64(endian, align), Uint64(endian, align)
  • Float32(endian, align), Float64(endian, align)
  • String(endian, align), LuaInt(endian, align), LuaNum(endian, align)
lua
    -- Create buffer with mixed data
    local buffer = Data.DataView.ArrayBuffer(32)
    buffer:SetInt32(0, 123)
    buffer:SetFloat32(4, 4.56)
    buffer:SetInt16(8, 789)

    -- Create stream for sequential reading
    local stream = Data.DataView.DataStream.New(buffer)

    -- Read sequentially (offset advances automatically)
    local int1 = stream:Int32()    -- 123, offset now at 4
    local float1 = stream:Float32() -- 4.56, offset now at 8
    local int2 = stream:Int16()    -- 789, offset now at 10

    print("Sequential read:", int1, float1, int2)

التحميل (Streaming)

هذا الموديول يعطي دوال مساعدة لتحميل ملفات اللعبة مثل الموديلات والأنيميشنات والتكستشر وغيرها مع تنظيف تلقائي ومعالجة المهلة كل الدوال تتعامل مع عملية التحميل مع فحص صحيح ومعالجة أخطاء، وتمنع المشاكل الشائعة في تحميل الملفات

تحميل الملفات#

استخدم الدوال تحت لتحميل ملفات اللعبة مع تنظيف تلقائي

LoadModel#
modelstring|integerrequired

اسم الموديل (نص) أو الـ hash (رقم) المراد تحميله

timeoutinteger

مهلة اختيارية بالملي ثانية عشان يفك تحميل الموديل تلقائياً ويحرر الذاكرة

returnnil

يحمّل الموديل ويفحصه، ويرمي خطأ إذا كان غلط أو فشل التحميل خلال 5 ثواني

LoadTextureDict#
dictstringrequired

اسم قاموس التكستشر المراد تحميله

timeoutinteger

مهلة اختيارية بالملي ثانية عشان يفك تحميل قاموس التكستشر تلقائياً

returnnil

يحمّل قاموس التكستشر مع فحص ومعالجة أخطاء

LoadParticleFx#
dictstringrequired

اسم قاموس المؤثرات (particles) المراد تحميله

timeoutinteger

مهلة اختيارية بالملي ثانية عشان يشيل ملف المؤثرات تلقائياً

returnnil

يحمّل قاموس المؤثرات عشان تستخدمه مع أنظمة الـ particles

LoadAnimDict#
dictstringrequired

اسم قاموس الأنيميشن المراد تحميله

timeoutinteger

مهلة اختيارية بالملي ثانية عشان يشيل قاموس الأنيميشن تلقائياً

returnnil

يحمّل قاموس الأنيميشن مع فحص وجوده

LoadWeaponAsset#
weaponstring|integerrequired

اسم السلاح (نص) أو الـ hash (رقم) المراد تحميله

p1integerrequired

معامل غير معروف (غالباً 31)

p2booleanrequired

معامل غير معروف (غالباً false)

timeoutinteger

مهلة اختيارية بالملي ثانية عشان يشيل ملف السلاح تلقائياً

returnnil

يحمّل ملف السلاح مع فحص

LoadMoveNetworkDef#
netDefstringrequired

اسم تعريف move network المراد تحميله

timeoutinteger

مهلة اختيارية بالملي ثانية عشان يشيل تعريف الـ network تلقائياً

returnnil

يحمّل تعريف move network لأنظمة الحركة المتقدمة

LoadClipSet#
clipSetstringrequired

اسم مجموعة الـ clips المراد تحميلها

timeoutinteger

مهلة اختيارية بالملي ثانية عشان يشيل مجموعة الـ clips تلقائياً

returnnil

يحمّل مجموعة clips للأنيميشن لطرق مشي الشخصيات

RequestCollisionAtCoord#
coordsvector3required

الإحداثيات اللي ينحمّل فيها التصادم

returnnil

يحمّل بيانات تصادم الأرض عند الإحداثيات المحددة

RequestCollisionForModel#
modelstring|integerrequired

اسم الموديل أو الـ hash اللي ينحمّل له التصادم

returnnil

يحمّل بيانات التصادم لموديل معيّن

RequestIpl#
iplstring|integerrequired

اسم IPL (Interior Proxy List) أو الـ hash المراد تحميله

returnnil

يحمّل IPL للداخليات أو أجزاء الخريطة، ويحذّر إذا كان محمّل من قبل

LoadScene#
posvector3required

الموقع اللي ينحمّل المشهد حوله

offsetvector3required

الإزاحة من الموقع

radiusnumberrequired

النطاق اللي ينحمّل داخله المشهد

p7integerrequired

معامل غير معروف (غالباً 0)

returnnil

يحمّل منطقة العالم حول الكيان - استخدمه بحذر لأنه ممكن يسبب كراش مع كثرة الـ MLOs

Import#

استيراد موديول streaming

       
lua
    -- Import the streaming module
    local Assets = Import 'streaming' --[[@as STREAMING]]

    -- Use any function
    Assets.Streaming.LoadModel('A_C_BEAR_01')
    Assets.Streaming.LoadAnimDict('amb@world_human_drinking@coffee@male@idle_a')

الكلاس

هذا الموديول يعطي نظام برمجة كائنية كامل لـ Lua مع كلاسات ووراثة وأعضاء خاصة ودوال قراءة/تعديل تلقائية يدعم أنماط OOP التقليدية في Lua والطرق المنظمة الحديثة مع إدارة تلقائية للخصائص مستوحى من كلاسات JavaScript

نظام OOP#

استخدم الدوال تحت لإنشاء كلاسات بدعم OOP كامل

Create#
basetable|class

الكلاس الأساسي اللي يورث منه، أو جدول بالدوال/الخصائص الأولية

classNamestring

اسم اختياري للكلاس (ينستخدم في رسائل الخطأ)

returnclass

يرجع كلاس جديد يقدر ينشئ نسخ بـ :New()

lua
    -- Import the class module
    local Lib = Import 'class' --[[@as CLASS]]

    -- Create a basic class
    local MyClass = Lib.Class:Create({
        constructor = function(self, name)
            self.name = name
        end,

        getName = function(self)
            return self.name
        end
    }, "MyClass")

    -- Create instance
    local instance = MyClass:New("Test")
    print(instance:getName()) -- "Test"
  • مثال بأسلوب Lua التقليدي
lua
 local MyClass = Lib.Class:Create({},"MyClass")

 function MyClass:constructor(name)
    self.name = name
 end

 function MyClass:getName()
    return self.name
 end

 local instance = MyClass:New("Test")
 print(instance:getName()) -- "Test"
New#
...any

المعاملات اللي تنرسل للـ constructor

returninstance

يرجع نسخة جديدة من الكلاس

ينشئ نسخ جديدة من الكلاس. يدعم constructors بالجدول أو بالمعاملات.

lua
    -- Table-based constructor
    local instance1 = MyClass:New({
        name = "John",
        age = 30
    })

    -- Argument-based constructor
    local instance2 = MyClass:New("John", 30)
وراثة الكلاسات#

الكلاسات تقدر ترث من كلاسات ثانية وتحصل على كل دوال وخصائص الكلاس الأب.

lua
    -- Base class
    local Entity = Lib.Class:Create({
        constructor = function(self, id)
            self.id = id
            self.created = os.time()
        end,

        getId = function(self)
            return self.id
        end,

        getInfo = function(self)
            return "Entity " .. self.id
        end
    }, "Entity")

    -- Inherited class
    local Ped = Lib.Class:Create(Entity, "Ped")

    function Ped:constructor(id, model)
        self:super(id) -- Call parent constructor
        self.model = model
    end

    function Ped:getInfo()
        return "Ped " .. self.id .. " (" .. self.model .. ")"
    end

    -- Usage
    local ped = Ped:New(123, "A_M_M_FARMER_01")
    print(ped:getInfo()) -- "Ped 123 (A_M_M_FARMER_01)"
    print(ped:getId())   -- 123 (inherited method)
super#
...any

المعاملات اللي تنرسل لـ constructor الأب

returnnil

يستدعي constructor الكلاس الأب

ينستخدم داخل الـ constructor عشان يستدعي constructor الكلاس الأب.

lua
    local Ped = Lib.Class:Create(Entity, "Ped")
    function Ped:constructor(id, model)
        self:super(id) -- Call parent constructor
        self.model = model
    end
خصائص تلقائية#

عرّف دوال قراءة وتعديل تلقائية للخصائص باستخدام جداول get و set.

lua
    local Person = Lib.Class:Create({
        constructor = function(self, name, age)
            self.name = name
            self.age = age
        end,
        -- can be used to organize your code as well just like JS classes
        get = {
            name = function(self)
                return self.name:upper() -- Always return uppercase
            end,

            age = function(self)
                return self.age
            end,

            isAdult = function(self)
                return self.age >= 18
            end
        },
        -- can be used to organize your code as well just like JS classes
        set = {
            name = function(self, value)
                if type(value) ~= "string" then
                    error("Name must be a string")
                end
                self.name = value
            end,

            age = function(self, value)
                if type(value) ~= "number" or value < 0 then
                    error("Age must be a positive number")
                end
                self.age = value
            end
        }
    })

    local person = Person:New("john", 25)

    -- Using getters
    print(person.name)    -- "JOHN" (automatic uppercase)
    print(person.isAdult) -- true

    -- Using setters
    person.name = "jane"  -- Validates and stores
    person.age = 30       -- Validates and stores
الخصائص والدوال الخاصة#

الأعضاء اللي تبدأ بشرطة سفلية _ خاصة وما تنوصل إلا من داخل نفس الكلاس.

lua
    local BankAccount = Lib.Class:Create({
        constructor = function(self, accountNumber, initialBalance)
            self._accountNumber = accountNumber  -- Private
            self._balance = initialBalance       -- Private
            self.accountType = "Checking"        -- Public
        end,

        -- Public method that accesses private members
        getBalance = function(self)
            self:_validateAccess() -- Private method call
            return self._balance
        end,

        deposit = function(self, amount)
            if amount > 0 then
                self._balance = self._balance + amount
                return true
            end
            return false
        end,

        -- Private method
        _validateAccess = function(self)
            print("Validating access to account " .. self._accountNumber)
        end,

        -- Private method
        _calculateInterest = function(self)
            return self._balance * 0.01
        end
    }, "BankAccount")

    local account = BankAccount:New("12345", 1000)

    -- ✅ Public access
    print(account:getBalance()) -- 1000
    account:deposit(500)

    -- ❌ Private access will error
    -- print(account._balance)      -- ERROR
    -- account:_validateAccess()    -- ERROR
الوراثة والخصوصية#

الأعضاء الخاصة خاصة بالكلاس وما تقدر الكلاسات الفرعية توصل لها.

lua
    local Vehicle = Lib.Class:Create({
        constructor = function(self, model)
            self._engine = "V8"     -- Private to Vehicle
            self.model = model      -- Public
        end,

        getEngineInfo = function(self)
            return "Engine: " .. self._engine -- ✅ Same class access
        end,

        _startEngine = function(self)
            print("Starting " .. self._engine .. " engine")
        end
    })

    local Car = Lib.Class:Create(Vehicle, "Car")

    function Car:constructor(model, doors)
        self:super(model)
        self.doors = doors
        -- self._engine = "Modified"  -- ❌ Would error - can't access parent private
    end

    function Car:tryAccessPrivate()
        -- ❌ Cannot access parent's private members
        -- local engine = self._engine     -- ERROR
        -- self:_startEngine()             -- ERROR
        print("Cannot access parent private members")
    end

    local car = Car:New("Mustang", 2)
    print(car:getEngineInfo()) -- ✅ "Engine: V8" (via public method)
    car:tryAccessPrivate()     -- Shows privacy enforcement
مثال كامل#

مثال شامل لنظام الكلاسات

       
lua
    -- Import the class module
    local Lib = Import 'class' --[[@as CLASS]]

    -- Base Entity class
    local Entity = Lib.Class:Create({
        constructor = function(self, data)
            self._id = data.id or 0           -- Private ID
            self._position = data.pos or vector3(0,0,0)  -- Private position
            self.name = data.name or "Entity" -- Public name
            self._created = os.time()         -- Private creation time
        end,

        -- Public methods
        getId = function(self)
            return self._id
        end,

        getPosition = function(self)
            return self._position
        end,

        setPosition = function(self, pos)
            self._position = pos
            self:_onPositionChanged() -- Private method call
        end,

        getAge = function(self)
            return os.time() - self._created
        end,

        -- Private methods
        _onPositionChanged = function(self)
            print("Entity " .. self._id .. " moved to " .. tostring(self._position))
        end,

        -- Automatic getters/setters
        get = {
            displayName = function(self)
                return self.name .. " (#" .. self._id .. ")"
            end
        },

        set = {
            name = function(self, value)
                if type(value) ~= "string" or #value == 0 then
                    error("Name must be a non-empty string")
                end
                self.name = value
            end
        }
    }, "Entity")

    -- Ped class inheriting from Entity
    local Ped = Lib.Class:Create(Entity, "Ped")

    function Ped:constructor(data)
        self:super(data) -- Call parent constructor
        self._model = data.model or "A_M_M_FARMER_01"  -- Private model
        self._health = data.health or 100              -- Private health
        self.faction = data.faction or "Civilian"      -- Public faction
    end

    function Ped:spawn()
        local pos = self:getPosition()
        local handle = CreatePed(joaat(self._model), pos.x, pos.y, pos.z, 0.0, true, false, false, false)
        self._handle = handle
        print("Spawned " .. self.displayName .. " at " .. tostring(pos))
        return handle
    end

    function Ped:damage(amount)
        self._health = math.max(0, self._health - amount)
        if self._health <= 0 then
            self:_onDeath()
        end
    end

    -- Private method
    function Ped:_onDeath()
        print(self.displayName .. " has died")
        if self._handle then
            DeletePed(self._handle)
        end
    end

    -- Getters for private properties
    Ped.get.health = function(self)
        return self._health
    end

    Ped.get.model = function(self)
        return self._model
    end

    -- Usage
    local ped = Ped:New({
        id = 123,
        name = "John Marston",
        pos = vector3(100, 200, 300),
        model = "CS_JOHNMARSTON",
        health = 150,
        faction = "Van der Linde Gang"
    })

    -- Public interface
    print(ped.displayName)           -- "John Marston (#123)"
    print("Health:", ped.health)     -- 150 (via getter)
    print("Age:", ped:getAge(), "seconds old")

    ped:setPosition(vector3(150, 250, 350))
    ped:spawn()
    ped:damage(50)
    print("Health after damage:", ped.health) -- 100

    -- Validation works
    ped.name = "Arthur Morgan" -- ✅ Valid
    -- ped.name = ""           -- ❌ Would error

    -- Privacy enforced
    -- print(ped._health)      -- ❌ Would error
    -- ped:_onDeath()          -- ❌ Would error
أسلوب Lua التقليدي#

باستخدام صيغة دوال lua التقليدية

       
lua
    local Lib = Import 'class' --[[@as CLASS]]

    -- Create class with traditional Lua methods
    local Timer = Lib.Class:Create({},"Timer")

    function Timer:constructor(name, duration)
        self.name = name or "Timer"
        self._startTime = nil
        self._duration = duration or 5000
        self._isRunning = false
    end

    function Timer:start()
        self._startTime = GetGameTimer()
        self._isRunning = true
        print(self.name .. " started for " .. self._duration .. "ms")
    end

    function Timer:stop()
        self._isRunning = false
        print(self.name .. " stopped")
    end

    function Timer:isExpired()
        if not self._isRunning or not self._startTime then
            return false
        end
        return (GetGameTimer() - self._startTime) >= self._duration
    end

    function Timer:getTimeLeft()
        if not self._isRunning or not self._startTime then
            return 0
        end
        local elapsed = GetGameTimer() - self._startTime
        return math.max(0, self._duration - elapsed)
    end

    -- Usage
    local timer = Timer:New("Countdown", 10000)
    timer:start()

    -- Check in a loop or thread
    CreateThread(function()
        while not timer:isExpired() do
            print("Time left:", timer:getTimeLeft() .. "ms")
            Wait(1000)
        end
        print("Timer expired!")
        timer:stop()
    end)

الدوال

كلاسات مساعدة للتحكم بسير الكود والتوقيت والتنفيذ المشروط يعطي أنماط Switch-case وفترات متكررة ومهلات لمرة وحدة مع تحكم كامل بحالة التنفيذ مشترك بين بيئة السيرفر والكلاينت

Switch#

استخدم هذي الأدوات للتحكم المتقدم بسير الكود والتوقيت

valueany

القيمة اللي تتقارن مع الحالات

ينشئ هيكل switch-case يخليك تسلسل الحالات مع حالة افتراضية، مستوحى من JS

lua
     -- Import the functions module
     local Lib = Import 'functions' --[[@as FUNCTIONS]]

     -- Basic switch usage
     local result = Lib.Switch(playerLevel)
        :case(1, function(value)
            return "Beginner"
        end)
         :case(2, function(value)
            return "Intermediate"
        end)
         :case(3, function(value)
            return "Advanced"
        end)
         :default(function(value)
            return "Unknown Level: " .. value
        end)
        :execute()

    print(result)
SetInterval#
callbackfunctionrequired

الدالة اللي تتنفذ بشكل متكرر

delayintegerrequired

التأخير بين كل تنفيذ بالملي ثانية

customArgstable

المعاملات اللي تنرسل لدالة الـ callback

startboolean

هل تبدأ الفترة مباشرة

returnIntervalrequired

يرجع نسخة Interval عشان تتحكم فيها

ينشئ فترة متكررة تنفّذ دالة كل مدة محددة

lua
    -- Import the functions module
    local Lib = Import 'functions' --[[@as FUNCTIONS]]

    -- Create an interval that runs every 5 seconds
    local healthCheck = Lib.SetInterval(function(self, playerId)
        local player = GetPlayerPed(playerId)
        if player and DoesEntityExist(player) then
            local health = GetEntityHealth(player)
            print("Player " .. playerId .. " health: " .. health)
            self:Destroy() -- destroy the interval
        end
    end, 5000,{GetPlayerServerId(PlayerId())}, true)
GetState#
returnboolean

يرجع true إذا الفترة شغّالة، و false إذا موقفة

يرجع الحالة الحالية للفترة

lua
    local isRunning = healthCheck:GetState()
    print("Interval running: " .. tostring(isRunning))
Pause#
returnnil

يوقف تنفيذ الفترة مؤقتاً

Resume#
...any

معاملات جديدة تنرسل للـ callback

Update#
...any

معاملات جديدة تنرسل للـ callback

lua
    healthCheck:Update(newPlayerId, additionalData)
Destroy#
returnnil

يوقف الفترة وينظّفها بالكامل

SetTimeout#
callbackfunctionrequired

الدالة اللي تتنفذ بعد التأخير

delayintegerrequired

التأخير قبل التنفيذ بالملي ثانية

customArgstable

المعاملات اللي تنرسل لدالة الـ callback

returnTimeoutrequired

يرجع نسخة Timeout عشان تتحكم فيها

ينشئ تنفيذ متأخر لمرة وحدة تقدر تتحكم فيه

lua
    -- Import the functions module
    local Lib = Import 'functions' --[[@as FUNCTIONS]]

    -- Create a timeout that executes after 10 seconds
    local delayedAction = Lib.SetTimeout(function(message, playerId)
        print("Delayed message: " .. message)
    end, 10000, {"Welcome to the server!", PlayerId()})
GetState#
returnboolean

يرجع true إذا المهلة نشطة، و false إذا موقفة أو تنفذت

Pause#
returnnil

يوقف المهلة مؤقتاً ويمنع التنفيذ

Resume#
...any

معاملات جديدة تنرسل للـ callback، ويقبل تحديث المعاملات مثل دالة update

Update#
...any

معاملات جديدة تنرسل للـ callback

يحدّث معاملات الـ callback

lua
    delayedAction:Update("Modified message", differentPlayerId)
Destroy#
returnnil

يلغي المهلة وينظّفها بالكامل

المسجّل (Logger)

هذا الموديول المشترك ينستخدم لطباعة سجلات منسّقة فيها الوقت ومستوى السجل وبادئة اختيارية وسياق منظم الكونسول الأساسي يعرض اسم الريسورس أصلاً، فالمسجّل يضيف بس الوقت والمستوى ورسالتك سجلات DEBUG معطّلة افتراضياً لين تفعّلها بـ SetDebugEnabled(true) أو تجبرها بخيار debug

Import#
lua
local Logger = Import('logger').Logger --[[@as LOGGER]]
شكل المخرجات#
text
[12:34:56] [INFO] message
[12:34:56] [WARN] [BANK] message | charId=1 money=250
[12:34:56] [ERROR] something failed
Log#

الدالة الأساسية اللي تستخدمها كل دوال السجل الثانية

levelstringrequired

القيم المدعومة INFO و WARN و ERROR و DEBUG

...any

أجزاء الرسالة، والقيم تنضم مع بعض بالترتيب

contexttable

جدول سياق اختياري ينضاف كأزواج key=value

options.prefixstring

بادئة اختيارية تظهر قبل نص الرسالة

options.debugboolean

يجبر سجل DEBUG حتى لو وضع التصحيح معطّل

options.colorizeboolean

حطه false عشان تعطّل ألوان الكونسول

lua
local Logger = Import('logger').Logger --[[@as LOGGER]]

Logger:Log('INFO', 'player connected', {
    charId = 12,
    source = 4
}, {
    prefix = 'CHARACTER'
})
Info / Warn / Error / Debug#

دوال مختصرة لمستويات السجل المدعومة

lua
local Logger = Import('logger').Logger --[[@as LOGGER]]

Logger:Info('inventory loaded')
Logger:Warn('low ammo', { weapon = 'WEAPON_REPEATER_CARBINE' })
Logger:Error('failed to save character', { charId = 5 })

Logger:SetDebugEnabled(true)
Logger:Debug('debug output enabled')
SetDebugEnabled#

يفعّل أو يعطّل مخرجات التصحيح بشكل عام لنسخة المسجّل هذي

enabledbooleanrequired

حطه true عشان تسمح بسجلات DEBUG، و false عشان تعطّلها

GetDebugEnabled#

يرجع حالة التصحيح الحالية

returnboolean

true إذا سجلات التصحيح مفعّلة، وإلا false

مثال للكلاينت#
lua
local Logger = Import('logger').Logger --[[@as LOGGER]]

Logger:Info('client logger info output', {
    side = 'client',
    ped = PlayerPedId()
}, {
    prefix = 'TEST'
})
مثال للسيرفر#
lua
local Logger = Import('logger').Logger --[[@as LOGGER]]

Logger:SetDebugEnabled(true)
Logger:Debug('server logger debug output', {
    side = 'server',
    source = source
}, {
    prefix = 'TEST'
})

الـ Exports

المحدِّد (Selector)

هذا المحدِّد يخليك تختار لاعبين بواجهة NUI ويرجع رقم اللاعب اللي انختار

Select#
allow_selfboolean

السماح باختيار نفسك

amount_of_playersinteger

عدد اللاعبين المراد اختيارهم

distancenumber

مسافة اختيار اللاعبين

allow_in_vehicleboolean

السماح باختيار لاعبين داخل المركبات

allow_on_horseboolean

السماح باختيار لاعبين على الخيل

playeridinteger

رقم اللاعب اللي انختار

lua
local result <const> = exports.jrs_core:Select({
    allow_self = true,
    amount_of_players = 4,
    distance = 8.0,
    allow_in_vehicle = true,
    allow_on_horse = true
})

ProgressBar#

يخليك تنشئ شريط تقدم يظهر على الشاشة لمدة محددة

Start#
textstringrequired

النص اللي يظهر في شريط التقدم

colorstablerequired

جدول ألوان شريط التقدم: startColor و endColor ألوان النص، و backgroundColor و fillColor ألوان الخلفية والتعبئة في صورة شريط التقدم

durationintegerrequired

المدة بـ milliseconds لشريط التقدم

typestringrequired

نوع شريط التقدم، المتاح حالياً linear بس

positiontablerequired

جدول موقع شريط التقدم على الشاشة: top و left هي الموقع بـ %

imagestring

صورة شريط التقدم، المتاح حالياً png بس

callbackfunction

دالة callback إذا تبي تستخدمه بشكل غير متزامن

returnboolean

نتيجة شريط التقدم true أو false، وإذا false يعني شريط التقدم انلغى

lua
local data = {
    text = 'Some text here',
    colors = {
        -- for text
        startColor = 'white', -- starting color of the text
        endColor = 'black', -- ending color of the text
        -- these colors are filters they dont really represent the color that well but its an option if you want to change it
        -- for background
        -- https://colorpicker.dev/#21d70d use this website choose hwb and its the first number just add deg to it like this 330deg

        -- backgroundColor = '0deg', -- Changes grey bar to blue-ish
        --fillColor = '120deg',     -- Changes white bar to green-ish
    },
    duration = 5000,
    type = 'linear',                    -- only linear is avaliable for now
    position = { top = 90, left = 50 }, -- in % for position on the screen
    image = 'score_timer_extralong',    -- only png this is optional you can add your own image , images must be in this script images folder
}

-- SYNC
local result = exports.jrs_core:progressStart(data)
if not result then
    print('cancelled')
else
    print('completed')
end

--OR ASYNC
exports.jrs_core:progressStart(data, function(result)
    if result then
        print('Progress bar completed')
    else
        print('Progress bar cancelled')
    end
end)
Cancel#

إلغاء شريط التقدم

lua
    exports.jrs_core:progressCancel()

نسخ

يخليك ترسل طلب نسخ للحافظة من واجهة jrs_core NUI.

copyToClipBoard#
textstringrequired

النص المراد نسخه للحافظة

lua
exports.jrs_core:copyToClipBoard("Hello from jrs_core")

الكثافة

يخليك تشوف أو تغيّر مضاعفات كثافة السكان اللي يتحكم فيها jrs_core وقت التشغيل.

الموديول يحتفظ بقيمة افتراضية ويقدر يطبّق قيمة مؤقتة. إذا فيه قيمة مؤقتة تنستخدم أولاً، وإذا ما فيه تنستخدم القيمة الافتراضية.

أسماء الكثافة الصحيحة هي:

lua
"AnimalDensity"
"HumanDensity"
"PedDensity"
"VehicleDensity"
"ScenarioAnimalDensity"
"ScenarioHumanDensity"
"ScenarioPedDensity"
"ParkedVehicleDensity"
"RandomVehicleDensity"
GetDensityMultipliers#
namestring

اسم الكثافة. إذا ما انحط يرجع الـ export جدول المضاعفات كامل.

returntable

يرجع عنصر كثافة واحد أو جدول الكثافة كامل. العنصر الواحد فيه value المضبوط، وممكن يكون فيه temp_value إذا فيه قيمة مؤقتة نشطة.

lua
local allMultipliers = exports.jrs_core:GetDensityMultipliers()

local vehicleDensity = exports.jrs_core:GetDensityMultipliers("VehicleDensity")
print(vehicleDensity.value, vehicleDensity.temp_value)
SetDefaultDensityMultipliers#
sourceintegerrequired

رقم اللاعب المستهدف أو -1 للكل.

namestringrequired

واحد من أسماء الكثافة الصحيحة المذكورة فوق.

valuenumberrequired

قيمة مضاعف الكثافة. استخدم قيم بين 0.0 و 1.0.

lua
local target <const> = source
exports.jrs_core:SetDefaultDensityMultipliers(target, "VehicleDensity", 0.2)
SetTemporaryDensityMultipliers#
sourceintegerrequired

رقم اللاعب المستهدف أو -1 للكل.

namestringrequired

واحد من أسماء الكثافة الصحيحة المذكورة فوق.

valuenumberrequired

قيمة مضاعف الكثافة، استخدم قيم بين 0.0 و 1.0.

timerinteger

وقت اختياري بالثواني قبل ما تنشال قيمة الكثافة المؤقتة تلقائياً.

lua
local target <const> = source
exports.jrs_core:SetTemporaryDensityMultipliers(target, "VehicleDensity", 0.2)
RemoveTemporayDensityMultipliers#
sourceintegerrequired

رقم اللاعب المستهدف أو -1 للكل.

namestringrequired

واحد من أسماء الكثافة الصحيحة المذكورة فوق.

lua
local target <const> = source
exports.jrs_core:RemoveTemporayDensityMultipliers(target, "ScenarioHumanDensity")

المجمّع (Collector)

ما انطبق للحين

الذاكرة المؤقتة (Cache)

نظام ذاكرة مؤقتة يقلل عدد استدعاءات الـ natives الأكثر استخداماً مثل PlayerPedId

CACHE#

CACHE جدول عام في الكلاينت فيه بيانات مخزّنة لـ Ped،Player،ServerID،Vehicle،Mount،Weapon هذي تتحدث كل 5 ملي ثانية، و Vehicle و Mount ترجع 0 لما اللاعب مو داخل مركبة أو على مطية

LastVehicle و LastMount و LastWeapon تحتفظ بالقيمة السابقة لما تتغير، وما ترجع 0

returnany

البيانات المخزّنة

lua
local ped = CACHE.Ped -- current player ped id
local player = CACHE.Player -- current player id
local serverId = CACHE.ServerID -- current player server id
local vehicle = CACHE.Vehicle -- current vehicle or 0 if not in a vehicle
local mount = CACHE.Mount -- current mounted entity or 0 if not mounted
local weapon = CACHE.Weapon -- current held weapon
local isDead = CACHE.IsDead -- current player is dead or not
local lastVehicle = CACHE.LastVehicle -- last vehicle the player was in
local lastMount = CACHE.LastMount -- last mount the player was on
local lastWeapon = CACHE.LastWeapon -- last weapon the player held
CACHE#

هذي تعطيك تحكم أكثر بنظام الذاكرة المؤقتة، وكلها false افتراضياً ولازم تعطّل اللي ما تحتاجه

lua
-- at the top of your client file.
CACHE.SkipWeapon = true -- no need for weapon cache
CACHE.SkipVehicle = true -- no need for vehicle cache
CACHE.SkipMount = true -- no need for mount cache
CACHE.Wait = 500 -- by default is 500 , you can adjust to your needs
OnPedChange#

تسجيل callback يتشغّل لما يتغير ped اللاعب، ورقم الـ ped الجديد ينرسل للـ callback

callbackfunctionrequired

الدالة اللي تتشغّل برقم الـ ped الجديد لما يتغير ped اللاعب

lua
CACHE.OnPedChange(function(pedId)
    print('ped changed', pedId)
end)
OnPlayerDeath#

تسجيل callback يتشغّل لما يموت اللاعب، ويعتمد على فحص IsDead فلازم CACHE.SkipIsDead يبقى false

callbackfunctionrequired

الدالة اللي تتشغّل لما يموت اللاعب

lua
CACHE.OnPlayerDeath(function()
    print('player died')
end)
JRS Core · فريمورك RedM مجاني ومفتوح المصدر · من فريق JRS