FlexHour est un système de montres de luxe pour FiveM. Les joueurs achètent leurs montres auprès d'une vendeuse en boutique, les configurent, les portent, les exhibent, les font entretenir et les échangent. Tout un trafic de contrefaçons tourne à côté.
Le produit se compose de deux ressources : concept_flexhour (le script) et flexhour_boutique (l'intérieur de la boutique, où l'on entre à pied). La boutique a son propre guide : Boutique FlexHour.
FlexHour utilise Cfx Asset Escrow. Après le paiement sur Tebex, les ressources apparaissent sur Keymaster dans Granted Assets, sur le compte Cfx.re avec lequel vous vous êtes connecté au paiement.
concept_flexhour et flexhour_boutique arrivent dans le même achat, en deux téléchargements séparés. Téléchargez et installez les deux.concept_flexhour. Si vous renommez le dossier, vous obtenez No such export useBox in resource concept_flexhour.config.lua et les fichiers locales/ restent modifiables. Le reste est protégé par escrow.| Ressource | Remarques |
|---|---|
ox_lib |
Utilisé pour les callbacks et les traductions. FlexHour dessine lui-même ses menus, formulaires, boîtes oui/non et barre de progression. |
oxmysql |
Les tables de la base de données sont créées au premier démarrage. |
concept_bridge 1.1.0 ou plus récent |
Testé avec 1.1.1. Une ressource gratuite et séparée sous GPL-3.0 : concept_bridge. Elle n'est pas incluse dans ce produit. N'utilisez qu'un seul bridge. |
| Un framework | QBCore, qbx_core, ESX ou ox_core |
| Un inventaire avec métadonnées par objet | ox_inventory est recommandé (voir plus bas) |
| Une ressource de target | ox_target, qb-target ou sleepless_interact |
concept_flexhour et flexhour_boutique dans votre dossier resources.server.cfg après leurs dépendances. Le bridge charge ses modules depuis ce qui tourne déjà, alors démarrez-le après votre framework, votre inventaire et votre target :ensure ox_lib
ensure oxmysql
ensure your_framework # es_extended / qb-core / qbx_core / ox_core
ensure ox_inventory # or your inventory
ensure ox_target # or your target
ensure concept_bridge
ensure concept_flexhour
ensure flexhour_boutique # the boutique interior, after concept_flexhour
add_ace group.admin flexhour.admin allow
/fhmodels. La commande liste les modèles de montres qui ne sont pas streamés. Si la liste est vide, le dossier stream/ est complet.Chaque modèle de montre est un objet distinct, nommé fh_. La configuration est stockée dans les métadonnées de l'objet : métal du boîtier, cadran, lunette, sertissage, numéro de série, gravure et état. Les boutiques, les échanges et d'autres scripts peuvent donner un modèle précis.
ox_inventory
docs/ox_items.lua (les 23 modèles) dans ox_inventory/data/items.lua.['flexhour_box'] = {
label = 'FlexHour Box',
weight = 450,
stack = false,
close = true,
description = 'Something shiny inside.',
client = { export = 'concept_flexhour.useBox' },
},
['flexhour_replica_kit'] = {
label = 'Replica Kit',
weight = 900,
stack = true,
close = true,
description = 'Blank case, cheap movement, dial stencils, gold plating. Not from any boutique.',
},
web/img/*.png et web/img/items/*.png dans ox_inventory/web/images/. Il y a 78 icônes de montres : une par modèle et par matériau de boîtier, plus une par édition limitée. Chaque montre pointe vers sa propre icône via metadata.image.Inventaires de type qb
Ajoutez les objets de docs/qb_items.lua (format QBCore). FlexHour les enregistre comme utilisables au démarrage. Sur ces inventaires, l'objet affiche le nom et l'image du modèle. Le détail de la configuration se trouve dans le champ info de l'objet et dans la vue d'examen (I pendant que la montre est portée).
FlexHour accède au framework (argent, identité, métiers), à l'inventaire, au target et aux notifications via concept_bridge.
| Élément | Pris en charge | Statut |
|---|---|---|
| Framework | QBCore, qbx_core, ESX, ox_core | Les comptes sont cash et bank. Le bridge associe cash au compte money d'ESX. |
| Inventaire | ox_inventory | Recommandé. Testé en jeu. |
| Inventaire | qb-inventory, ps-inventory, qs-inventory, tgiann-inventory, origen_inventory, codem-inventory, core_inventory, one-inventory | Doit conserver les métadonnées par objet. Couvert par des tests automatisés, pas encore testé en jeu. |
| Inventaire | L'inventaire intégré d'ESX | Non pris en charge. Il n'a ni métadonnées d'objet ni emplacements, et une montre est ses métadonnées. La console vous prévient au démarrage. |
| Target | ox_target, qb-target, sleepless_interact | Vous pouvez aussi utiliser une invite de touche à la place d'un target : voir Config.Interaction. |
config.lua contient tous les réglages qu'un serveur peut modifier. Changez une valeur et redémarrez la ressource. Si vous omettez un réglage, FlexHour utilise sa valeur par défaut. Ce qui n'est pas un réglage ne peut pas être remplacé depuis config.lua.
| Réglage | Défaut | Rôle |
|---|---|---|
Config.PayAccounts |
{ 'cash', 'bank' } |
Comptes à débiter, dans l'ordre. Le premier qui couvre le prix paie. |
Config.Delivery |
'box' |
'box' : les achats arrivent dans un écrin et le joueur le déballe. 'direct' : la montre va directement dans l'inventaire. |
Config.Interaction |
{ mode = 'target', key = 38, keyName = 'E' } |
Comment les joueurs utilisent vendeuses, vitrines et lieux : avec le target ou avec une invite de touche. |
Config.Notify |
{ system = 'flexhour', position = 'top-right' } |
Les notifications de FlexHour, ou celles de votre serveur (via le bridge). |
Config.InspectKey |
'I' |
Touche pour examiner la montre portée. Les joueurs peuvent la changer dans les réglages de touches de GTA. |
Config.FlexCommand |
'flex' |
Commande du flex au poignet. |
Config.FlexLoopCommand |
'flex2' |
Commande du flex en boucle. |
Config.AdminAce |
'flexhour.admin' |
Permission ACE des outils admin. |
Config.AdminOpenToAll |
false |
true rend chaque joueur admin. À utiliser uniquement pour les tests. |
Config.TryOnSeconds |
12 |
Durée d'un essayage chez la vendeuse. |
Config.Clerks est la liste des vendeuses de boutique. La vendeuse fournie se tient à Vinewood avec le modèle a_f_y_business_02, un scénario WORLD_HUMAN_STAND_IMPATIENT, un blip (sprite 617, couleur 46, échelle 0.8), et vend les niveaux budget, mid, luxury et mythic.
Si flexhour_boutique tourne, sa vendeuse se tient derrière le comptoir de la boutique. Cette position est enregistrée dans data/clerks.json, qui a priorité sur config.lua. Si vous utilisez FlexHour sans la boutique, ouvrez /fhclerk et choisissez Put the config.lua clerks back.
Config.Negotiate)| Réglage | Défaut | Rôle |
|---|---|---|
enabled |
true |
Les joueurs peuvent marchander avec les vendeuses. |
rounds |
3 |
Manches de mini-jeu avant l'offre finale : lire la vendeuse, une énigme et un jeu de mémoire. |
cooldownSeconds |
90 |
Délai par joueur après chaque négociation. |
showFloor |
true |
Affiche le prix le plus bas que la vendeuse accepterait. |
onWalkAway |
'list' |
'list' : le joueur peut encore acheter au prix catalogue. 'abort' : la vente s'arrête. |
Config.Services)| Réglage | Défaut | Rôle |
|---|---|---|
strapSwap |
1500 |
Frais de changement de bracelet, plus la différence de prix entre les bracelets. |
replatePercent |
0.35 |
Coût du replaquage, en part du prix catalogue. |
replateMin |
2500 |
Le prix de replaquage le plus bas. |
icePerLevel |
0.40 |
Coût de chaque niveau de sertissage, en part du prix catalogue du boîtier. |
engrave |
750 |
Gravure (jusqu'à 24 caractères). |
polish |
400 |
Polissage, qui restaure l'état. |
authenticate |
150 |
Certificat d'authenticité. |
authDays |
14 |
Nombre de jours de validité du certificat. 0 signifie pour toujours. |
Config.Limited)Config.Limited fixe combien d'exemplaires de chaque modèle limité peuvent exister au total. Voir Éditions limitées.
Config.Wear)| Réglage | Défaut | Rôle |
|---|---|---|
keepWorn |
false |
false : une montre portée reste un objet d'inventaire. true : pendant qu'elle est portée, FlexHour la garde dans sa propre table pour qu'elle ne puisse pas être perdue. Voir Montres portées. |
restoreOnSpawn |
true |
La montre est toujours au poignet après une reconnexion. S'applique quand keepWorn = false. Une montre gardée reste toujours en place. |
gameWatch |
'hide' |
Ce qui arrive aux accessoires de poignet de GTA. 'hide' : ils sont retirés pendant qu'une montre FlexHour est portée. 'block' : l'emplacement du poignet gauche reste toujours vide. 'off' : ils ne sont pas touchés. |
conditionLossPerHour |
0.5 |
État perdu par heure de port. Les répliques s'usent plus vite. |
hideInVehicle |
false |
Masquer les montres dans les véhicules. |
playerAdjust |
true |
Les joueurs peuvent affiner leur propre réglage avec /watchfit. Les autres joueurs voient le résultat. |
allowScale |
true |
Le gizmo de réglage peut aussi redimensionner la montre (de 0.75 à 1.25). |
fitPresets |
3 |
Emplacements de réglage enregistrés par joueur, utilisés avec /watchpreset. |
sleeve.enabled |
true |
Les joueurs peuvent remonter la manche avec /watchsleeve. |
Config.Wear.rob)| Réglage | Défaut | Rôle |
|---|---|---|
enabled |
true |
Une montre portée peut être volée. |
seconds |
6 |
Temps nécessaire pour prendre la montre. |
when |
{ dead = true, handsUp = true, cuffed = true } |
Les états dans lesquels le porteur doit se trouver. |
cooldownMinutes |
10 |
Délai avant qu'un voleur puisse voler à nouveau. |
protectMinutes |
30 |
Durée de protection d'une victime après un vol. |
command |
'stealwatch' |
Commande de vol. false désactive la commande. |
handsUpAnims |
{} |
Les animations « mains en l'air » de votre serveur : { { 'dict', 'clip' }, ... }. |
minigame |
false |
Votre propre mini-jeu : function(victim) return true end. Renvoyez true pour continuer, false en cas d'échec. |
Config.Fakes)| Réglage | Défaut | Rôle |
|---|---|---|
enabled |
true |
Le trafic de contrefaçons est actif. |
dealer.coords / dealer.model |
dans config.lua / g_m_y_ballaeast_01 |
Où se tient le vendeur de kits, et son modèle de ped. |
dealer.kitPrice |
2500 |
Prix de base du kit. Le niveau du kit le multiplie. |
dealer.cooldown |
900 |
Secondes par personnage entre deux kits. |
workshop.coords / workshop.prop |
dans config.lua / 'prop_tool_bench02' |
Où se trouve l'établi. prop = false utilise une table de la carte au lieu de faire apparaître un établi. |
fence.coords / fence.model |
dans config.lua / s_m_y_dealer_01 |
Où se tient le receleur, et son modèle de ped. |
fence.account |
'cash' |
Compte sur lequel le receleur paie. Utilisez 'black_money' si votre framework l'a. |
fence.maxPayout |
30000 |
Le maximum que le receleur paie pour une montre. |
fence.cooldown |
600 |
Secondes par personnage entre deux ventes. |
fence.alertChance |
0.10 |
Probabilité qu'une vente soit signalée à la police. |
fence.alertChanceFake |
0.25 |
La même probabilité quand la montre est une réplique. |
onAlert |
function(src, coords, build) end |
Hook côté serveur pour votre script de dispatch. |
Pour placer les trois lieux en jeu, utilisez /fhfake dealer, /fhfake workshop ou /fhfake fence. Les lieux placés sont enregistrés dans data/fakes.json, qui a priorité sur config.lua.
Tout ce que lisent les joueurs vient de locales/.json : notifications, menus, la page de la boutique (ui_*), les cartes de négociation (card_*), les indices de la vendeuse (tell_*) et ce que disent les vendeuses, le receleur et le vendeur de kits (neg_*).
Langues incluses : anglais (en), hongrois (hu), allemand (de), espagnol (es) et français (fr). FlexHour utilise le réglage de langue d'ox_lib. Mettez-le dans server.cfg :
setr ox:locale "en" # or "hu", "de", "es", "fr"
Pour ajouter une langue, copiez en.json en .json et traduisez les valeurs. Les énigmes de négociation sont conservées côté serveur dans les cinq langues. Les noms des montres, matériaux et bracelets sont des noms de produits et ne sont pas traduits.
| Commande | Rôle |
|---|---|
/watch |
Mettre ou retirer une montre. |
/watchfit |
Affiner le réglage avec un gizmo (voir ci-dessous). |
/watchhand |
Passer la montre à l'autre poignet. |
/watchsleeve |
Remonter ou baisser la manche. |
/watchpreset |
Enregistrer ou charger un préréglage. |
/flex |
Flex au poignet. |
/flex2 |
Flex en boucle. |
I |
Examiner la montre portée. |
X |
Ranger l'écrin que vous tenez. Touche modifiable. |
/stealwatch |
Voler une montre portée (voir Vol). |
/fhhelp |
Lister les commandes dans le chat. |
Le gizmo de réglage fonctionne ainsi :
allowScale est activé.flexhour.admin)| Commande | Rôle |
|---|---|
/fhclerk |
Déplacer, renommer ou retirer les vendeuses placées, ou remettre celles de config.lua. |
/fhclerk |
Placer une nouvelle vendeuse. Visez avec le fantôme l'endroit où l'écrin doit se poser sur un comptoir. |
/fhstand |
Placer une vitrine là où vous êtes. |
/fhfake [dealer|workshop|fence] |
Gérer ou placer les lieux de contrefaçon. |
/fhgive [id] |
Donner une montre en écrin et choisir sa configuration. |
/fhwrist |
Gizmo de réglage au poignet. G enregistre le réglage comme défaut du serveur pour votre modèle de ped. |
/fhmodels |
Lister les modèles de montres non streamés. |
Les outils admin vérifient l'ACE de Config.AdminAce (par défaut flexhour.admin) :
add_ace group.admin flexhour.admin allow
Avant l'arrivée des joueurs, vérifiez que Config.AdminOpenToAll vaut false. Avec true, chaque joueur est admin : il peut se donner des montres et placer vendeuses et vitrines, et la ligne ACE ne sert à rien. Tant que c'est activé, la console affiche un avertissement rouge à chaque démarrage.
La vendeuse ouvre la boutique. Le joueur choisit un modèle, puis le métal du boîtier, le cadran, le bracelet et sa couleur, la lunette, les aiguilles et le niveau de sertissage. Chaque niveau a ses propres options. Le joueur peut essayer la montre pendant TryOnSeconds, puis l'acheter, ou négocier d'abord. Avec Delivery = 'box', la montre arrive dans un flexhour_box. Utiliser l'écrin joue un rituel de déballage sur le comptoir, et le joueur garde l'écrin en main jusqu'à le ranger avec X.
Chaque montre authentique reçoit un numéro de série unique (FH-…), enregistré dans le registre (flexhour_serials).
Chaque vendeuse reçoit à chaque session une personnalité cachée faite de cinq traits : vanité, avidité, fierté, loyauté et nervosité. Le langage corporel donne des indices. Le joueur joue des cartes comme Compliment, Liquide, Prix cassé, Bluff, Habitué, Concurrent, Lot et Histoire, et enchaîne des manches mêlant lecture de la vendeuse, énigmes et jeu de mémoire. Le résultat est l'offre finale. Le vendeur de kits et le receleur utilisent de la même manière un jeu de cartes de rue.
Les admins placent des vitrines avec /fhstand et garnissent chaque coussin depuis le menu de la vitrine. Les vitrines vendent au prix de leur étiquette, qui doit être entre 70 % et 160 % du prix catalogue, et leur stock est illimité. Une vitrine à moins de 30 m d'une vendeuse peut être négociée avec celle-ci. Dans cette version, les joueurs ne peuvent pas posséder de vitrine, et les éditions limitées ne peuvent pas y être exposées.
Un joueur porte une montre à la fois, à l'un ou l'autre poignet. Les réglages intégrés couvrent les personnages freemode. Pour les peds personnalisés, les admins enregistrent un réglage par modèle de ped, et les joueurs peuvent affiner le leur. Les autres joueurs voient la montre de près : aiguilles en direct, reflets et pierres qui brillent la nuit. Les actions du joueur sont le flex, l'examen et la manche.
La vendeuse propose le changement de bracelet, le replaquage, le sertissage, la gravure, le polissage et l'authentification. L'authentification donne à une montre authentique un certificat valable authDays jours. Sur une réplique, l'authentification montre que c'est un faux.
Il existe 14 pièces numérotées. Chacune est une configuration fixe, avec un cadran, une finition ou un bracelet qu'aucune montre standard ne peut avoir. Le serveur plafonne le nombre d'exemplaires, et chaque acheteur reçoit son propre numéro (par exemple « No. 3 / 10 »). Une fois toutes les pièces vendues, l'édition quitte la boutique. Les vendeuses les vendent dans le groupe Limited editions de la liste.
Sur une édition limitée, le sertissage, la gravure et le polissage sont autorisés. Le changement de bracelet et le replaquage sont refusés, pour que la pièce reste d'origine.
Le trafic de contrefaçons fonctionne en trois étapes :
Une réplique a l'air authentique dans l'inventaire, mais son numéro de série n'est pas dans le registre, et plus sa qualité est basse, plus elle se trahit : impression du cadran de travers, heure qui dérive, trotteuse saccadée ou arrêtée, usure plus rapide et placage or qui s'efface.
Avec la valeur par défaut Config.Wear.keepWorn = false, une montre est toujours un objet d'inventaire, même quand elle est portée. Elle reste dans son emplacement, et tout ce qui arrive à l'inventaire lui arrive aussi : effacement à la mort, fouille ou autre script de vol.
Avec keepWorn = true, mettre une montre la retire de l'inventaire et FlexHour la garde dans flexhour_wrist. La retirer la remet en objet. Pendant qu'elle est portée, rien de ce qui arrive à l'inventaire ne peut la prendre : effacement à la mort, confiscation, fouille, abandon, coffre ou coffre de véhicule. Pour vendre, offrir, ranger ou faire entretenir la montre, le joueur doit d'abord la retirer avec /watch.
Si vous repassez keepWorn à false, chaque personnage récupère sa montre portée dans son inventaire à sa prochaine connexion.
Une montre portée ne peut être prise que d'une seule façon : par le vol de FlexHour. Un joueur à côté d'un porteur mort, mains en l'air ou menotté peut prendre la montre avec l'option du target, l'invite [E] ou /stealwatch. La même montre, avec le même numéro de série, finit dans les poches du voleur. D'autres ressources peuvent réagir à l'événement flexhour:watchRobbed.
Les menus de vêtements du jeu peuvent mettre une montre au poignet gauche (emplacement de prop 6) ou un bracelet au poignet droit (emplacement 7). Avec gameWatch = 'hide', l'accessoire GTA est retiré tant qu'une montre FlexHour est sur ce poignet. Si un menu de vêtements enregistre la tenue entre-temps, la tenue est enregistrée sans cet accessoire. Retirez la montre FlexHour avant d'enregistrer une tenue, ou réglez gameWatch sur 'off'.
-- Give a player a watch. build = { base = '', material = ..., dial = ..., strap = ..., iced = 0 }
-- Only base is required; anything you leave out or set to something invalid falls back to that model's defaults.
-- boxed = true (default) delivers it in a flexhour_box. Returns true, serial.
local ok, serial = exports.concept_flexhour:GiveWatch(source, { base = 'timor_basic' }, true)
-- Release the watch a deleted or banned character was wearing (keepWorn = true).
-- identifier = the character id from your framework (the owner column of flexhour_wrist), or an online player's server id.
-- Returns true, serial, or false when nothing was on that wrist.
local released, serial = exports.concept_flexhour:ReleaseWrist(identifier)
Les identifiants de modèle se trouvent dans shared/catalog.lua (FH.BaseOrder). Le nom de l'objet sans le préfixe fh_ fonctionne aussi.
concept_flexhour.useBox et concept_flexhour.useWatch sont les exports d'objet que l'inventaire appelle. Vous n'avez pas besoin de les appeler vous-même.
| Événement | Arguments | Quand |
|---|---|---|
flexhour:purchased |
src, build, price, kind |
Un joueur a acheté une montre. |
flexhour:watchRobbed |
robber, victim, serial, build |
Une montre portée a été volée. |
flexhour:fenceAlert |
src, coords, build |
Une vente au receleur a été signalée. Appelle aussi Config.Fakes.onAlert. |
flexhour:wristReleased |
owner, serial, build |
ReleaseWrist a retiré une montre portée. |
flexhour:suspect |
src, reason, serial |
Un doublon possible ('duplicate', 'watch_twice'). |
AddEventHandler('flexhour:watchRobbed', function(robber, victim, serial, build)
-- log it, alert the police, ...
end)
Les tables sont créées au premier démarrage :
| Table | Contenu |
|---|---|
flexhour_serials |
Le registre des montres authentiques (numéro de série, configuration, propriétaire). |
flexhour_wrist |
Les montres portées gardées par FlexHour (keepWorn = true). |
flexhour_worn |
Ce que porte chaque personnage. |
flexhour_fit |
Les réglages de poignet enregistrés. |
flexhour_fit_presets |
Les préréglages des joueurs. |
flexhour_stands |
Les vitrines et leur stock. |
flexhour_meta |
État interne. |
FlexHour ne construit que ce que vous pouvez réellement voir. Les limites sont fixes :
| Problème | Solution |
|---|---|
missing ox_inventory items dans la console |
Ajoutez les objets de Objets. |
model "fh_…" is not streamed dans F8 |
Le dossier stream/ est incomplet. Lancez /fhmodels, puis recopiez stream/ depuis le téléchargement. |
| La montre flotte à côté de la main | Lancez /watchfit. Pour tout un modèle de ped, un admin enregistre le réglage par défaut avec G. |
No such export useBox in resource concept_flexhour |
Le dossier a été renommé. Gardez concept_flexhour. |
ESX's built-in inventory cannot hold a watch |
Installez un inventaire avec métadonnées d'objet. |
| La montre disparaît de l'inventaire quand on la met | C'est keepWorn = true : la montre est au poignet. /watch la retire. |
| La vendeuse ou le receleur ne liste pas ma montre | Elle est à votre poignet. Retirez-la d'abord. |
| L'argent n'est pas prélevé ou pas versé | Config.PayAccounts doit utiliser des noms de comptes que votre framework connaît via le bridge (cash, bank, money). |
| Tout le monde peut utiliser les commandes admin | Réglez Config.AdminOpenToAll = false. |
Un inventaire n'écrit pas chaque changement immédiatement en base de données, donc un crash brutal peut le ramener quelques minutes en arrière.
Arrêtez le serveur via txAdmin, et non en fermant la fenêtre.
Config.AdminOpenToAll vaut false./fhmodels ne liste rien.setr ox:locale).flexhour_boutique démarre après concept_flexhour.We aim to reply on Discord within 24 hours on business days.
Besoin d'aide pour l'installation ? Rejoindre le Discord ou support@conceptstudio.store.