Czym jest VDM?
Vehicle Deathmatch (VDM) odnosi się do używania pojazdu jako broni w celu celowego taranowania, zabijania lub ranienia innych graczy bez odpowiedniego uzasadnienia fabularnego. Na serwerach roleplay FiveM, VDM narusza podstawowe zasady serwera i zakłóca doświadczenie roleplay, którego szukają gracze.
Dlaczego VDM ma znaczenie
Serwery Roleplay działają na zasadzie realistycznej interakcji. Gdy gracz celowo taranuje swój pojazd w innych bez kontekstu fabularnego, to:
- Łamie immersję dla wszystkich uczestników
- Uniemożliwia rozwijanie znaczących historii
- Tworzy niesprawiedliwe przewagi w rozgrywce
- Prowadzi do frustracji graczy i spadku populacji serwera
Typowe scenariusze VDM
Jasne naruszenia VDM:
- Wjeżdżanie na chodniki, aby potrącić pieszych
- Taranowanie stojących pojazdów na światłach
- Używanie pojazdów do blokowania wejść do szpitali
- Celowe powodowanie czołowych zderzeń
Szare strefy wymagające kontekstu:
- Manewry policyjne PIT podczas pościgów
- Ataki pojazdami gangów z wcześniejszą fabułą
- Przypadkowe kolizje podczas wyścigów
- Reakcje pojazdów uprzywilejowanych
Implementacja techniczna: Systemy anty-VDM
Skrypt wykrywania po stronie serwera
-- resources/anti-vdm/server.lua
local vdmWarnings = {}
local VDM_THRESHOLD = 3
local DAMAGE_THRESHOLD = 50
RegisterServerEvent('vdm:checkCollision')
AddEventHandler('vdm:checkCollision', function(targetId, damage, speed)
local source = source
-- Validate input
if not targetId or not damage or not speed then return end
-- Check if damage and speed exceed thresholds
if damage > DAMAGE_THRESHOLD and speed > 30 then
local identifier = GetPlayerIdentifier(source, 0)
-- Initialize warning count
if not vdmWarnings[identifier] then
vdmWarnings[identifier] = 0
end
vdmWarnings[identifier] = vdmWarnings[identifier] + 1
-- Log incident
local logData = {
attacker = GetPlayerName(source),
victim = GetPlayerName(targetId),
damage = damage,
speed = speed,
timestamp = os.time()
}
TriggerEvent('vdm:logIncident', logData)
-- Take action based on warnings
if vdmWarnings[identifier] >= VDM_THRESHOLD then
DropPlayer(source, 'Kicked for VDM violations')
vdmWarnings[identifier] = 0
else
TriggerClientEvent('chat:addMessage', source, {
args = {'^1[WARNING]', 'VDM detected. Warning ' ..
vdmWarnings[identifier] .. '/' .. VDM_THRESHOLD}
})
end
end
end)
Monitorowanie po stronie klienta
-- resources/anti-vdm/client.lua
local lastCollision = 0
local COLLISION_COOLDOWN = 5000 -- 5 seconds
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
local playerPed = PlayerPedId()
if IsPedInAnyVehicle(playerPed, false) then
local vehicle = GetVehiclePedIsIn(playerPed, false)
if GetPedInVehicleSeat(vehicle, -1) == playerPed then
if HasEntityCollidedWithAnything(vehicle) then
local currentTime = GetGameTimer()
if currentTime - lastCollision > COLLISION_COOLDOWN then
local speed = GetEntitySpeed(vehicle) * 3.6 -- Convert to km/h
-- Check for pedestrian collision
local coords = GetEntityCoords(vehicle)
local closestPed = GetClosestPed(coords.x, coords.y, coords.z,
5.0, 1, 0, 0, 0, -1)
if DoesEntityExist(closestPed) and IsEntityAPed(closestPed) then
local targetPlayer = NetworkGetPlayerIndexFromPed(closestPed)
if targetPlayer ~= -1 then
local damage = GetEntityHealth(closestPed)
TriggerServerEvent('vdm:checkCollision',
GetPlayerServerId(targetPlayer),
damage, speed)
end
end
lastCollision = currentTime
end
end
end
end
end
end)
Konfiguracja serwera
FiveM Dodatki do server.cfg:
# Anti-VDM Configuration set vdm_enabled true set vdm_max_warnings 3 set vdm_damage_threshold 50 set vdm_speed_threshold 30 set vdm_log_incidents true set vdm_webhook "https://discord.com/api/webhooks/YOUR_WEBHOOK_HERE" # Ensure anti-vdm resource starts ensure anti-vdm
Najlepsze praktyki dla administratorów serwerów
1. Jasne określenie zasad
Utwórz szczegółowe zasady VDM w dokumentacji serwera:
Rule 2.1 - Vehicle Deathmatch (VDM) - Using any vehicle as a weapon is prohibited - Exceptions: Authorized police tactics, sanctioned events - Punishment: 1st offense - Warning, 2nd - 24h ban, 3rd - Permanent ban
2. Protokół szkolenia personelu
Przeszkol moderatorów w identyfikacji VDM:
- Przeglądaj logi obrażeń
- Sprawdź prędkość gracza w momencie uderzenia
- Zweryfikuj kontekst fabularny
- Dokumentuj dowody (klipy, zrzuty ekranu)
3. System zgłaszania graczy
-- Simple reporting command
RegisterCommand('reportvdm', function(source, args, rawCommand)
local targetId = tonumber(args[1])
local reason = table.concat(args, ' ', 2)
if not targetId or not reason then
TriggerClientEvent('chat:addMessage', source, {
args = {'^1[ERROR]', 'Usage: /reportvdm [player_id] [reason]'}
})
return
end
-- Create report ticket
local report = {
reporter = GetPlayerName(source),
reported = GetPlayerName(targetId),
reason = reason,
timestamp = os.date('%Y-%m-%d %H:%M:%S'),
status = 'pending'
}
-- Store in database or send to Discord
TriggerEvent('vdm:createReport', report)
end, false)
Typowe wyzwania w implementacji
Fałszywe alarmy
- Wykrywanie kolizji spowodowane opóźnieniami
- Desynchronizacja między graczami
- Legitymowane wypadki
Rozwiązanie: Wprowadź okresy karencji i sprawdzanie kontekstu:
-- Check if players are in active scenario local function isInActiveRP(playerId) -- Check database for active scenarios -- Return true if player is in police chase, race, etc. end
Wpływ na wydajność
Monitoruj użycie zasobów skryptu:
-- Add to fxmanifest.lua resource_monitor_mode 'yes'
Integracja z popularnymi frameworkami
Framework ESX
ESX = nil
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
-- Add VDM violations to player record
RegisterServerEvent('vdm:recordViolation')
AddEventHandler('vdm:recordViolation', function(targetId)
local xPlayer = ESX.GetPlayerFromId(source)
MySQL.Async.execute('INSERT INTO vdm_violations SET identifier = @identifier, timestamp = @timestamp',
{
['@identifier'] = xPlayer.identifier,
['@timestamp'] = os.time()
})
end)
Framework QBCore
local QBCore = exports['qb-core']:GetCoreObject()
-- Integration with admin menu
QBCore.Commands.Add('checkvdm', 'Check player VDM history', {{name = 'id', help = 'Player ID'}}, true, function(source, args)
local Player = QBCore.Functions.GetPlayer(tonumber(args[1]))
if Player then
-- Fetch VDM history
MySQL.Async.fetchAll('SELECT * FROM vdm_logs WHERE citizenid = @citizenid', {
['@citizenid'] = Player.PlayerData.citizenid
}, function(result)
TriggerClientEvent('qb-admin:client:showVDMHistory', source, result)
end)
end
end, 'admin')
Testowanie Twojego systemu Anti-VDM
Zautomatyzowany zestaw testów
-- tests/vdm_test.lua
local function testVDMDetection()
-- Simulate collision event
local mockData = {
attacker = 1,
victim = 2,
damage = 75,
speed = 45
}
TriggerEvent('vdm:checkCollision', mockData.victim, mockData.damage, mockData.speed)
-- Verify warning was issued
-- Check if log was created
-- Confirm webhook was triggered
end
Metryki wydajności
Śledź skuteczność systemu:
-- Database schema CREATE TABLE vdm_metrics ( id INT AUTO_INCREMENT PRIMARY KEY, date DATE, total_incidents INT, warnings_issued INT, players_kicked INT, false_positives INT );
Podsumowanie
Zapobieganie VDM wymaga wdrożenia technicznego, jasnych zasad i konsekwentnego egzekwowania, aby utrzymać wysokiej jakości środowiska roleplay na serwerach FiveM.
