forked from Simnation/Main
ed
This commit is contained in:
parent
29c786ff04
commit
6442ff325b
35 changed files with 376 additions and 1949 deletions
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
# 💬 Dialog
|
|
||||||
This is a Dialog script where you can talk to specific peds you spawn in config or in other scripts. <br>
|
|
||||||
|
|
||||||
## ❓Installation
|
|
||||||
Pretty simple install given the ui is already built for you. Just drag the root folder into your servers resources folder and make sure to ensure the folder inside of your server.cfg.
|
|
||||||
|
|
||||||
## ❗ Dependencies
|
|
||||||
This resouce is very light on depenedacies. If you do not plan to use this script to spawn peds and would rather spawn them via you own script there are 0 dependencies. Otherwise you will need [ox_target](https://github.com/overextended/ox_target) or [qb-target](https://github.com/qbcore-framework/qb-target)
|
|
||||||
|
|
||||||
## ℹ️️ Other Info
|
|
||||||
[**Discord**](https://discord.gg/peYKn8CxHG) <br>
|
|
||||||
[**Preview**](https://youtu.be/0JWGxLMnOic) <br>
|
|
||||||
[**Forums**](https://forum.cfx.re/t/free-npc-dialog/5200606) <br>
|
|
||||||
[**Documentation**](https://st4lth.gitbook.io/st4lth/dialog) <br>
|
|
||||||
|
|
||||||

|
|
|
@ -1,37 +0,0 @@
|
||||||
-- Replace the existing onResourceStart event handler with this:
|
|
||||||
AddEventHandler('onResourceStart', function(resourceName)
|
|
||||||
if (GetCurrentResourceName() == resourceName) then
|
|
||||||
-- Use next() instead of # to check if the table has any entries
|
|
||||||
if next(Config.peds) ~= nil then
|
|
||||||
print("Resource started, spawning peds")
|
|
||||||
SpawnPeds()
|
|
||||||
else
|
|
||||||
print("Resource started, but Config.peds is empty")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Also update the framework loading event handler:
|
|
||||||
if Config.FrameworkLoadinEvent ~= '' then
|
|
||||||
RegisterNetEvent(Config.FrameworkLoadinEvent, function()
|
|
||||||
print("Framework loading event triggered")
|
|
||||||
if next(Config.peds) ~= nil then
|
|
||||||
print("Spawning peds after framework loaded")
|
|
||||||
SpawnPeds()
|
|
||||||
else
|
|
||||||
print("Framework loaded, but Config.peds is empty")
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add a debug command to help troubleshoot
|
|
||||||
RegisterCommand('debugpeds', function()
|
|
||||||
print("Debug peds command triggered")
|
|
||||||
local count = 0
|
|
||||||
for k, v in pairs(Config.peds) do
|
|
||||||
count = count + 1
|
|
||||||
print("Found ped: " .. k)
|
|
||||||
end
|
|
||||||
print("Total peds in config: " .. count)
|
|
||||||
SpawnPeds()
|
|
||||||
end, false)
|
|
|
@ -1,148 +0,0 @@
|
||||||
local loadModel = function(modelHash)
|
|
||||||
if not IsModelValid(modelHash) then
|
|
||||||
print(modelHash..' Is not a valid model')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
RequestModel(modelHash)
|
|
||||||
RequestCollisionForModel(modelHash)
|
|
||||||
|
|
||||||
while not HasModelLoaded(modelHash) or not HasCollisionForModelLoaded(modelHash) do
|
|
||||||
Wait(10)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local getClosestPed = function(coords, max)
|
|
||||||
local all = GetGamePool('CPed')
|
|
||||||
local closest, closestCoords
|
|
||||||
max = max or 2.0
|
|
||||||
|
|
||||||
for i = 1, #all do
|
|
||||||
local ped = all[i]
|
|
||||||
|
|
||||||
if IsPedAPlayer(ped) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local pedCoords = GetEntityCoords(ped)
|
|
||||||
local distance = #(coords - pedCoords)
|
|
||||||
|
|
||||||
if distance < max then
|
|
||||||
max = distance
|
|
||||||
closest = ped
|
|
||||||
closestCoords = pedCoords
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return closest, closestCoords
|
|
||||||
end
|
|
||||||
|
|
||||||
local loadanimDict = function(animDict)
|
|
||||||
if not DoesAnimDictExist(animDict) then
|
|
||||||
print(animDict..' Is not a valid animation dict')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
RequestAnimDict(animDict)
|
|
||||||
|
|
||||||
while not HasAnimDictLoaded(animDict) do
|
|
||||||
Wait(10)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local playAnimation = function(animData)
|
|
||||||
if not IsEntityPlayingAnim(animData.ped, animData.dict, animData.lib, 3) then
|
|
||||||
if not animData.flag then animData.flag = 49 end
|
|
||||||
|
|
||||||
loadanimDict(animData.dict)
|
|
||||||
TaskPlayAnim(animData.ped, animData.dict, animData.lib, 2.0, -1.0, -1, animData.flag, 0, 0, 0, 0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
SpawnPeds = function()
|
|
||||||
for v, k in pairs(Config.peds) do
|
|
||||||
Peds[v] = k
|
|
||||||
SpawnPed(v, k)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
SpawnPed = function(id, data)
|
|
||||||
local ped, pedDist = getClosestPed(data.coords)
|
|
||||||
if data.dict then
|
|
||||||
dict = data.dict
|
|
||||||
else
|
|
||||||
dict = "missbigscore2aig_6"
|
|
||||||
end
|
|
||||||
|
|
||||||
if data.lib then
|
|
||||||
lib = data.lib
|
|
||||||
else
|
|
||||||
lib = "wait_loop"
|
|
||||||
end
|
|
||||||
|
|
||||||
if DoesEntityExist(ped) and pedDist <= 1.2 then
|
|
||||||
DeletePed(ped)
|
|
||||||
end
|
|
||||||
|
|
||||||
loadModel(data.model)
|
|
||||||
|
|
||||||
Peds[id].ped = CreatePed(5, GetHashKey(data.model), data.coords.x, data.coords.y, data.coords.z - 1.0, data.heading, false, false)
|
|
||||||
|
|
||||||
SetEntityHeading(Peds[id].ped, data.heading)
|
|
||||||
|
|
||||||
SetPedCombatAttributes(Peds[id].ped, 46, true)
|
|
||||||
SetPedFleeAttributes(Peds[id].ped, 0, 0)
|
|
||||||
SetBlockingOfNonTemporaryEvents(Peds[id].ped, true)
|
|
||||||
|
|
||||||
SetEntityAsMissionEntity(Peds[id].ped, true, true)
|
|
||||||
FreezeEntityPosition(Peds[id].ped, true)
|
|
||||||
SetEntityInvincible(Peds[id].ped, true)
|
|
||||||
SetPedDiesWhenInjured(Peds[id].ped, false)
|
|
||||||
SetPedHearingRange(Peds[id].ped, 1.0)
|
|
||||||
SetPedAlertness(Peds[id].ped, 0)
|
|
||||||
|
|
||||||
if data.type ~= 'scenario' then
|
|
||||||
playAnimation({
|
|
||||||
ped = Peds[id].ped,
|
|
||||||
dict = dict,
|
|
||||||
lib = lib,
|
|
||||||
flag = 1
|
|
||||||
})
|
|
||||||
else
|
|
||||||
TaskStartScenarioInPlace(Peds[id].ped, data.anim, 0, false)
|
|
||||||
end
|
|
||||||
|
|
||||||
opts = {
|
|
||||||
label = data.label,
|
|
||||||
icon = data.icon,
|
|
||||||
action = function()
|
|
||||||
if data.data then
|
|
||||||
OpenDialog(Peds[id].ped, data.data)
|
|
||||||
else
|
|
||||||
if data.server then
|
|
||||||
TriggerServerEvent(data.event, Peds[id].ped)
|
|
||||||
else
|
|
||||||
TriggerEvent(data.event, Peds[id].ped)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
if Config.Target == 'qb' then
|
|
||||||
exports['qb-target']:AddTargetEntity(Peds[id].ped, {
|
|
||||||
options = { opts },
|
|
||||||
distance = 2.0
|
|
||||||
})
|
|
||||||
elseif Config.Target == 'ox' then
|
|
||||||
exports.ox_target:addLocalEntity(Peds[id].ped, {opts}) -- Use opts directly
|
|
||||||
else
|
|
||||||
print("^1[ERROR] Invalid Target Config! Check your Config.Target setting.^0")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
SetInvisible = function()
|
|
||||||
while Open do
|
|
||||||
SetEntityLocallyInvisible(PlayerPedId())
|
|
||||||
Wait(5)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,60 +0,0 @@
|
||||||
Config = {
|
|
||||||
Target = 'qb',
|
|
||||||
FrameworkLoadinEvent = 'QBCore:Client:OnPlayerLoaded',
|
|
||||||
peds = {
|
|
||||||
['hafenarbeiter'] = {
|
|
||||||
label = 'Rede mit dem Hafenarbeiter',
|
|
||||||
icon = 'fa-solid fa-hard-hat',
|
|
||||||
model = "S_M_M_DockWork_01",
|
|
||||||
coords = vector3(1243.29, -3196.67, 6.03),
|
|
||||||
heading = 90,
|
|
||||||
data = {
|
|
||||||
firstname = 'Kalle',
|
|
||||||
lastname = 'Kutter',
|
|
||||||
text = "Moin... du wirkst nich wie jemand, der hier offiziell was abholen will.",
|
|
||||||
buttons = {
|
|
||||||
{
|
|
||||||
text = "Kommt drauf an, was es hier so gibt...",
|
|
||||||
data = {
|
|
||||||
text = "Hehehe... naja, sagen wir mal so: Manche Container stehen nachts ein bisschen... unbeaufsichtigt rum.",
|
|
||||||
buttons = {
|
|
||||||
{
|
|
||||||
text = "Ach ja? Und dann?",
|
|
||||||
data = {
|
|
||||||
text = "Na, wenn einer wüsste, wie man da *rein* kommt... bräuchte er sicher was mit Kraft oder Strom, verstehste?",
|
|
||||||
buttons = {
|
|
||||||
{
|
|
||||||
text = "Klar. Ich versteh schon.",
|
|
||||||
data = {
|
|
||||||
text = "Gut. Dann hab ich dir ja nix gesagt, oder?",
|
|
||||||
buttons = {
|
|
||||||
{
|
|
||||||
text = "Du hast mich nie gesehen.",
|
|
||||||
close = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text = "Klingt mir zu heiß...",
|
|
||||||
close = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text = "Ich glaub, ich hab mich verlaufen...",
|
|
||||||
close = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text = "Nur mal umschauen, Chef.",
|
|
||||||
close = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} -- schließt `peds`
|
|
||||||
} -- schließt `Config`
|
|
|
@ -1,24 +0,0 @@
|
||||||
fx_version 'cerulean'
|
|
||||||
game 'gta5'
|
|
||||||
|
|
||||||
author 'ST4lTH'
|
|
||||||
description 'Dialog'
|
|
||||||
version '1.0.0'
|
|
||||||
|
|
||||||
client_scripts {
|
|
||||||
'client/*.lua',
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_scripts {
|
|
||||||
'config.lua',
|
|
||||||
}
|
|
||||||
|
|
||||||
files {
|
|
||||||
'web/dist/index.html',
|
|
||||||
'web/dist/**/*',
|
|
||||||
}
|
|
||||||
|
|
||||||
lua54 'yes'
|
|
||||||
|
|
||||||
ui_page 'web/dist/index.html'
|
|
||||||
--ui_page 'http://localhost:3000/' -- Dev
|
|
|
@ -1,4 +0,0 @@
|
||||||
> 1%
|
|
||||||
last 2 versions
|
|
||||||
not dead
|
|
||||||
not ie 11
|
|
|
@ -1,5 +0,0 @@
|
||||||
[*.{js,jsx,ts,tsx,vue}]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
insert_final_newline = true
|
|
22
resources/[tools]/dialog/web/.gitignore
vendored
22
resources/[tools]/dialog/web/.gitignore
vendored
|
@ -1,22 +0,0 @@
|
||||||
.DS_Store
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
|
|
||||||
# local env files
|
|
||||||
.env.local
|
|
||||||
.env.*.local
|
|
||||||
|
|
||||||
# Log files
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.idea
|
|
||||||
.vscode
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
|
@ -1,44 +0,0 @@
|
||||||
# default
|
|
||||||
|
|
||||||
## Project setup
|
|
||||||
|
|
||||||
```
|
|
||||||
# yarn
|
|
||||||
yarn
|
|
||||||
|
|
||||||
# npm
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# pnpm
|
|
||||||
pnpm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and hot-reloads for development
|
|
||||||
|
|
||||||
```
|
|
||||||
# yarn
|
|
||||||
yarn dev
|
|
||||||
|
|
||||||
# npm
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# pnpm
|
|
||||||
pnpm dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and minifies for production
|
|
||||||
|
|
||||||
```
|
|
||||||
# yarn
|
|
||||||
yarn build
|
|
||||||
|
|
||||||
# npm
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# pnpm
|
|
||||||
pnpm build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Customize configuration
|
|
||||||
|
|
||||||
See [Configuration Reference](https://vitejs.dev/config/).
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
resources/[tools]/dialog/web/dist/favicon.ico
vendored
BIN
resources/[tools]/dialog/web/dist/favicon.ico
vendored
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
18
resources/[tools]/dialog/web/dist/index.html
vendored
18
resources/[tools]/dialog/web/dist/index.html
vendored
|
@ -1,18 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" href="./favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Welcome to Vuetify 3</title>
|
|
||||||
<script type="module" crossorigin src="./assets/index-8c3f21c3.js"></script>
|
|
||||||
<link rel="stylesheet" href="./assets/index-a3506647.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,16 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Welcome to Vuetify 3</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script type="module" src="/src/main.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es5",
|
|
||||||
"module": "esnext",
|
|
||||||
"baseUrl": "./",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"paths": {
|
|
||||||
"@/*": [
|
|
||||||
"src/*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"lib": [
|
|
||||||
"esnext",
|
|
||||||
"dom",
|
|
||||||
"dom.iterable",
|
|
||||||
"scripthost"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
1141
resources/[tools]/dialog/web/package-lock.json
generated
1141
resources/[tools]/dialog/web/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"name": "web",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "vite build",
|
|
||||||
"preview": "vite preview"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@mdi/font": "7.0.96",
|
|
||||||
"roboto-fontface": "*",
|
|
||||||
"vue": "^3.2.0",
|
|
||||||
"vuetify": "^3.0.0",
|
|
||||||
"webfontloader": "^1.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@vitejs/plugin-vue": "^4.0.0",
|
|
||||||
"sass": "^1.69.7",
|
|
||||||
"vite": "^4.2.0",
|
|
||||||
"vite-plugin-vuetify": "^1.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
|
@ -1,165 +0,0 @@
|
||||||
<template>
|
|
||||||
<v-app style="background: transparent!important;">
|
|
||||||
<v-fade-transition>
|
|
||||||
<div class="dialog-bg" v-if="show">
|
|
||||||
<v-card color="bg" class="card ">
|
|
||||||
<v-card-title class="title">
|
|
||||||
<div>
|
|
||||||
<span class="font-weight-bold mr-2">
|
|
||||||
{{ data.firstname }}
|
|
||||||
</span>
|
|
||||||
<span class="font-weight-light">
|
|
||||||
{{ data.lastname }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div style="flex-grow: 1;">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="note" v-if="data.rep">
|
|
||||||
{{ data.rep }} Rep
|
|
||||||
</div>
|
|
||||||
<div class="note" v-if="data.type">
|
|
||||||
{{ data.type }}
|
|
||||||
</div>
|
|
||||||
</v-card-title>
|
|
||||||
<div class="text-dialog">
|
|
||||||
<div class="text bg-grey-darken-4 rounded">
|
|
||||||
{{ data.text }}
|
|
||||||
</div>
|
|
||||||
<div class="buttons">
|
|
||||||
<div class="button" v-for="(item, index) in data.buttons" @keyup.index="click(item)" @click="click(item)">
|
|
||||||
<div class="number">
|
|
||||||
<p>
|
|
||||||
{{ index+1 }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{{ item.text }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</v-card>
|
|
||||||
</div>
|
|
||||||
</v-fade-transition>
|
|
||||||
</v-app>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'App',
|
|
||||||
components: {
|
|
||||||
},
|
|
||||||
data: () => ({
|
|
||||||
show: false,
|
|
||||||
data: {
|
|
||||||
firstname: 'John',
|
|
||||||
lastname: 'Doe',
|
|
||||||
text: 'Lorem ipsum dolor sit amet',
|
|
||||||
type: '',
|
|
||||||
rep: '',
|
|
||||||
buttons: [
|
|
||||||
{ text: 'Lorem ipsum dolor sit amet' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
click(data){
|
|
||||||
post('click', data, (resp) => {
|
|
||||||
if (resp == 'close') {
|
|
||||||
this.show = false;
|
|
||||||
this.data = null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.escapeListener = window.addEventListener("keyup", (event) => {
|
|
||||||
if (!this.show) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (event.keyCode || 49 && event.keyCode || 51 && event.keyCode || 52 && event.keyCode || 53) {
|
|
||||||
if ( this.data.buttons[event.keyCode - 49] ) {
|
|
||||||
this.click(this.data.buttons[event.keyCode - 49])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.messageListener = window.addEventListener("message", (event) => {
|
|
||||||
const item = event.data || event.detail; //'detail' is for debugging via browsers
|
|
||||||
if (item.type == 'New') {
|
|
||||||
this.data = item.data
|
|
||||||
this.show = true
|
|
||||||
} else if (item.type == 'Continue') {
|
|
||||||
this.data.text = item.data.text
|
|
||||||
this.data.buttons = item.data.buttons
|
|
||||||
} else if (item.type == 'Set') {
|
|
||||||
this.data = item.data
|
|
||||||
this.show = true
|
|
||||||
} else if (item.type == 'Close') {
|
|
||||||
this.show = false;
|
|
||||||
this.data = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const resource = 'dialog';
|
|
||||||
|
|
||||||
const post = (event, data, cb) => {
|
|
||||||
if (event) {
|
|
||||||
fetch(`https://${resource}/${event}`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json; charset=UTF-8",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(data || {}),
|
|
||||||
})
|
|
||||||
.then((resp) => resp.json())
|
|
||||||
.then((resp) => {
|
|
||||||
if (cb) {
|
|
||||||
cb(resp);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
html {
|
|
||||||
overflow: hidden!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
|
||||||
color-scheme: light !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
background: transparent!important;
|
|
||||||
background-color: transparent!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* width */
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 0px;
|
|
||||||
height: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Track */
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
background: #f1f1f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle */
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
background: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle on hover */
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
|
@ -1,6 +0,0 @@
|
||||||
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M261.126 140.65L164.624 307.732L256.001 466L377.028 256.5L498.001 47H315.192L261.126 140.65Z" fill="#1697F6"/>
|
|
||||||
<path d="M135.027 256.5L141.365 267.518L231.64 111.178L268.731 47H256H14L135.027 256.5Z" fill="#AEDDFF"/>
|
|
||||||
<path d="M315.191 47C360.935 197.446 256 466 256 466L164.624 307.732L315.191 47Z" fill="#1867C0"/>
|
|
||||||
<path d="M268.731 47C76.0026 47 141.366 267.518 141.366 267.518L268.731 47Z" fill="#7BC6FF"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 526 B |
|
@ -1,68 +0,0 @@
|
||||||
|
|
||||||
.dialog-bg {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: radial-gradient(circle, rgba(133,133,133,0) 41%, rgba(1,214,193,0.3491771708683473) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
position: absolute!important;
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
margin: auto !important;
|
|
||||||
width: fit-content;
|
|
||||||
bottom: 10vh;
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
.note {
|
|
||||||
margin-left: 10px;
|
|
||||||
height: fit-content;
|
|
||||||
font-size: 15px;
|
|
||||||
background-color: rgba(0, 255, 255, 0.681);
|
|
||||||
border-radius: 5px;
|
|
||||||
color: #0e0e0e;
|
|
||||||
padding: 8px;
|
|
||||||
line-height: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.text-dialog {
|
|
||||||
margin: 2px 10px 10px 10px;
|
|
||||||
.text {
|
|
||||||
width: 610px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
background: radial-gradient(circle, rgb(58, 58, 58) 0%, rgb(36, 36, 36) 100%);
|
|
||||||
}
|
|
||||||
.buttons {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 302px 302px;
|
|
||||||
grid-row: auto auto;
|
|
||||||
grid-column-gap: 7px;
|
|
||||||
grid-row-gap: 7px;
|
|
||||||
.button {
|
|
||||||
display: flex;
|
|
||||||
padding: 3px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
align-items: center;
|
|
||||||
background-color: rgb(36, 36, 36);
|
|
||||||
.number {
|
|
||||||
margin-right: 8px;
|
|
||||||
width: 23px;
|
|
||||||
height: 23px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: rgb(0, 255, 255);
|
|
||||||
p {
|
|
||||||
color: #414041;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
/**
|
|
||||||
* main.js
|
|
||||||
*
|
|
||||||
* Bootstraps Vuetify and other plugins then mounts the App`
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Components
|
|
||||||
|
|
||||||
import './assets/styles/style.scss'
|
|
||||||
|
|
||||||
import App from './App.vue'
|
|
||||||
|
|
||||||
// Composables
|
|
||||||
import { createApp } from 'vue'
|
|
||||||
|
|
||||||
// Plugins
|
|
||||||
import { registerPlugins } from '@/plugins'
|
|
||||||
|
|
||||||
const app = createApp(App)
|
|
||||||
|
|
||||||
registerPlugins(app)
|
|
||||||
|
|
||||||
app.mount('#app')
|
|
|
@ -1,14 +0,0 @@
|
||||||
/**
|
|
||||||
* plugins/index.js
|
|
||||||
*
|
|
||||||
* Automatically included in `./src/main.js`
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Plugins
|
|
||||||
import { loadFonts } from './webfontloader'
|
|
||||||
import vuetify from './vuetify'
|
|
||||||
|
|
||||||
export function registerPlugins (app) {
|
|
||||||
loadFonts()
|
|
||||||
app.use(vuetify)
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/**
|
|
||||||
* plugins/vuetify.js
|
|
||||||
*
|
|
||||||
* Framework documentation: https://vuetifyjs.com`
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Styles
|
|
||||||
import '@mdi/font/css/materialdesignicons.css'
|
|
||||||
import 'vuetify/styles'
|
|
||||||
|
|
||||||
// Composables
|
|
||||||
import { createVuetify } from 'vuetify'
|
|
||||||
|
|
||||||
// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides
|
|
||||||
export default createVuetify({
|
|
||||||
theme: {
|
|
||||||
defaultTheme: 'dark',
|
|
||||||
themes: {
|
|
||||||
dark: {
|
|
||||||
colors: {
|
|
||||||
primary: '#1867C0',
|
|
||||||
secondary: '#5CBBF6',
|
|
||||||
bg: '#121212'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
|
@ -1,15 +0,0 @@
|
||||||
/**
|
|
||||||
* plugins/webfontloader.js
|
|
||||||
*
|
|
||||||
* webfontloader documentation: https://github.com/typekit/webfontloader
|
|
||||||
*/
|
|
||||||
|
|
||||||
export async function loadFonts () {
|
|
||||||
const webFontLoader = await import(/* webpackChunkName: "webfontloader" */'webfontloader')
|
|
||||||
|
|
||||||
webFontLoader.load({
|
|
||||||
google: {
|
|
||||||
families: ['Roboto:100,300,400,500,700,900&display=swap'],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
// Plugins
|
|
||||||
import vue from '@vitejs/plugin-vue'
|
|
||||||
import vuetify, { transformAssetUrls } from 'vite-plugin-vuetify'
|
|
||||||
|
|
||||||
// Utilities
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import { fileURLToPath, URL } from 'node:url'
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [
|
|
||||||
vue({
|
|
||||||
template: { transformAssetUrls }
|
|
||||||
}),
|
|
||||||
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
|
|
||||||
vuetify({
|
|
||||||
autoImport: true,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
define: { 'process.env': {} },
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
|
||||||
},
|
|
||||||
extensions: [
|
|
||||||
'.js',
|
|
||||||
'.json',
|
|
||||||
'.jsx',
|
|
||||||
'.mjs',
|
|
||||||
'.ts',
|
|
||||||
'.tsx',
|
|
||||||
'.vue',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
port: 3000,
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
outDir: "./dist",
|
|
||||||
},
|
|
||||||
base: "",
|
|
||||||
})
|
|
142
resources/[tools]/nordi_talk_to_npc/client/client.lua
Normal file
142
resources/[tools]/nordi_talk_to_npc/client/client.lua
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
local QBCore = exports['qb-core']:GetCoreObject()
|
||||||
|
local spawnedNPCs = {}
|
||||||
|
|
||||||
|
-- NPC Spawn Function
|
||||||
|
local function SpawnNPC(npcId, npcData)
|
||||||
|
local model = GetHashKey(npcData.model)
|
||||||
|
|
||||||
|
RequestModel(model)
|
||||||
|
while not HasModelLoaded(model) do
|
||||||
|
Wait(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local npc = CreatePed(4, model, npcData.coords.x, npcData.coords.y, npcData.coords.z - 1.0, npcData.coords.w, false, true)
|
||||||
|
|
||||||
|
SetEntityHeading(npc, npcData.coords.w)
|
||||||
|
FreezeEntityPosition(npc, true)
|
||||||
|
SetEntityInvincible(npc, true)
|
||||||
|
SetBlockingOfNonTemporaryEvents(npc, true)
|
||||||
|
|
||||||
|
-- QB-Target hinzufügen
|
||||||
|
exports['qb-target']:AddTargetEntity(npc, {
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
type = 'client',
|
||||||
|
event = 'npc-dialog:client:openDialog',
|
||||||
|
icon = npcData.targetIcon,
|
||||||
|
label = npcData.targetLabel,
|
||||||
|
npcId = npcId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
distance = 2.0
|
||||||
|
})
|
||||||
|
|
||||||
|
spawnedNPCs[npcId] = npc
|
||||||
|
|
||||||
|
SetModelAsNoLongerNeeded(model)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Alle NPCs spawnen
|
||||||
|
CreateThread(function()
|
||||||
|
for npcId, npcData in pairs(Config.NPCs) do
|
||||||
|
SpawnNPC(npcId, npcData)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Rekursive Funktion zum Erstellen der Dialog-Optionen
|
||||||
|
local function CreateDialogOptions(options, npcId, parentId)
|
||||||
|
local contextOptions = {}
|
||||||
|
|
||||||
|
for i, option in ipairs(options) do
|
||||||
|
local optionData = {
|
||||||
|
title = option.title,
|
||||||
|
description = option.description,
|
||||||
|
icon = option.icon,
|
||||||
|
}
|
||||||
|
|
||||||
|
if option.info then
|
||||||
|
-- Direkte Info anzeigen
|
||||||
|
optionData.onSelect = function()
|
||||||
|
lib.alertDialog({
|
||||||
|
header = option.title,
|
||||||
|
content = option.info,
|
||||||
|
centered = true,
|
||||||
|
cancel = true,
|
||||||
|
labels = {
|
||||||
|
cancel = 'Zurück'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
elseif option.response then
|
||||||
|
-- Weiteres Dialog-Level
|
||||||
|
optionData.onSelect = function()
|
||||||
|
local contextId = 'npc_dialog_' .. npcId .. '_' .. i .. '_' .. (parentId or 'main')
|
||||||
|
local responseOptions = CreateDialogOptions(option.response.options, npcId, contextId)
|
||||||
|
|
||||||
|
-- Zurück-Option hinzufügen
|
||||||
|
table.insert(responseOptions, {
|
||||||
|
title = "← Zurück",
|
||||||
|
description = "Zum vorherigen Dialog",
|
||||||
|
icon = 'arrow-left',
|
||||||
|
onSelect = function()
|
||||||
|
if parentId then
|
||||||
|
lib.showContext(parentId)
|
||||||
|
else
|
||||||
|
lib.showContext('npc_dialog_' .. npcId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
lib.registerContext({
|
||||||
|
id = contextId,
|
||||||
|
title = option.response.title,
|
||||||
|
options = responseOptions
|
||||||
|
})
|
||||||
|
|
||||||
|
lib.showContext(contextId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(contextOptions, optionData)
|
||||||
|
end
|
||||||
|
|
||||||
|
return contextOptions
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Dialog öffnen
|
||||||
|
RegisterNetEvent('npc-dialog:client:openDialog', function(data)
|
||||||
|
local npcId = data.npcId
|
||||||
|
local npcData = Config.NPCs[npcId]
|
||||||
|
if not npcData then return end
|
||||||
|
|
||||||
|
local options = CreateDialogOptions(npcData.dialog.options, npcId)
|
||||||
|
|
||||||
|
-- Verlassen Option hinzufügen
|
||||||
|
table.insert(options, {
|
||||||
|
title = "Verlassen",
|
||||||
|
description = "Dialog beenden",
|
||||||
|
icon = 'times',
|
||||||
|
onSelect = function()
|
||||||
|
-- Dialog schließt sich automatisch
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
lib.registerContext({
|
||||||
|
id = 'npc_dialog_' .. npcId,
|
||||||
|
title = npcData.dialog.title,
|
||||||
|
options = options
|
||||||
|
})
|
||||||
|
|
||||||
|
lib.showContext('npc_dialog_' .. npcId)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Cleanup beim Resource Stop
|
||||||
|
AddEventHandler('onResourceStop', function(resourceName)
|
||||||
|
if GetCurrentResourceName() ~= resourceName then return end
|
||||||
|
|
||||||
|
for _, npc in pairs(spawnedNPCs) do
|
||||||
|
if DoesEntityExist(npc) then
|
||||||
|
DeleteEntity(npc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
213
resources/[tools]/nordi_talk_to_npc/config.lua
Normal file
213
resources/[tools]/nordi_talk_to_npc/config.lua
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
Config = {}
|
||||||
|
|
||||||
|
Config.NPCs = {
|
||||||
|
['kalle_kutter'] = {
|
||||||
|
model = 's_m_m_dockwork_01',
|
||||||
|
coords = vector4(1234.56, -3210.45, 5.9, 90.0),
|
||||||
|
name = "Kalle Kutter",
|
||||||
|
targetLabel = 'Red mit dem Hafenarbeiter',
|
||||||
|
targetIcon = 'fa-solid fa-hard-hat',
|
||||||
|
dialog = {
|
||||||
|
title = "Kalle Kutter - Hafenarbeiter",
|
||||||
|
description = "Moin... du wirkst nich wie jemand, der hier offiziell was abholen will.",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Kommt drauf an, was es hier so gibt...",
|
||||||
|
description = "Neugierig nachfragen",
|
||||||
|
icon = 'eye',
|
||||||
|
response = {
|
||||||
|
title = "Kalle Kutter",
|
||||||
|
description = "Hehehe... naja, sagen wir mal so: Manche Container & Trailer stehen nachts ein bisschen... unbeaufsichtigt rum.",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Ach ja? Und dann?",
|
||||||
|
description = "Weiterfragen",
|
||||||
|
icon = 'question',
|
||||||
|
response = {
|
||||||
|
title = "Kalle Kutter",
|
||||||
|
description = "Na, wenn einer wüsste, wie man da *rein* kommt... bräuchte er sicher was mit Kraft oder Strom, verstehste?",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Klar. Ich versteh schon.",
|
||||||
|
description = "Verstehen zeigen",
|
||||||
|
icon = 'handshake',
|
||||||
|
response = {
|
||||||
|
title = "Kalle Kutter",
|
||||||
|
description = "Gut. Dann hab ich dir ja nix gesagt, oder?",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Du hast mich nie gesehen.",
|
||||||
|
description = "Verschwiegenheit zusichern",
|
||||||
|
icon = 'eye-slash',
|
||||||
|
info = "Kalle nickt zufrieden und wendet sich wieder seiner Arbeit zu.\n\n*Du hast einen Hinweis auf nächtliche Aktivitäten am Hafen erhalten...*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Klingt mir zu heiß...",
|
||||||
|
description = "Ablehnen",
|
||||||
|
icon = 'times',
|
||||||
|
info = "Kalle zuckt mit den Schultern.\n\n'Deine Entscheidung, Kumpel. Aber vergiss unser Gespräch.'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Ich glaub, ich hab mich verlaufen...",
|
||||||
|
description = "Rückzieher machen",
|
||||||
|
icon = 'walking',
|
||||||
|
info = "Kalle mustert dich misstrauisch.\n\n'Ja... das glaub ich auch. Verschwinde besser.'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Nur mal umschauen, Chef.",
|
||||||
|
description = "Unschuldig tun",
|
||||||
|
icon = 'smile',
|
||||||
|
info = "Kalle brummt etwas Unverständliches und wendet sich ab.\n\n'Dann schau zu, dass du wieder wegkommst...'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
['maria_helper'] = {
|
||||||
|
model = 'a_f_y_business_01',
|
||||||
|
coords = vector4(-1037.23, -2738.94, 20.17, 330.0),
|
||||||
|
name = "Maria die Helferin",
|
||||||
|
targetLabel = 'Mit Maria sprechen',
|
||||||
|
targetIcon = 'fas fa-info-circle',
|
||||||
|
dialog = {
|
||||||
|
title = "Maria die Helferin",
|
||||||
|
description = "Hallo Schatz! Du siehst aus als könntest du Hilfe gebrauchen. Lass uns reden!",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Hi Maria! Kannst du mir helfen?",
|
||||||
|
description = "Höflich um Hilfe bitten",
|
||||||
|
icon = 'hands-helping',
|
||||||
|
response = {
|
||||||
|
title = "Maria die Helferin",
|
||||||
|
description = "Natürlich helfe ich dir gerne! Dafür bin ich ja da. Ich liebe es, neuen Leuten zu helfen sich hier zurechtzufinden. Was bereitet dir Kopfzerbrechen?",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Ich verstehe das Jobsystem nicht",
|
||||||
|
description = "Nach Jobs fragen",
|
||||||
|
icon = 'briefcase',
|
||||||
|
response = {
|
||||||
|
title = "Maria die Helferin",
|
||||||
|
description = "Ach so! Das Jobsystem kann am Anfang verwirrend sein. Aber keine Sorge, ich erkläre es dir gerne. Was möchtest du wissen?",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Wie finde ich einen Job?",
|
||||||
|
description = "Jobsuche",
|
||||||
|
icon = 'search',
|
||||||
|
info = "Jobs finden in Los Santos:\n\n1. Gehe zum Rathaus (Stadtzentrum)\n2. Nutze den Job-Computer\n3. Wähle einen verfügbaren Job\n4. Folge den Anweisungen\n5. Verdiene dein erstes Geld!\n\nEinfache Jobs: Taxi, Müll, Lieferungen\nSchwere Jobs: Polizei, Medic, Mechaniker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Welcher Job ist für Anfänger?",
|
||||||
|
description = "Anfänger-Jobs",
|
||||||
|
icon = 'play',
|
||||||
|
response = {
|
||||||
|
title = "Maria die Helferin",
|
||||||
|
description = "Für Anfänger empfehle ich immer die einfachen Jobs. Sie bringen zwar nicht so viel Geld, aber du lernst die Stadt kennen und es ist stressfrei.",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Taxi fahren",
|
||||||
|
description = "Als Taxifahrer arbeiten",
|
||||||
|
icon = 'taxi',
|
||||||
|
info = "Taxi Job - Perfekt für Anfänger:\n\n• Lerne die ganze Stadt kennen\n• Triff verschiedene Leute\n• Flexibel - arbeite wann du willst\n• Gutes Geld für Anfänger\n• Kein Stress\n\nHole dir ein Taxi am Taxi-Depot und leg los!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Müll sammeln",
|
||||||
|
description = "Müllmann werden",
|
||||||
|
icon = 'trash',
|
||||||
|
info = "Müll Job - Einfach und entspannt:\n\n• Fahre durch die Stadt\n• Sammle Müll an verschiedenen Punkten\n• Regelmäßiges Einkommen\n• Keine besonderen Fähigkeiten nötig\n• Kannst Musik hören dabei\n\nNicht glamourös, aber ehrliche Arbeit!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Ich habe Probleme mit anderen Spielern",
|
||||||
|
description = "Soziale Probleme",
|
||||||
|
icon = 'users',
|
||||||
|
response = {
|
||||||
|
title = "Maria die Helferin",
|
||||||
|
description = "Oh nein, das tut mir leid zu hören! Leider gibt es überall schwarze Schafe. Aber lass dich nicht entmutigen, die meisten hier sind wirklich nett. Was ist passiert?",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Jemand war unhöflich zu mir",
|
||||||
|
description = "Über Unhöflichkeit beschweren",
|
||||||
|
icon = 'frown',
|
||||||
|
info = "Umgang mit unhöflichen Spielern:\n\n• Bleib ruhig und professionell\n• Lass dich nicht provozieren\n• Nutze /report bei Regelverstößen\n• Blockiere toxische Spieler\n• Suche dir nette Leute als Freunde\n\nDie meisten Spieler sind freundlich - lass dir nicht die Laune verderben!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Ich wurde grundlos angegriffen",
|
||||||
|
description = "RDM/VDM Problem",
|
||||||
|
icon = 'exclamation-triangle',
|
||||||
|
info = "Bei Regelbrüchen (RDM/VDM):\n\n• Sofort /report [Spieler-ID] [Grund]\n• Screenshots/Videos als Beweis\n• Nicht zurück angreifen\n• Admins werden sich darum kümmern\n• Solche Spieler werden bestraft\n\nDeine Sicherheit ist wichtig - melde jeden Regelbruch!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Wie ist das Leben hier so?",
|
||||||
|
description = "Smalltalk über die Stadt",
|
||||||
|
icon = 'comment',
|
||||||
|
response = {
|
||||||
|
title = "Maria die Helferin",
|
||||||
|
description = "Oh, das Leben hier ist aufregend! Jeden Tag passiert etwas Neues. Ich liebe diese Stadt, auch wenn sie manchmal chaotisch ist. Was denkst du denn bisher darüber?",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Es ist überwältigend",
|
||||||
|
description = "Sich überfordert fühlen",
|
||||||
|
icon = 'dizzy',
|
||||||
|
response = {
|
||||||
|
title = "Maria die Helferin",
|
||||||
|
description = "Das kann ich total verstehen! Als ich hierher kam, war ich auch völlig überfordert. So viele Menschen, so viel Lärm, so viele Möglichkeiten. Aber weißt du was? Das wird besser!",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Wie hast du dich eingelebt?",
|
||||||
|
description = "Nach Erfahrungen fragen",
|
||||||
|
icon = 'question',
|
||||||
|
info = "Marias Eingewöhnungs-Tipps:\n\n• Nimm dir Zeit - kein Stress\n• Suche dir 2-3 feste Orte als 'Basis'\n• Lerne jeden Tag eine neue Straße\n• Sprich mit Leuten - die meisten helfen gern\n• Hab Geduld mit dir selbst\n\n'Rom wurde auch nicht an einem Tag erbaut!'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Wird es wirklich einfacher?",
|
||||||
|
description = "Bestätigung suchen",
|
||||||
|
icon = 'heart',
|
||||||
|
info = "Marias aufmunternde Worte:\n\n'Ja, das verspreche ich dir! In ein paar Wochen wirst du dich wie zu Hause fühlen. Du wirst deine Lieblingsorte haben, nette Leute kennen und die Stadt lieben.\n\nJeder hat mal klein angefangen. Gib nicht auf!'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title = "Es gefällt mir sehr gut!",
|
||||||
|
description = "Begeisterung zeigen",
|
||||||
|
icon = 'smile',
|
||||||
|
response = {
|
||||||
|
title = "Maria die Helferin",
|
||||||
|
description = "Das freut mich so sehr zu hören! Du hast die richtige Einstellung. Mit so einer positiven Art wirst du hier viele Freunde finden und erfolgreich sein!",
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
title = "Was liebst du am meisten hier?",
|
||||||
|
description = "Nach Marias Lieblingssachen fragen",
|
||||||
|
icon = 'heart',
|
||||||
|
info = "Was Maria an Los Santos liebt:\n\n• Die Vielfalt der Menschen\n• Jeden Tag neue Abenteuer\n• Die wunderschönen Sonnenuntergänge\n• Die Möglichkeit, alles zu werden\n• Die Freundschaften die entstehen\n• Das Gefühl von Freiheit\n\n'Diese Stadt hat eine besondere Magie!'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
resources/[tools]/nordi_talk_to_npc/fxmanifest.lua
Normal file
21
resources/[tools]/nordi_talk_to_npc/fxmanifest.lua
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
fx_version 'cerulean'
|
||||||
|
game 'gta5'
|
||||||
|
|
||||||
|
author 'YourName'
|
||||||
|
description 'Simple NPC Info Dialog System'
|
||||||
|
version '1.0.0'
|
||||||
|
|
||||||
|
shared_scripts {
|
||||||
|
'@ox_lib/init.lua',
|
||||||
|
'config.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
client_scripts {
|
||||||
|
'client/client.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
'qb-core',
|
||||||
|
'qb-target',
|
||||||
|
'ox_lib'
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue