العودة إلى المدونة
Tutorial7 دقيقة قراءة

شاشة إنشاء الشخصيات في FiveM: دليل الواجهة والبرمجة

تصميم شاشة إنشاء شخصية مذهلة لـ FiveM. تحكمات الوجه، الملابس، المشاهد الخلفية وأفضل منشئي الشخصيات المجانيين والمدفوعين.

Agency Scripts

المؤسس والمطور الرئيسي في Agency Scripts

لماذا تهم إنشاء الشخصيات في اللعب التمثيلي

إنشاء الشخصية هو اللحظة التفاعلية الأولى التي يختبرها اللاعب على خادم FiveM الخاص بك للعب الأدوار. يحدد النغمة لكل ما يلي. منشئ شخصية مصقول وغامر يخبر اللاعبين الجدد أن خادمك مبني بشكل احترافي ويستحق استثمار وقتهم فيه. منشئ بسيط أو به أخطاء يوجههم مباشرة إلى متصفح الخوادم للبحث عن بدائل. بخلاف الانطباعات الأولى، يحدد منشئ الشخصية الهوية البصرية التي يحملها كل لاعب طوال تجربة لعب الأدوار بأكملها. يحدد مزيج الأصول، ملامح الوجه، تسريحات الشعر، الملابس، والتفاصيل البيوغرافية مثل الاسم وتاريخ الميلاد. النجاح في ذلك يعني بناء نظام يتواصل مع نظام المظهر الأصلي لـ GTA V، يعرض الخيارات من خلال واجهة NUI بديهية، يحفظ الاختيارات في قاعدة بيانات، ويعيد تحميلها بشكل موثوق في كل مرة يظهر فيها اللاعب.

فهم نظام مظهر الشخصيات في GTA V

تستخدم GTA V نظام مظهر قائم على التراث حيث يتم دمج وجه الشخصية من نموذجين للوالدين. هناك 46 أماً وأباً ممكنين، كل منهم له هياكل وجه مميزة. ال SetPedHeadBlendData native يتحكم في هذا الدمج، حيث يقبل قيم شكل ومزج الجلد بين 0.0 و1.0 التي تحدد مدى تشابه الشخصية مع كل والد. بالإضافة إلى الوراثة، يقدم اللعبة 20 فئة تراكب من خلال SetPedHeadOverlay يغطي ميزات مثل العيوب، شعر الوجه، الحواجب، الشيخوخة، المكياج، وتلف الجلد. لكل طبقة قيمة شفافية خاصة بها ويمكن تلوينها بشكل مستقل باستخدام SetPedHeadOverlayColor. يتم التعامل مع الشعر بشكل منفصل من خلال SetPedComponentVariation للنموذج و SetPedHairColor للألوان والتظليل. يستخدم لون العين SetPedEyeColor مع قيم تتراوح من 0 إلى 31. فهم هذه الدوال الأصلية ضروري لأن واجهة NUI الخاصة بك تحتاج إلى ربط منزلقات ومحددات سهلة الاستخدام بهذه الدوال المحددة.

-- client/appearance.lua
function ApplyAppearance(ped, data)
    -- Heritage blend (mother, father, shape mix, skin mix)
    SetPedHeadBlendData(ped,
        data.mother, data.father, 0,
        data.mother, data.father, 0,
        data.shapeMix, data.skinMix, 0.0,
        false
    )

    -- Face features (-1.0 to 1.0 for each of 20 features)
    for i = 0, 19 do
        SetPedFaceFeature(ped, i, data.features[i] or 0.0)
    end

    -- Overlays (blemishes, beard, eyebrows, aging, makeup, etc.)
    for i = 0, 12 do
        local overlay = data.overlays[i] or {style = 0, opacity = 0.0}
        SetPedHeadOverlay(ped, i, overlay.style, overlay.opacity)
        if overlay.color then
            SetPedHeadOverlayColor(ped, i, overlay.colorType or 1,
                overlay.color, overlay.secondColor or overlay.color)
        end
    end

    -- Hair
    SetPedComponentVariation(ped, 2, data.hair or 0, 0, 2)
    SetPedHairColor(ped, data.hairColor or 0, data.hairHighlight or 0)

    -- Eye color
    SetPedEyeColor(ped, data.eyeColor or 0)
end

بناء واجهة NUI

NUI (واجهة المستخدم الطبيعية) هي تراكب HTML وCSS وJavaScript التي يتفاعل معها اللاعبون أثناء إنشاء شخصياتهم. منشئ الشخصيات المصمم جيدًا يقسم العملية إلى خطوات منطقية: المعلومات البيوغرافية أولاً، ثم اختيار الأصل، ملامح الوجه، التراكبات مثل شعر الوجه والمكياج، تصفيف الشعر، وأخيرًا الملابس. يجب أن يعرض كل خطوة تحديثات المعاينة في الوقت الحقيقي على نموذج الشخصية حتى يرى اللاعبون كيف تبدو اختياراتهم بالضبط. استخدم تخطيطًا تبويبيًا أو على شكل معالج حتى لا يغمر اللاعبون بعشرات الخيارات دفعة واحدة. تعمل منزلقات النطاق جيدًا للقيم المستمرة مثل مزيج الشكل وملامح الوجه، بينما تعمل محددات الشبكة مع معاينات مصغرة بشكل أفضل للخيارات المنفصلة مثل تسريحات الشعر وعناصر الملابس. أرسل كل تغيير إلى سكربت العميل عبر fetch أو نظام رسائل NUI بحيث يتم تحديث الشخصية على الفور.

<!-- nui/index.html (simplified structure) -->
<div id="creator" class="creator-wrapper">
  <div class="steps-nav">
    <button data-step="bio" class="active">Identity</button>
    <button data-step="heritage">Heritage</button>
    <button data-step="features">Features</button>
    <button data-step="overlays">Appearance</button>
    <button data-step="hair">Hair</button>
    <button data-step="clothing">Clothing</button>
  </div>

  <div class="step-content" id="step-heritage">
    <label>Mother</label>
    <input type="range" id="mother" min="0" max="45" value="0">
    <label>Father</label>
    <input type="range" id="father" min="0" max="45" value="0">
    <label>Resemblance (Shape Mix)</label>
    <input type="range" id="shapeMix" min="0" max="100" value="50">
    <label>Skin Tone (Skin Mix)</label>
    <input type="range" id="skinMix" min="0" max="100" value="50">
  </div>
</div>

<script>
document.querySelectorAll('input[type="range"]').forEach(slider => {
  slider.addEventListener('input', () => {
    fetch('https://myresource/updateAppearance', {
      method: 'POST',
      body: JSON.stringify({
        type: slider.id,
        value: parseFloat(slider.value)
      })
    });
  });
});
</script>

نظام الكاميرا لمعاينة الشخصية

نظام كاميرا مخصص ضروري لتجربة إنشاء شخصية مصقولة. يحتاج اللاعبون إلى رؤية مقربة للميزات الوجهية عند ضبط مزيج الأصول والطبقات، لقطات متوسطة للشعر وملابس الجزء العلوي من الجسم، ولقطات كاملة للجسم للسراويل والأحذية. نفذ متحكم كاميرا يتنقل بسلاسة بين مواقع محددة مسبقًا بناءً على الخطوة النشطة في الإنشاء. استخدم CreateCam مع DEFAULT_SCRIPTED_CAMERA type و RenderScriptCams للسيطرة على كاميرا اللعبة. للتدوير، اسمح للاعبين بسحب الماوس للدوران حول شخصيتهم عن طريق تعديل اتجاه الكاميرا مع إبقائها موجهة إلى الشخصية. حركة خفيفة أثناء الخمول على الشخصية، مثل WORLD_HUMAN_STAND_IMPATIENT السيناريو، يحافظ على مظهر الشخصية طبيعيًا أثناء عملية الإنشاء بدلاً من الوقوف في وضع T جامد.

-- client/camera.lua
local creatorCam = nil
local camAngle = 0.0

local CamPositions = {
    bio      = {offset = vector3(0.0, 0.9, 0.65), fov = 35.0},
    heritage = {offset = vector3(0.0, 0.7, 0.65), fov = 30.0},
    features = {offset = vector3(0.0, 0.5, 0.68), fov = 22.0},
    overlays = {offset = vector3(0.0, 0.5, 0.68), fov = 22.0},
    hair     = {offset = vector3(0.0, 0.6, 0.72), fov = 25.0},
    clothing = {offset = vector3(0.0, 2.2, 0.30), fov = 45.0},
}

function SetupCreatorCam(ped, step)
    local pos = CamPositions[step] or CamPositions.bio
    local pedCoords = GetEntityCoords(ped)
    local target = pedCoords + vector3(0.0, 0.0, pos.offset.z)

    if not creatorCam then
        creatorCam = CreateCam('DEFAULT_SCRIPTED_CAMERA', true)
        RenderScriptCams(true, true, 500, true, false)
    end

    local rad = math.rad(camAngle)
    local camPos = pedCoords + vector3(
        math.sin(rad) * pos.offset.y,
        math.cos(rad) * pos.offset.y,
        pos.offset.z
    )

    SetCamCoord(creatorCam, camPos.x, camPos.y, camPos.z)
    PointCamAtCoord(creatorCam, target.x, target.y, target.z)
    SetCamFov(creatorCam, pos.fov)
    SetCamActive(creatorCam, true)
end

حفظ وتحميل بيانات الشخصية

تحتاج جميع بيانات مظهر الشخصية إلى البقاء في قاعدة بيانات بحيث تبقى بعد إعادة تشغيل الخادم ويمكن تحميلها في كل مرة يظهر فيها اللاعب. قم بهيكلة جدول قاعدة البيانات الخاص بك لتخزين المظهر الكامل ككائن JSON جنبًا إلى جنب مع حقول السيرة الذاتية مثل الاسم الأول، الاسم الأخير، تاريخ الميلاد، الجنس، والجنسية. عندما ينهي اللاعب الإنشاء ويؤكد شخصيته، يرسل العميل كائن البيانات الكامل إلى الخادم، الذي يتحقق من نطاقات الإدخال ويدخله في قاعدة البيانات. عند تسجيل الدخول اللاحق، يسترجع الخادم بيانات الشخصية أثناء تدفق الظهور ويرسلها مرة أخرى إلى العميل، الذي يستدعي نفس ApplyAppearance function المستخدمة أثناء الإنشاء. لخوادم الشخصيات المتعددة، خزّن معرف فتحة الشخصية بحيث يمكن لكل لاعب أن يمتلك عدة شخصيات بمظاهر مستقلة.

-- server/database.lua
-- Using oxmysql for database operations
function SaveCharacter(playerId, charData)
    local identifier = GetPlayerIdentifier(playerId, 0)
    local appearance = json.encode(charData.appearance)

    MySQL.insert([[
        INSERT INTO characters
            (identifier, slot, firstname, lastname,
             dateofbirth, gender, nationality, appearance)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    ]], {
        identifier,
        charData.slot or 1,
        charData.firstname,
        charData.lastname,
        charData.dob,
        charData.gender,
        charData.nationality,
        appearance
    })
end

function LoadCharacter(playerId, slot)
    local identifier = GetPlayerIdentifier(playerId, 0)
    local result = MySQL.single.await([[
        SELECT * FROM characters
        WHERE identifier = ? AND slot = ?
    ]], {identifier, slot})

    if result then
        result.appearance = json.decode(result.appearance)
    end
    return result
end

-- Spawn handler
RegisterNetEvent('character:loaded', function(slot)
    local src = source
    local char = LoadCharacter(src, slot)
    if char then
        TriggerClientEvent('character:applyAppearance', src, char.appearance)
    end
end)

تكامل الملابس وتنوع المكونات

تُدار الملابس في GTA V من خلال تنوع المكونات وتنوع الدعائم. تغطي المكونات أجزاء الجسم مثل الجذع، الأرجل، القدمين، الإكسسوارات، والقمصان الداخلية، بينما تتعامل الدعائم مع العناصر القابلة للإرفاق مثل القبعات، النظارات، الأقراط، والساعات. ال SetPedComponentVariation native يأخذ معرف المكون، معرف الرسم، معرف النسيج، ومعرف اللوحة. التحدي هو أن الرسومات المتاحة تختلف بين نماذج الشخصيات الذكور والإناث، وبعض تركيبات الرسم والنسيج غير صالحة. يحتاج NUI الخاص بك إلى استعلام الحد الأقصى لعدد الرسومات لكل مكون باستخدام GetNumberOfPedDrawableVariations والحد الأقصى للنسيج لكل عنصر قابل للرسم باستخدام GetNumberOfPedTextureVariations. أنشئ محدد الملابس الخاص بك ليملأ الخيارات ديناميكياً بناءً على الجنس المختار حتى يرى اللاعبون فقط التركيبات الصالحة. خزّن بيانات الملابس جنباً إلى جنب مع بيانات المظهر وطبقها أثناء تدفق الظهور باستخدام نفس نيتيفات تغييرات المكونات.

إجراءات التحقق ومكافحة الإساءة

لا تثق أبداً بالبيانات القادمة من العميل بدون تحقق. يمكن للاعبين الذين يملكون عملاء معدلة إرسال قيم مظهر خارج النطاقات الطبيعية، مما قد يتسبب في تعطل عملاء آخرين أو استغلال عيوب بصرية. تحقق من كل حقل على جانب الخادم قبل الحفظ في قاعدة البيانات. يجب أن تكون مؤشرات Heritage بين 0 و45، وقيم المزج بين 0.0 و1.0، وقيم ميزات الوجه بين -1.0 و1.0، ومؤشرات التراكب ضمن النطاق الصحيح لكل نوع تراكب. ارفض أو قم بتقييد أي قيم خارج النطاق. بالإضافة إلى ذلك، نفذ تحديد معدل على أحداث تحديث المظهر أثناء الإنشاء لمنع العملاء الخبيثين من إغراق الخادم بتغييرات مظهر سريعة. فترة تبريد 100 مللي ثانية بين التحديثات غير ملحوظة للاعبين الشرعيين لكنها توقف الرسائل المزعجة الآلية. أخيراً، قفل تدفق إنشاء الشخصية خلف إدارة جلسة مناسبة حتى لا يتمكن اللاعبون من تشغيل أحداث الإنشاء خارج التدفق المقصود.

جاهز للبدء؟

احصل على السكربتات من متجرنا، أو انضم إلى Discord للدعم والتحديثات ونظرة على ما هو قادم.