Auto-sync 2026-04-15 22:20
This commit is contained in:
parent
9b30857065
commit
4d7f4efcea
@ -2,6 +2,13 @@
|
|||||||
-- MercyV Bike – Client
|
-- MercyV Bike – Client
|
||||||
-- ═══════════════════════════════════════════════════════════════
|
-- ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
-- NUI beim Start sicher versteckt halten
|
||||||
|
AddEventHandler('onClientResourceStart', function(res)
|
||||||
|
if res ~= GetCurrentResourceName() then return end
|
||||||
|
SetNuiFocus(false, false)
|
||||||
|
SendNUIMessage({ action = "CLOSE" })
|
||||||
|
end)
|
||||||
|
|
||||||
local NPCEntity = nil
|
local NPCEntity = nil
|
||||||
local NPCData = nil
|
local NPCData = nil
|
||||||
local IsAdmin = false
|
local IsAdmin = false
|
||||||
|
|||||||
@ -4,13 +4,13 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>MercyV Bike</title>
|
<title>MercyV Bike</title>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<script src="vue.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.14/vue.min.js"></script>
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="app" v-show="show">
|
<div id="app" v-show="show" style="display:none;">
|
||||||
|
|
||||||
<!-- ══════════════════ HAUPT-PANEL ══════════════════ -->
|
<!-- ══════════════════ HAUPT-PANEL ══════════════════ -->
|
||||||
<div class="mb-backdrop" v-show="!showAdmin">
|
<div class="mb-backdrop" v-show="!showAdmin">
|
||||||
|
|||||||
@ -11,7 +11,7 @@ function postNUI(event, data) {
|
|||||||
const app = createApp({
|
const app = createApp({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: false,
|
show: false, // WICHTIG: immer false beim Start
|
||||||
showAdmin: false,
|
showAdmin: false,
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
bikes: [],
|
bikes: [],
|
||||||
@ -28,6 +28,11 @@ const app = createApp({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
// Vue ist gemountet - div kann jetzt gesteuert werden
|
||||||
|
document.getElementById('app').style.display = '';
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
close() {
|
close() {
|
||||||
this.show = false;
|
this.show = false;
|
||||||
|
|||||||
@ -2,11 +2,6 @@
|
|||||||
MercyV Bike – NUI Style (gleiche Sprache wie mercyv-garage)
|
MercyV Bike – NUI Style (gleiche Sprache wie mercyv-garage)
|
||||||
═══════════════════════════════════════════════════ */
|
═══════════════════════════════════════════════════ */
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: "GilroyBold";
|
|
||||||
src: url("../mercyv-garage/nui/fonts/Gilroy-Bold.ttf") format("truetype");
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--accent: #E8830A;
|
--accent: #E8830A;
|
||||||
--accent-hover: #F59D2A;
|
--accent-hover: #F59D2A;
|
||||||
@ -22,7 +17,7 @@
|
|||||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: "GilroyBold", -apple-system, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-weight: 700;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -71,7 +66,7 @@ body {
|
|||||||
background: rgba(232,131,10,0.15);
|
background: rgba(232,131,10,0.15);
|
||||||
display: flex; align-items: center; justify-content: center;
|
display: flex; align-items: center; justify-content: center;
|
||||||
}
|
}
|
||||||
.mb-title-main { font-size: 16px; font-family: "GilroyBold", sans-serif; display: block; }
|
.mb-title-main { font-size: 16px; font-family: inherit; font-weight: 700; display: block; }
|
||||||
.mb-title-sub { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.4px; display: block; }
|
.mb-title-sub { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.4px; display: block; }
|
||||||
|
|
||||||
.mb-close-btn {
|
.mb-close-btn {
|
||||||
@ -115,7 +110,7 @@ body {
|
|||||||
.mb-bike-card:hover { border-color: rgba(232,131,10,0.4); transform: translateY(-2px); }
|
.mb-bike-card:hover { border-color: rgba(232,131,10,0.4); transform: translateY(-2px); }
|
||||||
.mb-bike-active { border-color: var(--accent) !important; background: rgba(232,131,10,0.08) !important; }
|
.mb-bike-active { border-color: var(--accent) !important; background: rgba(232,131,10,0.08) !important; }
|
||||||
.mb-bike-img { width: 120px; height: 75px; object-fit: contain; }
|
.mb-bike-img { width: 120px; height: 75px; object-fit: contain; }
|
||||||
.mb-bike-name { font-size: 13px; font-family: "GilroyBold", sans-serif; text-align: center; }
|
.mb-bike-name { font-size: 13px; font-family: inherit; font-weight: 700; text-align: center; }
|
||||||
.mb-bike-free { font-size: 11px; color: var(--accent); }
|
.mb-bike-free { font-size: 11px; color: var(--accent); }
|
||||||
.mb-bike-free i { margin-right: 4px; }
|
.mb-bike-free i { margin-right: 4px; }
|
||||||
|
|
||||||
@ -123,7 +118,7 @@ body {
|
|||||||
.mb-claim-btn {
|
.mb-claim-btn {
|
||||||
padding: 13px 32px;
|
padding: 13px 32px;
|
||||||
background: var(--accent); border: none; border-radius: 8px;
|
background: var(--accent); border: none; border-radius: 8px;
|
||||||
color: #fff; font-size: 15px; font-family: "GilroyBold", sans-serif;
|
color: #fff; font-size: 15px; font-family: inherit; font-weight: 700;
|
||||||
cursor: pointer; letter-spacing: 0.04em;
|
cursor: pointer; letter-spacing: 0.04em;
|
||||||
transition: background 0.15s, transform 0.1s;
|
transition: background 0.15s, transform 0.1s;
|
||||||
}
|
}
|
||||||
@ -172,7 +167,7 @@ body {
|
|||||||
.mb-save-btn {
|
.mb-save-btn {
|
||||||
padding: 12px; border-radius: 8px;
|
padding: 12px; border-radius: 8px;
|
||||||
background: var(--accent); border: none;
|
background: var(--accent); border: none;
|
||||||
color: #fff; font-size: 14px; font-family: "GilroyBold", sans-serif;
|
color: #fff; font-size: 14px; font-family: inherit; font-weight: 700;
|
||||||
cursor: pointer; letter-spacing: 0.04em;
|
cursor: pointer; letter-spacing: 0.04em;
|
||||||
transition: background 0.15s, transform 0.1s;
|
transition: background 0.15s, transform 0.1s;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,8 +74,8 @@ AddEventHandler('onResourceStart', function(res)
|
|||||||
`heading` FLOAT DEFAULT 0
|
`heading` FLOAT DEFAULT 0
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||||
]])
|
]])
|
||||||
TriggerClientEvent('mercyv-bike:syncNPC', -1, NPCData)
|
|
||||||
print('^2[mercyv-bike]^0 NPC-Daten geladen.')
|
print('^2[mercyv-bike]^0 NPC-Daten geladen.')
|
||||||
|
-- Kein Broadcast hier - jeder Client bekommt die Daten beim clientReady
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- ── Client ready ───────────────────────────────────────────────
|
-- ── Client ready ───────────────────────────────────────────────
|
||||||
|
|||||||
@ -641,14 +641,14 @@ CreateThread(function()
|
|||||||
SetEntityInvincible(npcEntity, true)
|
SetEntityInvincible(npcEntity, true)
|
||||||
SetBlockingOfNonTemporaryEvents(npcEntity, true)
|
SetBlockingOfNonTemporaryEvents(npcEntity, true)
|
||||||
|
|
||||||
|
-- ox_target Optionen für den NPC
|
||||||
-- ox_target Optionen für den NPC
|
-- ox_target Optionen für den NPC
|
||||||
exports.ox_target:addLocalEntity(npcEntity, {
|
exports.ox_target:addLocalEntity(npcEntity, {
|
||||||
{
|
{
|
||||||
name = 'medic_npc_heal',
|
name = 'medic_npc_heal',
|
||||||
icon = 'fas fa-kit-medical',
|
icon = 'fas fa-kit-medical',
|
||||||
label = 'Sich selbst heilen (Kostenlos)',
|
label = 'Sich selbst heilen ($1000)', -- Text angepasst
|
||||||
canInteract = function()
|
canInteract = function()
|
||||||
-- Wird nur angezeigt, wenn man lebt und nicht volle HP (200) hat
|
|
||||||
return deathState == 'ALIVE' and GetEntityHealth(PlayerPedId()) < 200
|
return deathState == 'ALIVE' and GetEntityHealth(PlayerPedId()) < 200
|
||||||
end,
|
end,
|
||||||
onSelect = function()
|
onSelect = function()
|
||||||
@ -658,9 +658,8 @@ CreateThread(function()
|
|||||||
{
|
{
|
||||||
name = 'medic_npc_revive',
|
name = 'medic_npc_revive',
|
||||||
icon = 'fas fa-heart-pulse',
|
icon = 'fas fa-heart-pulse',
|
||||||
label = 'Person in der Nähe wiederbeleben',
|
label = 'Person in der Nähe wiederbeleben ($1500)', -- Text angepasst
|
||||||
canInteract = function()
|
canInteract = function()
|
||||||
-- Prüfen ob jemand am Boden liegt in der Nähe des Spielers
|
|
||||||
local coords = GetEntityCoords(PlayerPedId())
|
local coords = GetEntityCoords(PlayerPedId())
|
||||||
local players = ESX.Game.GetPlayersInArea(coords, 5.0)
|
local players = ESX.Game.GetPlayersInArea(coords, 5.0)
|
||||||
|
|
||||||
@ -692,5 +691,4 @@ CreateThread(function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
end)
|
|
||||||
@ -333,6 +333,12 @@ end)
|
|||||||
-- NPC MEDICAL SERVER LOGIC
|
-- NPC MEDICAL SERVER LOGIC
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
|
||||||
|
-- Preise für den NPC-Arzt einstellen
|
||||||
|
local NPCCosts = {
|
||||||
|
Heal = 1000, -- Kosten für "Sich selbst heilen"
|
||||||
|
Revive = 1500 -- Kosten für "Andere Person wiederbeleben"
|
||||||
|
}
|
||||||
|
|
||||||
-- Hilfsfunktion: Prüft ob EMS im Dienst ist
|
-- Hilfsfunktion: Prüft ob EMS im Dienst ist
|
||||||
local function IsEMSOnDuty()
|
local function IsEMSOnDuty()
|
||||||
local xPlayers = ESX.GetExtendedPlayers('job', 'ambulance') -- Ersetze 'ambulance' falls dein Job anders heißt
|
local xPlayers = ESX.GetExtendedPlayers('job', 'ambulance') -- Ersetze 'ambulance' falls dein Job anders heißt
|
||||||
@ -343,6 +349,7 @@ end
|
|||||||
RegisterNetEvent('mercyv-deathscreen:server:npcHealSelf')
|
RegisterNetEvent('mercyv-deathscreen:server:npcHealSelf')
|
||||||
AddEventHandler('mercyv-deathscreen:server:npcHealSelf', function()
|
AddEventHandler('mercyv-deathscreen:server:npcHealSelf', function()
|
||||||
local src = source
|
local src = source
|
||||||
|
|
||||||
if IsEMSOnDuty() then
|
if IsEMSOnDuty() then
|
||||||
TriggerClientEvent('esx:showNotification', src, 'Es sind Sanitäter im Dienst! Bitte rufe den Notruf.')
|
TriggerClientEvent('esx:showNotification', src, 'Es sind Sanitäter im Dienst! Bitte rufe den Notruf.')
|
||||||
return
|
return
|
||||||
@ -350,8 +357,20 @@ AddEventHandler('mercyv-deathscreen:server:npcHealSelf', function()
|
|||||||
|
|
||||||
local xPlayer = ESX.GetPlayerFromId(src)
|
local xPlayer = ESX.GetPlayerFromId(src)
|
||||||
if xPlayer then
|
if xPlayer then
|
||||||
|
local cost = NPCCosts.Heal
|
||||||
|
|
||||||
|
-- Bezahl-Logik (zuerst Bargeld, dann Bank)
|
||||||
|
if xPlayer.getMoney() >= cost then
|
||||||
|
xPlayer.removeMoney(cost)
|
||||||
|
elseif xPlayer.getAccount('bank').money >= cost then
|
||||||
|
xPlayer.removeAccountMoney('bank', cost)
|
||||||
|
else
|
||||||
|
TriggerClientEvent('esx:showNotification', src, 'Du hast nicht genug Geld! (Kosten: $' .. cost .. ')')
|
||||||
|
return -- Bricht hier ab, wenn kein Geld da ist
|
||||||
|
end
|
||||||
|
|
||||||
TriggerClientEvent('mercyv-deathscreen:client:healed', src, 200, 'big')
|
TriggerClientEvent('mercyv-deathscreen:client:healed', src, 200, 'big')
|
||||||
TriggerClientEvent('esx:showNotification', src, 'Der Arzt hat deine Wunden versorgt.')
|
TriggerClientEvent('esx:showNotification', src, 'Der Arzt hat deine Wunden für $' .. cost .. ' versorgt.')
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -359,13 +378,33 @@ end)
|
|||||||
RegisterNetEvent('mercyv-deathscreen:server:npcReviveOther')
|
RegisterNetEvent('mercyv-deathscreen:server:npcReviveOther')
|
||||||
AddEventHandler('mercyv-deathscreen:server:npcReviveOther', function(targetId)
|
AddEventHandler('mercyv-deathscreen:server:npcReviveOther', function(targetId)
|
||||||
local src = source
|
local src = source
|
||||||
|
|
||||||
if IsEMSOnDuty() then
|
if IsEMSOnDuty() then
|
||||||
TriggerClientEvent('esx:showNotification', src, 'Es sind Sanitäter im Dienst! Bitte rufe den Notruf.')
|
TriggerClientEvent('esx:showNotification', src, 'Es sind Sanitäter im Dienst! Bitte rufe den Notruf.')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local xPlayer = ESX.GetPlayerFromId(src)
|
||||||
|
if xPlayer then
|
||||||
|
local cost = NPCCosts.Revive
|
||||||
|
|
||||||
|
-- Bezahl-Logik (zuerst Bargeld, dann Bank)
|
||||||
|
if xPlayer.getMoney() >= cost then
|
||||||
|
xPlayer.removeMoney(cost)
|
||||||
|
elseif xPlayer.getAccount('bank').money >= cost then
|
||||||
|
xPlayer.removeAccountMoney('bank', cost)
|
||||||
|
else
|
||||||
|
TriggerClientEvent('esx:showNotification', src, 'Du hast nicht genug Geld! (Kosten: $' .. cost .. ')')
|
||||||
|
return -- Bricht hier ab, wenn kein Geld da ist
|
||||||
|
end
|
||||||
|
|
||||||
if RevivePlayer(targetId) then
|
if RevivePlayer(targetId) then
|
||||||
TriggerClientEvent('esx:showNotification', src, 'Du hast die Person mit Hilfe des Arztes wiederbelebt.')
|
TriggerClientEvent('esx:showNotification', src, 'Du hast die Person für $' .. cost .. ' wiederbelebt.')
|
||||||
TriggerClientEvent('esx:showNotification', targetId, 'Du wurdest von jemandem beim NPC-Arzt gerettet.')
|
TriggerClientEvent('esx:showNotification', targetId, 'Du wurdest von jemandem beim NPC-Arzt gerettet.')
|
||||||
|
else
|
||||||
|
-- Falls die Wiederbelebung fehlschlägt, geben wir das Geld zurück
|
||||||
|
xPlayer.addMoney(cost)
|
||||||
|
TriggerClientEvent('esx:showNotification', src, 'Fehler bei der Wiederbelebung. Geld wurde erstattet.')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
Loading…
x
Reference in New Issue
Block a user