Przejdź do treści
Cała dokumentacja

PVP

System PvP ze strefami FFA, strefami Only i drużynowymi meczami w lobby. Każda strefa i każdy mecz działa we własnym wymiarze. Do tego dochodzi ranking i panel meczu. Tabelę skrypt tworzy sam.

Wymagania
  • ESX Legacy (es_extended, testowane z 1.14)
  • oxmysql
  • OneSync
  • W ESX musi być ustawione Config.EnablePVP = true (domyślnie)
  • Do menu garażu na mapach z pojazdami: esxmenudefault (lub własne menu przez ClientVehicleMenu)

Funkcje

  • Strefy FFA: Każdy na każdego. W każdej strefie stałe bronie albo własne bronie gracza. Respawn z kamizelką i krótką ochroną po spawnie.
  • Strefy Only: Wszyscy mają te same bronie, opcjonalnie z pojazdem (np. BF 400) przy każdym spawnie.
  • Lobby: Drużyna A przeciw drużynie B w trybie best-of z rundą decydującą. Do wyboru są mapa, tryb (pieszo lub pojazd), rundy, do 3 broni i opcjonalne hasło. Właściciel może wyrzucać, mieszać i rozwiązać lobby.
  • Obserwowanie: Kto odpadnie w rundzie, obserwuje żywych kolegów z drużyny i przełącza ich ← →.
  • Panel meczu u góry pośrodku i Ranking z filtrami FFA, Only i Lobby (łącznie z wygranymi i przegranymi).
  • Ochrona broni: Stałe bronie istnieją tylko w PvP. Prawdziwe bronie i ich amunicja pozostają chronione.
  • Logi na Discordzie, eksporty i własne funkcje do podłączania innych skryptów.

Instalacja

  1. Wrzuć folder off_pvp do swojego folderu resources.
  2. Dodaj do server.cfg, po oxmysql i ESX:
cfg
ensure oxmysql
ensure es_extended
ensure off_pvp
  1. Dostosuj punkty PvP, strefy i mapy w config/ do swojego serwera.

Tabela off_pvp_stats tworzy się automatycznie przy pierwszym starcie.

Przykładowe współrzędne

Strefy w config/settings/config.ffa.lua i config/settings/config.only.lua oraz mapy w config/settings/config.lobby.lua to tylko przykłady. Sprawdź wszystkie pozycje w grze i wpisz własne.

Konfiguracja

Ustawienia są w config/settings/: config.lua dla wszystkiego, co ogólne, config.ffa.lua, config.only.lua i config.lobby.lua dla trzech trybów.

config/settings/config.lua

OpcjaDomyślnieOpis
serverInfo.name'OFF SCRIPTS'Nazwa serwera, widoczna w interfejsie zamiast „OFF SCRIPTS”
serverInfo.locale'de'Język: de, en, pl, fr, es lub it
serverInfo.color{ 155, 89, 255 }Kolor UI (RGB)
serverInfo.design3Wygląd interfejsu: 1 = Klasyczny, 2 = Paragon, 3 = Storefront
blurtrueRozmyte tło, dopóki menu jest otwarte
quitCommand'quitffa'Komenda do opuszczania FFA, Only, lobby i trwających meczów
defaultPed's_m_y_valet_01'NPC dla punktów bez prawidłowego ped
points1 przykładPunkty PvP, w których E otwiera menu (patrz niżej)
markerpatrz plikWygląd punktów z markerem: type, size, alpha, drawDistance
respawn.seconds3Czas oczekiwania na respawn w FFA i Only
respawn.protection3Sekundy nieśmiertelności po spawnie
respawn.armour100Kamizelka po spawnie
killHealtruePo każdym zabójstwie pełne życie i pełna kamizelka (FFA, Only i Lobby)
leaderboardSize50Tylu graczy pokazuje ranking dla każdego trybu (3–500)

Punkty PvP (points):

PoleOpis
idUnikalna nazwa punktu
labelNazwa w tekście pomocy i na blipie
positionvec4(x, y, z, heading)
interaction'ped' = NPC, 'marker' = marker na ziemi
pedModel NPC, bez prawidłowego modelu używany jest defaultPed
scenarioAnimacja NPC (opcjonalnie)
blip{ sprite, color, scale }, false = brak blipa

config/settings/config.ffa.lua i config/settings/config.only.lua

Config.ffa i Config.only zawierają strefy. Każda strefa ma:

PoleOpis
idUnikalna nazwa, jednocześnie nazwa obrazka: web/dist/assets/maps/<id>.png
labelNazwa w menu
centerŚrodek strefy, vec3
radiusPromień w metrach. Kto go opuści, trafia na losowy spawn
maxPlayersLiczba graczy jednocześnie
spawnsLista vec4. Przy respawnie wybierany jest spawn najdalej od innych graczy
weapons{ name, ammo }. FFA: opcjonalnie, bez listy walczy się własnymi broniami i zużywa prawdziwą amunicję. Only: wymagane
vehicleTylko Only, opcjonalnie: { model, label }. Gracz spawnuje się na tym pojeździe

config/settings/config.lobby.lua

Config.lobby zawiera ustawienia lobby:

OpcjaDomyślnieOpis
maxPlayers10Gracze na lobby, na drużynę maksymalnie połowa
maxLobbies8Liczba lobby jednocześnie
maxWeapons3Bronie, które można wybrać przy tworzeniu
rounds1 / 15 / 5Rundy: min, max i default
prepareSeconds3Przygotowanie przed każdą rundą (zamrożenie, bez broni), w pierwszej rundzie 3 sekundy dłużej
roundEndSeconds1Przerwa po rundzie
resultSeconds1Wyświetlanie wyniku, potem powrót
roundMinutes5Limit czasu na rundę, 0 = bez limitu
spectateDelay3Sekundy od śmierci do obserwowania
startRange50.0Tak blisko punktu PvP muszą być wszyscy członkowie przy starcie
overtimeRounds1Rundy decydujące przy remisie, 0 = remis
armour100Kamizelka na początku każdej rundy
weapons10 broniBronie do wyboru przy tworzeniu: { name, ammo }
vehicles3 pojazdyDomyślne pojazdy dla map z pojazdami bez własnej listy: { model, label }

Config.maps zawiera mapy dla lobby:

PoleOpis
id / labelUnikalna nazwa (= nazwa obrazka jak przy strefach) i nazwa wyświetlana
mode'foot' = pieszo, 'vehicle' = mapa z pojazdami
center / radiusKula wyświetlana w meczu (vec3 i metry). Służy tylko do wyświetlania, nie ma granicy
vehiclesOpcjonalnie, własna lista pojazdów { model, label }. Bez listy obowiązuje Config.lobby.vehicles
teams.a / teams.bNa drużynę jeden spawn (vec4). Wszyscy gracze drużyny zaczynają tam każdą rundę
garage / vehicleSpawnTylko mapy z pojazdami, na drużynę: marker garażu (vec3) i punkt wyjazdu (vec4)

config/functions.lua

Tutaj podłączasz własne skrypty. Błędy w nich trafiają do konsoli, skrypt działa dalej. kind to zawsze 'ffa', 'only' lub 'lobby'.

FunkcjaStronaDo czego
ServerCanJoin(source, kind, id)Serwerreturn false, 'Text' blokuje dołączenie i start lobby, np. w więzieniu
ServerKill(killer, victim, kind, id)SerwerZaliczone zabójstwo, np. pieniądze jako nagroda
ServerDeath(victim, killer, kind, id, teamkill)SerwerKażda śmierć, killer może być nil
ServerMatchEnded(lobbyId, result)SerwerMecz zakończony: { winner, score, map, teams }, winner = 'a', 'b' lub nil
ServerJoined(source, kind, id)SerwerGracz wchodzi do strefy lub meczu
ServerLeft(source, kind, id, reason)Serwerreason = 'quit', 'drop', 'end', 'kick' lub 'stop'
Notify(message, type) / HelpNotify(text)KlientPowiadomienie i tekst pomocy · Serwer: Notify(source, message, type)
ClientRevive(position)KlientOżywianie, np. własny skrypt ambulance
ClientDeath(kind) / ClientRespawn(kind)KlientŚmierć i respawn w PvP, np. ukryj ekran śmierci
ClientGiveLoadout(loadout)KlientDawanie i oddawanie broni
ClientSetFuel(vehicle, fuel)KlientSkrypt paliwa
ClientVehicleSpawned(vehicle, plate, kind)KlientPojazd PvP zespawnowany, np. daj kluczyki
ClientVehicleMenu(vehicles, onSelect)KlientMenu garażu na mapach z pojazdami (domyślnie: menu ESX Default)
ClientStateChanged(state)Klient{ kind, id, team } przy wejściu, nil przy wyjściu, np. zablokuj telefon lub własny HUD

config/settings/config.server.lua i języki

Webhooki Discorda dla lobby (lobby utworzone, mecz rozpoczęty, mecz zakończony, lobby rozwiązane) i zones (wejście do strefy i wyjście). '' wyłącza log. Wszystkie teksty są w config/locales/ (jeden plik na język).

W grze

  • Menu: E w punkcie PvP. Działa tylko, gdy żyjesz, jesteś pieszo, w normalnym wymiarze i nie w gangwarze.
  • FFA i Only: Dołącz teleportuje cię do strefy. Po śmierci po respawn.seconds grasz dalej na spawnie. Na górze widzisz zabójstwa, śmierci i graczy w strefie.
  • Wychodzenie: /quitffa (lub twój quitCommand) przenosi cię z powrotem w miejsce, w którym dołączyłeś. Życie i kamizelka są jak wcześniej, własne bronie wracają. Komenda opuszcza też czekające lobby.
  • Utwórz lobby: Wybierz mapę, tryb, rundy, bronie i opcjonalnie hasło. Nowi gracze trafiają do mniejszej drużyny. Zmiana drużyny działa, dopóki druga drużyna nie jest pełna. Po 5 błędnych hasłach lobby jest dla ciebie zablokowane na 60 sekund.
  • Właściciel: startuje, miesza, wyrzuca i rozwiązuje. Gdy właściciel wyjdzie, przejmuje następny członek.
  • Start: Kto jest martwy, w innym wymiarze, w gangwarze lub dalej niż startRange od punktu PvP, wylatuje z lobby. Każda drużyna potrzebuje co najmniej jednego gracza.
  • Mecz:
  • Każda runda zaczyna się od przygotowania (zamrożenie, bez broni), potem są bronie i kamizelka.
  • Rundę wygrywa ten, kto wyeliminuje całą drużynę przeciwną. W trakcie rundy nie ma respawnu. Jeśli dwaj ostatni zginą jednocześnie, nikt nie dostaje punktu.
  • Gdy skończy się limit czasu, wygrywa drużyna z większą liczbą żywych graczy, przy remisie nikt nie dostaje punktu.
  • Mecz wygrywa ten, kto pierwszy zdobędzie ponad połowę rund. Gdy wszystkie rundy są rozegrane, wygrywa wyższy wynik. Przy remisie są rundy decydujące (overtimeRounds), potem remis.
  • Friendly fire jest włączony. Teamkill liczy się jako śmierć, nie jako zabójstwo.
  • Kto opuści trwający mecz, dostaje porażkę. Jeśli drużyna jest potem pusta, druga od razu wygrywa.
  • Potem wszyscy wracają do miejsca startu, lobby zostaje otwarte i znów czeka.
  • Obserwowanie: Po spectateDelay sekundach obserwujesz żywego kolegę z drużyny. Na dole pośrodku są jego nazwa i strzałki. ← i → przełączają.
  • Garaż (mapy z pojazdami): W trakcie rundy E przy markerze garażu twojej drużyny otwiera listę pojazdów. Każdy gracz ma jeden pojazd, nowy zastępuje stary.
  • Ranking: Najlepsi gracze w każdym trybie (liczba przez leaderboardSize), posortowani według zabójstw. Nowe wartości pojawiają się najpóźniej po minucie, po meczu od razu.

Dla deweloperów

lua
-- Serwer
local inPvp = exports.off_pvp:IsInPvp(source)        -- FFA, Only lub trwający mecz
local ffa = exports.off_pvp:IsFFA(source)
local only = exports.off_pvp:IsOnly(source)
local lobby = exports.off_pvp:IsLobby(source)        -- w trwającym meczu
local inLobby = exports.off_pvp:IsInLobby(source)    -- członek lobby, czeka lub jest w meczu
local info = exports.off_pvp:GetPvp(source)          -- { kind, id, team, alive, kills, deaths } lub nil
local removed = exports.off_pvp:RemoveFromPvp(source) -- zabiera gracza ze strefy, meczu lub czekającego lobby, true/false
local stats = exports.off_pvp:GetStats(source)       -- { ffa = { kills, deaths }, only = { ... }, lobby = { kills, deaths, wins, losses } } lub nil

-- Klient
local inPvp = exports.off_pvp:IsInPvp()
local ffa = exports.off_pvp:IsFFA()
local only = exports.off_pvp:IsOnly()
local lobby = exports.off_pvp:IsLobby()
local spectating = exports.off_pvp:IsSpectating()
local info = exports.off_pvp:GetPvp()                -- { kind, id, team, phase } lub nil
  • Statebag offPvp: 'ffa', 'only' lub 'lobby', dopóki gracz jest w strefie lub meczu.
  • offinventory: canOpen() w off_inventory/config/functions.lua blokuje ekwipunek i bagażnik w PvP, gdy tylko offpvp działa.

Częste problemy

Przy starcie skrypt zgłasza błędy i wskazówki w konsoli serwera. Błędne strefy i mapy są tam wymienione i pomijane.

ProblemRozwiązanie
„To teraz niemożliwe.” przy otwieraniuJesteś martwy, w innym wymiarze lub w gangwarze.
Brak strefy lub mapy w menuSprawdź konsolę, wpis ma błąd (np. brak spawnów).
Brak obrazka strefy lub mapyBrakuje web/dist/assets/maps/<id>.png.
Garaż nie otwiera menuUruchom esxmenudefault lub dostosuj ClientVehicleMenu.
Gracze nie zadają sobie obrażeńUstaw w ESX Config.EnablePVP = true.
Skrypt ambulance pokazuje w PvP ekran śmierciUkryj go w ClientDeath i pokaż z powrotem w ClientRespawn.
Po crashu w złym miejscuPrzy następnym logowaniu wracasz automatycznie do miejsca startu.
Restart zasobu w trakcie meczuWszyscy wracają, mecz nie jest liczony. Lepiej nie restartować w trakcie meczów.

Jeszcze nie kupiony?

Zobacz PVP w sklepie