Files
devx-rp/resources/[devx]/devx_stripclub/server/main.lua
T
2026-08-05 01:29:39 +02:00

140 lines
6.0 KiB
Lua

local actionCooldowns = {}
MySQL.ready(function()
MySQL.query.await([[
CREATE TABLE IF NOT EXISTS devx_club_relations (
character_id BIGINT UNSIGNED NOT NULL,
relation_key VARCHAR(32) NOT NULL,
satisfaction TINYINT UNSIGNED NOT NULL DEFAULT 0,
contact_unlocked TINYINT(1) NOT NULL DEFAULT 0,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (character_id, relation_key),
CONSTRAINT fk_devx_club_character FOREIGN KEY (character_id)
REFERENCES devx_characters (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
]])
end)
local function relation(characterId)
local row = MySQL.single.await([[
SELECT satisfaction, contact_unlocked AS contactUnlocked
FROM devx_club_relations WHERE character_id = ? AND relation_key = ? LIMIT 1
]], { characterId, DevXStripclub.Nikki.key })
return {
satisfaction = row and tonumber(row.satisfaction) or 0,
contactUnlocked = row and tonumber(row.contactUnlocked) == 1 or false
}
end
local function saveRelation(characterId, satisfaction, unlocked)
MySQL.query.await([[
INSERT INTO devx_club_relations (character_id, relation_key, satisfaction, contact_unlocked)
VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE satisfaction = VALUES(satisfaction), contact_unlocked = VALUES(contact_unlocked)
]], { characterId, DevXStripclub.Nikki.key, satisfaction, unlocked and 1 or 0 })
end
DevXRegisterCallback('stripclub:state', function(source)
local player = exports.devx_core:GetPlayer(source)
if not player then return { ok = false, error = 'Kein Charakter aktiv.' } end
local current = relation(player.characterId)
current.ok = true
current.name = DevXStripclub.Nikki.name
current.threshold = DevXStripclub.Nikki.contactThreshold
return current
end)
DevXRegisterCallback('stripclub:interact', function(source, payload)
local player = exports.devx_core:GetPlayer(source)
local action = payload and payload.action
if not player or (action ~= 'talk' and action ~= 'lounge') then return { ok = false, error = 'Ungültige Anfrage.' } end
local now = os.time()
local cooldown = actionCooldowns[source] or 0
if cooldown > now then return { ok = false, error = ('Warte noch %s Sekunden.'):format(cooldown - now) } end
local gain = DevXStripclub.TalkGain
if action == 'lounge' then
local paid, result = exports.devx_banking:ChargeCharacter(
player.characterId, DevXStripclub.LoungePrice, 'VIP-Lounge', 'Vanilla Unicorn'
)
if not paid then return { ok = false, error = result } end
exports.devx_core:SetBankCache(source, result)
gain = DevXStripclub.LoungeGain
actionCooldowns[source] = now + 45
else
actionCooldowns[source] = now + 15
end
local current = relation(player.characterId)
current.satisfaction = math.min(DevXStripclub.Nikki.contactThreshold, current.satisfaction + gain)
local newlyUnlocked = not current.contactUnlocked and current.satisfaction >= DevXStripclub.Nikki.contactThreshold
if newlyUnlocked then current.contactUnlocked = true end
saveRelation(player.characterId, current.satisfaction, current.contactUnlocked)
if current.contactUnlocked then
exports.devx_phone:AddSystemContact(
player.characterId, DevXStripclub.Nikki.name, DevXStripclub.Nikki.phone,
'npc_companion', { relationKey = DevXStripclub.Nikki.key }
)
TriggerClientEvent('devx_phone:client:refresh', source)
end
return {
ok = true,
satisfaction = current.satisfaction,
threshold = DevXStripclub.Nikki.contactThreshold,
contactUnlocked = current.contactUnlocked,
newlyUnlocked = newlyUnlocked,
action = action
}
end)
local function inviteCompanion(source)
local player = exports.devx_core:GetPlayer(source)
if not player then return { ok = false, error = 'Kein Charakter aktiv.' } end
local current = relation(player.characterId)
if not current.contactUnlocked then return { ok = false, error = 'Dieser Kontakt ist noch nicht freigeschaltet.' } end
local location = exports.devx_housing:GetPlayerHousingLocation(source)
if not location or location.type ~= 'unit' then
return { ok = false, error = 'Du musst dich in deinem Apartment befinden.' }
end
if tonumber(location.ownerCharacterId) ~= tonumber(player.characterId) then
return { ok = false, error = 'Du kannst Nikki nur in dein eigenes Apartment einladen.' }
end
local spawn = location.interior and location.interior.companionSpawn
if not spawn then return { ok = false, error = 'Für dieses Apartment ist kein Treffpunkt eingerichtet.' } end
TriggerClientEvent('devx_stripclub:client:spawnCompanion', source, {
name = DevXStripclub.Nikki.name,
model = DevXStripclub.Nikki.model,
spawn = spawn
})
return { ok = true, message = 'Nikki ist auf dem Weg zu deinem Apartment.' }
end
exports('InviteCompanion', inviteCompanion)
DevXRegisterCallback('stripclub:inviteCompanion', function(source)
return inviteCompanion(source)
end)
RegisterCommand('resetnikki', function(source, args)
if source ~= 0 and not IsPlayerAceAllowed(source, 'devx.admin') then return end
local target = tonumber(args[1]) or source
local player = exports.devx_core:GetPlayer(target)
if not player then return end
MySQL.query.await('DELETE FROM devx_club_relations WHERE character_id = ? AND relation_key = ?', {
player.characterId, DevXStripclub.Nikki.key
})
MySQL.query.await("DELETE FROM devx_phone_contacts WHERE character_id = ? AND contact_type = 'npc_companion'", {
player.characterId
})
TriggerClientEvent('devx_phone:client:refresh', target)
TriggerClientEvent('devx_housing:client:notify', target, 'Nikki-Beziehung wurde zurückgesetzt.')
end, false)
AddEventHandler('playerDropped', function() actionCooldowns[source] = nil end)