คู่มือการตั้งค่า
คู่มือนี้จะอธิบายการตั้งค่าต่างๆ ของระบบ AFU Enhanced Shop พร้อมตัวอย่างและคำอธิบาย
สารบัญ
การตั้งค่าพื้นฐาน (settings.lua)
การตั้งค่าร้านค้า (shops/*.lua)
การตั้งค่าฮุค (hooks/)
การตั้งค่าฐานข้อมูล (queries.lua)
การตั้งค่าพื้นฐาน (settings.lua)
-- เส้นทางไปยังไฟล์รูปภาพสินค้า ใช้สำหรับแสดงภาพสินค้าในหน้าร้านค้า
Config.ItemsImagePath = "nui://inventory/web/assets/icons/"
-- จำนวนรายการสั่งซื้อ (Preset) สูงสุดที่ผู้เล่นสามารถบันทึกได้
Config.MaxPresetPerPlayer = 10
-- เปิดใช้งานระบบน้ำหนัก (true) หรือระบบจำกัดจำนวน (false)
Config.WeightSystem = true
-- อัตราภาษีสำหรับการชำระเงินแต่ละประเภท (หน่วย: เปอร์เซ็นต์)
Config.TaxPercent = {
money = 0, -- ภาษีสำหรับการชำระด้วยเงินสด (ไม่มีภาษี)
bank = 5, -- ภาษีสำหรับการชำระด้วยเงินในธนาคาร (5%)
}
-- นิยามชื่อส่วนลดที่มีในระบบ
ENUMDiscountPreset = {
PRESET_1 = "PRESET_1", -- ส่วนลดประเภทที่ 1
-- เพิ่มส่วนลดประเภทอื่นๆ ได้ตามต้องการ
-- PRESET_2 = "PRESET_2",
-- GOLD_MEMBER = "GOLD_MEMBER",
}
-- รายละเอียดของส่วนลดแต่ละประเภท
Config.DiscountPresets = {
[ENUMDiscountPreset.PRESET_1] = {
label = "ส่วนลด VIP Card Lv.1", -- ชื่อที่แสดงของส่วนลด
percentDiscount = 10, -- เปอร์เซ็นต์ส่วนลด (10%)
maxDiscountPrice = 1000, -- จำนวนเงินส่วนลดสูงสุด (1,000)
Remove = true, -- ลบไอเทมที่ใช้เป็นส่วนลดหลังใช้งาน (true = ลบ)
itemsDiscount = { -- รายการไอเทมที่ใช้เป็นส่วนลด
"vip_card_lv_1", -- ชื่อไอเทมในระบบ
},
-- ฟังก์ชันตรวจสอบเงื่อนไขเพิ่มเติม (เช่น เช็คสถานะ VIP)
AlwaysHas = function(source)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return false end
return true -- ส่งคืนค่า true หากผู้เล่นมีสิทธิ์ใช้ส่วนลดนี้
end,
},
-- ตัวอย่างส่วนลดเพิ่มเติม
--[[
[ENUMDiscountPreset.GOLD_MEMBER] = {
label = "ส่วนลดสมาชิกระดับทอง",
percentDiscount = 20, -- ลด 20%
maxDiscountPrice = 2000, -- ส่วนลดสูงสุด 2,000
Remove = false, -- ไม่ลบไอเทมหลังใช้งาน
itemsDiscount = {
"gold_member_card",
},
AlwaysHas = function(source)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return false end
-- ตรวจสอบเงื่อนไขเพิ่มเติม
return xPlayer.job.grade >= 3 -- ตัวอย่าง: ตรวจสอบระดับอาชีพ
end,
}
--]]
}
การตั้งค่าร้านค้า (shops/*.lua)
ตัวอย่างร้านค้าทั่วไป (general.lua)
-- สร้างร้านค้าทั่วไปที่ทุกคนสามารถเข้าถึงได้
local shop = {
name = "General Store", -- ชื่อร้านค้า
categories = { -- หมวดหมู่สินค้า
{
name = "General", -- ชื่อหมวดหมู่
items = { -- รายการสินค้าในหมวดหมู่
{
name = "cannabis_leaf", -- ชื่อไอเทมในระบบ
type = EItemType.ITEM, -- ประเภทไอเทม (ITEM = สิ่งของ)
price = 5, -- ราคา (5)
},
{
name = "bread",
type = EItemType.ITEM,
price = 1,
},
}
},
{
name = "Drinks", -- หมวดหมู่เครื่องดื่ม
items = {
{
name = "water",
type = EItemType.ITEM,
price = 2,
},
{
name = "coffee",
type = EItemType.ITEM,
price = 2,
},
}
}
},
allowJobs = ESystem.ALLOW_ALL_JOBS, -- อนุญาตให้ทุกอาชีพเข้าถึงได้
allowDiscountPresets = { -- ส่วนลดที่อนุญาตให้ใช้ในร้านนี้
ENUMDiscountPreset.PRESET_1, -- อนุญาตให้ใช้ส่วนลด PRESET_1
},
locations = { -- ตำแหน่งร้านค้า (vector4 = x, y, z, heading)
vector4(-212.9444, -950.8653, 29.34077, 0.0),
},
}
ตัวอย่างร้านค้าเฉพาะอาชีพ (police.lua)
-- สร้างร้านค้าสำหรับตำรวจเท่านั้น
local shop = {
name = "Police Store", -- ชื่อร้านค้า
categories = { -- หมวดหมู่สินค้า
{
name = "Guns", -- หมวดหมู่อาวุธ
items = {
{
name = "WEAPON_PISTOL", -- ชื่ออาวุธในระบบ
type = EItemType.WEAPON, -- ประเภทไอเทม (WEAPON = อาวุธ)
price = 0, -- ราคา (0 = ฟรี)
},
{
name = "WEAPON_ASSAULTRIFLE",
type = EItemType.WEAPON,
price = 1000,
},
}
},
{
name = "Tools", -- หมวดหมู่เครื่องมือ
items = {
{
name = "handcuffs",
type = EItemType.ITEM,
price = 0,
},
{
name = "WEAPON_BAT",
type = EItemType.WEAPON,
price = 0,
},
}
}
},
allowJobs = { -- อาชีพที่สามารถเข้าถึงร้านนี้ได้
"police", -- อนุญาตเฉพาะตำรวจ
},
allowDiscountPresets = { -- ส่วนลดที่อนุญาตให้ใช้ในร้านนี้
ESystem.NO_DISCOUNT_PRESET, -- ไม่อนุญาตให้ใช้ส่วนลดใดๆ
},
locations = { -- ตำแหน่งร้านค้า
vector4(450.0, -980.0, 30.0, 0.0), -- พิกัดสถานีตำรวจ
},
}
การตั้งค่าฮุค (hooks)
ฮุคเป็นฟังก์ชันที่ใช้เชื่อมต่อกับระบบอื่นๆ ของเซิร์ฟเวอร์ คุณสามารถปรับแต่งได้ตามการทำงานของเซิร์ฟเวอร์ของคุณ
ฮุคฝั่งไคลเอนต์ (client.lua)
-- ฟังก์ชันเริ่มต้นระบบฝั่งไคลเอนต์
function ClientHooks.Init()
-- เชื่อมต่อกับ ESX Framework
ESX = nil
while not ESX do
Wait(0)
ESX = exports["es_extended"]:getSharedObject()
end
-- รอจนกว่าผู้เล่นจะโหลดเสร็จ
while not ESX.IsPlayerLoaded() do
Wait(0)
end
-- ดึงข้อมูลผู้เล่น
local playerData = ESX.GetPlayerData()
if not playerData then
logger.error("player data not found")
return
end
end
-- ฟังก์ชันตรวจสอบว่าผู้เล่นมีเงินเพียงพอหรือไม่
-- @param payBy ประเภทการชำระเงิน (CASH หรือ BANK)
-- @param totalPrice ราคารวม
-- @return boolean, NeedMoreMoneyTotal
function ClientHooks.EnoughMoney(payBy, totalPrice)
local playerData = ESX.GetPlayerData()
-- ตรวจสอบเงินของผู้เล่นตามประเภทการชำระ
-- คืนค่า true หากมีเงินพอ, false หากไม่พอ พร้อมจำนวนเงินที่ขาด
end
-- ฟังก์ชันตรวจสอบว่าผู้เล่นมีไอเทมนี้หรือไม่
function ClientHooks.HaveItem(itemName)
-- ตรวจสอบว่าผู้เล่นมีไอเทมในระบบหรือไม่
-- คืนค่า true หากมี, false หากไม่มี
end
ฮุคฝั่งเซิร์ฟเวอร์ (server.lua)
-- ฟังก์ชันเริ่มต้นระบบฝั่งเซิร์ฟเวอร์
function Hooks.Init()
-- เชื่อมต่อกับ ESX Framework
ESX = exports["es_extended"]:getSharedObject()
while not ESX do
Wait(0)
ESX = exports["es_extended"]:getSharedObject()
end
end
-- ฟังก์ชันตรวจสอบอาชีพของผู้เล่น
-- @param source ไอดีผู้เล่น
-- @param job ชื่ออาชีพที่ต้องการตรวจสอบ
-- @return boolean
function Hooks.IsAllowPlayerJob(source, job)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return false end
return xPlayer.job.name == job
end
-- ฟังก์ชันหักเงินผู้เล่น
-- @param source ไอดีผู้เล่น
-- @param payType ประเภทการชำระเงิน (CASH หรือ BANK)
-- @param money จำนวนเงินที่ต้องการหัก
-- @return boolean
function Hooks.RemoveMoney(source, payType, money)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return false end
if payType == ENUMPayBy.CASH then
xPlayer.removeAccountMoney("money", money)
elseif payType == ENUMPayBy.BANK then
xPlayer.removeAccountMoney('bank', money)
else
return false
end
return true
end
-- ฟังก์ชันเพิ่มไอเทมให้ผู้เล่น
-- @param source ไอดีผู้เล่น
-- @param items ตารางรายการไอเทม
-- @return boolean
function Hooks.GiveItems(source, items)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return false end
for _, item in next, items do
xPlayer.addInventoryItem(item.name, item.total)
end
return true
end
การตั้งค่าฐานข้อมูล (queries.lua)
-- ฟังก์ชันสร้างตารางฐานข้อมูล
function Queries.MigrateDatabase()
local query = [[
CREATE TABLE IF NOT EXISTS afu_shop_preset (
id INT AUTO_INCREMENT PRIMARY KEY,
identifier VARCHAR(60) NOT NULL,
name VARCHAR(100) NOT NULL,
items LONGTEXT NOT NULL
)
]]
MySQL.query.await(query)
logger.success('migrated database')
end
-- ฟังก์ชันดึงจำนวน Preset ของผู้เล่น
-- @param source ไอดีผู้เล่น
-- @return number จำนวน Preset
function Queries.GetPresetCount(source)
local identifier = GetPlayerIdentifierByType(source, 'steam')
local result = MySQL.query.await('SELECT COUNT(*) FROM afu_shop_preset WHERE identifier = ?',
{ identifier }
)
return result[1]['COUNT(*)']
end
-- ฟังก์ชันสร้าง Preset ใหม่
-- @param source ไอดีผู้เล่น
-- @param name ชื่อ Preset
-- @param items รายการไอเทมใน Preset
-- @return Error|nil
function Queries.CreatePreset(source, name, items)
local identifier = GetPlayerIdentifierByType(source, 'steam')
local id = MySQL.insert.await('INSERT INTO `afu_shop_preset` (identifier, name, items) VALUES (?, ?, ?)', {
identifier, name, json.encode(items)
})
if not id or id == 0 then
return errors.New('failed to insert preset id not generated')
end
return nil
end
-- ฟังก์ชันลบ Preset
-- @param source ไอดีผู้เล่น
-- @param id ไอดีของ Preset
-- @return Error|nil
function Queries.DeletePreset(source, id)
local identifier = GetPlayerIdentifierByType(source, 'steam')
local result = MySQL.query.await('DELETE FROM `afu_shop_preset` WHERE id = ? AND identifier = ?', {
id, identifier
})
if result.affectedRows == 0 then
return errors.New(('failed to delete preset id: %s'):format(id))
end
return nil
end
-- ฟังก์ชันโหลด Preset ทั้งหมดของผู้เล่น
-- @param source ไอดีผู้เล่น
-- @return table รายการ Preset
function Queries.LoadPresets(source)
local identifier = GetPlayerIdentifierByType(source, 'steam')
local presets = MySQL.query.await('SELECT `id`, `name`, `items` FROM `afu_shop_preset` WHERE identifier = ?', {
identifier
})
for _, preset in next, (presets) do
local items = json.decode(preset.items)
preset.items = items
end
return presets
end
ตัวอย่างการสร้างร้านค้าใหม่
หากคุณต้องการสร้างร้านค้าใหม่ คุณสามารถสร้างไฟล์ใหม่ใน config/shops/
ตามตัวอย่างด้านล่าง:
ตัวอย่างร้านค้าอาหาร (food_shop.lua)
---@type table<number, Shop>
ConfigShops = ConfigShops or {}
---@type Shop
local shop = {
name = "ร้านอาหาร", -- ชื่อร้านค้า
categories = {
{
name = "อาหารคาว", -- หมวดหมู่อาหารคาว
items = {
{
name = "food_padthai", -- ชื่อไอเทมในระบบ
type = EItemType.ITEM,
price = 50, -- ราคา 50
},
{
name = "food_kaopadkrapao",
type = EItemType.ITEM,
price = 45,
},
}
},
{
name = "อาหารหวาน", -- หมวดหมู่อาหารหวาน
items = {
{
name = "food_itime",
type = EItemType.ITEM,
price = 35,
},
{
name = "food_kakang",
type = EItemType.ITEM,
price = 30,
},
}
}
},
allowJobs = ESystem.ALLOW_ALL_JOBS, -- อนุญาตให้ทุกอาชีพเข้าถึงได้
allowDiscountPresets = {
ENUMDiscountPreset.PRESET_1, -- อนุญาตให้ใช้ส่วนลด PRESET_1
},
locations = {
vector4(80.8980, -1192.9641, 29.6341, 275.9749), -- พิกัดร้านอาหาร
},
}
ConfigShops[#ConfigShops + 1] = shop -- เพิ่มร้านค้าเข้าไปในระบบ
ตัวอย่างการเพิ่มส่วนลดใหม่
หากคุณต้องการเพิ่มส่วนลดใหม่ คุณสามารถเพิ่มใน config/settings.lua
ตามตัวอย่างด้านล่าง:
-- 1. เพิ่ม Enum ใหม่
ENUMDiscountPreset = {
PRESET_1 = "PRESET_1",
MEMBER_CARD = "MEMBER_CARD", -- เพิ่มประเภทส่วนลดใหม่
}
-- 2. เพิ่มรายละเอียดส่วนลด
Config.DiscountPresets = {
[ENUMDiscountPreset.PRESET_1] = {
-- ค่าเดิม
},
[ENUMDiscountPreset.MEMBER_CARD] = {
label = "ส่วนลดบัตรสมาชิก",
percentDiscount = 15, -- ลด 15%
maxDiscountPrice = 5000, -- ส่วนลดสูงสุด 5,000
Remove = false, -- ไม่ลบไอเทมหลังใช้งาน
itemsDiscount = {
"membership_card",
},
AlwaysHas = function(source)
-- ตรวจสอบเงื่อนไขเพิ่มเติม (ถ้ามี)
return true
end,
}
}
💬 พัฒนาโดย AFU Squad 🐌 @Copyright Danyouknowme x Txrxx x Hex ☕ ขอบคุณสำหรับการสนับสนุน 💳 ซื้อโทเคนได้ที่ awayfromus.dev