interface PedOptions {
ped_model: string;
ped_name: string;
ped_group?: string;
interaction?: {
useKeyInteractions: boolean;
showLabelOverHead: boolean;
distCanInteract: number; // float
distShowLabel: number; // float
textOverHead?: string;
interactionText?: string;
};
cam: {
enabled: boolean;
offset?: vector3;
fov?: number; // float
pointZOffset?: number; // float
};
pos: {
coords: vector3,
heading: number; // float
};
blip?: {
sprite: number;
color: number;
scale: number; // float
name: string;
shortRange: boolean;
},
animations: {
idleAnim?: {
dict?: string;
name?: string;
scenario?: string;
};
openAnim?: {
dict?: string;
name?: string;
scenario?: string;
// If you don't specify duration animation will be cancelled when player closes menu.
duration?: number; // In miliseconds
};
closeAnim?: {
dict?: string;
name?: string;
scenario?: string;
// Specify duration when to reset back to idle animation
duration: number;
};
};
menus?: {
regular?: {
[key: string]: RegularMenu;
},
dynamic?: {
[globally_unique_key: string]: DynamicMenu;
}
};
// Will be explained below
dialog?: (create: Function, close: Function) => void;
}
interface RegularMenu {
type: 'buy' | 'sell',
// If not specified, title will be peds name.
title?: string;
description?: string;
moneyType?: string; // This value will be passed to add/remove/has money function.
items: {
{
name: string;
price: number;
// In case when your image is not [name].[default_extension]
image?: string;
// If you're using fetchItems you don't have to specify it.
label?: string;
}[]
}
}
interface DynamicMenu {
type: 'buy' | 'sell';
// If not specified, title will be peds name.
title?: string;
description?: string;
moneyType?: string; // This value will be passed to add/remove/has money function.
items: {
{
name: string;
// You can define it if you're not planning that this item price will change.
price?: number;
// In case when your image is not [name].[default_extension]
image?: string;
// If you're using fetchItems you don't have to specify it.
label?: string;
}[]
}
}
type callback = (data: CallbackData) => void;
interface CallbackData {
id: string; // Unique dialog ID, used to open dialogs
ped: Entity;
coords: vector3;
}
Dialog Function
Function that should be passed to dialog options dialog . You will have two functions to control your dialog flow, create and close.
If you set the dialog button action to close you don't need to handle that action; it will be automatically managed by the script.
local dialogFlow = function(create, close)
create(options, function(action)
if action == 'action_1' then
close()
return
end
create(options2, function(action2)
if action2 == 'action_44444' then
-- do some stuff or create another menu
end
end)
end)
end
type create = (options: DialogOptions, callback: CallbackFunction) => void
type CallbackFunction = (action: string) => void;
type close = () => void;
interface DialogOptions {
message: string;
buttons: DialogButton[];
sound?: {
// path in /sounds/ dir
src: string;
volume?: number; // float (from 0.0 to 1.0)
};
typeWriter: {
enabled: boolean;
duration?: number; // in miliseconds
// Players will not be able to click any buttons until typewriter is finished.
disableButtons: boolean;
}
}
interface DialogButton {
text: string;
action: string;
}
Adding Sound
It should be easy to understand, but I'll mention a few things. When adding a sound, first upload it to web/sounds/your_folder/soundFile. You can use any sound format (mp3, m4a, ogg, etc.). For better organization, I highly recommend adding each set of sounds to separate folders, but it's fine if you add everything to the web/sounds/ directory. Then, set the full path, including the folder name and file extension, in sound.src.
Example
example file is located in web/sounds/jaxon/jaxon_entry.mp3 .
{
sound = {
src = 'jaxon/jaxon_entry.mp3',
volume = 0.9
},
... -- Other create function parameters.
}
Menus
To allow a player to open a menu, set the menu key as the button action.
Everything should be clear on how to use regular menus. Dynamic menus are a bit trickier. To set up a dynamic menu, you need to add item names without including their prices, as this will be handled by the script on the server side. Then, locate the file on the server at server/dynamicMenus.lua and add your item price ranges there.
If you want some items to have fixed prices, you can define their prices inside the dynamic menu, but then do not define them on the server side.
interface DynamicMenus {
// Make sure this key is globally unique!!
[globally_unique_key: string]: DynamicObject;
}
interface DynamicObject {
// how often to update prices globally
updateInterval: number; // in seconds (NOT MILISECONDS)
items: {
[item_name: string] = {
min: number;
max: number;
}
}
}
DynamicMenus = {
['kevin-dynamic-1'] = {
updateInterval = 10,
items = {
['seeds_tomato'] = { min = 100, max = 200 },
['seeds_carrot'] = { min = 50, max = 100 },
['seeds_cucumber'] = { min = 10, max = 20 }
}
}
}