ब्लॉग पर वापस
Tutorial12 मिनट पढ़ें

FiveM टैटू और बार्बर सिस्टम: कस्टमाइज़ेशन स्क्रिप्ट्स

अपने FiveM शहर में टैटू पार्लर और बार्बरशॉप जोड़ें। कैमरा कोण, UI, अपॉइंटमेंट फ्लो और रोलप्ले के लिए शीर्ष अनुकूलन स्क्रिप्ट।

Agency Scripts

Agency Scripts के संस्थापक और प्रमुख डेवलपर

पेड अपीयरेंस कंपोनेंट्स को समझना

FiveM में टैटू और बार्बर शॉप सिस्टम बनाना GTA V के पेड (कैरेक्टर) उपस्थिति को कैसे संभालता है, इसकी ठोस समझ की मांग करता है। उपस्थिति प्रणाली कई घटक श्रेणियों में विभाजित है: हेड ओवरले जैसे दाग-धब्बे, चेहरे के बाल, भौंहें, और मेकअप, ड्रॉएबल घटक कपड़े और बालों की शैलियों के लिए, और टैटू सजावट जो पेड मॉडल पर लेयर होती हैं। प्रत्येक घटक प्रकार विभिन्न नेटिव फंक्शंस का उपयोग करता है और अपनी इंडेक्सिंग प्रणाली का पालन करता है। हेड ओवरले में इंडेक्स 0-12 का उपयोग दाग-धब्बे (0), चेहरे के बाल (1), भौंहें (2), उम्र बढ़ना (3), मेकअप (4), ब्लश (5), और लिपस्टिक (8) जैसी विशेषताओं को नियंत्रित करने के लिए किया जाता है। बालों की शैलियाँ ड्रॉएबल घटक प्रणाली के माध्यम से इंडेक्स 2 पर सेट की जाती हैं। टैटू पूरी तरह से अलग सजावट प्रणाली का उपयोग करते हैं जिसमें संग्रह नाम और हैश मान होते हैं। UI बनाने से पहले, आपको प्रत्येक घटक के लिए उपलब्ध सभी विकल्पों का मानचित्रण करना होगा, जिसमें वर्तमान पेड मॉडल के लिए उपलब्ध विभिन्नताओं की संख्या शामिल है, क्योंकि पुरुष और महिला कैरेक्टर के पास उपलब्ध शैलियों के अलग-अलग सेट होते हैं। उपयोग करें GetNumHeadOverlayValues(overlayIndex) रनटाइम पर प्रत्येक ओवरले प्रकार के लिए कितने विकल्प मौजूद हैं यह पूछने के लिए।

चरित्र पूर्वावलोकन के लिए कैमरा सिस्टम

एक उत्कृष्ट नाई और टैटू अनुभव इस बात पर निर्भर करता है कि खिलाड़ी वास्तविक समय में जो वे चुन रहे हैं उसे देख सके। एक कस्टम कैमरा सिस्टम बनाएं जो खिलाड़ी विकल्पों के माध्यम से ब्राउज़ करते समय संबंधित शरीर के हिस्से पर केंद्रित हो। बाल संपादित करते समय, कैमरे को सिर पर ज़ूम करें। धड़ के टैटू चुनते समय, कैमरे को पीछे खींचें ताकि ऊपरी शरीर दिखे। पैर के टैटू पर काम करते समय, कैमरे को निचले शरीर को फ्रेम करने के लिए स्थिति दें। स्क्रिप्टेड कैमरा नेटिव्स का उपयोग करें ताकि खिलाड़ी श्रेणियों के बीच स्विच करते समय दृश्य बिंदुओं के बीच चिकनी संक्रमण हो। यहां एक कैमरा प्रबंधन प्रणाली है जो कई ज़ूम स्तरों और शरीर के फोकस क्षेत्रों को संभालती है:

local customCam = nil
local camActive = false

local CameraPresets = {
    head = {offset = vector3(0.0, 0.65, 0.65), fov = 35.0},
    face = {offset = vector3(0.0, 0.45, 0.62), fov = 25.0},
    torso = {offset = vector3(0.0, 1.2, 0.2), fov = 45.0},
    legs = {offset = vector3(0.0, 1.5, -0.5), fov = 50.0},
    full = {offset = vector3(0.0, 2.5, 0.2), fov = 50.0},
}

function SetupPreviewCamera(preset)
    local ped = PlayerPedId()
    local pedCoords = GetEntityCoords(ped)
    local pedHeading = GetEntityHeading(ped)
    local headingRad = math.rad(pedHeading)

    local cam = CameraPresets[preset] or CameraPresets.full
    local camX = pedCoords.x + cam.offset.y * math.sin(-headingRad)
    local camY = pedCoords.y + cam.offset.y * math.cos(-headingRad)
    local camZ = pedCoords.z + cam.offset.z

    if customCam then
        local newCam = CreateCam('DEFAULT_SCRIPTED_CAMERA', true)
        SetCamCoord(newCam, camX, camY, camZ)
        PointCamAtCoord(newCam, pedCoords.x, pedCoords.y, pedCoords.z + cam.offset.z)
        SetCamFov(newCam, cam.fov)
        SetCamActiveWithInterp(newCam, customCam, 800, 1, 1)

        Wait(800)
        DestroyCam(customCam, false)
        customCam = newCam
    else
        customCam = CreateCam('DEFAULT_SCRIPTED_CAMERA', true)
        SetCamCoord(customCam, camX, camY, camZ)
        PointCamAtCoord(customCam, pedCoords.x, pedCoords.y, pedCoords.z + cam.offset.z)
        SetCamFov(customCam, cam.fov)
        SetCamActive(customCam, true)
        RenderScriptCams(true, true, 500, true, false)
    end
    camActive = true
end

function DestroyPreviewCamera()
    if customCam then
        RenderScriptCams(false, true, 500, true, false)
        DestroyCam(customCam, false)
        customCam = nil
        camActive = false
    end
end

माउस या एनालॉग स्टिक रोटेशन समर्थन जोड़ें ताकि खिलाड़ी परिवर्तन पूर्वावलोकन करते समय अपने चरित्र को घुमा सकें। जब NUI इसे उपभोग नहीं कर रहा हो तो माउस मूवमेंट कैप्चर करें और इसे खिलाड़ी पेड के लिए हेडिंग रोटेशन के रूप में लागू करें। यह खिलाड़ियों को खरीदारी से पहले अपने टैटू को कई कोणों से जांचने देता है, जिससे खरीदारी का अनुभव काफी बेहतर होता है। अनुकूलन सत्र के दौरान खिलाड़ी पेड को जगह पर फ्रीज करें और एक आइडल एनीमेशन चलाएं ताकि चरित्र प्राकृतिक दिखे जबकि खिलाड़ी ब्राउज़ कर रहा हो।

बाल और दाढ़ी अनुकूलन

बाल और दाढ़ी अनुकूलन क्रमशः drawable कंपोनेंट और हेड ओवरले सिस्टम का उपयोग करता है। हेयर स्टाइल सेट किए जाते हैं SetPedComponentVariation कंपोनेंट इंडेक्स 2 (बाल) और इंडेक्स 1 (टेक्सचर/रंग विविधता) का उपयोग करते हुए। बालों का रंग अलग से लागू किया जाता है SetPedHairColor जो एक प्राथमिक रंग सूचकांक और एक हाइलाइट रंग सूचकांक लेता है। दाढ़ी शैलियाँ हेड ओवरले सिस्टम का उपयोग करती हैं जो सूचकांक 1 पर होती हैं और एक अपारदर्शिता मान होता है जो चेहरे के बालों की मोटाई या पतलापन नियंत्रित करता है। NUI बनाएं जो प्रत्येक उपलब्ध शैली के लिए थंबनेल या नाम दिखाए, और खिलाड़ी विकल्पों के माध्यम से क्लिक करते समय पेड को वास्तविक समय में अपडेट करे। यहाँ बाल और दाढ़ी परिवर्तनों को वास्तविक समय पूर्वावलोकन के साथ लागू करने के लिए Lua लॉजिक है:

function ApplyHairStyle(ped, styleIndex, textureIndex, primaryColor, highlightColor)
    SetPedComponentVariation(ped, 2, styleIndex, textureIndex or 0, 0)
    SetPedHairColor(ped, primaryColor, highlightColor)
end

function ApplyBeardStyle(ped, styleIndex, opacity, color)
    SetPedHeadOverlay(ped, 1, styleIndex, opacity or 1.0)
    SetPedHeadOverlayColor(ped, 1, 1, color, color)
end

function ApplyEyebrows(ped, styleIndex, opacity, color)
    SetPedHeadOverlay(ped, 2, styleIndex, opacity or 1.0)
    SetPedHeadOverlayColor(ped, 2, 1, color, color)
end

function GetAvailableHairStyles(ped)
    local styles = {}
    local numStyles = GetNumberOfPedDrawableVariations(ped, 2)

    for i = 0, numStyles - 1 do
        local numTextures = GetNumberOfPedTextureVariations(ped, 2, i)
        table.insert(styles, {
            index = i,
            textures = numTextures,
            label = 'Style ' .. (i + 1)
        })
    end

    return styles
end

function GetAvailableBeardStyles(ped)
    local styles = {}
    local numStyles = GetNumHeadOverlayValues(1)

    for i = 0, numStyles - 1 do
        table.insert(styles, {
            index = i,
            label = 'Beard ' .. (i + 1)
        })
    end

    return styles
end

NUI इंटरफ़ेस बाल रंगों को संख्यात्मक सूचकांकों के बजाय एक दृश्य पैलेट के रूप में प्रस्तुत करना चाहिए, GTA के आंतरिक रंग सूचकांकों को उनके वास्तविक RGB प्रतिनिधित्वों से मैप करते हुए। दाढ़ी की अस्पष्टता के लिए एक स्लाइडर शामिल करें जो खिलाड़ियों को हल्की दाढ़ी से लेकर पूरी मोटी दाढ़ी तक चेहरे के बालों की मोटाई को ठीक करने देता है। बार्बर मेनू खोलने से पहले खिलाड़ी की पिछली उपस्थिति संग्रहीत करें ताकि यदि वे रद्द करें पर क्लिक करें तो आप सभी परिवर्तन पूर्ववत कर सकें, जिससे आकस्मिक परिवर्तन से खिलाड़ी के पैसे खर्च होने से बचा जा सके।

टैटू ओवरले सिस्टम

GTA V में टैटू डेकोरेशन सिस्टम का उपयोग करते हैं, जो कलेक्शन और ओवरले हैश जोड़ों का उपयोग करके पेड मॉडल पर टेक्सचर ओवरले लगाता है। प्रत्येक टैटू एक कलेक्शन नाम (जैसे "mpairraces_overlays") और एक ओवरले नाम (जैसे "MP_Airraces_Tattoo_000_M") द्वारा परिभाषित होता है जो विशिष्ट टैटू एसेट की पहचान करता है। टैटू लगाएं AddPedDecorationFromHashes और सभी टैटू हटाएं ClearPedDecorations. मुश्किल हिस्सा यह है कि एकल टैटू हटाने के लिए कोई नेटिव नहीं है, इसलिए जब कोई खिलाड़ी एक टैटू हटाना चाहता है, तो आपको सभी डेकोरेशन साफ़ करनी होती हैं और हटाए गए को छोड़कर सब कुछ फिर से लागू करना होता है। इसका मतलब है कि आपको अपने डेटा मॉडल में खिलाड़ी के वर्तमान टैटू की पूरी सूची बनाए रखनी होगी। टैटू संग्रह और आवेदन प्रबंधन का तरीका यहाँ है:

-- Tattoo database structure
local TattooZones = {
    head = {label = 'Head', camera = 'face'},
    torso = {label = 'Torso', camera = 'torso'},
    left_arm = {label = 'Left Arm', camera = 'torso'},
    right_arm = {label = 'Right Arm', camera = 'torso'},
    left_leg = {label = 'Left Leg', camera = 'legs'},
    right_leg = {label = 'Right Leg', camera = 'legs'},
    back = {label = 'Back', camera = 'torso'}
}

-- Available tattoos per zone (abbreviated, real list has hundreds)
Config.Tattoos = {
    torso = {
        {collection = 'mpairraces_overlays', overlay = 'MP_Airraces_Tattoo_000_M',
         label = 'Wing Design', price = 500, zone = 'torso'},
        {collection = 'mpbiker_overlays', overlay = 'MP_MP_Biker_Tat_000_M',
         label = 'Flame Skull', price = 750, zone = 'torso'},
    },
    left_arm = {
        {collection = 'mpchristmas2_overlays', overlay = 'MP_Xmas2_M_Tat_000',
         label = 'Sleeve Art', price = 600, zone = 'left_arm'},
    }
}

function ApplyAllTattoos(ped, tattooList)
    ClearPedDecorations(ped)

    for _, tattoo in ipairs(tattooList) do
        local collectionHash = GetHashKey(tattoo.collection)
        local overlayHash = GetHashKey(tattoo.overlay)
        AddPedDecorationFromHashes(ped, collectionHash, overlayHash)
    end
end

function PreviewTattoo(ped, tattoo, currentTattoos)
    local previewList = {}
    for _, t in ipairs(currentTattoos) do
        table.insert(previewList, t)
    end
    table.insert(previewList, tattoo)
    ApplyAllTattoos(ped, previewList)
end

function RemoveTattoo(ped, tattooIndex, currentTattoos)
    local newList = {}
    for i, t in ipairs(currentTattoos) do
        if i ~= tattooIndex then
            table.insert(newList, t)
        end
    end
    ApplyAllTattoos(ped, newList)
    return newList
end

GTA V में टैटू कैटलॉग में सैकड़ों प्रविष्टियाँ होती हैं जो कई DLC संग्रहों में फैली होती हैं। उन्हें अपने कॉन्फ़िगरेशन में शरीर के क्षेत्र के अनुसार व्यवस्थित करें ताकि NUI क्षेत्र द्वारा फ़िल्टर कर सके। प्रत्येक टैटू के लिए, खिलाड़ी के पेड मॉडल के आधार पर पुरुष या महिला संस्करण का उपयोग किया जाना चाहिए, क्योंकि अधिकांश टैटू के अलग-अलग एसेट नाम होते हैं जो _M या _F पर समाप्त होते हैं। जब खिलाड़ी कैटलॉग में टैटू पर होवर करता है तो पूर्वावलोकन दिखाएं, और केवल चयन की पुष्टि करने पर ही शुल्क लें।

मेकअप और फेस पेंट सिस्टम

मेकअप कई इंडेक्स पर हेड ओवरले सिस्टम का उपयोग करता है: ब्लश (5), लिपस्टिक (8), और अतिरिक्त प्रभावों के लिए चेस्ट हेयर या कॉम्प्लेक्शन ओवरले। प्रत्येक मेकअप प्रकार के कई स्टाइल विकल्प और एक अपारदर्शिता स्लाइडर होता है जो तीव्रता को नियंत्रित करता है। बार्बर शॉप NUI में एक मेकअप सेक्शन बनाएं जो प्रत्येक श्रेणी को विज़ुअल स्वैचेस के साथ प्रस्तुत करता है जो उपलब्ध रंग दिखाते हैं। मेकअप के लिए रंग प्रणाली उपयोग करती है SetPedHeadOverlayColor रंग प्रकार पैरामीटर के साथ: डिफ़ॉल्ट रंगों के लिए type 0, बालों के रंगों के लिए type 1 (दाढ़ी और भौंहों के लिए उपयोग किया जाता है), और मेकअप रंगों के लिए type 2। मेकअप विशेष रूप से रंग प्रकार 2 का उपयोग करता है जो विभिन्न त्वचा टोन, लाल, गुलाबी और नाटकीय रंगों सहित कॉस्मेटिक रंगों का पैलेट प्रदान करता है। प्रत्येक मेकअप घटक के लिए एक अपारदर्शिता स्लाइडर जोड़ें ताकि खिलाड़ी सूक्ष्म प्राकृतिक लुक या बोल्ड नाटकीय शैलियाँ प्राप्त कर सकें। सभी मेकअप सेटिंग्स को खिलाड़ी की उपस्थिति डेटा के साथ संग्रहीत करें ताकि वे सत्रों के बीच बनी रहें, और खिलाड़ी के घर में एक दर्पण इंटरैक्शन प्रदान करें जहाँ वे दुकान पर जाए बिना मेकअप समायोजित कर सकें।

भुगतान प्रणाली और मूल्य निर्धारण

भुगतान प्रणाली को ट्रैक करना चाहिए कि खिलाड़ी ने अपने सत्र के दौरान क्या बदला और प्रदान की गई सेवाओं के आधार पर कुल लागत की गणना करनी चाहिए। जब खिलाड़ी दुकान मेनू खोलता है, तो उनकी वर्तमान उपस्थिति का स्नैपशॉट लें। जैसे-जैसे वे परिवर्तन करते हैं, प्रत्येक संशोधन को एक सत्र कार्ट में ट्रैक करें जो कुल जोड़ता है। जब वे पुष्टि करते हैं और बाहर निकलते हैं, तो सभी किए गए परिवर्तनों के लिए कुल शुल्क लें। यदि वे रद्द करते हैं, तो स्नैपशॉट पर वापस जाएं। स्तरित मूल्य निर्धारण लागू करें जहाँ बुनियादी हेयरकट प्रीमियम शैलियों की तुलना में कम कीमत के हों, और टैटू की कीमत आकार और जटिलता के आधार पर भिन्न हो। यहाँ एक सत्र ट्रैकिंग और भुगतान प्रणाली है:

local sessionChanges = {}
local originalAppearance = nil

function StartCustomizationSession()
    local ped = PlayerPedId()
    originalAppearance = CaptureFullAppearance(ped)
    sessionChanges = {}
end

function TrackChange(category, item, price)
    -- Remove previous change in same category if exists
    for i = #sessionChanges, 1, -1 do
        if sessionChanges[i].category == category then
            table.remove(sessionChanges, i)
        end
    end

    table.insert(sessionChanges, {
        category = category,
        item = item,
        price = price
    })

    UpdateCartUI()
end

function UpdateCartUI()
    local total = 0
    local items = {}

    for _, change in ipairs(sessionChanges) do
        total = total + change.price
        table.insert(items, {
            label = change.category .. ': ' .. change.item,
            price = change.price
        })
    end

    SendNUIMessage({
        action = 'updateCart',
        items = items,
        total = total
    })
end

function ConfirmAndPay()
    local total = 0
    for _, change in ipairs(sessionChanges) do
        total = total + change.price
    end

    TriggerServerEvent('appearance:server:pay', total, sessionChanges)
end

function CancelSession()
    if originalAppearance then
        RestoreFullAppearance(PlayerPedId(), originalAppearance)
    end
    sessionChanges = {}
    DestroyPreviewCamera()
end

सर्वर साइड पर, उपस्थिति परिवर्तन को लागू करने से पहले यह सत्यापित करें कि खिलाड़ी के पास पर्याप्त धनराशि है। यदि भुगतान विफल होता है, तो क्लाइंट को परिवर्तन वापस करने के लिए सूचित करें। पैकेज डील्स की पेशकश करने पर विचार करें जहाँ हेयरकट और दाढ़ी ट्रिम एक साथ लेने पर व्यक्तिगत सेवाओं के योग से कम कीमत होती है, जिससे खिलाड़ी एक ही बार में पूरी सेवाओं का उपयोग करने के लिए प्रोत्साहित होते हैं।

आउटफिट सेविंग और वार्डरोब इंटीग्रेशन

बार्बर और टैटू सिस्टम को एक आउटफिट सेविंग फीचर के साथ बढ़ाएं जो खिलाड़ियों को पूर्ण उपस्थिति कॉन्फ़िगरेशन को नामित प्रीसेट के रूप में संग्रहीत करने देता है। प्रत्येक प्रीसेट खिलाड़ी की पूरी उपस्थिति की स्थिति को कैप्चर करता है जिसमें हेयर स्टाइल और रंग, चेहरे के बाल, मेकअप, और सभी सक्रिय टैटू शामिल हैं। खिलाड़ी फिर घर के वार्डरोब में या दुकान पर पुनः जाकर सहेजे गए लुक के बीच स्विच कर सकते हैं। आउटफिट्स को डेटाबेस में खिलाड़ी के नागरिक ID से लिंक किए गए JSON ब्लॉब के रूप में संग्रहित करें जिसमें सभी उपस्थिति डेटा हो। प्रति खिलाड़ी सहेजे गए आउटफिट्स की संख्या सीमित करें या अतिरिक्त स्लॉट प्रीमियम फीचर के रूप में प्रदान करें। खिलाड़ी के घर में वार्डरोब इंटरैक्शन एक सरल NUI पैनल प्रस्तुत करना चाहिए जो सहेजे गए आउटफिट्स की सूची दिखाए और एक पूर्वावलोकन फ़ंक्शन हो जो प्रत्येक लुक को अस्थायी रूप से लागू करता है ताकि खिलाड़ी प्रतिबद्ध होने से पहले इसे देख सके। यह व्यक्तिगत उपस्थिति प्रणाली को हाउसिंग सिस्टम से जोड़ता है, जिससे दोनों फीचर अलग-अलग की तुलना में एक साथ अधिक मूल्यवान बनते हैं।

शॉप लोकेशंस और NPC बार्बर इंटीग्रेशन

मानचित्र पर कई दुकान स्थानों को परिभाषित करें, प्रत्येक में विभिन्न उपलब्ध सेवाएं और मूल्य गुणक हो सकते हैं। दक्षिणी क्षेत्र में एक बजट बार्बर सस्ते दामों पर बुनियादी कट प्रदान कर सकता है, जबकि Vinewood में एक उच्च-स्तरीय सैलून प्रीमियम दरें लेता है लेकिन विशेष शैलियाँ और रंग प्रदान करता है। जब कोई खिलाड़ी बार्बर कुर्सी या टैटू स्टेशन के पास पहुंचता है तो टारगेट सिस्टम या निकटता मार्करों का उपयोग करके दुकान मेनू ट्रिगर करें। खिलाड़ी को कुर्सी में बैठाने के लिए उपयोग करें TaskStartScenarioInPlace नाई की दुकानों के लिए बैठने के परिदृश्य के साथ, या टैटू सत्रों के लिए उन्हें एक विशिष्ट स्थान पर खड़ा करें। प्रत्येक स्थान पर NPC नाई या टैटू कलाकारों को उपयुक्त पेड मॉडल का उपयोग करके स्पॉन करें और उन्हें निष्क्रिय एनिमेशन सौंपें जो उन्हें काम करते हुए दिखाते हैं। जब कोई खिलाड़ी दुकान के साथ इंटरैक्ट करता है, तो NPC खिलाड़ी के पास काम करने वाली एनिमेशन चला सकता है ताकि सेवा का अनुकरण हो, जिससे अनुभव में दृश्य डूबाव बढ़े। सत्र के बाद, NPC अपनी निष्क्रिय स्थिति में लौटता है। डेटाबेस में प्रति-दुकान राजस्व ट्रैक करें ताकि खिलाड़ी-स्वामित्व वाली दुकान गेमप्ले का समर्थन किया जा सके जहाँ उद्यमी अपनी नाई की दुकानें या टैटू पार्लर खरीदते और प्रबंधित करते हैं, कीमतें निर्धारित करते हैं और NPC स्टाफ या अन्य खिलाड़ियों को कर्मचारी के रूप में नियुक्त करते हैं।

शुरू करने के लिए तैयार?

हमारी शॉप से स्क्रिप्ट लें, या सपोर्ट, अपडेट और आगे आने वाली चीज़ों की झलक के लिए Discord से जुड़ें।