Jump to content

Libraries

59 files

  1. NativeUI

    NativeUI for RageMP!
    This can only be used Clientside!
    Documentation: Click
    Github: Click

    16380 downloads

       (20 reviews)

    18 comments

    Updated

  2. Efficient Attachment Sync

    Most of the server developers (ones that don't patiently wait for *something large*, though this resource is powerful enough) use their own server-side object attachments implementation that represents some large JSON with all the object and attachment information. This resource lets you cache "static attachments" in the client-side code so thanks to efficient utilization of the shared data it just uses a small shared variable to do the attachment processing without any need to create server-side objects nor send its data.
     
    For example, if you want to attach a specific object to specific ped bone with spefic bone offset and object rotation, this will only use a ~4-8 byte shared variable keeping it accurate. User-made implementations I have seen before usually take ~100 bytes per an object.
     
    API: Client-side
    mp.attachmentMngr.register(attachmentId, model, bone, offset, rotation) mp.attachmentMngr.addLocal(attachmentId) (synced!) mp.attachmentMngr.removeLocal(attachmentId) (synced!)  
    API: Server-side
    player.addAttachment(attachmentId, remove) player.hasAttachment(attachmentId)  
    Example Resource
    There's an example resource in /client-packages/epic-attachments folder. It lets you toggle attachments (there are like 30 attachments) using a NativeUI-based menu. Thanks to root for his contributions made to the example resource.
     
     
     

    4039 downloads

       (14 reviews)

    7 comments

    Updated

  3. MC-RP Object Editor

    This is a public release of the object editor used on the Mafia City Roleplay server. 
    Usage client-side: 
    let obj = mp.objects.new(mp.game.joaat(model), new mp.Vector3(position.x, position.y, position.z)); mp.events.call('objecteditor:start', obj.id); mp.events.add('objecteditor:finish', (objId, pos, rot) => { if(obj.id == objId) { // send pos and rot to server and save or do whatever. return; } });  
    Github Link: https://github.com/Ahmad45123/ragemp-objecteditor

    391 downloads

       (2 reviews)

    6 comments

    Updated

  4. RageMP-BigData

    RageMP-BigData
    This plugin was created for experiment and might not be what you are looking for, this is intended to be used for sending big data to clients in chunks to make the size unlimited for the server owners, this will eliminate original rage-mp events limit and will be as fast as them when being used for small data, but i suggest that you use original ones just in case.
    This is still experimental and the way it works might change in a future update

    GITHUB LINK : https://github.com/safra36/RageMP-BigData
    API
    for obvious reasons i made this only to go from server-side to client-side and not client-side to server-side, there is a commented code about this and with a bit of knowlegde you can get it to work but it's not recommended since it will basically flood your server if you have many players so stay of it!
    Server-Side Functions
    /** Send a big data to a player @param player valid muliplayer player object @param eventName the event which is defined on client-side (just a normal event name) @param DataArray It's an array of data like how player.call works, and it supports all types of data (objects, numbers, strings with no effect on the typing!) @callback dataReceived Optional callback triggers when the data is received in full by the client @param retry Optional param which is true by default, pass false to disable auto retry (this will cause the data to be lost, added by request but don't use it!) */ player.callBig(eventName, DataArray, dataReceived, &retry) /** Send a big data to all players @param eventName the event which is defined on client-side (just a normal event name) @param DataArray It's an array of data like how player.call works, and it supports all types of data (objects, numbers, strings with no effect on the typing! */ mp.players.callBig(eventName, DataArray) /** Set a big shared variable on players @param name name of the data @param data any type of data @callback dataReceived Optinal callback triggers when the data is received in full by the client @param retry Optional param which is true by default, pass false to disable auto retry (this will cause the data to be lost, added by request but don't use it!) */ player.setBigVariable(name, data, dataReceived, &retry) /** Get a previously set shared data on the client @param name name of the data */ player.getBigVariable(name) /** Set a big private data on client which is only set on a certain client, access it on server-side with player.privateData[dataName] You can use player.pdata.name instead from 0.0.3 @param name name of the data @param data any type of data @callback dataReceived Optinal callback triggers when the data is received in full by the client @param retry Optional param which is true by default, pass false to disable auto retry (this will cause the data to be lost, added by request but don't use it!) */ player.setPrivateData(name, data, dataReceived, &retry) /** Delete private data on server-side and client-side @param name name of the data */ player.deletePrivateData(name) Server-Side Variables
    /** * Setter * Sets private data on client like setPrivateData but without optional retry * Use with try catch, it can only be set if there is no other pending data on the target name (throw error if there is a pending data) */ player.pdata.dataName = value /** * Getter * Get private data which was set, must be used with await since the data may take time to reach client; */ var data = await player.pdata.dataName; Server-Side Events
    /** Detemine if a data has been fully received by the client @param player playerObject which has sent this signal @param id Id of the data sending session @param eventName Name of the even you have been called on the client previously using callBig */ mp.events.add('DataSender:End', (player, id, eventName) => {}) /** This will be called when the sent data was failed (there is an auto retry to put the data on player for sure but see this as a notification) @param id Id of the data sending session @param dataName Name of the data you have been set on the client @param errorCode -1 Means the data could not be parsed on client, -2 means there was some data chunks lost on the send proccess */ mp.events.add('DataSender:Failed', (id, dataName, errorCode) => {}) Client-Side Functions
    /** Get a shared variable of a player @param name data name that was set on the player */ player.getBigVariable(name) Client-Side Variables
    You can get client private data using mp.players.local.privateData[dataName] Client-Side Events
    /** Get notified when a shared data get's updated on server-side @param dataName shared data name @param entityId id of the entity which this it's shared data has been updated (currently it's only a player) @param type get type of entity which is updated (player, object, vehicle, ped but currenly it's only player) @param oldData previously set data if it's forst time then it's undefined @param newData the latest data has been set on this name */ mp.events.addBigDataHandler(dataName, (entityId, type, oldData, newData) => {}) /** Get notified when a shared data get's updated on server-side @param dataName private data name @param oldData previously set data if it's forst time then it's undefined @param newData the latest data has been set on this name */ mp.events.addPrivateDataHandler(dataName, (oldData, newData) => {}) Example (BigData Event Sample)
    Server-Side
    // Big data is an array of rage-mp cloths (something around 15MB of data) and other ones are regular data (can be big data as well) player.callBig('GetBigData', [BigData, 'Some Other Test Arguments', 3]); Client-Side
    mp.events.add('GetBigData', (BigJSONData, args1, argg2) => { mp.gui.chat.push(`Data: ${BigJSONData['Tops']['Male']['NONE'][0].name} - Type: ${typeof(BigJSONData)}`); mp.gui.chat.push(`Data: ${args1} - Type: ${typeof(args1)}`); mp.gui.chat.push(`Data: ${argg2} - Type: ${typeof(argg2)}`); }) Results

    Benchmark
    Well, the time it takes to transfer the data really depends on player network speed, data chunk size and the size of the data it self. For testing, i sent a very big json file contaning all rage-mp clothing with their torsos and names and prices (which i use on server-side my self), the file is something around 15MB, it took something about ~3s to transfer the whole data to the client, this is a beta version of the library but any help is accepted for optimizations.
    Installation
    Copy all the files to your packages/client-packages Make sure to add the client-side file to your index.js Enjoy! Known Issues
    If your data fails and you set a new data which does not fail, the old data is probably gonna replace the new data over retry  

    104 downloads

       (2 reviews)

    4 comments

    Updated

  5. Inventory API

    This resource provides an inventory API to server developers.
    This resource will not save anything on its own, it just provides you the functions to make your own inventory system using CEF/NativeUI/commands.
     
    Installing
    Put the files you downloaded in their respective places Read the documentation and examples to set up some items etc. All done  
    Features
    Easy to use (hopefully!) Events Custom attributes for items (see examples)  
    Inventory API
    const invAPI = require("../inventory-api"); /** * Adds an item to the inventory system. * @param {string} key Item identifier, such as "item_medkit". * @param {string} name Item name, such as "Medkit". * @param {string} description Item description, such as "Gives you 10 health". * @param {function} [onUse] Optional - Function that gets called when the item is used. * @param {function} [nameFunc] Optional - Function that gets called when getItemName() is used. * @param {function} [descFunc] Optional - Function that gets called when getItemDescription() is used. * @return {object} The added item, will be null if there are any mistakes. * @fires itemDefined */ invAPI.addItem(key, name, description, onUse, nameFunc, descFunc); /** * Returns whether the specified key is a registered or not. * @param {string} key Item identifier, such as "item_medkit". * @return {Boolean} True if registered, false otherwise. */ invAPI.hasItem(key); /** * Returns the specified item. * @param {string} key Item identifier, such as "item_medkit". * @return {object} The item at the specified key, will be undefined if the key isn't registered. */ invAPI.getItem(key); /** * Returns all registered item identifiers. * @return {string[]} An array of registered item identifiers. */ invAPI.getAllItems(); /** * Returns the human readable name of the specified item. * @param {string} key Item identifier, such as "item_medkit". * @param {string} [data] Optional - An object that has item attributes. * @return {string} Human readable item name. */ invAPI.getItemName(key, data); /** * Returns the description of the specified item. * @param {string} key Item identifier, such as "item_medkit". * @param {string} [data] Optional - An object that has item attributes. * @return {string} Item's description. */ invAPI.getItemDescription(key, data);  
    Inventory API Events
    /** * itemDefined * This event is called when an item is added to the system with invAPI.addItem() * @param {string} key Item identifier. * @param {string} name Human readable name of the item. * @param {string} description Description of the item. */ invAPI.on("itemDefined", (key, name, description) => { // Example: console.log(`Item defined, key: ${key} | name: ${name} | description: ${description}`); }); /** * itemAdded * This event is called when a player receives an item. * @param {player} player The player who received the item. * @param {string} key Item identifier. * @param {number} amount Amount the player received. * @param {object} data Item attributes. */ invAPI.on("itemAdded", (player, key, amount, data) => { // Example: console.log(`${player.name} received ${amount}x ${key}.`); }); /** * itemUsed * This event is called when a player uses an item. * @param {player} player The player who used the item. * @param {number} invIdx Index of the item in player's inventory. * @param {string} key Item identifier. * @param {object} data Item attributes. */ invAPI.on("itemUsed", (player, invIdx, key, data) => { // Example: console.log(`${player.name} used ${key}.`); }); /** * itemRemoved * This event is called when an item is removed from a player's inventory. * @param {player} player The player who lost an item. * @param {number} invIdx Index of the item that got removed in player's inventory. * @param {string} key Item identifier. * @param {number} amount Removed item amount. * @param {object} data Item attributes. */ invAPI.on("itemRemoved", (player, invIdx, key, amount, data) => { // Example: console.log(`${player.name} lost ${amount}x ${key}.`); }); /** * itemRemovedCompletely * This event is called when an item is no longer in a player's inventory. * @param {player} player The player who lost an item. * @param {string} key Item identifier. * @param {object} data Item attributes. */ invAPI.on("itemRemovedCompletely", (player, key, data) => { // Example: console.log(`${player.name} no longer has ${key} (${data ? "with data" : "without data"}) in their inventory.`); }); /** * inventoryReplaced * This event is called when a player's inventory array gets changed by player.setInventory() * @param {player} player The player who had an inventory change. * @param {object[]} oldInventory The player's old inventory array. * @param {object[]} newInventory The player's new inventory array. */ invAPI.on("inventoryReplaced", (player, oldInventory, newInventory) => { // Example: console.log(`${player.name} had their inventory replaced. (Old item count: ${oldInventory.length}, new: ${newInventory.length})`); });  
    Player API
    /** * Returns the inventory array of the player. * @return {object[]} An array that holds all items of the player. */ player.getInventory(); /** * Replaces the inventory array of the player with the specified one. * @param {Array} newInventory An array that's going to be the new inventory of the player. * @return {Boolean} True if successful, false otherwise. * @fires inventoryReplaced */ player.setInventory(newInventory); /** * Returns whether the player has the specified item or not. * @param {string} itemKey Item identifier. * @return {Boolean} True if player has the item, false otherwise. */ player.hasItem(itemKey); /** * Same as hasItem but for items with custom attributes. * @param {string} itemKey Item identifier. * @param {object} data An object that has item attributes. * @return {Boolean} True if player has the item, false otherwise. */ player.hasItemWithData(itemKey, data); /** * Gets the item's index in the player's inventory. * @param {string} itemKey Item identifier. * @return {number} Index of the item, -1 if not found. */ player.getItemIndex(itemKey); /** * Same as getItemIndex but for items with custom attributes. * @param {string} itemKey Item identifier. * @param {object} data An object that has item attributes. * @return {number} Index of the item, -1 if not found. */ player.getItemIndexWithData(itemKey, data); /** * Gets how many of the specified item exists in the player's inventory. * @param {string} itemKey Item identifier. * @return {number} Item amount. */ player.getItemAmount(itemKey); /** * Same as getItemAmount but for items with custom attributes. * @param {string} itemKey Item identifier. * @param {object} data An object that has item attributes. * @return {number} Item amount. */ player.getItemAmountWithData(itemKey, data); /** * Gets total amount of items the player has in their inventory. * @return {number} Amount of all items. */ player.getTotalItemAmount(); /** * Gives the specified item to the player. * @param {string} itemKey Item identifier. * @param {number} amount Amount to give. * @param {object} [data] Optional - An object that has item attributes. * @return {Boolean} True if successful, false otherwise. * @fires itemAdded */ player.giveItem(itemKey, amount, data); /** * Uses the item at the specified index of the player's inventory array. * @param {number} itemIdx Index of the item in player's inventory array. * @return {Boolean} True if successful, false otherwise. * @fires itemUsed */ player.useItem(itemIdx); /** * Removes the item at the specified index of the player's inventory array. * @param {number} itemIdx Index of the item in player's inventory array. * @param {number} [amount] Optional - Amount to remove. * @return {Boolean} True if successful, false otherwise. * @fires itemRemoved * @fires itemRemovedCompletely */ player.removeItem(itemIdx, amount);  
    Examples
    Full Test Script (used during development): https://gist.github.com/root-cause/6f15f0ee2276872c2d15a5333fed6a10
    Name/Description Function Test Script: https://gist.github.com/root-cause/500b6e197348e941aeebfa8f883486bb
    Source code is available on GitHub in case you don't want to download: https://github.com/root-cause/ragemp-inventory-api

    2649 downloads

       (11 reviews)

    4 comments

    Updated

  6. NativeUI Improved

    Improvements over the previous nativeui:
    Added `UIMenuDynamicListItem`. Descriptions are no longer cut off at 99 characters, but now support 99 * 3. `UIMenuListItem` and `UIMenuSliderItem` can now store extra data. Improved description line wrapping. Description caption is now only updated when necessary. Description background is now only updated (recalculated) when necessary. Bettered the position of the left arrow for list items. Added new badges (Sale, Arrows and Voice Icons). Added `Menu.RemoveItem(item: UIMenuItem)`. When binding an item to a menu, automatically add that item if it isn't in the menu items list already. Added `MenuOpen` event when `menu.Visible` is changed. When hovering over the currently selected ListItem's title text, the cursor will be MiddleFinger, just like in the original menus. `GoLeft` and `GoRight` now correctly handles disabled items. Added experimental automated menu pool system (It's a bit effy right now). MENUS ARE NO LONGER SHOWN BY DEFAULT. Added `closeChildren: boolean = false` parameter to `menu.Close()`. An optional parameter specifiing whether or not you want to close all children with the menu. NOTE BRIEFLY:
    The description and optimization updates for me saved over 20-30 FPS while a menu is open. You might want to be careful with menu pools right now. I haven't went deep into it but for simple menu pools it works GREAT. `MenuClose` event is NOT emitted when Visible is set to false. This is to allow users to reopen menus at it's same state, for e.g searching through a store. The GitHub will not match the file here. So please download the file from GitHub (dist/index.ts) or compile it yourself.  
    https://github.com/karscopsandrobbers/RAGEMP-NativeUI

    701 downloads

       (6 reviews)

    3 comments

    Updated

  7. Timer Bars 2

    Timer Bars 2 is a complete rewrite of my old Timer Bars resource. It's not backwards compatible, meaning you'll need to update your existing timerbar code if you want to switch to this resource.
     
    Changes
    Now requires RAGE Multiplayer 1.1.0 and above Now using offsets, sizes and logic from alexguirre's RAGENativeUI. It really is a great project and deserves some GitHub stars, check it out. OOP approach Probably a bit more efficient Definitely more pleasing to look at  
    Clientside API
    You can access the API by loading timerbars into a variable:
    const timerBarPool = require("timerbars");  
    timerbars/index.js exports these functions:
    // Adds timerbars into the internal timerbar pool. Values sent to this function must be an instance of TimerBarBase or they'll be ignored. add(...args); // Returns whether the internal timerbar pool has specified timerbar. has(timerBar); // Removes the specified timerbar from the internal timerbar pool. If you added the same timerbar multiple times, you'll need to use this function multiple times. remove(timerBar); // Empties the internal timerbar pool. clear();  
    Timer Bars
    TimerBarBase
    This is the base class for other timer bar classes, not really useful on its own since it just draws the title and background. You can inherit from this class to implement your own timer bar designs.
    /* Constructor */ new TimerBarBase(title); /* Properties */ // Title (left text) of the timer bar. Accepts and returns a string. title // Color of the timer bar's title. Accepts HUD color IDs or RGBA array, returns RGBA array. titleColor // Highlight color of the timer bar. Accepts HUD color IDs or RGBA array. Returns null if a highlight color isn't set and RGBA array otherwise. highlightColor /* Functions */ // Calls mp.game.gxt.reset on the internal GXT entries. Should be used if you're going to stop using a timer bar completely. resetGxt()  
    TextTimerBar
    This is the timer bar with a title and a text.
    /* Constructor */ new TextTimerBar(title, text); /* Properties */ // Inherited from TimerBarBase title titleColor highlightColor // Label (right text) of the timer bar. Accepts and returns a string. text // Color of the timer bar's label. Accepts HUD color IDs or RGBA array, returns RGBA array. textColor // Color of the timer bar's label and title, accepts HUD color IDs or RGBA array. No return value since it's just a setter. color /* Functions */ // Inherited from TimerBarBase resetGxt()  
    PlayerTimerBar
    This is the timer bar with a title and a text, except the title is styled to be like GTA Online's player name display.
    /* Constructor */ new PlayerTimerBar(title, text); /* Properties */ // Inherited from TimerBarBase title titleColor highlightColor // Inherited from TextTimerBar text textColor color /* Functions */ // Inherited from TimerBarBase resetGxt()  
    BarTimerBar
    This is the timer bar with a title and a progress bar.
    /* Constructor */ new BarTimerBar(title, progress); /* Properties */ // Inherited from TimerBarBase title titleColor highlightColor // Progress of the timer bar. Accepts and returns a number between 0.0 and 1.0. progress // Background color of the progress bar. Accepts HUD color IDs or RGBA array, returns RGBA array. backgroundColor // Foreground color of the progress bar. Accepts HUD color IDs or RGBA array, returns RGBA array. foregroundColor /* Functions */ // Inherited from TimerBarBase resetGxt()  
    CheckpointTimerBar
    This is the timer bar with a title and a bunch of circles.
    /* Constructor */ new CheckpointTimerBar(title, numCheckpoints); /* Static properties */ CheckpointTimerBar.state = { inProgress: 0, completed: 1, failed: 2 }; /* Properties */ // Inherited from TimerBarBase title titleColor highlightColor // The amount of checkpoints of the timer bar. Read only, returns a number. numCheckpoints // Color of the checkpoints with the state "completed". Accepts HUD color IDs or RGBA array, returns RGBA array. color // Color of the checkpoints with the state "inProgress". Accepts HUD color IDs or RGBA array, returns RGBA array. inProgressColor // Color of the checkpoints with the state "failed". Accepts HUD color IDs or RGBA array, returns RGBA array. failedColor /* Functions */ // Inherited from TimerBarBase resetGxt() // Sets a specified checkpoint's state, checkpoint indices start from 0 and go up to numCheckpoints - 1. Refer to static properties section for newState values. setCheckpointState(index, newState); // Sets all checkpoints state of the timer bar. Refer to static properties section for newState values. setAllCheckpointsState(newState); Check the wiki for HUD colors: https://wiki.rage.mp/index.php?title=Fonts_and_Colors#HUD_Colors
     
    Example
    Creating the timerbars in the screenshot:
    const timerBarPool = require("timerbars"); const TextTimerBar = require("timerbars/classes/TextTimerBar"); const PlayerTimerBar = require("timerbars/classes/PlayerTimerBar"); const BarTimerBar = require("timerbars/classes/BarTimerBar"); const CheckpointTimerBar = require("timerbars/classes/CheckpointTimerBar"); // Set up text bars const mapTimeBar = new TextTimerBar("MAP TIME", "00:08"); mapTimeBar.textColor = [224, 50, 50, 255]; // or 6 (HUD_COLOUR_RED) mapTimeBar.highlightColor = 8; // HUD_COLOUR_REDDARK const ksBar = new TextTimerBar("KILLSTREAK", "5"); // Set up progress bar const progressBar = new BarTimerBar("CAPTURING", 0.33); // Set up checkpoint bar const checkpointBar = new CheckpointTimerBar("BASES", 5); checkpointBar.color = 18; // HUD_COLOUR_GREEN, or [114, 204, 114, 255] for (let i = 0; i < 3; i++) { checkpointBar.setCheckpointState(i, CheckpointTimerBar.state.completed); } // Set up player bars const playerBars = [ new PlayerTimerBar("3rd: PlayerName3", "9 kills"), new PlayerTimerBar("2nd: PlayerName2", "12 kills"), new PlayerTimerBar("1st: AimbotNub", "30 kills") ]; playerBars.forEach((bar, index) => { bar.color = 107 + index; }); // Bars won't be drawn until they are in the timerBarPool, so press F6 to add them mp.keys.bind(0x75 /* F6 */, false, () => { timerBarPool.add(mapTimeBar, ksBar, progressBar, checkpointBar, ...playerBars); }); // ...and press F7 to clear the timerBarPool (or remove them individually with the timerBarPool.remove function) mp.keys.bind(0x76 /* F7 */, false, () => { timerBarPool.clear(); }); // Pressing F8 toggles a loading prompt, which makes the timerbars go up a bit mp.keys.bind(0x77 /* F8 */, false, () => { mp.game.gxt.set("TB_TEST_LOADING", "Preparing next map..."); if (!mp.game.invoke("0xD422FCC5F239A915") /* BUSYSPINNER_IS_ON */) { mp.game.ui.setLoadingPromptTextEntry("TB_TEST_LOADING"); mp.game.ui.showLoadingPrompt(1); } else { mp.game.invoke("0x10D373323E5B9C0D" /* BUSYSPINNER_OFF */); } }); Source code is available on GitHub in case you don't want to download: https://github.com/root-cause/ragemp-timerbars

    359 downloads

       (4 reviews)

    3 comments

    Updated

  8. Custom Sound CEF

    Simple CEF to play custom mp3's in the background. The CEF autodestroys after the sound has finished to not use our beloved PC resources.
     
    Copy client_packages and packages content in their respective directory, then import them.
    You can put your mp3's inside client_packages/Sound/sounds/ and trigger them with their filename. Only mp3 is supported right now, although ogg works as well, it's easily exchangeable and/or extensible to allow for both.
    As of right now, you can play a sound with the "/playsound NAME" command. You can use this as you want, this is only a barebones example to show how it works.
    I have not experimented when it comes to max sound length / filesize. I'd like to know though

    760 downloads

       (1 review)

    3 comments

    Submitted

  9. UI | Only HTML / CSS Design

    This is a UI for food, drink, money... its only a design. maked with html and css,
    you must script it on your server.
     
    If your Server has more than 100 registered players, than you must make a link with my rage.mp profile on your website.

    1716 downloads

       (0 reviews)

    2 comments

    Updated

  10. Login Window | Design

    Login Window Design 

    629 downloads

       (1 review)

    2 comments

    Updated

  11. Native Menu

    Here is an open-source native menu implementation for Rage-MP. (the documentation is not ready)
    https://github.com/BlueDadjun/Native-Menu-RageMP

    744 downloads

       (2 reviews)

    2 comments

    Updated

  12. [PHP][Discord] Show Player Count directly in Discord

    In this file I will get you started on how you can use Discord to show your current player count.
     
    First step is to create an application at:
    https://discord.com/developers/applications

    Once created click Bot on the left hand side.
    Click "Add Bot" and then "Yes, do it!"
    Change your Icon to something more pretty
    Click "COPY" underneath "Click to reveal token"
    Open the file in the ZIP.
    Install PHP composer if not already installed.
    Run composer require team-reflex/discord-php
    Edit the example_rage.php file and change the "Discord Token here" to the token you copied earlier
    Change line 17 IP:PORT to your Server IP and Port
    When ready run the file with php -q example_rage.php
    This script must always be running for it to appear on the Discord member section. Therefore I would recommend running Linux Screen and running the php -q command then detaching the screen to run it in the background.
    The script uses the Discord Heartbeat to keep it active within the list. It will also only poll the server after running the heartbeat 5 times which is every 42 seconds.
     
    To set it up with your Discord server you must do the following:
    Take the link you were at to setup your bot - it should look like: https://discord.com/developers/applications/IDHERE/bot
    Where it says IDHERE - take it and insert it here: https://discord.com/api/oauth2/authorize?client_id=IDHERE&scope=bot&permissions=1
    Once this page loads - select your discord server that you are an admin of. 
    This will authorize your bot to submit to your server.
     
    To make your bot appear at the top of the list, simply create a new permission role called Server
    Give it permission to send messages
    Set it a nice colour
    Drag it to the top of your list
    Go to the User that is now in your Member list showing player details and give the role of the server you just created
     
    Have fun!
     

    522 downloads

       (3 reviews)

    2 comments

    Updated

  13. [DISCONTINUED] Ajcom

    This library is discontinued and lacks some features. I'm working on a new remote call library which is faster and more secure
    Asynchronous Javascript Communication is a module to allow easy communication between server, client and CEF/browser. This module lets you call server handlers from clients (and vice versa) without dealing with adding and managing custom event handlers.
    You can easily call a handler and get your callback called as soon as everything is returned from the handler in a promise like way! Let's see how it works in action:
    // server side const ajcom = require("./ajcom") ajcom.register("getServerName", hCtx => { return mp.config.name }) // client side const ajcom = require("./[package name]/ajcom.js") mp.events.add("guiReady", () => { ajcom.callServer("getServerName").then((ctx, serverName) => { mp.gui.chat.push(`Welcome to ${serverName} ragemp server!`) }) }) That's all! Not convinced yet? See how the above code is done without ajcom:
    // server side mp.events.add("getServerName", (player) => { player.call("gotServerName", [mp.config.name]) }) // client side mp.events.add("gotServerName", (serverName) => { mp.gui.chat.push(`Welcome to ${serverName} ragemp server!`) }) mp.events.add("guiReady", () => { mp.events.callRemote("getServerName") }) See? It eases the event handling mess. But there's a lot more to ajcom. You can easily handle errors happening on handler's side or any of the callbacks, set delays and other stuff. The full documentation is available here
    Please post your questions and issues to the forum post
    Github repo

    84 downloads

       (2 reviews)

    1 comment

    Updated

  14. Attachment Sync (C#)

    Source code : https://github.com/J4YT/RAGE-Multiplayer-Attachment-Sync

    C# Attachment sync for RAGE Multiplayer Server and Client. 
    Equivalent for the Efficient Attachment System made by ragempdev and rootcause
    https://rage.mp/files/file/144-efficient-attachment-sync
    Credits to DasNiels for the server-side Efficient Attachment Sync C#
    https://github.com/DasNiels/EfficientAttachmentSyncCSharp
    It has only been tested on RAGE Multiplayer 1.1
     

    475 downloads

       (3 reviews)

    1 comment

    Updated

  15. [C#]RAGE:MP Discord Integration

    RAGEMP-DiscordIntegration
    This wrapper allows you easily create an instance of a discord bot within your RAGE:MP server.
    Features:
    1. Send messages to discord from your RAGE:MP Server.
    2. Send messages to your RAGE:MP Server from your Discord server.
    3. Register specific channel for the bot to listen. (Can be changed during runtime).
    3. Remove specific channel for the bot to STOP listening. (Can be changed during runtime).
    4. Update bot status on setup and/or during runtime
     
    How to use the wrapper
    1. Add the RAGEMP-DiscordIntegration.dll as a reference to your project in visual studio.
    2. Make sure to place the three provided Discord.Net.xx.dll into your server/runtime folder.
    3. Enjoy))))
    How to set up
    1. Create a new application on Discord Developers
    2. Create a bot.
    3. Invite bot to discord server.
    4. Use the token from your bot to initialize the bot as shown in the example below.
    5. Register/Remove channels from where your bot sends to all players.
    Example script.
    using GTANetworkAPI; using System; using System.Collections.Generic; using System.Text; public class Yes : Script { public Yes() { NAPI.Util.ConsoleOutput("Loaded: yes"); } [ServerEvent(Event.ResourceStart)] public void OnResourceStart() { Integration.DiscordIntegration.SetUpBotInstance("TOKEN_HERE", "RAGE:MP", Discord.ActivityType.Playing, Discord.UserStatus.DoNotDisturb); } [ServerEvent(Event.ChatMessage)] public async void OnChatMessage(Player player, string strMessage) { string strFormatted = $"[RAGE:MP] {player.Name}: {strMessage}"; await Integration.DiscordIntegration.SendMessage(3897429387492374, strFormatted, true).ConfigureAwait(true); } [Command("registerchannel")] public void RegisterDiscord(Player player, ulong discordChannelID) { bool bSuccess = Integration.DiscordIntegration.RegisterChannelForListenting(discordChannelID); player.SendChatMessage(bSuccess ? "Success" : "No Success"); } [Command("removechannel")] public void RemoveDiscordChannel(Player player, ulong discordChannelID) { bool bSuccess = Integration.DiscordIntegration.RemoveChannelFromListening(discordChannelID); player.SendChatMessage(bSuccess ? "Success" : "No Success"); } [Command("botstatus")] public async void UpdateBotStatusCommand(Player player, string gameName, Discord.ActivityType eActivityType, Discord.UserStatus eUserStatus) { await Integration.DiscordIntegration.UpdateBotStatus(gameName, eActivityType, eUserStatus).ConfigureAwait(true); } } Source code can be found on my github: https://github.com/JeremyEspresso/RAGEMP-DiscordIntegration

    Bugs or feature requests and what not. Just open an issue on the github and I will take a look soon™️.

    613 downloads

       (11 reviews)

    1 comment

    Updated

  16. Blood VFX

    Requires RAGE Multiplayer 1.1.0 and above.
    If you ever played the missions "Grass Roots - Michael" and "Grass Roots - Trevor", you'll remember these missions had special particle effects. This resource allows you to use those particle effects on your server.
     
    Installing
    Put BloodVfx.js into your server's client_packages directory, then add require('BloodVfx'); to client_packages/index.js.
     
    API (Clientside)
    /* This resource adds "bloodVfxMode" property to the mp.game.graphics object. Blood VFX modes: - VFX_MODE_DEFAULT = 0 - VFX_MODE_ALIEN = 1 - VFX_MODE_CLOWN = 2 - Invalid modes will be treated as VFX_MODE_DEFAULT. */ mp.game.graphics.bloodVfxMode  
    Example
    const KEY_F2 = 0x71; const KEY_F3 = 0x72; const KEY_F4 = 0x73; const VFX_MODE_DEFAULT = 0; const VFX_MODE_ALIEN = 1; const VFX_MODE_CLOWN = 2; // Pressing F2 will enable alien blood VFX. mp.keys.bind(KEY_F2, false, () => { mp.game.graphics.bloodVfxMode = VFX_MODE_ALIEN; }); // Pressing F3 will enable clown blood VFX. mp.keys.bind(KEY_F3, false, () => { mp.game.graphics.bloodVfxMode = VFX_MODE_CLOWN; }); // Pressing F4 will disable active blood VFX. mp.keys.bind(KEY_F4, false, () => { mp.game.graphics.bloodVfxMode = VFX_MODE_DEFAULT; });  
    Notes
    RAGEMP does not disable alien/clown blood VFX between sessions. (might change in the future) Meaning if you're playing on serverA that has clown blood VFX enabled and connect to serverB using the F1 menu, you'll still have clown blood VFX.  
    Source code is available on GitHub Gist in case you don't want to download: https://gist.github.com/root-cause/49e7b1601d531bb4c8ba18489ff6731c

    119 downloads

       (2 reviews)

    1 comment

    Updated

  17. Synced Time Progression

    I posted this in the forum, but it is probably better suited here.
     
    This is a very simple script that gives the same time progression experience as single player mode. The source for the time is current GMT time and the calculation rolls this time into an in-game day 24 hour period that lasts 48 minutes (IRL time). Note that as the calculations are based off GMT (and not local time) all clients using this will have the same in game time (dependent on whether their computer's time and timezone is set up correctly).
     
    To use it, simply copy the file somewhere and "require" it in your client_resources script.
     
    There's nothing to configure.
     
    Known Bugs:
    Because the date is not recalculated, it continues to reflect the current real world date regardless of how many in game 24 hour periods there are within the game.

    576 downloads

       (1 review)

    1 comment

    Updated

  18. Improved Commands

    This resource adds a very flexible command handler for serverside JavaScript.
     
    Installing
    Drag and drop the improved-commands folder to your server-files/packages/ folder.
    NOTE: The archive also contains a folder named improved-commands-example, it's an example resource so don't install it along with the library.
     
    Features
    Command aliases Capture command requests (and cancel them if you want to) Somewhat customizable command not found message (like serverside C#) beforeRun property that lets you do final checks before a command actually runs (see example)  
    API
    Instead of extending the global mp object, I've decided to export CommandEvents and CommandRegistry objects. You can access to the library by doing:
    const { CommandEvents, CommandRegistry } = require("../improved-commands");  
    API Properties
    /** * This property is used to toggle the "command not found" message feature. * Default value: false */ CommandRegistry.notFoundMessageEnabled; // get CommandRegistry.notFoundMessageEnabled = bool; // set /** * This property is used to set the "command not found" message. * Default value: "SERVER: Command not found." */ CommandRegistry.notFoundMessage; // get CommandRegistry.notFoundMessage = string; // set  
    API Functions
    /** * Adds a command to the registry. * The command object must contain "name" (string) and "run" (function) properties at the very least. * Optionally, the command object can have "aliases" (array of strings) and "beforeRun" (function, needs to return true for further execution) properties. * Other properties will be collected into an "extra" (object) property, which is useful for storing data on commands. */ CommandRegistry.add(command); /** * Returns all command names, aliases not included. * @return {string[]} */ CommandRegistry.getNames(); /** * Returns all command names with aliases. * @return {string[]} */ CommandRegistry.getNamesWithAliases(); /** * Returns the command object for the specified command name/alias. * @param {string} commandName * @return {Object|undefined} Will be undefined if there is no command with the given name/alias. */ CommandRegistry.find(commandName);  
    Events
    /** * receive * This event is emitted when a player tries to run a command. * @param {mp.Player} player The player who is trying to use the command. * @param {Object} command The command object. * @param {string} fullText All arguments that will be passed to the command, as one string. * @param {string[]} commandArgs All arguments that will be passed to the command. * @param {Object} cancel Whether the execution should be cancelled. Set this object's cancel property to true to stop further processing of the command. */ CommandEvents.on("receive", function (player, command, fullText, commandArgs, cancel) { // your code }); /** * fail * This event is emitted when an error is thrown during command execution. * @param {mp.Player} player The player whose command execution failed. * @param {Object} command The command object. * @param {string} fullText All arguments that were be passed to the command, as one string. * @param {string[]} commandArgs All arguments that were be passed to the command. * @param {Error} error The error that was thrown during command execution. */ CommandEvents.on("fail", function (player, command, fullText, commandArgs, error) { // your code });  
    Example
    const { CommandEvents, CommandRegistry } = require("../improved-commands"); // Should we inform the player when they enter an invalid command? Probably... // Note that commands added with mp.events.addCommand aren't known by this resource so they'll trigger the not found message // This is disabled by default CommandRegistry.notFoundMessageEnabled = true; // Events // Example: Players can't use commands in a vehicle CommandEvents.on("receive", function (player, command, fullText, commandArgs, cancel) { if (player.vehicle) { player.outputChatBox("You cannot use commands in a vehicle."); cancel.cancel = true; } }); // Example: Send a message to the player and print the error to the console on execution failure CommandEvents.on("fail", function (player, command, fullText, commandArgs, error) { player.outputChatBox(`Failed to run command "${command.name}".`); console.error(error.stack || error); }); // Commands // Example: /argtest lorem ipsum dolor sit amet -> results in "You wrote: lorem ipsum dolor sit amet" CommandRegistry.add({ name: "argtest", aliases: ["echo", "combineargs"], beforeRun: function (player, fullText) { if (fullText.length === 0) { player.outputChatBox("No arguments provided."); return false; } return true; }, run: function (player, fullText) { player.outputChatBox(`You wrote: ${fullText}`); } }); // Example: /freemode_male_only -> will only work when player's model is mp_m_freemode_01 CommandRegistry.add({ name: "freemode_male_only", beforeRun: function (player) { return player.model === mp.joaat("mp_m_freemode_01"); }, run: function (player) { player.outputChatBox("Yes, only freemode male can run this command."); } }); // Example: /boom -> will emit "fail" event CommandRegistry.add({ name: "boom", run: function (player) { throw new Error("error thrown"); } }); // Properties that aren't named "name", "aliases", "beforeRun" or "run" will be collected into the "extra" property // Example: /getweapon weapon_carbinerifle 500 -> will only work when player's adminLevel property value is equal to or higher than cmdAdminLevel extra property CommandRegistry.add({ name: "getweapon", aliases: ["giveweapon"], // You can access this property in handlers by using "this.extra.cmdAdminLevel" if the handlers are regular functions (meaning it doesn't work with arrow functions!) cmdAdminLevel: 5, beforeRun: function (player) { return player.adminLevel >= this.extra.cmdAdminLevel; }, run: function (player, fullText, weaponName, ammo = 9999) { // You can do this in beforeRun as well (see argtest example) if (!weaponName || weaponName.length === 0) { player.outputChatBox("Syntax: /getweapon [name]"); return; } player.giveWeapon(mp.joaat(weaponName), Number(ammo)); player.outputChatBox(`Gave yourself ${weaponName} with ${ammo} ammo.`); } }); // Example: Extra property #2 CommandRegistry.add({ name: "count_runs", // You can access this property in handlers by using "this.extra.timesRan" if the handlers are regular functions (meaning it doesn't work with arrow functions!) timesRan: 0, beforeRun: function (player) { player.outputChatBox(`This command was used ${this.extra.timesRan} time(s).`); return true; }, run: function (player) { this.extra.timesRan++; player.outputChatBox(`Now it's used ${this.extra.timesRan} time(s).`); } }); // Example: List all commands CommandRegistry.add({ name: "commands", aliases: ["cmds"], run: function (player) { const commands = CommandRegistry.getNamesWithAliases(); commands.sort(); player.outputChatBox(`Commands: ${commands.join(", ")}`); } }); // Example: Async beforeRun (v1.1 and above) // Important: You should check if player object is still valid by mp.players.exists(player) after awaiting // sleep function can be found here: https://stackoverflow.com/a/39914235 CommandRegistry.add({ name: "async", beforeRun: async function (player) { // Getting data from slow API await sleep(5000); const result = Math.random() < 0.5; if (result) { player.outputChatBox("You're allowed..."); } else { player.outputChatBox("You're not allowed..."); } return result; }, run: async function (player) { // Getting data from slow API again await sleep(2000); if (Math.random() < 0.5) { player.outputChatBox("You waited for nothing!"); } else { throw new Error("Failed so bad it caused an error"); // should emit fail } } });  
    Notes
    This resource does not know about commands added with mp.events.addCommand or C# commands. Meaning if you're using the command not found message feature, addCommand and C# commands will also result in command not found message. Commands are case insensitive. Also on GitHub: https://github.com/root-cause/ragemp-improved-commands

    294 downloads

       (5 reviews)

    1 comment

    Updated

  19. Weapon Component Sync

    This resource provides serverside weapon component API for developers and syncs applied weapon components.
     
    Installing
    Put the files you downloaded in their respective places Add require('weaponcomponents') to client_packages/index.js All done  
    Serverside API
    PRO TIP: Check RAGEMP Wiki or my weapon data resource for component names/hashes.
    /** * Adds the specified component to the player's specified weapon. * @param {Number} weaponHash The weapon's hash. * @param {Number} componentHash The component's hash. * @throws {TypeError} If any of the arguments is not a number. */ player.giveWeaponComponent(weaponHash, componentHash); /** * Returns whether the player's specified weapon has the specified component or not. * @param {Number} weaponHash The weapon's hash. * @param {Number} componentHash The component's hash. * @returns {Boolean} * @throws {TypeError} If any of the arguments is not a number. */ player.hasWeaponComponent(weaponHash, componentHash); /** * Returns the components of the player's specified weapon. * @param {Number} weaponHash The weapon's hash. * @returns {Number[]} An array of component hashes. * @throws {TypeError} If weaponHash argument is not a number. */ player.getWeaponComponents(weaponHash); /** * Removes the specified component from the player's specified weapon. * @param {Number} weaponHash The weapon's hash. * @param {Number} componentHash The component's hash. * @throws {TypeError} If any of the arguments is not a number. */ player.removeWeaponComponent(weaponHash, componentHash); /** * Removes all components of the player's specified weapon. * @param {Number} weaponHash The weapon's hash. * @throws {TypeError} If weaponHash argument is not a number. */ player.removeAllWeaponComponents(weaponHash); /** * Resets all components of the player's all weapons. */ player.resetAllWeaponComponents();  
    Example Commands
    1) /prosniper and /loudsniper
    Use /prosniper to get a sniper rifle with components and use /loudsniper to remove the suppressor.
    const sniperHash = mp.joaat("weapon_sniperrifle"); // Will give the player a sniper rifle and components (suppressor, advanced scope and luxury finish) mp.events.addCommand("prosniper", (player) => { player.giveWeapon(sniperHash, 9999); player.giveWeaponComponent(sniperHash, mp.joaat("COMPONENT_AT_AR_SUPP_02")); player.giveWeaponComponent(sniperHash, mp.joaat("COMPONENT_AT_SCOPE_MAX")); player.giveWeaponComponent(sniperHash, mp.joaat("COMPONENT_SNIPERRIFLE_VARMOD_LUXE")); }); // Will remove the suppressor from the player's sniper rifle mp.events.addCommand("loudsniper", (player) => { player.removeWeaponComponent(sniperHash, mp.joaat("COMPONENT_AT_AR_SUPP_02")); });  
    2) Test commands
    These are the commands I used while testing this script. 
    // /weapon is taken from freeroam gamemode mp.events.addCommand('weapon', (player, _, weaponName) => { if (weaponName.trim().length > 0) player.giveWeapon(mp.joaat(`weapon_${weaponName}`), 9999); else player.outputChatBox(`<b>Command syntax:</b> /weapon [weapon_name]`); }); // Example: /addcomp carbinerifle COMPONENT_CARBINERIFLE_CLIP_03 mp.events.addCommand("addcomp", (player, _, weapon, compName) => { player.giveWeaponComponent(mp.joaat("weapon_" + weapon), mp.joaat(compName)); }); // Example: /remcomp carbinerifle COMPONENT_CARBINERIFLE_CLIP_03 mp.events.addCommand("remcomp", (player, _, weapon, compName) => { player.removeWeaponComponent(mp.joaat("weapon_" + weapon), mp.joaat(compName)); }); // Example: /remallcomps carbinerifle mp.events.addCommand("remallcomps", (player, _, weapon) => { player.removeAllWeaponComponents(mp.joaat("weapon_" + weapon)); }); // Example: /resetcomps mp.events.addCommand("resetcomps", (player) => { player.resetAllWeaponComponents(); });  
    Notes
    Thanks to @ragempdev and @Jaimuzu for their contributions and help during the tests. If there are any reproducible bugs, feel free to report them. This resource will be obsolete after 0.4's weapon attachment/customization API arrives. JS was a mistake.

    1820 downloads

       (6 reviews)

    1 comment

    Updated

  20. Weapon Tint Sync

    This resource provides serverside weapon tint API for developers and syncs applied weapon tints.
     
    Installing
    Put the files you downloaded in their respective places Add require('weapontints') to client_packages/index.js All done  
    Serverside API
    PRO TIP: Check RAGEMP Wiki for tints.
    /** * Sets the tint of the player's specified weapon. * @param {Number} weaponHash The weapon hash. * @param {Number} tintIndex The tint index. * @throws {TypeError} If any of the arguments is not a number. */ player.setWeaponTint(weaponHash, tintIndex); /** * Gets the tint of the player's specified weapon. * @param {Number} weaponHash The weapon hash. * @returns {Number} Tint of the specified weapon. * @throws {TypeError} If weaponHash argument is not a number. */ player.getWeaponTint(weaponHash); /** * Returns an object that contains all weapon tints of the player. Key: weapon hash | Value: tint index * @returns {Object} */ player.getAllWeaponTints(); /** * Resets tints of the player's all weapons. */ player.resetAllWeaponTints();  
    Example Commands
    These are the commands I used while testing this script.
    // Example: /settint carbinerifle 3 mp.events.addCommand("settint", (player, _, weapon, tint) => { weapon = mp.joaat(`weapon_${weapon}`); tint = Number(tint); player.setWeaponTint(weapon, tint); }); // Example: /gettint carbinerifle mp.events.addCommand("gettint", (player, _, weapon) => { const weaponHash = mp.joaat(`weapon_${weapon}`); player.outputChatBox(`Tint of ${weapon}: ${player.getWeaponTint(weaponHash)}`); }); mp.events.addCommand("resettints", (player) => { player.resetAllWeaponTints(); });  
    Notes
    If there are any reproducible bugs, feel free to report them. This resource will be obsolete after 0.4's weapon attachment/customization API arrives.

    1241 downloads

       (3 reviews)

    1 comment

    Submitted

  21. Zone API

    This resource adds 3 functions to the serverside mp.world object that provides zone name and type information.
     
    Serverside API
    /** * Returns the name of the area/zone at specified coords, ignores heights. * @param {object} coords An object with "x" and "y" properties. * @return {string} Zone name. */ mp.world.getNameOfZone2D(coords); /** * Returns the name of the area/zone at specified coords. * @param {object} coords An object with "x", "y" and "z" properties, such as mp.Vector3. * @return {string} Zone name. */ mp.world.getNameOfZone3D(coords); /** * Returns the type of the area/zone at specified coords. * @param {object} coords An object with "x" and "y" properties. * @return {string} Zone type, either "city" or "countryside". */ mp.world.getTypeOfZone(coords);  
    Example
    const coords = new mp.Vector3(1823.961, 4708.14, 42.4991); // Grapeseed Bunker console.log(`Name 2D: ${mp.world.getNameOfZone2D(coords)}`); // Expected output: Grapeseed console.log(`Name 3D: ${mp.world.getNameOfZone3D(coords)}`); // Expected output: Grapeseed console.log(`Zone Type: ${mp.world.getTypeOfZone(coords)}`); // Expected output: countryside  
    Notes
    Available on GitHub: https://github.com/root-cause/ragemp-zone-api N.O.O.S.E area returns Tataviam Mountains instead. There might be other areas with inaccuracies, feel free to share a fix in comments/send a pull request.

    94 downloads

       (3 reviews)

    0 comments

    Updated

  22. Login Window | Only HTML / CSS Design

    This is a Login window, its only a design. maked with html and css,
    you must script it on your server.
     
    If your Server has more than 100 registered players, than you must make a link with my rage.mp profile on your website.

    598 downloads

       (3 reviews)

    0 comments

    Updated

  23. camerasManager

    This is a tool for using cameras.
    ONLY CLIENTSIDE;
    Using: 
    const camerasManager = require('./camerasManager.js'); //creating camera /** @param {String} - camera name @param {String} - type camera @param {Vector3} - position @param {Vector3} - rotation @param {Number} - fov */ const kemperrr_camera = camerasManager.createCamera('kemperrr_the_best?', 'default', new mp.Vector3(0, 0, 100), new mp.Vector3(), 50); //destroy camera /** @param {Camera} - destroyed camera */ camerasManager.destroyCamera(kemperrr_camera); //get camera by name /** @param {String} camera name */ const kemperrr_camera = camerasManager.getCamera('kemperrr_the_best?'); //activate camera /** @param {Camera} - camera to activate @param {Boolean} - toggle */ camerasManager.setActiveCamera(kemperrr_camera, true); //deactivate camera /** @param {Camera} - camera to activate @param {Boolean} - toggle */ camerasManager.setActiveCamera(kemperrr_camera, false); //activate with interpolation /** @param {Camera} - camera to activate @param {Vector3} - where the camera will fly @param {Vector3} - New camera rotation @param {Number} - The time for which the camera will fly by @param {Number} - hz @param {Number} - hz */ camerasManager.setActiveCameraWithInterp(kemperrr_camera, new mp.Vector3(100, 200, 100), new mp.Vector3(0, 0, 90), 5000, 0, 0); //get gameplay camera const gameplayCamera = camerasManager.gameplayCam; mp.game.notify(JSON.stringify(gameplayCamera.getDirection())); //get current active camera const activeCamera = camerasManager.activeCamera; mp.game.notify(JSON.stringify(activeCamera.getCoord())); //events //an event is triggered when any camera starts interpolating camerasManager.on('startInterp', (camera) => { mp.game.notify(JSON.stringify(camera.getCoord())); }); //the event is triggered when any camera has completed interpolation camerasManager.on('stopInterp', (camera) => { mp.game.notify(JSON.stringify(camera.getCoord())); });

    680 downloads

       (1 review)

    0 comments

    Updated

  24. mp.game.data

    This resource adds wrappers for these natives:
    GET_TATTOO_SHOP_DLC_ITEM_DATA GET_SHOP_PED_COMPONENT GET_SHOP_PED_PROP GET_DLC_WEAPON_DATA GET_DLC_WEAPON_COMPONENT_DATA GET_PED_HEAD_BLEND_DATA GET_WEAPON_HUD_STATS GET_WEAPON_COMPONENT_HUD_STATS GET_DLC_VEHICLE_DATA GET_SHOP_PED_OUTFIT GET_SHOP_PED_OUTFIT_PROP_VARIANT GET_SHOP_PED_OUTFIT_COMPONENT_VARIANT Before 1.1.0, you couldn't use these natives because they needed pointers to their respective structures but since 1.1 allows developers to use ArrayBuffers, that is no longer a problem. Thing is, you still need to create a buffer, invoke the native and read the data from your buffer. (too much work)
    This resource is made to prevent that.
     
    Installing
    Put gamedata into your server's client_packages directory, then add require('gamedata'); to client_packages/index.js.
     
    Clientside API
    This resource extends "mp.game" by adding a "data" object that contains multiple functions.
    /* Returns information about a decoration/tattoo. characterType: * 0 = Michael * 1 = Franklin * 2 = Trevor * 3 = MPMale * 4 = MPFemale decorationIndex: * Decoration/tattoo index between 0 and GET_NUM_TATTOO_SHOP_DLC_ITEMS(characterType). Returned object: * { lockHash, id, collection, preset, cost, eFacing, updateGroup, textLabel } This native was researched & documented by TomGrobbe. (https://github.com/TomGrobbe) */ mp.game.data.getTattooShopDlcItemData(characterType, decorationIndex); /* Returns information about a clothing item. componentHash: * Obtained by GET_HASH_NAME_FOR_COMPONENT. Returned object: * { lockHash, uniqueNameHash, locate, drawableIndex, textureIndex, cost, eCompType, eShopEnum, eCharacter, textLabel } */ mp.game.data.getShopPedComponent(componentHash); /* Returns information about a clothing item. (prop) propHash: * Obtained by GET_HASH_NAME_FOR_PROP. Returned object: * { lockHash, uniqueNameHash, locate, propIndex, textureIndex, cost, eAnchorPoint, eShopEnum, eCharacter, textLabel } */ mp.game.data.getShopPedProp(propHash); /* Returns information about a ped's headblend data. entityOrHandle: * Entity (mp.players.local) or handle (mp.players.local.handle) of the ped you want to get headblend data of. Returned object: * { shapeFirstId, shapeSecondId, shapeThirdId, skinFirstId, skinSecondId, skinThirdId, shapeMix, skinMix, thirdMix, isParent } */ mp.game.data.getPedHeadBlendData(entityOrHandle); /* Returns information about a weapon's HUD stats. weaponHash: * Hash of the weapon you want to get HUD stats of. Returned object: * { hudDamage, hudSpeed, hudCapacity, hudAccuracy, hudRange } */ mp.game.data.getWeaponHudStats(weaponHash); /* Returns information about a weapon component's HUD stats. componentHash: * Hash of the weapon component you want to get HUD stats of. Returned object: * { hudDamage, hudSpeed, hudCapacity, hudAccuracy, hudRange } */ mp.game.data.getWeaponComponentHudStats(componentHash); /* Returns information about a DLC weapon. dlcWeaponIndex: * DLC weapon index between 0 - GET_NUM_DLC_WEAPONS(). Returned object: * { lockHash, weaponHash, id, cost, ammoCost, ammoType, defaultClipSize, textLabel, weaponDesc, weaponTT, weaponUppercase } */ mp.game.data.getDlcWeaponData(dlcWeaponIndex); /* Returns information about a DLC weapon's component. dlcWeaponIndex: * DLC weapon index between 0 - GET_NUM_DLC_WEAPONS(). dlcWeaponComponentIndex: * DLC weapon component index between 0 - GET_NUM_DLC_WEAPON_COMPONENTS(dlcWeaponIndex). Returned object: * { attachBone, isDefault, lockHash, componentHash, id, cost, textLabel, componentDesc } */ mp.game.data.getDlcWeaponComponentData(dlcWeaponIndex, dlcWeaponComponentIndex); /* Returns information about a DLC vehicle. dlcVehicleIndex: * DLC vehicle index between 0 - GET_NUM_DLC_VEHICLES(). Returned object: * { lockHash, modelHash, cost } */ mp.game.data.getDlcVehicleData(dlcVehicleIndex); /* Returns information about an outfit. outfitHash: * uniqueNameHash of the outfit. Returned object: * { lockHash, uniqueNameHash, cost, numProps, numComponents, eShopEnum, eCharacter, textLabel } */ mp.game.data.getShopPedOutfit(outfitHash); /* Returns information about an outfit's component. outfitHash: * uniqueNameHash of the outfit. componentIndex: * index of the outfit's component. Returned object: * { uniqueNameHash, enumValue, eCompType } */ mp.game.data.getShopPedOutfitComponentVariant(outfitHash, componentIndex); /* Returns information about an outfit's prop. outfitHash: * uniqueNameHash of the outfit. propIndex: * index of the outfit's prop. Returned object: * { uniqueNameHash, enumValue, eAnchorPoint } */ mp.game.data.getShopPedOutfitPropVariant(outfitHash, propIndex);  
    Example Script
    Writes bunch of information to the console. (which you can access by pressing F11)
    mp.keys.bind(0x75, false, () => { // First freemode male tattoo const tattooData = mp.game.data.getTattooShopDlcItemData(3, 0); if (tattooData) { mp.console.logInfo(`Tattoo data: ${JSON.stringify(tattooData)}`); } // Player's top const component = 11; const componentHash = mp.game.invoke("0x0368B3A838070348", mp.players.local.handle, component, mp.players.local.getDrawableVariation(component), mp.players.local.getTextureVariation(component)); const topData = mp.game.data.getShopPedComponent(componentHash); if (topData) { mp.console.logInfo(`Top data: ${JSON.stringify(topData)}`); } // Player's hat const prop = 0; const propHash = mp.game.invoke("0x5D6160275CAEC8DD", mp.players.local.handle, prop, mp.players.local.getPropIndex(prop), mp.players.local.getPropTextureIndex(prop)); const hatData = mp.game.data.getShopPedProp(propHash); if (hatData) { mp.console.logInfo(`Hat data: ${JSON.stringify(hatData)}`); } // Headblend mp.players.local.setHeadBlendData(21, 2, 0, 21, 2, 0, 0.75, 0.5, 0.0, false); const blendData = mp.game.data.getPedHeadBlendData(mp.players.local.handle); if (blendData) { mp.console.logInfo(`Headblend data: ${JSON.stringify(blendData)}`); } // Current weapon HUD stats const weaponData = mp.game.data.getWeaponHudStats(mp.players.local.weapon); if (weaponData) { mp.console.logInfo(`Current weapon HUD stats: ${JSON.stringify(weaponData)}`); } // COMPONENT_AT_MUZZLE_04 HUD stats const componentData = mp.game.data.getWeaponComponentHudStats(mp.game.joaat("COMPONENT_AT_MUZZLE_04")); if (componentData) { mp.console.logInfo(`Component HUD stats: ${JSON.stringify(componentData)}`); } // DLC weapon data const dlcWeaponIndex = 7; const dlcWeaponData = mp.game.data.getDlcWeaponData(dlcWeaponIndex); if (dlcWeaponData) { mp.console.logInfo(`DLC weapon data: ${JSON.stringify(dlcWeaponData)}`); // First component of weapon const dlcWeaponCompData = mp.game.data.getDlcWeaponComponentData(dlcWeaponIndex, 0); if (dlcWeaponCompData) { mp.console.logInfo(`DLC weapon first component data: ${JSON.stringify(dlcWeaponCompData)}`); } } // DLC vehicle data const dlcVehicleIndex = 21; const dlcVehicleData = mp.game.data.getDlcVehicleData(dlcVehicleIndex); if (dlcVehicleData) { mp.console.logInfo(`DLC vehicle data: ${JSON.stringify(dlcVehicleData)}`); } // Outfit data const outfitHash = mp.game.joaat("DLC_MP_SUM24_M_OUTFIT_0"); // Pizza This... Outfit const outfitData = mp.game.data.getShopPedOutfit(outfitHash); if (outfitData) { mp.console.logInfo(`Outfit data: ${JSON.stringify(outfitData)}`); // First component of outfit if (outfitData.numComponents > 0) { const outfitComponentData = mp.game.data.getShopPedOutfitComponentVariant(outfitHash, 0); if (outfitComponentData) { mp.console.logInfo(`First component of outfit: ${JSON.stringify(outfitComponentData)}`); } } // First prop of outfit if (outfitData.numProps > 0) { const outfitPropData = mp.game.data.getShopPedOutfitPropVariant(outfitHash, 0); if (outfitPropData) { mp.console.logInfo(`First prop of outfit: ${JSON.stringify(outfitPropData)}`); } } } });  
    Notes
    If mp.game.invoke fails (trying to get non-DLC item data/invalid params etc.), return value of the function will be null. Most non-DLC items (core GTAV weapons like Pistol, Assault Rifle etc, initial freemode tattoos, initial freemode clothes) are not supported by the natives. Strings returned by the functions (textLabel, componentDesc etc.) are GXT entries. You're supposed to use them with getLabelText or GXT::get.

    414 downloads

       (2 reviews)

    0 comments

    Updated

  25. Better Clientside Commands

    This resource extends clientside mp.events object to make clientside command handling easier, which means no more splitting strings to use with if/else if or switch/case in playerCommand event
     
    Installing
    Put mp-commands into your server's client_packages directory, then add require('mp-commands'); to client_packages/index.js.
     
    Clientside API
    /** * Adds a clientside command. * @param {string} name Name of the command. * @param {function} handlerFn Function that will run when the command is used. * @throws {TypeError} name argument must be a string. * @throws {TypeError} handlerFn argument must be a function. * @throws {Error} Command with the given name already exists. */ mp.events.addCommand(name, handlerFn); /** * Returns clientside command names. * @return {string[]} */ mp.events.getCommandNames(); /** * Removes a clientside command. * @param {string} name Name of the command to remove. * @return {boolean} */ mp.events.removeCommand(name); /** * Removes all clientside commands. */ mp.events.removeAllCommands(); /** * (v2.0.0) Adds a console command. * @param {string} name Name of the console command. * @param {function} handlerFn Function that will run when the console command is used. * @throws {TypeError} name argument must be a string. * @throws {TypeError} handlerFn argument must be a function. * @throws {Error} Console command with the given name already exists. */ mp.console.addCommand(name, handlerFn); /** * (v2.0.0) Returns console command names. * @return {string[]} */ mp.console.getCommandNames(); /** * (v2.0.0) Removes a console command. * @param {string} name Name of the console command to remove. * @return {boolean} */ mp.console.removeCommand(name); /** * (v2.0.0) Removes all console commands. */ mp.console.removeAllCommands();  
    Example
    /* Looks like it's serverside code but it's not, updates GTA V's cash display. Usage: /updmoney [amount] */ mp.events.addCommand("updmoney", function (amount) { amount = Number(amount); if (!Number.isInteger(amount)) { mp.gui.chat.push("Invalid amount."); return; } mp.game.stats.statSetInt(mp.game.joaat("SP0_TOTAL_CASH"), amount, false); }); mp.events.addCommand("cmds", function () { mp.gui.chat.push(`Commands: ${mp.events.getCommandNames().join(", ")}`); });  
    Example (Console)
    NOTE: Console is a RAGE Multiplayer 1.1 feature, which means code below won't work on stable/prerelease/0.3.7 branch.
    // Write "hat 123 0" to the console and press enter to give yourself a cool helmet. mp.console.addCommand("hat", function (drawable, texture = 0) { drawable = Number(drawable); texture = Number(texture); if (!Number.isInteger(drawable) || !Number.isInteger(texture)) { mp.console.logError("Invalid drawable/texture."); return; } if (drawable < 0) { mp.players.local.clearProp(0); } else { mp.players.local.setPropIndex(0, drawable, texture, true); } }); // Write "cmds" to the console to see available console commands. mp.console.addCommand("cmds", function() { mp.console.logInfo(`Console commands: ${mp.console.getCommandNames().join(", ")}`); });  
    Notes
    I recommend loading mp-commands as the first script in client_packages/index.js so the functions become available in other scripts. Command names are case sensitive.

    1194 downloads

       (4 reviews)

    0 comments

    Updated


×
×
  • Create New...