diff --git a/config/discord.json b/config/discord.json
index 6afb8078..3fe219f5 100644
--- a/config/discord.json
+++ b/config/discord.json
@@ -1,10 +1,13 @@
{
- "sendChat": "true",
- "sendConnectEvents": "true",
- "sendVehicleEvents": "true",
- "sendDeathEvents": "true",
+ "sendChat": false,
+ "sendEvents": false,
+ "sendConnectEvents": false,
+ "sendVehicleEvents": false,
+ "sendDeathEvents": false,
+ "sendAdmin": false,
"webhook": {
- "enabled": "true",
- "webhookBaseURL": "https://example.com/something.php?message={0}&url={1}"
+ "enabled": false,
+ "webhookBaseURL": "http://127.0.0.1:8090/discord.php?message={0}&server={1}&type={2}&pass={3}",
+ "pass": "LWb7T3ZyCam7Nzen"
}
}
\ No newline at end of file
diff --git a/files/images/flags/fi.png b/files/images/flags/fi.png
new file mode 100644
index 00000000..f7eb60dd
Binary files /dev/null and b/files/images/flags/fi.png differ
diff --git a/meta.xml b/meta.xml
index 6faa6d21..55c0ae83 100644
--- a/meta.xml
+++ b/meta.xml
@@ -149,6 +149,7 @@
+
diff --git a/scripts/client/animation.js b/scripts/client/animation.js
index 1afad949..f62db4f7 100644
--- a/scripts/client/animation.js
+++ b/scripts/client/animation.js
@@ -139,7 +139,7 @@ function makePedStopAnimation(pedId) {
/**
* @param {number} animationSlot - The slot index of the animation
- * @return {Array} The animation's data (array)
+ * @return {AnimationData} The animation's data (array)
*/
function getAnimationData(animationSlot, gameId = getGame()) {
return getGameConfig().animations[gameId][animationSlot];
diff --git a/scripts/client/business.js b/scripts/client/business.js
index bbcd3cc8..2c07f0de 100644
--- a/scripts/client/business.js
+++ b/scripts/client/business.js
@@ -27,7 +27,7 @@ class BusinessData {
function receiveBusinessFromServer(businessId, name, entrancePosition, blipModel, pickupModel, hasInterior, hasItems) {
logToConsole(LOG_DEBUG, `[VRR.Business] Received business ${businessId} (${name}) from server`);
- if(getGame() == VRR_GAME_GTA_IV) {
+ if(!areServerElementsSupported()) {
if(getBusinessData(businessId) != false) {
let businessData = getBusinessData(businessId);
businessData.name = name;
diff --git a/scripts/client/event.js b/scripts/client/event.js
index 90875da8..26c75abe 100644
--- a/scripts/client/event.js
+++ b/scripts/client/event.js
@@ -53,19 +53,15 @@ function addAllEventHandlers() {
addEventHandler("OnCameraProcess", onCameraProcess);
addEventHandler("OnMouseWheel", onMouseWheel);
+
+ addEventHandler("OnEntityProcess", onEntityProcess);
}
// ===========================================================================
function onResourceStart(event, resource) {
sendResourceStartedSignalToServer();
- //setUpInitialGame();
//garbageCollectorInterval = setInterval(collectAllGarbage, 1000*60);
-
- resourceStarted = true;
- if(resourceReady == true) {
- initClient();
- }
}
// ===========================================================================
@@ -78,10 +74,6 @@ function onResourceStop(event, resource) {
function onResourceReady(event, resource) {
sendResourceReadySignalToServer();
- resourceReady = true;
- if(resourceStarted == true) {
- initClient();
- }
}
// ===========================================================================
@@ -109,6 +101,7 @@ function onProcess(event, deltaTime) {
processVehicleBurning();
//checkChatBoxAutoHide(); // Will be uncommented on 1.4.0 GTAC update
//processVehicleFires();
+
}
// ===========================================================================
@@ -245,4 +238,16 @@ function onMouseWheel(event, mouseId, deltaCoordinates, flipped) {
processMouseWheelForChatBox(mouseId, deltaCoordinates, flipped);
}
+// ===========================================================================
+
+function onEntityProcess(event, entity) {
+ if(!isSpawned) {
+ return false;
+ }
+
+ //if(entity.isType(ELEMENT_PED) && !entity.isType(ELEMENT_PLAYER)) {
+ // processNPCMovement(entity);
+ //}
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/gui.js b/scripts/client/gui.js
index 8adbbe9a..a621196a 100644
--- a/scripts/client/gui.js
+++ b/scripts/client/gui.js
@@ -66,11 +66,14 @@ function initGUI() {
guiReady = true;
logToConsole(LOG_DEBUG, `[VRR.GUI] All GUI created successfully!`);
- sendNetworkEventToServer("vrr.guiReady", true);
+ loadLocaleConfig();
loadAllLocaleStrings();
+
resetGUIStrings();
resetLocaleChooserOptions();
+
+ sendNetworkEventToServer("vrr.guiReady", true);
};
// ===========================================================================
@@ -160,106 +163,7 @@ function isAnyGUIActive() {
// ===========================================================================
-addNetworkEventHandler("vrr.showCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show character selection window`);
- showCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, skinId);
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.switchCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to update character selection window with new info`);
- switchCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, skinId);
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.showError", function(errorMessage, errorTitle, buttonText) {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show error window`);
- showError(errorMessage, errorTitle, buttonText);
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.showPrompt", function(promptMessage, promptTitle, yesButtonText, noButtonText) {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show prompt window`);
- showYesNoPromptGUI(promptMessage, promptTitle, yesButtonText, noButtonText);
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.showInfo", function(infoMessage, buttonText) {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show info dialog`);
- showInfo(infoMessage, buttonText);
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.loginSuccess", function() {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of successful login from server`);
- loginSuccess();
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.characterSelectSuccess", function() {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of successful character selection from server`);
- characterSelectSuccess();
- setChatWindowEnabled(true);
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.loginFailed", function(remainingAttempts) {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of failed login from server`);
- loginFailed(remainingAttempts);
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.registrationSuccess", function() {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of successful registration from server`);
- registrationSuccess();
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.registrationFailed", function(errorMessage) {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of failed registration from server`);
- registrationFailed(errorMessage);
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.newCharacterFailed", function(errorMessage) {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of failed registration from server`);
- newCharacterFailed(errorMessage);
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.changePassword", function() {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal to change password from server`);
- showChangePasswordGUI();
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.showResetPasswordCodeInput", function() {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal to input reset password code from server`);
- resetPasswordCodeInputGUI();
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.showLocaleChooser", function() {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal to show locale chooser from server`);
- showLocaleChooserGUI();
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.guiColour", function(red1, green1, blue1, red2, green2, blue2, red3, green3, blue3) {
+function setGUIColours(red1, green1, blue1, red2, green2, blue2, red3, green3, blue3) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received new GUI colours from server: ${red1}, ${green1}, ${blue1} / ${red2}, ${green2}, ${blue2} / ${red3}, ${green3}, ${blue3}`);
primaryColour = [red1, green1, blue1];
secondaryColour = [red2, green2, blue2];
@@ -267,15 +171,7 @@ addNetworkEventHandler("vrr.guiColour", function(red1, green1, blue1, red2, gree
focusedColour = [red1+focusedColourOffset, green1+focusedColourOffset, blue1+focusedColourOffset];
initGUI();
-});
-
-// ===========================================================================
-
-addNetworkEventHandler("vrr.guiInit", function() {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Initializing MexUI app`);
- //initGUI();
- sendNetworkEventToServer("vrr.guiReady", true);
-});
+}
// ===========================================================================
diff --git a/scripts/client/gui/changepass.js b/scripts/client/gui/changepass.js
index 2927eea1..39476dfd 100644
--- a/scripts/client/gui/changepass.js
+++ b/scripts/client/gui/changepass.js
@@ -133,16 +133,17 @@ function checkChangePassword() {
// ===========================================================================
-function showChangePasswordGUI() {
+function showChangePasswordGUI(errorMessage) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Showing change password window`);
closeAllWindows();
setChatWindowEnabled(false);
mexui.setInput(true);
passwordChange.window.shown = true;
+ passwordChange.messageLabel = errorMessage;
mexui.focusedControl = passwordChange.passwordInput;
guiSubmitKey = checkChangePassword;
- showLocaleChooserGUI();
+ showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), passwordChange.window.position.y+passwordChange.window.size.y+20));
}
// ===========================================================================
diff --git a/scripts/client/gui/charselect.js b/scripts/client/gui/charselect.js
index d4b8f7ca..434e3a91 100644
--- a/scripts/client/gui/charselect.js
+++ b/scripts/client/gui/charselect.js
@@ -171,7 +171,7 @@ function showCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, ski
guiLeftKey = selectPreviousCharacter;
guiRightKey = selectNextCharacter;
- showLocaleChooserGUI();
+ showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), characterSelect.window.position.y+characterSelect.window.size.y+20));
}
// ===========================================================================
diff --git a/scripts/client/gui/error.js b/scripts/client/gui/error.js
index e9802edf..360afa9e 100644
--- a/scripts/client/gui/error.js
+++ b/scripts/client/gui/error.js
@@ -17,7 +17,7 @@ let errorDialog = {
function initErrorDialogGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating error GUI ...`);
- errorDialog.window = mexui.window(game.width/2-200, game.height/2-70, 500, 140, 'ERROR', {
+ errorDialog.window = mexui.window(getScreenWidth()/2-200, getScreenHeight()/2-70, 400, 140, 'ERROR', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -34,7 +34,7 @@ function initErrorDialogGUI() {
},
});
- errorDialog.messageLabel = errorDialog.window.text(15, 50, 470, 75, 'Error Message', {
+ errorDialog.messageLabel = errorDialog.window.text(15, 50, 370, 20, 'Error Message', {
main: {
textSize: 10.0,
textAlign: 0.5,
@@ -70,7 +70,7 @@ function showErrorGUI(errorMessage, errorTitle, buttonText) {
mexui.setInput(true);
errorDialog.messageLabel.text = errorMessage;
errorDialog.okayButton.text = buttonText;
- errprDialog.window.title = errorTitle;
+ errorDialog.window.title = errorTitle;
errorDialog.window.shown = true;
}
diff --git a/scripts/client/gui/info.js b/scripts/client/gui/info.js
index f2f4582b..c6066df8 100644
--- a/scripts/client/gui/info.js
+++ b/scripts/client/gui/info.js
@@ -17,7 +17,7 @@ let infoDialog = {
function initInfoDialogGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating info dialog GUI ...`);
- infoDialog.window = mexui.window(game.width/2-200, game.height/2-70, 400, 140, 'Information', {
+ infoDialog.window = mexui.window(getScreenWidth()/2-200, getScreenHeight()/2-70, 400, 140, 'Information', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
},
@@ -70,7 +70,7 @@ function closeInfoDialog() {
// ===========================================================================
-function showInfo(infoMessage, infoTitle, buttonText) {
+function showInfoGUI(infoMessage, infoTitle, buttonText) {
closeAllWindows();
logToConsole(LOG_DEBUG, `[VRR.GUI] Showing info dialog window. Info: ${infoTitle} - ${infoMessage}`);
mexui.setInput(true);
diff --git a/scripts/client/gui/localechooser.js b/scripts/client/gui/localechooser.js
index 3552bcdc..e0bdf063 100644
--- a/scripts/client/gui/localechooser.js
+++ b/scripts/client/gui/localechooser.js
@@ -52,8 +52,8 @@ function closeLocaleChooserGUI() {
// ===========================================================================
-function showLocaleChooserGUI(position = toVector2(0, 0)) {
- if(position.x != 0 && position.y != 0) {
+function showLocaleChooserGUI(position = toVector2(0.0, 0.0)) {
+ if(position.x != 0.0 && position.y != 0.0) {
localeChooser.window.position = position;
} else {
localeChooser.window.position = toVector2((getScreenWidth()/2)-(localeChooser.window.size.x/2), getScreenHeight()-100);
diff --git a/scripts/client/gui/login.js b/scripts/client/gui/login.js
index 98994b71..e33ef2c2 100644
--- a/scripts/client/gui/login.js
+++ b/scripts/client/gui/login.js
@@ -43,7 +43,7 @@ let loginHTML =
function initLoginGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating login GUI ...`);
- login.window = mexui.window(game.width/2-150, game.height/2-135, 300, 275, 'LOGIN', {
+ login.window = mexui.window(getScreenWidth()/2-150, getScreenHeight()/2-135, 300, 275, 'LOGIN', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -118,7 +118,7 @@ function initLoginGUI() {
},
}, checkLogin);
- login.forgotPasswordButton = login.window.button(200, 240, 80, 15, 'RESET PASS', {
+ login.forgotPasswordButton = login.window.button(180, 240, 100, 15, 'RESET PASS', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(0, 0, 0, 255),
@@ -131,7 +131,7 @@ function initLoginGUI() {
},
}, switchToPasswordResetGUI);
- login.resetPasswordLabel = login.window.text(125, 240, 60, 15, 'Forgot your password?', {
+ login.resetPasswordLabel = login.window.text(110, 240, 60, 15, 'Forgot your password?', {
main: {
textSize: 8.0,
textAlign: 1.0,
@@ -157,7 +157,7 @@ function showLoginGUI() {
mexui.focusedControl = login.passwordInput;
guiSubmitKey = checkLogin;
- showLocaleChooserGUI();
+ showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), login.window.position.y+login.window.size.y+20));
//showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
}
diff --git a/scripts/client/gui/newchar.js b/scripts/client/gui/newchar.js
index e823e495..5a13504a 100644
--- a/scripts/client/gui/newchar.js
+++ b/scripts/client/gui/newchar.js
@@ -20,7 +20,7 @@ let newCharacter = {
function initNewCharacterGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating new character GUI ...`);
- newCharacter.window = mexui.window(game.width/2-130, game.height/2-115, 300, 230, 'NEW CHARACTER', {
+ newCharacter.window = mexui.window(getScreenWidth()/2-130, getScreenHeight()/2-115, 300, 230, 'NEW CHARACTER', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -158,9 +158,9 @@ function showNewCharacterGUI() {
mexui.setInput(true);
newCharacter.window.shown = true;
mexui.focusedInput = newCharacter.firstNameInput;
- guiSubmitButton = checkNewCharacter;
+ guiSubmitKey = checkNewCharacter;
- showLocaleChooserGUI();
+ showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), newCharacter.window.position.y+newCharacter.window.size.y+20));
}
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/gui/register.js b/scripts/client/gui/register.js
index ffa20936..110e39e4 100644
--- a/scripts/client/gui/register.js
+++ b/scripts/client/gui/register.js
@@ -21,7 +21,7 @@ let register = {
function initRegisterGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating register GUI ...`);
- register.window = mexui.window(game.width/2-150, game.height/2-150, 300, 300, 'Register', {
+ register.window = mexui.window(getScreenWidth()/2-150, getScreenHeight()/2-150, 300, 300, 'Register', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -162,7 +162,7 @@ function showRegistrationGUI() {
mexui.focusedControl = register.passwordInput;
guiSubmitKey = checkRegistration;
- showLocaleChooserGUI();
+ showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), register.window.position.y+register.window.size.y+20));
//showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
}
diff --git a/scripts/client/gui/resetpass.js b/scripts/client/gui/resetpass.js
index 4f74645b..f81eafc4 100644
--- a/scripts/client/gui/resetpass.js
+++ b/scripts/client/gui/resetpass.js
@@ -21,7 +21,7 @@ let passwordReset = {
function initResetPasswordGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating password reset GUI ...`);
- passwordReset.window = mexui.window(game.width/2-150, game.height/2-130, 300, 260, 'RESET PASSWORD', {
+ passwordReset.window = mexui.window(getScreenWidth()/2-150, getScreenHeight()/2-135, 300, 275, 'RESET PASSWORD', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -42,7 +42,7 @@ function initResetPasswordGUI() {
passwordReset.window.titleBarHeight = 0;
passwordReset.window.titleBarShown = false;
- passwordReset.logoImage = passwordReset.window.image(5, 20, 290, 80, mainLogoPath, {
+ passwordReset.logoImage = passwordReset.window.image(100, 20, 100, 100, mainLogoPath, {
focused: {
borderColour: toColour(0, 0, 0, 0),
},
@@ -82,7 +82,7 @@ function initResetPasswordGUI() {
});
passwordReset.emailInput.placeholder = "Email";
- passwordReset.resetPasswordButton = passwordReset.window.button(20, 205, 260, 30, 'RESET PASSWORD', {
+ passwordReset.resetPasswordButton = passwordReset.window.button(180, 240, 100, 15, 'RESET PASSWORD', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
@@ -108,7 +108,7 @@ function initResetPasswordGUI() {
},
}, switchToLoginGUI);
- passwordReset.backToLoginLabel = passwordReset.window.text(125, 240, 60, 15, 'Remember your password?', {
+ passwordReset.backToLoginLabel = passwordReset.window.text(110, 240, 60, 15, 'Remember your password?', {
main: {
textSize: 8.0,
textAlign: 1.0,
@@ -132,9 +132,9 @@ function showResetPasswordGUI() {
mexui.setInput(true);
passwordReset.window.shown = true;
mexui.focusedControl = passwordReset.emailInput;
- guiSubmitButton = checkResetPassword;
+ guiSubmitKey = checkResetPassword;
- showLocaleChooserGUI();
+ showLocaleChooserGUI(new Vec2(getScreenWidth()/2-(localeChooser.window.size.x/2), passwordReset.window.position.y+passwordReset.window.size.y+20));
//showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
}
@@ -157,15 +157,31 @@ function resetPasswordFailed(errorMessage) {
// ===========================================================================
function resetPasswordCodeInputGUI() {
- logToConsole(LOG_DEBUG, `[VRR.GUI] Server reports password reset was successful`);
-
- passwordReset.messageLabel.text = "Check your email for a verification code";
- passwordReset.messageLabel.styles.main.textColour = toColour(180, 32, 32, 255);
- passwordReset.emailInput.text = "";
- passwordReset.emailInput.placeholder = "Verification Code";
-
- guiSubmitButton = checkResetPassword;
+ logToConsole(LOG_DEBUG|LOG_WARN, `[VRR.GUI] Server reports password reset email confirmation was successful. Asking for code ...`);
closeAllWindows();
+
+ passwordReset.messageLabel.text = getLocaleString("GUIResetPasswordCodeInputLabel");
+ //passwordReset.messageLabel.styles.main.textColour = toColour(180, 32, 32, 255);
+ passwordReset.emailInput.text = "";
+ passwordReset.emailInput.placeholder = getLocaleString("GUIResetPasswordCodePlaceholder");
+
+ guiSubmitKey = checkResetPassword;
+ showResetPasswordGUI();
+}
+
+// ===========================================================================
+
+function resetPasswordEmailInputGUI() {
+ logToConsole(LOG_DEBUG|LOG_WARN, `[VRR.GUI] Server reports password reset request was approved. Asking for email ...`);
+ closeAllWindows();
+
+ passwordReset.messageLabel.text = getLocaleString("GUIResetPasswordConfirmEmailLabel");
+ //passwordReset.messageLabel.styles.main.textColour = toColour(180, 32, 32, 255);
+ passwordReset.emailInput.text = "";
+ passwordReset.emailInput.placeholder = getLocaleString("GUIResetPasswordEmailPlaceholder");
+
+ guiSubmitKey = checkResetPassword;
+ showResetPasswordGUI();
}
// ===========================================================================
diff --git a/scripts/client/house.js b/scripts/client/house.js
index ecdc5d9a..0eaa47e9 100644
--- a/scripts/client/house.js
+++ b/scripts/client/house.js
@@ -8,9 +8,10 @@
// ===========================================================================
class HouseData {
- constructor(houseId, entrancePosition, blipModel, pickupModel, hasInterior) {
+ constructor(houseId, description, entrancePosition, blipModel, pickupModel, hasInterior) {
this.index = -1;
this.houseId = houseId;
+ this.description = description;
this.entrancePosition = entrancePosition;
this.blipModel = blipModel;
this.pickupModel = pickupModel;
@@ -21,12 +22,13 @@ class HouseData {
// ===========================================================================
-function receiveHouseFromServer(houseId, entrancePosition, blipModel, pickupModel, hasInterior) {
+function receiveHouseFromServer(houseId, description, entrancePosition, blipModel, pickupModel, hasInterior) {
logToConsole(LOG_DEBUG, `[VRR.House] Received house ${houseId} (${name}) from server`);
- if(getGame() == VRR_GAME_GTA_IV) {
+ if(!areServerElementsSupported()) {
if(getHouseData(houseId) != false) {
let houseData = getHouseData(houseId);
+ houseData.description = description;
houseData.entrancePosition = entrancePosition;
houseData.blipModel = blipModel;
houseData.pickupModel = pickupModel;
@@ -65,7 +67,7 @@ function receiveHouseFromServer(houseId, entrancePosition, blipModel, pickupMode
}
} else {
logToConsole(LOG_DEBUG, `[VRR.House] House ${houseId} doesn't exist. Adding ...`);
- let tempHouseData = new HouseData(houseId, entrancePosition, blipModel, pickupModel, hasInterior);
+ let tempHouseData = new HouseData(houseId, description, entrancePosition, blipModel, pickupModel, hasInterior);
if(blipModel != -1) {
let blipId = createGameBlip(tempHouseData.blipModel, tempHouseData.entrancePosition, "House");
if(blipId != -1) {
diff --git a/scripts/client/nametag.js b/scripts/client/nametag.js
index 174a6331..699b9bc6 100644
--- a/scripts/client/nametag.js
+++ b/scripts/client/nametag.js
@@ -139,7 +139,7 @@ function drawNametag(x, y, health, armour, text, ping, alpha, distance, colour,
// ===========================================================================
-function updateNametags(element) {
+function updateNametag(element) {
if(!areWorldLabelsSupported()) {
return false;
}
@@ -147,10 +147,11 @@ function updateNametags(element) {
if(localPlayer != null) {
let playerPos = localPlayer.position;
let elementPos = element.position;
- let client = getClientFromPlayerElement(element);
elementPos[2] += 0.9;
+ //if(typeof element.getComponentPosition()) {
+
let screenPos = getScreenFromWorldPosition(elementPos);
if (screenPos[2] >= 0.0) {
let health = element.health/100.0;
@@ -178,20 +179,22 @@ function updateNametags(element) {
let paused = false;
let ping = -1;
- if(typeof playerNames[element.name] != "undefined") {
- name = playerNames[element.name];
- }
+ if(element.isType(ELEMENT_PLAYER)) {
+ if(typeof playerNames[element.name] != "undefined") {
+ name = playerNames[element.name];
+ }
- if(typeof playerPaused[element.name] != "undefined") {
- paused = playerPaused[element.name];
- }
+ if(typeof playerPaused[element.name] != "undefined") {
+ paused = playerPaused[element.name];
+ }
- if(typeof playerColours[element.name] != "undefined") {
- colour = playerColours[element.name];
- }
+ if(typeof playerColours[element.name] != "undefined") {
+ colour = playerColours[element.name];
+ }
- if(typeof playerPing[element.name] != "undefined") {
- ping = playerPing[element.name];
+ if(typeof playerPing[element.name] != "undefined") {
+ ping = playerPing[element.name];
+ }
}
drawNametag(screenPos[0], screenPos[1], health, armour, name, ping, 1.0-distance/nametagDistance, distance, colour, paused, element.skin);
@@ -218,9 +221,9 @@ function processNameTagRendering(event) {
// return false;
//}
- getElementsByType(ELEMENT_PLAYER).forEach(function(player) {
- if(player != localPlayer) {
- updateNametags(player);
+ getElementsByType(ELEMENT_PED).forEach(function(ped) {
+ if(ped != localPlayer) {
+ updateNametag(ped);
}
});
}
diff --git a/scripts/client/native/connected.js b/scripts/client/native/connected.js
index 3f03b76b..1cea7b56 100644
--- a/scripts/client/native/connected.js
+++ b/scripts/client/native/connected.js
@@ -155,6 +155,12 @@ function getClosestCivilian(position) {
// ===========================================================================
+function getClosestPlayer(position) {
+ return getElementsByType(ELEMENT_PLAYER).reduce((i, j) => ((i.position.distance(position) <= j.position.distance(position)) ? i : j));
+}
+
+// ===========================================================================
+
function is2dPositionOnScreen(pos2d) {
return pos2d.x >= 0 && pos2d.y >= 0 && pos2d.x <= game.width && pos2d.y <= game.height;
}
@@ -674,4 +680,21 @@ function setPedInvincible(ped, state) {
ped.invincible = state;
}
+// ===========================================================================
+
+function setPedLookAt(ped, position) {
+ if(getGame() == VRR_GAME_GTA_SA) {
+ ped.lookAt(position, 10000);
+ return true;
+ } else {
+ setElementHeading(ped.id, getHeadingFromPosToPos(getElementPosition(ped.id), position));
+ }
+}
+
+// ===========================================================================
+
+function setElementHeading(elementId, heading) {
+ getElementFromId(elementId).heading = heading;
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/npc.js b/scripts/client/npc.js
new file mode 100644
index 00000000..5d823bf6
--- /dev/null
+++ b/scripts/client/npc.js
@@ -0,0 +1,19 @@
+// ===========================================================================
+// Vortrex's Roleplay Resource
+// https://github.com/VortrexFTW/gtac_roleplay
+// ===========================================================================
+// FILE: npc.js
+// DESC: Provides NPC functions and processing
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+function processNPCMovement(npc) {
+ //if(npc.isSyncer == true) {
+ if(getEntityData(npc, "vrr.lookAtClosestPlayer") == true) {
+ let closestPlayer = getClosestPlayer(getElementPosition(npc.id));
+ setPedLookAt(npc, getElementPosition(closestPlayer.id));
+ }
+ //}
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/server.js b/scripts/client/server.js
index fd37932f..844d7fb3 100644
--- a/scripts/client/server.js
+++ b/scripts/client/server.js
@@ -86,6 +86,23 @@ function addAllNetworkHandlers() {
addNetworkEventHandler("vrr.showNewCharacter", showNewCharacterGUI);
addNetworkEventHandler("vrr.showLogin", showLoginGUI);
addNetworkEventHandler("vrr.2fa", showTwoFactorAuthGUI);
+ addNetworkEventHandler("vrr.showResetPasswordCodeInput", resetPasswordCodeInputGUI);
+ addNetworkEventHandler("vrr.showResetPasswordEmailInput", resetPasswordEmailInputGUI);
+ addNetworkEventHandler("vrr.showChangePassword", showChangePasswordGUI);
+ addNetworkEventHandler("vrr.showCharacterSelect", showCharacterSelectGUI);
+ addNetworkEventHandler("vrr.switchCharacterSelect", switchCharacterSelectGUI);
+ addNetworkEventHandler("vrr.showError", showErrorGUI);
+ addNetworkEventHandler("vrr.showInfo", showInfoGUI);
+ addNetworkEventHandler("vrr.showPrompt", showYesNoPromptGUI);
+ addNetworkEventHandler("vrr.loginSuccess", loginSuccess);
+ addNetworkEventHandler("vrr.characterSelectSuccess", characterSelectSuccess);
+ addNetworkEventHandler("vrr.loginFailed", loginFailed);
+ addNetworkEventHandler("vrr.registrationSuccess", registrationSuccess);
+ addNetworkEventHandler("vrr.registrationFailed", registrationFailed);
+ addNetworkEventHandler("vrr.newCharacterFailed", newCharacterFailed);
+ addNetworkEventHandler("vrr.changePassword", showChangePasswordGUI);
+ addNetworkEventHandler("vrr.showLocaleChooser", showLocaleChooserGUI);
+ addNetworkEventHandler("vrr.guiColour", setGUIColours);
// Business
addNetworkEventHandler("vrr.business", receiveBusinessFromServer);
@@ -121,9 +138,9 @@ function addAllNetworkHandlers() {
addNetworkEventHandler("vrr.nametag", updatePlayerNameTag);
addNetworkEventHandler("vrr.nametagDistance", setNameTagDistance);
addNetworkEventHandler("vrr.ping", updatePlayerPing);
- addNetworkEventHandler("vrr.pedAnim", makePedPlayAnimation);
- addNetworkEventHandler("vrr.pedStopAnim", makePedStopAnimation);
- addNetworkEventHandler("vrr.forcePedAnim", forcePedAnimation);
+ addNetworkEventHandler("vrr.anim", makePedPlayAnimation);
+ addNetworkEventHandler("vrr.stopAnim", makePedStopAnimation);
+ addNetworkEventHandler("vrr.forceAnim", forcePedAnimation);
addNetworkEventHandler("vrr.clientInfo", serverRequestedClientInfo);
addNetworkEventHandler("vrr.interiorLights", updateInteriorLightsState);
addNetworkEventHandler("vrr.cutsceneInterior", setCutsceneInterior);
@@ -184,11 +201,23 @@ function set2DRendering(hudState, labelState, smallGameMessageState, scoreboardS
function onServerSpawnedLocalPlayer(state) {
logToConsole(LOG_DEBUG, `[VRR.Main] Setting spawned state to ${state}`);
isSpawned = state;
+ setUpInitialGame();
if(state) {
- setUpInitialGame();
setTimeout(function() {
calledDeathEvent = false;
}, 1000);
+
+ getPeds().filter(ped => !ped.isType(ELEMENT_PLAYER)).forEach(ped => {
+ syncCivilianProperties(ped);
+ });
+
+ getPlayers().forEach(player => {
+ syncPlayerProperties(player);
+ });
+
+ getVehicles().forEach(veh => {
+ syncVehicleProperties(veh);
+ });
}
}
diff --git a/scripts/client/startup.js b/scripts/client/startup.js
index 1b0ce9ee..ce4b5c04 100644
--- a/scripts/client/startup.js
+++ b/scripts/client/startup.js
@@ -25,168 +25,175 @@ function initClientScripts() {
// ===========================================================================
function setUpInitialGame() {
- switch(getGame()) {
- case [VRR_GAME_GTA_III]: {
- game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
- game.setGameStat(STAT_PROGRESSMADE, 9999);
- game.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
- //game.SET_CAR_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
- //game.SET_PED_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
- game.onMission = true; // Disables taxi/vigilante/etc and other start mission triggers
- SetStandardControlsEnabled(true); // Provided by mouse camera script (mousecam.js)
- break;
- }
+ if(getGame() == VRR_GAME_GTA_III) {
+ logToConsole(LOG_DEBUG|LOG_WARN, "Setting up initial game stuff for GTA III ...");
- case [VRR_GAME_GTA_VC]: {
- game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
- game.setGameStat(STAT_PROGRESSMADE, 9999);
- game.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
- //game.SET_CAR_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
- //game.SET_PED_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
+ // Turn off unlimited sprint
+ game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
- game.REQUEST_ANIMATION("bikev");
- game.REQUEST_ANIMATION("bikeh");
- game.REQUEST_ANIMATION("biked");
- game.REQUEST_ANIMATION("knife");
- game.REQUEST_ANIMATION("python");
- game.REQUEST_ANIMATION("shotgun");
- game.REQUEST_ANIMATION("buddy");
- game.REQUEST_ANIMATION("tec");
- game.REQUEST_ANIMATION("uzi");
- game.REQUEST_ANIMATION("rifle");
- game.REQUEST_ANIMATION("m60");
- game.REQUEST_ANIMATION("sniper");
- game.REQUEST_ANIMATION("grenade");
- game.REQUEST_ANIMATION("flame");
- game.REQUEST_ANIMATION("medic");
- game.REQUEST_ANIMATION("sunbathe");
- //game.REQUEST_ANIMATION("playidles");
- game.REQUEST_ANIMATION("riot");
- game.REQUEST_ANIMATION("strip");
- game.REQUEST_ANIMATION("lance");
- game.REQUEST_ANIMATION("skate");
+ // Set completed game progress
+ game.setGameStat(STAT_PROGRESSMADE, 9999);
+ game.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
- game.LOAD_ALL_MODELS_NOW();
- game.onMission = true; // Disables taxi/vigilante/etc and other start mission triggers
- SetStandardControlsEnabled(true); // Provided by mouse camera script (mousecam.js)
- break;
- }
+ // Traffic and ped density
+ //game.SET_CAR_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
+ //game.SET_PED_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
- case [VRR_GAME_GTA_SA]: {
- game.setGameStat(STAT_WEAPONTYPE_PISTOL_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_PISTOL_SILENCED_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_DESERT_EAGLE_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_SHOTGUN_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_SAWNOFF_SHOTGUN_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_SPAS12_SHOTGUN_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_MICRO_UZI_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_MP5_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_AK47_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_M4_SKILL, 400);
- game.setGameStat(STAT_DRIVING_SKILL, 9999);
- game.setGameStat(STAT_FAT, 9999);
- game.setGameStat(STAT_ENERGY, 9999);
- game.setGameStat(STAT_CYCLE_SKILL, 9999);
- game.setGameStat(STAT_BIKE_SKILL, 9999);
- game.setGameStat(STAT_GAMBLING, 9999);
- game.setGameStat(STAT_PROGRESS_MADE, 9999);
- game.setGameStat(STAT_RESPECT, 0);
- game.setGameStat(STAT_RESPECT_TOTAL, 0);
- game.setGameStat(STAT_SEX_APPEAL, 0);
- game.setGameStat(STAT_STAMINA, 9999);
- game.setGameStat(STAT_TOTAL_PROGRESS, 9999);
- game.setGameStat(STAT_UNDERWATER_STAMINA, 9999);
- game.setGameStat(STAT_BODY_MUSCLE, 9999);
+ // Disables taxi/vigilante/etc and other start mission triggers
+ game.onMission = true;
- game.setDefaultInteriors(false); // Disables default yellow cone at doors for entering places in singleplayer
- game.onMission = true; // Disables taxi/vigilante/etc and other start mission triggers
- break;
- }
+ // Provided by mouse camera script (mousecam.js)
+ SetStandardControlsEnabled(true);
+ } else if(getGame() == VRR_GAME_GTA_VC) {
+ logToConsole(LOG_DEBUG|LOG_WARN, "Setting up initial game stuff for GTA Vice City ...");
- case [VRR_GAME_GTA_IV]: {
- natives.allowEmergencyServices(false);
- natives.setCreateRandomCops(true);
- natives.setMaxWantedLevel(0);
- natives.setWantedMultiplier(0.0);
- natives.allowPlayerToCarryNonMissionObjects(natives.getPlayerId(), true);
- natives.setPlayerTeam(natives.getPlayerId(), 0);
- natives.loadAllObjectsNow();
- natives.setCellphoneRanked(false);
- natives.setOverrideNoSprintingOnPhoneInMultiplayer(false);
- natives.setSyncWeatherAndGameTime(false);
- natives.usePlayerColourInsteadOfTeamColour(true);
- natives.disablePauseMenu(true);
- //natives.allowReactionAnims(localPlayer, false);
- natives.allowGameToPauseForStreaming(false);
- natives.allowStuntJumpsToTrigger(false);
- natives.setPickupsFixCars(false);
- natives.forceFullVoice(localPlayer);
+ // Turn off unlimited sprint
+ game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
- // HUD and Display
- //natives.displayCash(false);
- //natives.displayAmmo(false);
- //natives.displayHud(false);
- //natives.displayRadar(false);
- //natives.displayAreaName(false);
- natives.displayPlayerNames(true);
- natives.setPoliceRadarBlips(false);
- natives.removeTemporaryRadarBlipsForPickups();
- natives.displayNonMinigameHelpMessages(false);
- natives.setDisplayPlayerNameAndIcon(natives.getPlayerId(), true);
+ // Set completed game progress
+ game.setGameStat(STAT_PROGRESSMADE, 99999);
+ game.setGameStat(STAT_TOTALPROGRESSINGAME, 99999);
- // Item/Money Dropping
- natives.setMoneyCarriedByAllNewPeds(0);
- natives.setDeadPedsDropWeapons(false);
- natives.setPlayersDropMoneyInNetworkGame(false);
+ // Traffic and ped density
+ //game.SET_CAR_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
+ //game.SET_PED_DENSITY_MULTIPLIER(3.0); // No visual effect. Needs tweaking and testing.
- // Population
- //natives.dontSuppressAnyCarModels(5.0);
- //natives.dontSuppressAnyPedModels(5.0);
- //natives.forceGenerateParkedCarsTooCloseToOthers(true);
- //natives.setParkedCarDensityMultiplier(5.0);
- //natives.setRandomCarDensityMultiplier(5.0);
- //natives.setPedDensityMultiplier(5.0);
- //natives.setCarDensityMultiplier(5.0);
- //natives.setScenarioPedDensityMultiplier(5.0, 5.0);
- natives.switchRandomTrains(true);
- natives.switchRandomBoats(true);
- natives.switchAmbientPlanes(true);
- natives.switchMadDrivers(false);
+ // Load all anim libs
+ game.REQUEST_ANIMATION("bikev");
+ game.REQUEST_ANIMATION("bikeh");
+ game.REQUEST_ANIMATION("biked");
+ game.REQUEST_ANIMATION("knife");
+ game.REQUEST_ANIMATION("python");
+ game.REQUEST_ANIMATION("shotgun");
+ game.REQUEST_ANIMATION("buddy");
+ game.REQUEST_ANIMATION("tec");
+ game.REQUEST_ANIMATION("uzi");
+ game.REQUEST_ANIMATION("rifle");
+ game.REQUEST_ANIMATION("m60");
+ game.REQUEST_ANIMATION("sniper");
+ game.REQUEST_ANIMATION("grenade");
+ game.REQUEST_ANIMATION("flame");
+ game.REQUEST_ANIMATION("medic");
+ game.REQUEST_ANIMATION("sunbathe");
+ //game.REQUEST_ANIMATION("playidles");
+ game.REQUEST_ANIMATION("riot");
+ game.REQUEST_ANIMATION("strip");
+ game.REQUEST_ANIMATION("lance");
+ game.REQUEST_ANIMATION("skate");
- // Singleplayer Cellphone
- //natives.requestScript("spcellphone");
- //natives.startNewScript("spcellphone", 0);
- // Script "v-blockedscripts" blocks the mpcellphone scripts
- natives.setMessagesWaiting(false); // Seems to have no effect
- natives.setMobilePhoneRadioState(false);
+ //game.LOAD_ALL_MODELS_NOW();
+ // Disables taxi/vigilante/etc and other start mission triggers
+ game.onMission = true;
- // Animation libraries
- natives.requestAnims("DANCING");
+ // Provided by mouse camera script (mousecam.js)
+ SetStandardControlsEnabled(true);
+ } else if(getGame() == VRR_GAME_GTA_SA) {
+ logToConsole(LOG_DEBUG|LOG_WARN, "Setting up initial game stuff for GTA San Andreas ...");
+ // Turn weapon skills down a bit
+ game.setGameStat(STAT_WEAPONTYPE_PISTOL_SKILL, 400);
+ game.setGameStat(STAT_WEAPONTYPE_PISTOL_SILENCED_SKILL, 400);
+ game.setGameStat(STAT_WEAPONTYPE_DESERT_EAGLE_SKILL, 400);
+ game.setGameStat(STAT_WEAPONTYPE_SHOTGUN_SKILL, 400);
+ game.setGameStat(STAT_WEAPONTYPE_SAWNOFF_SHOTGUN_SKILL, 400);
+ game.setGameStat(STAT_WEAPONTYPE_SPAS12_SHOTGUN_SKILL, 400);
+ game.setGameStat(STAT_WEAPONTYPE_MICRO_UZI_SKILL, 400);
+ game.setGameStat(STAT_WEAPONTYPE_MP5_SKILL, 400);
+ game.setGameStat(STAT_WEAPONTYPE_AK47_SKILL, 400);
+ game.setGameStat(STAT_WEAPONTYPE_M4_SKILL, 400);
- // Some last steps
- //natives.loadAllObjectsNow();
- break;
- }
+ // Pro driving skill
+ game.setGameStat(STAT_DRIVING_SKILL, 9999);
- case VRR_GAME_MAFIA_ONE: {
- game.mapEnabled = false;
- game.setTrafficEnabled(false);
- break;
- }
+ // Only visual for CJ, but affects all peds fight speed, bicycle hop, etc
+ game.setGameStat(STAT_FAT, 9999);
+ game.setGameStat(STAT_ENERGY, 9999);
+ game.setGameStat(STAT_CYCLE_SKILL, 9999);
+ game.setGameStat(STAT_BIKE_SKILL, 9999);
+ game.setGameStat(STAT_GAMBLING, 9999);
+ game.setGameStat(STAT_PROGRESS_MADE, 9999);
+ game.setGameStat(STAT_RESPECT, 0);
+ game.setGameStat(STAT_RESPECT_TOTAL, 0);
+ game.setGameStat(STAT_SEX_APPEAL, 0);
+ game.setGameStat(STAT_STAMINA, 9999);
+ game.setGameStat(STAT_TOTAL_PROGRESS, 9999);
+ game.setGameStat(STAT_UNDERWATER_STAMINA, 9999);
+ game.setGameStat(STAT_BODY_MUSCLE, 9999);
+
+ // Disables default yellow cone at doors for entering places in singleplayer
+ game.setDefaultInteriors(false);
+
+ // Disables taxi/vigilante/etc and other start mission triggers
+ game.onMission = true;
+ } else if(getGame() == VRR_GAME_GTA_IV) {
+ natives.allowEmergencyServices(false);
+ natives.setCreateRandomCops(true);
+ natives.setMaxWantedLevel(0);
+ natives.setWantedMultiplier(0.0);
+ natives.allowPlayerToCarryNonMissionObjects(natives.getPlayerId(), true);
+ natives.setPlayerTeam(natives.getPlayerId(), 0);
+ natives.loadAllObjectsNow();
+ natives.setCellphoneRanked(false);
+ natives.setOverrideNoSprintingOnPhoneInMultiplayer(false);
+ natives.setSyncWeatherAndGameTime(false);
+ natives.usePlayerColourInsteadOfTeamColour(true);
+ natives.disablePauseMenu(true);
+ //natives.allowReactionAnims(localPlayer, false);
+ natives.allowGameToPauseForStreaming(false);
+ natives.allowStuntJumpsToTrigger(false);
+ natives.setPickupsFixCars(false);
+ natives.forceFullVoice(localPlayer);
+
+ // HUD and Display
+ //natives.displayCash(false);
+ //natives.displayAmmo(false);
+ //natives.displayHud(false);
+ //natives.displayRadar(false);
+ //natives.displayAreaName(false);
+ natives.displayPlayerNames(true);
+ natives.setPoliceRadarBlips(false);
+ natives.removeTemporaryRadarBlipsForPickups();
+ natives.displayNonMinigameHelpMessages(false);
+ natives.setDisplayPlayerNameAndIcon(natives.getPlayerId(), true);
+
+ // Item/Money Dropping
+ natives.setMoneyCarriedByAllNewPeds(0);
+ natives.setDeadPedsDropWeapons(false);
+ natives.setPlayersDropMoneyInNetworkGame(false);
+
+ // Population
+ //natives.dontSuppressAnyCarModels(5.0);
+ //natives.dontSuppressAnyPedModels(5.0);
+ //natives.forceGenerateParkedCarsTooCloseToOthers(true);
+ //natives.setParkedCarDensityMultiplier(5.0);
+ //natives.setRandomCarDensityMultiplier(5.0);
+ //natives.setPedDensityMultiplier(5.0);
+ //natives.setCarDensityMultiplier(5.0);
+ //natives.setScenarioPedDensityMultiplier(5.0, 5.0);
+ natives.switchRandomTrains(true);
+ natives.switchRandomBoats(true);
+ natives.switchAmbientPlanes(true);
+ natives.switchMadDrivers(false);
+
+ // Singleplayer Cellphone
+ //natives.requestScript("spcellphone");
+ //natives.startNewScript("spcellphone", 0);
+ // Script "v-blockedscripts" blocks the mpcellphone scripts
+ natives.setMessagesWaiting(false); // Seems to have no effect
+ natives.setMobilePhoneRadioState(false);
+
+ // Animation libraries
+ natives.requestAnims("DANCING");
+
+ // Some last steps
+ //natives.loadAllObjectsNow();
+ } else if(getGame() == VRR_GAME_MAFIA_ONE) {
+ game.mapEnabled = false;
+ game.setTrafficEnabled(false);
}
}
// ===========================================================================
-function initClient() {
- loadLocaleConfig();
- loadAllLocaleStrings();
-
- setUpInitialGame();
-}
-
-// ===========================================================================
-
initClientScripts();
// ===========================================================================
diff --git a/scripts/client/sync.js b/scripts/client/sync.js
index aab557f8..4c727cec 100644
--- a/scripts/client/sync.js
+++ b/scripts/client/sync.js
@@ -128,10 +128,10 @@ function syncVehicleProperties(vehicle) {
}
if(getGame() == VRR_GAME_GTA_SA) {
- let allUpgrades = getGameConfig().vehicleUpgrades[getGame()];
- for(let i in allUpgrades) {
- vehicle.removeUpgrade(i);
- }
+ //let allUpgrades = getGameConfig().vehicleUpgrades[getGame()];
+ //for(let i in allUpgrades) {
+ // vehicle.removeUpgrade(i);
+ //}
if(doesEntityDataExist(vehicle, "vrr.upgrades")) {
let upgrades = getEntityData(vehicle, "vrr.upgrades");
@@ -246,8 +246,9 @@ function syncCivilianProperties(civilian) {
}
if(doesEntityDataExist(civilian, "vrr.anim")) {
- let animData = getEntityData(civilian, "vrr.anim");
- civilian.addAnimation(animData[0], animData[1]);
+ let animationSlot = getEntityData(civilian, "vrr.anim");
+ let animationData = getAnimationData(animationSlot);
+ civilian.addAnimation(animationData.groupId, animationData.animId);
}
}
@@ -366,26 +367,6 @@ function syncPlayerProperties(player) {
// ===========================================================================
-function syncObjectProperties(object) {
- if(!areServerElementsSupported()) {
- return false;
- }
-
- if(getGame() == VRR_GAME_GTA_III || getGame() == VRR_GAME_GTA_VC) {
- if(doesEntityDataExist(object, "vrr.scale")) {
- let scaleFactor = getEntityData(object, "vrr.scale");
- let tempMatrix = object.matrix;
- tempMatrix.setScale(toVector3(scaleFactor.x, scaleFactor.y, scaleFactor.z));
- let tempPosition = object.position;
- object.matrix = tempMatrix;
- tempPosition.z += scaleFactor.z;
- object.position = tempPosition;
- }
- }
-}
-
-// ===========================================================================
-
function syncElementProperties(element) {
if(!areServerElementsSupported()) {
return false;
@@ -428,10 +409,6 @@ function syncElementProperties(element) {
syncPlayerProperties(element);
break;
- case ELEMENT_OBJECT:
- syncObjectProperties(element);
- break;
-
default:
break;
}
diff --git a/scripts/server/account.js b/scripts/server/account.js
index 492ac187..8f68aa8c 100644
--- a/scripts/server/account.js
+++ b/scripts/server/account.js
@@ -1016,27 +1016,48 @@ function checkAccountResetPasswordRequest(client, inputText) {
return false;
}
- if(getPlayerData(client).passwordResetState == VRR_RESETPASS_STATE_NONE) {
- if(toLowerCase(getPlayerData(client).accountData.emailAddress) != toLowerCase(inputText)) {
- logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (email not correct)`);
- return false;
+ switch(getPlayerData(client).passwordResetState) {
+ case VRR_RESETPASS_STATE_EMAILCONFIRM: {
+ if(toLowerCase(getPlayerData(client).accountData.emailAddress) != toLowerCase(inputText)) {
+ logToConsole(LOG_INFO|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (email not correct)`);
+ showPlayerErrorGUI(client, getLocaleString(client, "GUIErrorResetPasswordFailedInvalidEmail"), getLocaleString(client, "GUIErrorTitle"), getLocaleString(client, "GUIOkButton"));
+ return false;
+ }
+
+ let passwordResetCode = toUpperCase(generateEmailVerificationCode());
+ getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_CODEINPUT;
+ getPlayerData(client).passwordResetCode = passwordResetCode;
+ showPlayerResetPasswordCodeInputGUI(client);
+ sendPasswordResetEmail(client, passwordResetCode);
+ logToConsole(LOG_INFO, `${getPlayerDisplayForConsole(client)} submitted successful email for password reset. Sending email and awaiting verification code input ...`);
+ break;
}
- let passwordResetCode = toUpperCase(generateEmailVerificationCode());
- getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_CODEINPUT;
- getPlayerData(client).passwordResetCode = passwordResetCode;
- sendPasswordResetEmail(client, passwordResetCode);
- showPlayerResetPasswordCodeInputGUI(client);
- logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} reset their password. Awaiting verification code input ...`);
- } else if(getPlayerData(client).passwordResetState == VRR_RESETPASS_STATE_CODEINPUT) {
- if(getPlayerData(client).passwordResetCode == toUpperCase(inputText)) {
- getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_SETPASS;
- showPlayerChangePasswordGUI(client);
- logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} entered the correct reset password verification code. Awaiting new password input ...`);
- } else {
- getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_NONE;
- disconnectPlayer(client);
- logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (verification code not correct)`);
+ case VRR_RESETPASS_STATE_CODEINPUT: {
+ if(inputText != "") {
+ if(getPlayerData(client).passwordResetCode == toUpperCase(inputText)) {
+ getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_SETPASS;
+ showPlayerChangePasswordGUI(client, getLocaleString(client));
+ logToConsole(LOG_INFO, `${getPlayerDisplayForConsole(client)} entered the correct reset password verification code. Awaiting new password input ...`);
+ } else {
+ getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_NONE;
+ getPlayerData(client).passwordResetAttemptsRemaining = getPlayerData(client).passwordResetAttemptsRemaining - 1;
+ logToConsole(LOG_INFO|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (verification code not correct, ${getPlayerData(client).passwordResetAttemptsRemaining} attempts remaining)`);
+ if(getPlayerData(client).passwordResetAttemptsRemaining <= 0) {
+ logToConsole(LOG_INFO|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (verification code not correct, no more attempts remaining, kicking ...)`);
+ disconnectPlayer(client);
+ return false;
+ }
+ }
+ }
+ break;
+ }
+
+ case VRR_RESETPASS_STATE_NONE: {
+ logToConsole(LOG_INFO, `${getPlayerDisplayForConsole(client)} requested a password reset. Awaiting email input ...`);
+ showPlayerResetPasswordEmailInputGUI(client);
+ getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_EMAILCONFIRM;
+ break;
}
}
@@ -1414,14 +1435,8 @@ function isAccountEmailVerified(accountData) {
// ===========================================================================
-function isAccountTwoFactorAuthenticationVerified(accountData) {
- return hasBitFlag(accountData.flags.moderation, getModerationFlagValue("TwoFactorAuthVerified"));
-}
-
-// ===========================================================================
-
function doesPlayerHaveTwoFactorAuthEnabled(client) {
- return hasBitFlag(getPlayerData(client).accountData.settings, getAccountSettingsFlagValue("TwoFactorAuth"));
+ return hasBitFlag(getPlayerData(client).accountData.settings, getAccountSettingsFlagValue("TwoStepAuth"));
}
// ===========================================================================
diff --git a/scripts/server/business.js b/scripts/server/business.js
index eb598145..a41e4c9c 100644
--- a/scripts/server/business.js
+++ b/scripts/server/business.js
@@ -747,14 +747,14 @@ function getBusinessInfoCommand(command, params, client) {
[`ID`, `${businessData.index}/${businessData.databaseId}`],
[`Owner`, `${ownerName} (${getBusinessOwnerTypeText(businessData.ownerType)})`],
[`Locked`, `${getLockedUnlockedFromBool(businessData.locked)}`],
- [`BuyPrice`, `${businessData.buyPrice}`],
- [`RentPrice`, `${businessData.rentPrice}`],
+ [`BuyPrice`, `$${businessData.buyPrice}`],
+ //[`RentPrice`, `${businessData.rentPrice}`],
[`HasInterior`, `${getYesNoFromBool(businessData.hasInterior)}`],
[`CustomInterior`, `${getYesNoFromBool(businessData.customInterior)}`],
[`HasBuyableItems`, `${getYesNoFromBool(doesBusinessHaveAnyItemsToBuy(businessId))}`],
- [`EntranceFee`, `${businessData.entranceFee}`],
+ [`EntranceFee`, `$${businessData.entranceFee}`],
[`InteriorLights`, `${getOnOffFromBool(businessData.interiorLights)}`],
- [`Balance`, `${businessData.till}`],
+ [`Balance`, `$${businessData.till}`],
[`RadioStation`, `${businessData.streamingRadioStation}`],
[`LabelHelpType`, `${businessData.labelHelpType}`],
];
@@ -940,6 +940,65 @@ function setBusinessInteriorTypeCommand(command, params, client) {
// ===========================================================================
+/**
+ * This is a command handler function.
+ *
+ * @param {string} command - The command name used by the player
+ * @param {string} params - The parameters/args string used with the command by the player
+ * @param {Client} client - The client/player that used the command
+ * @return {bool} Whether or not the command was successful
+ *
+ */
+ function addBusinessPropertyTemplateEntities(command, params, client) {
+ let propertyTemplateParam = getParam(params, " ", 1) || "business";
+ let businessId = getPlayerBusiness(client);
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
+ return false;
+ }
+
+ if(typeof getGameConfig().interiors[getGame()] == "undefined") {
+ messagePlayerError(client, `There are no property templates available for this game!`);
+ return false;
+ }
+
+ if(isNaN(propertyTemplateParam)) {
+ if(isNull(getGameConfig().interiors[getGame()][typeParam])) {
+ messagePlayerError(client, "Invalid interior type! Use an interior type name");
+ let interiorTypesList = Object.keys(getGameConfig().properties[getGame()]);
+ let chunkedList = splitArrayIntoChunks(interiorTypesList, 10);
+
+ messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPropertyTemplateTypes")));
+ for(let i in chunkedList) {
+ messagePlayerInfo(client, chunkedList[i].join(", "));
+ }
+ return false;
+ }
+
+ getBusinessData(businessId).exitPosition = getGameConfig().interiors[getGame()][typeParam][0];
+ getBusinessData(businessId).exitInterior = getGameConfig().interiors[getGame()][typeParam][1];
+ getBusinessData(businessId).exitDimension = getBusinessData(businessId).databaseId+getGlobalConfig().businessDimensionStart;
+ getBusinessData(businessId).exitPickupModel = getGameConfig().pickupModels[getGame()].Exit;
+ getBusinessData(businessId).hasInterior = true;
+ getBusinessData(businessId).customInterior = getGameConfig().interiors[getGame()][typeParam][2];
+ getBusinessData(businessId).interiorCutscene = getGameConfig().interiors[getGame()][typeParam][3];
+ }
+
+ //deleteBusinessExitPickup(businessId);
+ //deleteBusinessExitBlip(businessId);
+ //createBusinessExitBlip(businessId);
+ //createBusinessExitPickup(businessId);
+
+ resetBusinessPickups(businessId);
+
+ getBusinessData(businessId).needsSaved = true;
+
+ messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set business {businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR} interior type to {ALTCOLOUR}${typeParam}`);
+}
+
+// ===========================================================================
+
/**
* This is a command handler function.
*
@@ -1649,6 +1708,8 @@ function saveBusinessToDatabase(businessId) {
["biz_label_help_type", tempBusinessData.labelHelpType],
["biz_radiostation", tempBusinessData.streamingRadioStation],
["biz_custom_interior", boolToInt(tempBusinessData.customInterior)],
+ ["biz_buy_price", boolToInt(tempBusinessData.buyPrice)],
+ //["biz_rent_price", boolToInt(tempBusinessData.rentPrice)],
];
let dbQuery = null;
@@ -1749,24 +1810,33 @@ function createBusinessEntrancePickup(businessId) {
logToConsole(LOG_VERBOSE, `[VRR.Job]: Creating entrance pickup for business ${businessData.name} (model ${pickupModelId})`);
- let entrancePickup = createGamePickup(pickupModelId, businessData.entrancePosition, getGameConfig().pickupTypes[getGame()].business);
- if(entrancePickup != null) {
- if(businessData.entranceDimension != -1) {
- setElementDimension(entrancePickup, businessData.entranceDimension);
- setElementOnAllDimensions(entrancePickup, false);
- } else {
- setElementOnAllDimensions(entrancePickup, true);
- }
+ if(areServerElementsSupported()) {
+ let entrancePickup = createGamePickup(pickupModelId, businessData.entrancePosition, getGameConfig().pickupTypes[getGame()].business);
+ if(entrancePickup != null) {
+ if(businessData.entranceDimension != -1) {
+ setElementDimension(entrancePickup, businessData.entranceDimension);
+ setElementOnAllDimensions(entrancePickup, false);
+ } else {
+ setElementOnAllDimensions(entrancePickup, true);
+ }
- if(getGlobalConfig().businessPickupStreamInDistance == -1 || getGlobalConfig().businessPickupStreamOutDistance == -1) {
- entrancePickup.netFlags.distanceStreaming = false;
- } else {
- setElementStreamInDistance(entrancePickup, getGlobalConfig().businessPickupStreamInDistance);
- setElementStreamOutDistance(entrancePickup, getGlobalConfig().businessPickupStreamOutDistance);
+ if(getGlobalConfig().businessPickupStreamInDistance == -1 || getGlobalConfig().businessPickupStreamOutDistance == -1) {
+ entrancePickup.netFlags.distanceStreaming = false;
+ } else {
+ setElementStreamInDistance(entrancePickup, getGlobalConfig().businessPickupStreamInDistance);
+ setElementStreamOutDistance(entrancePickup, getGlobalConfig().businessPickupStreamOutDistance);
+ }
+ setElementTransient(entrancePickup, false);
+ getBusinessData(businessId).entrancePickup = entrancePickup;
+ updateBusinessPickupLabelData(businessId);
}
- setElementTransient(entrancePickup, false);
- getBusinessData(businessId).entrancePickup = entrancePickup;
- updateBusinessPickupLabelData(businessId);
+ } else {
+ let pickupModelId = getGameConfig().pickupModels[getGame()].Business;
+
+ if(businessData.entrancePickupModel != 0) {
+ pickupModelId = businessData.entrancePickupModel;
+ }
+ sendBusinessToPlayer(null, businessId, businessData.name, businessData.entrancePosition, blipModelId, pickupModelId, businessData.hasInterior, doesBusinessHaveAnyItemsToBuy(businessId));
}
return false;
@@ -1782,10 +1852,6 @@ function createBusinessEntrancePickup(businessId) {
*
*/
function createBusinessEntranceBlip(businessId) {
- if(!areServerElementsSupported()) {
- return false;
- }
-
if(!getServerConfig().createBusinessBlips) {
return false;
}
@@ -1808,23 +1874,25 @@ function createBusinessEntranceBlip(businessId) {
logToConsole(LOG_VERBOSE, `[VRR.Job]: Creating entrance blip for business ${businessData.name} (model ${blipModelId})`);
- let entranceBlip = createGameBlip(businessData.entrancePosition, blipModelId, getColourByType("businessBlue"));
- if(entranceBlip != null) {
- if(businessData.entranceDimension != -1) {
- setElementDimension(entranceBlip, businessData.entranceDimension);
- setElementOnAllDimensions(entranceBlip, false);
- } else {
- setElementOnAllDimensions(entranceBlip, true);
- }
+ if(areServerElementsSupported()) {
+ let entranceBlip = createGameBlip(businessData.entrancePosition, blipModelId, 1, getColourByType("businessBlue"));
+ if(entranceBlip != null) {
+ if(businessData.entranceDimension != -1) {
+ setElementDimension(entranceBlip, businessData.entranceDimension);
+ setElementOnAllDimensions(entranceBlip, false);
+ } else {
+ setElementOnAllDimensions(entranceBlip, true);
+ }
- if(getGlobalConfig().businessBlipStreamInDistance == -1 || getGlobalConfig().businessBlipStreamOutDistance == -1) {
- entranceBlip.netFlags.distanceStreaming = false;
- } else {
- setElementStreamInDistance(entranceBlip, getGlobalConfig().businessBlipStreamInDistance);
- setElementStreamOutDistance(entranceBlip, getGlobalConfig().businessBlipStreamOutDistance);
+ if(getGlobalConfig().businessBlipStreamInDistance == -1 || getGlobalConfig().businessBlipStreamOutDistance == -1) {
+ entranceBlip.netFlags.distanceStreaming = false;
+ } else {
+ setElementStreamInDistance(entranceBlip, getGlobalConfig().businessBlipStreamInDistance);
+ setElementStreamOutDistance(entranceBlip, getGlobalConfig().businessBlipStreamOutDistance);
+ }
+ setElementTransient(entranceBlip, false);
+ businessData.entranceBlip = entranceBlip;
}
- setElementTransient(entranceBlip, false);
- businessData.entranceBlip = entranceBlip;
}
}
@@ -1956,6 +2024,9 @@ function deleteBusiness(businessId, deletedBy = 0) {
let dbConnection = connectToDatabase();
let dbQuery = null;
+ deleteBusinessBlips(businessId);
+ deleteBusinessPickups(businessId);
+
if(dbConnection) {
dbQuery = queryDatabase(dbConnection, `DELETE FROM biz_main WHERE biz_id = ${tempBusinessData.databaseId}`);
if(dbQuery) {
@@ -1964,9 +2035,6 @@ function deleteBusiness(businessId, deletedBy = 0) {
disconnectFromDatabase(dbConnection);
}
- deleteBusinessBlips(businessId);
- deleteBusinessPickups(businessId);
-
removePlayersFromBusiness(businessId);
getServerData().businesses.splice(businessId, 1);
@@ -2508,10 +2576,19 @@ function cacheBusinessItems(businessId) {
clearArray(getBusinessData(businessId).floorItemCache);
clearArray(getBusinessData(businessId).storageItemCache);
- let businessData = getBusinessData(businessId);
- logToConsole(LOG_VERBOSE, `[VRR.Business] Caching business items for business ${businessId} (${businessData.name}) ...`);
- getBusinessData(businessId).floorItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_BIZFLOOR && item.ownerId == businessData.databaseId);
- getBusinessData(businessId).storageItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_BIZSTORAGE && item.ownerId == businessData.databaseId);
+ //let businessData = getBusinessData(businessId);
+ //logToConsole(LOG_VERBOSE, `[VRR.Business] Caching business items for business ${businessId} (${businessData.name}) ...`);
+ //getBusinessData(businessId).floorItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_BIZFLOOR && item.ownerId == businessData.databaseId).map(i => i.index);
+ //getBusinessData(businessId).storageItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_BIZSTORAGE && item.ownerId == businessData.databaseId);
+
+ logToConsole(LOG_VERBOSE, `[VRR.Business] Caching business items for business ${businessId} (${getBusinessData(businessId).name}) ...`);
+ for(let i in getServerData().items) {
+ if(getItemData(i).ownerType == VRR_ITEM_OWNER_BIZFLOOR && getItemData(i).ownerId == getBusinessData(businessId).databaseId) {
+ getBusinessData(businessId).floorItemCache.push(i);
+ } else if(getItemData(i).ownerType == VRR_ITEM_OWNER_BIZSTORAGE && getItemData(i).ownerId == getBusinessData(businessId).databaseId) {
+ getBusinessData(businessId).storageItemCache.push(i);
+ }
+ }
logToConsole(LOG_VERBOSE, `[VRR.Business] Successfully cached ${getBusinessData(businessId).floorItemCache.length} floor items and ${getBusinessData(businessId).storageItemCache} storage items for business ${businessId} (${getBusinessData(businessId).name})!`);
}
diff --git a/scripts/server/chat.js b/scripts/server/chat.js
index 0a6e3bad..8bc9223b 100644
--- a/scripts/server/chat.js
+++ b/scripts/server/chat.js
@@ -38,7 +38,7 @@ function processPlayerChat(client, messageText) {
}
messageText = messageText.substring(0, 128);
- messagePlayerNormal(null, `💬 ${getCharacterFullName(client)}: ${messageText}`);
+ messagePlayerNormal(null, `💬 ${getCharacterFullName(client)}: {MAINCOLOUR}${messageText}`, getPlayerColour(client));
messageDiscordChatChannel(`💬 ${getCharacterFullName(client)}: ${messageText}`);
} else {
messagePlayerNormal(null, `🛡️ (ADMIN) - ${messageText}`);
diff --git a/scripts/server/clan.js b/scripts/server/clan.js
index db657535..5fa85af6 100644
--- a/scripts/server/clan.js
+++ b/scripts/server/clan.js
@@ -142,7 +142,7 @@ function listClansCommand(command, params, client) {
let chunkedList = splitArrayIntoChunks(nameList, 5);
- messagePlayerInfo(client, `{clanOrange}== {jobYellow}Clans {clanOrange}====================================`);
+ messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderClansList")));
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
@@ -169,7 +169,7 @@ function listClanRanksCommand(command, params, client) {
let chunkedList = splitArrayIntoChunks(rankNameList, 5);
- messagePlayerInfo(client, `{clanOrange}== {jobYellow}Clan Ranks (${getClanData(clanId).name}) {clanOrange}=====================`);
+ messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderClanRanksList")));
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
@@ -191,7 +191,7 @@ function createClanCommand(command, params, client) {
// Create clan without owner. Can set owner with /clanowner afterward
createClan(params);
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}created clan {clanOrange}${params}`);
+ messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created clan {clanOrange}${params}`);
}
// ===========================================================================
@@ -209,7 +209,7 @@ function deleteClanCommand(command, params, client) {
return false;
}
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}deleted clan {clanOrange}${getClanData(clanId).name}`);
+ messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}deleted clan {clanOrange}${getClanData(clanId).name}`);
deleteClan(clanId);
}
@@ -240,10 +240,13 @@ function setClanOwnerCommand(command, params, client) {
}
getClanData(clanId).owner = getPlayerCurrentSubAccount(targetClient).databaseId;
+ getClanData(clanId).needsSaved = true;
+
getPlayerCurrentSubAccount(targetClient).clan = getClanData(clanId).databaseId;
getPlayerCurrentSubAccount(targetClient).clanFlags = getClanFlagValue("All");
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).name} {MAINCOLOUR}owner to {ALTCOLOUR}${getCharacterFullName(targetClient)}`);
+ //messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).name} {MAINCOLOUR}owner to {ALTCOLOUR}${getCharacterFullName(targetClient)}`);
+ messagePlayerSuccess(client, `You changed the clan owner to {ALTCOLOUR}${getCharacterFullName(targetClient)}`);
}
// ===========================================================================
@@ -266,9 +269,11 @@ function setClanTagCommand(command, params, client) {
return false;
}
- getClanData(clanId).params = params;
+ getClanData(clanId).tag = params;
+ getClanData(clanId).needsSaved = true;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).index} {MAINCOLOUR}tag to {ALTCOLOUR}${params}`);
+ //messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).index} {MAINCOLOUR}tag to {ALTCOLOUR}${params}`);
+ messagePlayerSuccess(client, `You changed the clan tag to {ALTCOLOUR}${params}`);
}
// ===========================================================================
@@ -292,8 +297,10 @@ function setClanNameCommand(command, params, client) {
}
getClanData(clanId).name = params;
+ getClanData(clanId).needsSaved = true;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).index} {MAINCOLOUR}name to {ALTCOLOUR}${params}`);
+ //messageAdmins(`{adminOrange}${getPlayerName(client)} {MAINCOLOUR}set clan {clanOrange}${getClanData(clanId).index} {MAINCOLOUR}name to {ALTCOLOUR}${params}`);
+ messagePlayerSuccess(client, `You changed the clan name to {ALTCOLOUR}${params}`);
}
// ===========================================================================
@@ -354,8 +361,9 @@ function deleteClanRankCommand(command, params, client) {
}
removeClanRank(clanId, rankId);
+ getClanData(clanId).needsSaved = true;
- messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${tempRankName} {MAINCOLOUR}rank`);
+ messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${tempRankName}{MAINCOLOUR} rank`);
}
// ===========================================================================
@@ -397,7 +405,7 @@ function setClanMemberTagCommand(command, params, client) {
}
}
- getPlayerCurrentSubAccount(targetClient).ClanTag = getParam(params, " ", 2);
+ getPlayerCurrentSubAccount(targetClient).clanTag = getParam(params, " ", 2);
messagePlayerSuccess(client, `You set {ALTCOLOUR}${getCharacterFullName(targetClient)}'s {MAINCOLOUR}clan tag to {ALTCOLOUR}${getParam(params, " ", 2)}`);
messagePlayerAlert(client, `{ALTCOLOUR}${getCharacterFullName(targetClient)} {MAINCOLOUR}set your clan tag to {ALTCOLOUR}${getParam(params, " ", 2)}`);
@@ -431,7 +439,8 @@ function setClanRankTagCommand(command, params, client) {
}
}
- getServerData().clans[clanId].rankId[rankId].customTag = newTag;
+ getClanRankData(clanId, rankId).customTag = newTag;
+ getClanRankData(clanId, rankId).needsSaved = true;
}
// ===========================================================================
@@ -479,7 +488,8 @@ function setClanRankLevelCommand(command, params, client) {
return false;
}
- getServerData().clans[clanId].rankId[rankId].level = toInteger(newLevel);
+ getClanRankData(clanId, rankId).level = toInteger(newLevel);
+ getClanRankData(clanId, rankId).needsSaved = true;
}
// ===========================================================================
@@ -618,7 +628,8 @@ function addClanRankFlagCommand(command, params, client) {
let flagValue = getClanFlagValue(getParam(params, " ", 2));
- addBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
+ getClanRankData(clanId, rankId).flags = addBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
+ getClanRankData(clanId, rankId).needsSaved = true;
messagePlayerSuccess(client, `You added the {ALTCOLOUR}${getParam(params, " ", 2)} {MAINCOLOUR}clan flag to rank {ALTCOLOUR}${getClanRankData(clanId, rankId).name}`);
}
@@ -656,7 +667,8 @@ function removeClanRankFlagCommand(command, params, client) {
let flagValue = getClanFlagValue(getParam(params, " ", 2));
- removeBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
+ getClanRankData(clanId, rankId).flags = removeBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
+ getClanRankData(clanId, rankId).needsSaved = true;
messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${getParam(params, " ", 2)} {MAINCOLOUR}clan flag from rank {ALTCOLOUR}${getClanRankData(clanId, rankId).name}`);
}
@@ -781,6 +793,7 @@ function setClanRankTitleCommand(command, params, client) {
let oldRankName = getClanRankData(clanId, rankId).name;
getClanRankData(clanId, rankId).name = getParam(params, " ", 2);
+ getClanRankData(clanId, rankId).needsSaved = true;
messagePlayerSuccess(client, `You changed the name of rank ${rankId} from {ALTCOLOUR}${oldRankName} {MAINCOLOUR}to {ALTCOLOUR}${params}`);
}
diff --git a/scripts/server/class.js b/scripts/server/class.js
index e31ddf87..aa8f7ea4 100644
--- a/scripts/server/class.js
+++ b/scripts/server/class.js
@@ -135,6 +135,15 @@ class ServerConfigData {
sendChat: intToBool(dbAssoc["svr_discord_send_chat"]),
sendAdmin: intToBool(dbAssoc["svr_discord_send_admin"]),
};
+
+ this.economy = {
+ inflationMultiplier: toFloat(dbAssoc["svr_inflation_multiplier"]),
+ incomeTaxRate: toFloat(dbAssoc["svr_income_tax_rate"]),
+ passiveIncome: toFloat(dbAssoc["svr_passive_income"]),
+ }
+
+ this.devServer = intToBool(toInteger(server.getCVar("vrr_devserver")));
+ this.testerOnly = intToBool(toInteger(server.getCVar("vrr_testeronly")));
}
}
};
@@ -153,6 +162,7 @@ class ClientData {
this.connectTime = 0;
this.clientVersion = "0.0.0";
this.loginAttemptsRemaining = 3;
+ this.passwordResetAttemptsRemaining = 3;
this.afk = false;
this.jobRoute = -1;
@@ -918,21 +928,7 @@ class VehicleData {
this.colour4 = (vehicle) ? vehicle.colour4 : 1;
this.livery = 3;
- this.extras = [
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- ];
+ this.mods = [];
// Vehicle Attributes
this.locked = false;
@@ -955,6 +951,7 @@ class VehicleData {
this.needsSaved = false;
this.whoAdded = 0;
this.whenAdded = 0;
+ this.licensePlate = "";
this.interior = 0;
this.dimension = 0;
@@ -991,23 +988,6 @@ class VehicleData {
this.colour4 = toInteger(dbAssoc["veh_col4"]);
this.livery = toInteger(dbAssoc["veh_livery"]);
- // Extras (components on SA, extras on IV+)
- this.extras = [
- toInteger(dbAssoc["veh_extra1"]),
- toInteger(dbAssoc["veh_extra2"]),
- toInteger(dbAssoc["veh_extra3"]),
- toInteger(dbAssoc["veh_extra4"]),
- toInteger(dbAssoc["veh_extra5"]),
- toInteger(dbAssoc["veh_extra6"]),
- toInteger(dbAssoc["veh_extra7"]),
- toInteger(dbAssoc["veh_extra8"]),
- toInteger(dbAssoc["veh_extra9"]),
- toInteger(dbAssoc["veh_extra10"]),
- toInteger(dbAssoc["veh_extra11"]),
- toInteger(dbAssoc["veh_extra12"]),
- toInteger(dbAssoc["veh_extra13"]),
- ];
-
// Vehicle Attributes
this.locked = intToBool(toInteger(dbAssoc["veh_locked"]));
this.engine = intToBool(toInteger(dbAssoc["veh_engine"]));
@@ -1024,6 +1004,7 @@ class VehicleData {
this.needsSaved = false;
this.whoAdded = toInteger(dbAssoc["veh_who_added"]);
this.whenAdded = toInteger(dbAssoc["veh_when_added"]);
+ this.licensePlate = toInteger(dbAssoc["veh_license_plate"]);
this.interior = toInteger(dbAssoc["veh_int"]);
this.dimension = toInteger(dbAssoc["veh_vw"]);
@@ -1475,9 +1456,7 @@ class NPCData {
constructor(dbAssoc = false) {
this.databaseId = 0;
this.serverId = 0;
- this.firstName = "John";
- this.lastName = "Doe";
- this.middleName = "Q";
+ this.name = "NPC";
this.skin = 0;
this.cash = 0;
this.position = toVector3(0.0, 0.0, 0.0);
@@ -1496,12 +1475,15 @@ class NPCData {
this.fightStyle = 0;
this.health = 100;
this.armour = 100;
- this.currentAction = VRR_NPCACTION_NONE;
+ this.currentAction = VRR_NPC_ACTION_NONE;
this.triggers = [];
this.typeFlags = 0;
this.heedThreats = false;
this.threats = 0;
this.invincible = false;
+ this.animationName = "";
+ this.ownerType = VRR_NPCOWNER_NONE;
+ this.ownerId = 0;
this.bodyParts = {
hair: [0,0],
@@ -1528,9 +1510,7 @@ class NPCData {
if(dbAssoc) {
this.databaseId = toInteger(dbAssoc["npc_id"]);
this.serverId = toInteger(dbAssoc["npc_server"]);
- this.firstName = dbAssoc["npc_name_first"];
- this.lastName = dbAssoc["npc_name_last"];
- this.middleName = dbAssoc["npc_name_middle"] || "";
+ this.name = dbAssoc["npc_name"];
this.skin = toInteger(dbAssoc["npc_skin"]);
this.cash = toInteger(dbAssoc["npc_cash"]);
this.position = toVector3(toFloat(dbAssoc["npc_pos_x"]), toFloat(dbAssoc["npc_pos_y"]), toFloat(dbAssoc["npc_pos_z"]));
@@ -1551,6 +1531,7 @@ class NPCData {
this.heedThreats = intToBool(dbAssoc["npc_headthreats"]);
this.threats = toInteger(dbAssoc["npc_threats"]);
this.invincible = intToBool(dbAssoc["npc_invincible"]);
+ this.animationName = intToBool(dbAssoc["npc_animation"]);
this.bodyParts = {
hair: [toInteger(dbAssoc["npc_hd_part_hair_model"]) || 0, toInteger(dbAssoc["npc_hd_part_hair_texture"]) || 0],
diff --git a/scripts/server/client.js b/scripts/server/client.js
index de4bbd08..9e896186 100644
--- a/scripts/server/client.js
+++ b/scripts/server/client.js
@@ -272,13 +272,6 @@ function sendJobRouteLocationToPlayer(client, position, colour) {
// ===========================================================================
-function showPlayerChangePasswordGUI(client) {
- logToConsole(LOG_DEBUG, `[VRR.Client] Sending change password GUI signal to ${getPlayerDisplayForConsole(client)}`);
- sendNetworkEventToPlayer("vrr.changePassword", client);
-}
-
-// ===========================================================================
-
function showPlayerLoginSuccessGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending login success GUI signal to ${getPlayerDisplayForConsole(client)}`);
sendNetworkEventToPlayer("vrr.loginSuccess", client);
@@ -344,18 +337,25 @@ function showPlayerNewCharacterGUI(client) {
function showPlayerChangePasswordGUI(client, errorMessage = "") {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show change password GUI signal to ${getPlayerDisplayForConsole(client)}`);
- sendNetworkEventToPlayer("vrr.showChangePassword", client);
+ sendNetworkEventToPlayer("vrr.showChangePassword", client, errorMessage);
}
// ===========================================================================
function showPlayerResetPasswordCodeInputGUI(client) {
- logToConsole(LOG_DEBUG, `[VRR.Client] Sending show reset password GUI signal to ${getPlayerDisplayForConsole(client)}`);
+ logToConsole(LOG_DEBUG, `[VRR.Client] Sending show reset password code input GUI signal to ${getPlayerDisplayForConsole(client)}`);
sendNetworkEventToPlayer("vrr.showResetPasswordCodeInput", client);
}
// ===========================================================================
+function showPlayerResetPasswordEmailInputGUI(client) {
+ logToConsole(LOG_DEBUG, `[VRR.Client] Sending show reset password email input GUI signal to ${getPlayerDisplayForConsole(client)}`);
+ sendNetworkEventToPlayer("vrr.showResetPasswordEmailInput", client);
+}
+
+// ===========================================================================
+
function showPlayerCharacterSelectGUI(client, firstName, lastName, cash, clan, lastPlayed, skin) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending character select GUI signal to ${getPlayerDisplayForConsole(client)}`);
sendNetworkEventToPlayer("vrr.showCharacterSelect", client, firstName, lastName, cash, clan, lastPlayed, skin);
@@ -400,7 +400,7 @@ function showPlayerInfoGUI(client, infoMessage, infoTitle, buttonText = "OK") {
function showPlayerErrorGUI(client, errorMessage, errorTitle, buttonText = "OK") {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show error GUI signal to ${getPlayerDisplayForConsole(client)} (Title: ${errorTitle}, Message: ${errorMessage})`);
- sendNetworkEventToPlayer("vrr.showInfo", client, errorMessage, errorTitle, buttonText);
+ sendNetworkEventToPlayer("vrr.showError", client, errorMessage, errorTitle, buttonText);
}
// ===========================================================================
@@ -990,21 +990,21 @@ function sendPlayerEnterPropertyKey(client, key) {
function makePedPlayAnimation(ped, animationSlot, positionOffset) {
setEntityData(ped, "vrr.anim", animationSlot, true);
- sendNetworkEventToPlayer("vrr.pedAnim", null, getPedForNetworkEvent(ped), animationSlot, positionOffset);
+ sendNetworkEventToPlayer("vrr.anim", null, getPedForNetworkEvent(ped), animationSlot, positionOffset);
}
// ===========================================================================
function makePedStopAnimation(ped) {
removeEntityData(ped, "vrr.anim");
- sendNetworkEventToPlayer("vrr.pedStopAnim", null, getPedForNetworkEvent(ped));
+ sendNetworkEventToPlayer("vrr.stopAnim", null, getPedForNetworkEvent(ped));
}
// ===========================================================================
function forcePedAnimation(ped, animationSlot, positionOffset = 0) {
addEntityData(ped, "vrr.anim", animationSlot, true);
- sendNetworkEventToPlayer("vrr.forcePedAnim", null, getPedForNetworkEvent(ped), animationSlot, positionOffset);
+ sendNetworkEventToPlayer("vrr.forceAnim", null, getPedForNetworkEvent(ped), animationSlot, positionOffset);
}
// ===========================================================================
@@ -1094,8 +1094,8 @@ function sendBusinessToPlayer(client, businessId, name, entrancePosition, blipMo
// ==========================================================================
-function sendHouseToPlayer(client, houseId, entrancePosition, blipModel, pickupModel, hasInterior) {
- sendNetworkEventToPlayer("vrr.house", client, houseId, entrancePosition, blipModel, pickupModel, hasInterior);
+function sendHouseToPlayer(client, houseId, description, entrancePosition, blipModel, pickupModel, hasInterior) {
+ sendNetworkEventToPlayer("vrr.house", client, houseId, description, entrancePosition, blipModel, pickupModel, hasInterior);
}
// ==========================================================================
diff --git a/scripts/server/command.js b/scripts/server/command.js
index 88d0a7bb..8c448de8 100644
--- a/scripts/server/command.js
+++ b/scripts/server/command.js
@@ -411,8 +411,10 @@ function loadCommands() {
npc: [
new CommandData("addnpc", createNPCCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Creates an NPC with the specified skin"),
new CommandData("delnpc", deleteNPCCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Deletes the nearest NPC"),
- //new CommandData("npcinfo", getNPCInfoCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Shows info about the nearest NPC"),
+ new CommandData("npcinfo", getNPCInfoCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Shows info about the nearest NPC"),
new CommandData("npcanim", setNPCAnimationCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Plays the specified animation on the nearest NPC"),
+ new CommandData("npcname", setNPCNameCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Sets the name of the nearest NPC"),
+ new CommandData("npclookatplr", toggleNPCLookAtClosestPlayerCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Makes the NPC look at the closest player"),
//new CommandData("npcrespawnall", respawnAllNPCsCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Respawns all NPCs"),
//new CommandData("npcrespawn", respawnNPCCommand, "", getStaffFlagValue("ManageNPCs"), true, false, "Respawns the nearest NPC"),
],
@@ -465,12 +467,12 @@ function loadCommands() {
new CommandData("dn", teleportDownCommand, "[distance in meters]", getStaffFlagValue("BasicModeration"), true, true, "Teleports you downward a certain distance in meters."),
new CommandData("int", playerInteriorCommand, " [interior id]", getStaffFlagValue("BasicModeration"), true, true, "Gets or sets a player's game interior."),
new CommandData("vw", playerVirtualWorldCommand, " [virtual world id]", getStaffFlagValue("BasicModeration"), true, true, "Gets or sets a player's virtual world/dimension."),
- new CommandData("addstaffflag", addPlayerStaffFlagCommand, " ", getStaffFlagValue("ManageAdmins"), true, true, "Gives a player a staff flag by name (this server only)."),
- new CommandData("delstaffflag", removePlayerStaffFlagCommand, " ", getStaffFlagValue("ManageAdmins"), true, true, "Takes a player's staff flag by name (this server only)."),
- new CommandData("getstaffflags", getPlayerStaffFlagsCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Shows a list of all staff flags a player has (this server only)."),
+ new CommandData("addplrstaffflag", addPlayerStaffFlagCommand, " ", getStaffFlagValue("ManageAdmins"), true, true, "Gives a player a staff flag by name (this server only)."),
+ new CommandData("delplrstaffflag", removePlayerStaffFlagCommand, " ", getStaffFlagValue("ManageAdmins"), true, true, "Takes a player's staff flag by name (this server only)."),
+ new CommandData("plrstaffflags", getPlayerStaffFlagsCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Shows a list of all staff flags a player has (this server only)."),
new CommandData("clearstaffflags", removePlayerStaffFlagsCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Removes all staff flags for a player (this server only)."),
- new CommandData("staffflags", getStaffFlagsCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Shows a list of all valid staff flag names."),
- new CommandData("stafftitle", setPlayerStaffTitleCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Sets a player's staff title."),
+ new CommandData("allstaffflags", getStaffFlagsCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Shows a list of all valid staff flag names."),
+ new CommandData("plrstafftitle", setPlayerStaffTitleCommand, "", getStaffFlagValue("ManageAdmins"), true, true, "Sets a player's staff title."),
new CommandData("givemoney", givePlayerMoneyCommand, " ", getStaffFlagValue("serverManager"), true, true),
new CommandData("nonrpname", forceCharacterNameChangeCommand, "", getStaffFlagValue("BasicModeration"), true, true, "Forces a player to change their current character's name."),
new CommandData("setname", setCharacterNameCommand, " ", getStaffFlagValue("BasicModeration"), true, true, "Changes a character's name directly."),
@@ -523,6 +525,8 @@ function loadCommands() {
utilities: [],
vehicle: [
new CommandData("addveh", createVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, false),
+ //new CommandData("spawnveh", createVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, false),
+ //new CommandData("createveh", createVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, false),
new CommandData("tempveh", createTemporaryVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, false),
new CommandData("delveh", deleteVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, false),
new CommandData("nearveh", getNearbyVehiclesCommand, "", getStaffFlagValue("None"), true, false),
@@ -543,9 +547,13 @@ function loadCommands() {
new CommandData("vehjob", setVehicleJobCommand, "[job id/name]", getStaffFlagValue("ManageVehicles"), true, true),
new CommandData("vehdelowner", removeVehicleOwnerCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
new CommandData("vehrank", setVehicleRankCommand, "", getStaffFlagValue("None"), true, true),
+ new CommandData("vehiclerank", setVehicleRankCommand, "", getStaffFlagValue("None"), true, true),
new CommandData("vehinfo", getVehicleInfoCommand, "", getStaffFlagValue("None"), true, true),
+ new CommandData("vehicleinfo", getVehicleInfoCommand, "", getStaffFlagValue("None"), true, true),
new CommandData("vehpark", toggleVehicleSpawnLockCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
-
+ new CommandData("parkveh", toggleVehicleSpawnLockCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
+ new CommandData("vehiclepark", toggleVehicleSpawnLockCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
+ new CommandData("parkvehicle", toggleVehicleSpawnLockCommand, "", getStaffFlagValue("ManageVehicles"), true, true),
new CommandData("vehrespawnall", respawnAllVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all vehicles (also respawns all traffic vehicles)"),
new CommandData("vehrespawnempty", respawnEmptyVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all empty/unoccupied vehicles"),
new CommandData("vehrespawnjob", respawnJobVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all job vehicles"),
@@ -555,7 +563,6 @@ function loadCommands() {
new CommandData("vehrespawnbiz", respawnBusinessVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all business-owned vehicles"),
new CommandData("vehrespawn", respawnVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns your current vehicle"),
new CommandData("vehreloadall", reloadAllVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Deletes and reloads all vehicles from database"),
-
new CommandData("carrespawnall", respawnAllVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all vehicles (also respawns all traffic vehicles)"),
new CommandData("carrespawnempty", respawnEmptyVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all empty/unoccupied vehicles"),
new CommandData("carrespawnjob", respawnJobVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all job vehicles"),
@@ -565,15 +572,34 @@ function loadCommands() {
new CommandData("carrespawnbiz", respawnBusinessVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns all business-owned vehicles"),
new CommandData("carrespawn", respawnVehicleCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Respawns your current vehicle"),
new CommandData("carreloadall", reloadAllVehiclesCommand, "", getStaffFlagValue("ManageVehicles"), true, true, "Deletes and reloads all vehicles from database"),
-
new CommandData("vehrent", rentVehicleCommand, "", getStaffFlagValue("None"), true, true, "Starts renting your current vehicle (if rentable)"),
+ new CommandData("rentveh", rentVehicleCommand, "", getStaffFlagValue("None"), true, true, "Starts renting your current vehicle (if rentable)"),
+ new CommandData("vehiclerent", rentVehicleCommand, "", getStaffFlagValue("None"), true, true, "Starts renting your current vehicle (if rentable)"),
+ new CommandData("rentvehicle", rentVehicleCommand, "", getStaffFlagValue("None"), true, true, "Starts renting your current vehicle (if rentable)"),
new CommandData("vehrentprice", setVehicleRentPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
new CommandData("vehbuyprice", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
+ new CommandData("vehiclebuyprice", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
+ new CommandData("vehprice", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
+ new CommandData("vehicleprice", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
+ new CommandData("rentpriceveh", setVehicleRentPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
+ new CommandData("buypriceveh", setVehicleBuyPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
+ new CommandData("stoprentveh", stopRentingVehicleCommand, "", getStaffFlagValue("None"), true, true, "Stops renting your vehicle"),
new CommandData("vehstoprent", stopRentingVehicleCommand, "", getStaffFlagValue("None"), true, true, "Stops renting your vehicle"),
+ new CommandData("vehiclerentprice", setVehicleRentPriceCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's rent price"),
+ new CommandData("vehiclestoprent", stopRentingVehicleCommand, "", getStaffFlagValue("None"), true, true, "Stops renting your vehicle"),
new CommandData("vehbuy", buyVehicleCommand, "", getStaffFlagValue("None"), true, true, "Purchases your vehicle"),
+ new CommandData("vehiclebuy", buyVehicleCommand, "", getStaffFlagValue("None"), true, true, "Purchases your vehicle"),
+ new CommandData("buyveh", buyVehicleCommand, "", getStaffFlagValue("None"), true, true, "Purchases your vehicle"),
+ new CommandData("buyvehicle", buyVehicleCommand, "", getStaffFlagValue("None"), true, true, "Purchases your vehicle"),
new CommandData("vehcolour", vehicleAdminColourCommand, " ", getStaffFlagValue("None"), true, true, "Sets a vehicle's colour"),
+ new CommandData("vehiclecolour", vehicleAdminColourCommand, " ", getStaffFlagValue("None"), true, true, "Sets a vehicle's colour"),
new CommandData("vehlivery", vehicleAdminLiveryCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's livery/paintjob"),
+ new CommandData("vehiclelivery", vehicleAdminLiveryCommand, "", getStaffFlagValue("None"), true, true, "Sets your vehicle's livery/paintjob"),
new CommandData("vehrepair", vehicleAdminRepairCommand, "", getStaffFlagValue("None"), true, true, "Repairs your vehicle"),
+ new CommandData("vehiclerepair", vehicleAdminRepairCommand, "", getStaffFlagValue("None"), true, true, "Repairs your vehicle"),
+ new CommandData("repairveh", vehicleAdminRepairCommand, "", getStaffFlagValue("None"), true, true, "Repairs your vehicle"),
+ new CommandData("repairvehicle", vehicleAdminRepairCommand, "", getStaffFlagValue("None"), true, true, "Repairs your vehicle"),
+
new CommandData("passenger", enterVehicleAsPassengerCommand, "", getStaffFlagValue("None"), true, true, "Enters a vehicle as passenger"),
],
};
@@ -799,7 +825,7 @@ function processPlayerCommand(command, params, client) {
if(!isConsole(client)) {
if(!doesPlayerHaveStaffPermission(client, getCommandRequiredPermissions(toLowerCase(command)))) {
logToConsole(LOG_WARN, `[VRR.Command] ${getPlayerDisplayForConsole(client)} attempted to use command, but failed (no permission): /${command} ${paramsDisplay}`);
- messagePlayerError(client, "CommandNoPermissions", `{ALTCOLOUR}/${toLowerCase(command)}{MAINCOLOUR}`);
+ messagePlayerError(client, getLocaleString(client, "CommandNoPermissions", `{ALTCOLOUR}/${toLowerCase(command)}{MAINCOLOUR}`));
return false;
}
}
diff --git a/scripts/server/config.js b/scripts/server/config.js
index 79b32068..34e0c931 100644
--- a/scripts/server/config.js
+++ b/scripts/server/config.js
@@ -201,9 +201,6 @@ function loadServerConfigFromId(tempServerId) {
function applyConfigToServer(tempServerConfig) {
logToConsole(LOG_INFO, "[VRR.Config]: Applying server config ...");
- getServerConfig().devServer = intToBool(toInteger(server.getCVar("vrr_devserver")));
- getServerConfig().testerOnly = intToBool(toInteger(server.getCVar("vrr_testeronly")));
-
logToConsole(LOG_DEBUG, "[VRR.Config]: Server config applied successfully!");
if(isTimeSupported()) {
diff --git a/scripts/server/const.js b/scripts/server/const.js
index 811f0aa5..adf23695 100644
--- a/scripts/server/const.js
+++ b/scripts/server/const.js
@@ -308,6 +308,7 @@ const VRR_2FA_STATE_SETUP_CODEFROMAPP = 3; // Waiting on player to enter c
const VRR_RESETPASS_STATE_NONE = 0; // None
const VRR_RESETPASS_STATE_CODEINPUT = 1; // Waiting on player to enter code sent via email
const VRR_RESETPASS_STATE_SETPASS = 2; // Waiting on player to enter new password
+const VRR_RESETPASS_STATE_EMAILCONFIRM = 3; // Waiting on player to enter their email to confirm it's correct
// NPC Trigger Condition Match Types
const VRR_NPC_COND_MATCH_NONE = 0; // None (invalid)
@@ -358,4 +359,13 @@ const VRR_GPS_TYPE_GAMELOC = 5; // Game Location
// Discord Webhook Types
const VRR_DISCORD_WEBHOOK_NONE = 0;
const VRR_DISCORD_WEBHOOK_LOG = 1;
-const VRR_DISCORD_WEBHOOK_ADMIN = 2;
\ No newline at end of file
+const VRR_DISCORD_WEBHOOK_ADMIN = 2;
+
+// NPC Owner Types
+const VRR_NPCOWNER_NONE = 0; // Not owned
+const VRR_NPCOWNER_PLAYER = 1; // Owned by a player (character/subaccount)
+const VRR_NPCOWNER_JOB = 2; // Owned by a job
+const VRR_NPCOWNER_CLAN = 3; // Owned by a clan
+const VRR_NPCOWNER_FACTION = 4; // Owned by a faction (not used at the moment)
+const VRR_NPCOWNER_PUBLIC = 5; // Public NPC. Anybody can do stuff with it.
+const VRR_NPCOWNER_BIZ = 6; // Owned by a business
\ No newline at end of file
diff --git a/scripts/server/economy.js b/scripts/server/economy.js
index 5531cf2d..e42479cb 100644
--- a/scripts/server/economy.js
+++ b/scripts/server/economy.js
@@ -41,7 +41,7 @@ function playerPayDay(client) {
grossIncome = grossIncome*2;
}
- let incomeTaxAmount = calculateIncomeTax(wealth);
+ let incomeTaxAmount = Math.round(calculateIncomeTax(wealth));
let netIncome = grossIncome-incomeTaxAmount;
diff --git a/scripts/server/event.js b/scripts/server/event.js
index d752bd59..0aced8c3 100644
--- a/scripts/server/event.js
+++ b/scripts/server/event.js
@@ -15,7 +15,35 @@ function initEventScript() {
// ===========================================================================
-function onInitialConnectionToServer(ipAddress, port) {
+function addAllEventHandlers() {
+ addEventHandler("onResourceStart", onResourceStart);
+ addEventHandler("onResourceStop", onResourceStop);
+ addEventHandler("onServerStop", onResourceStop);
+
+ addEventHandler("onProcess", onProcess);
+ addEventHandler("onEntityProcess", onEntityProcess);
+
+ addEventHandler("onPlayerConnect", onPlayerConnect);
+ addEventHandler("onPlayerJoin", onPlayerJoin);
+ addEventHandler("onPlayerJoined", onPlayerJoined);
+ addEventHandler("onPlayerChat", onPlayerChat);
+ addEventHandler("onPlayerQuit", onPlayerQuit);
+ addEventHandler("onElementStreamIn", onElementStreamIn);
+ addEventHandler("onElementStreamOut", onElementStreamOut);
+
+ addEventHandler("onPedSpawn", onPedSpawn);
+ addEventHandler("onPedEnterVehicle", onPedEnteringVehicle);
+ addEventHandler("onPedExitVehicle", onPedExitingVehicle);
+
+ addEventHandler("onPedEnteringVehicle", onPedEnteringVehicle);
+ addEventHandler("onPedExitingVehicle", onPedExitingVehicle);
+
+ //addEventHandler("OnPlayerCommand", onPlayerCommand);
+}
+
+// ===========================================================================
+
+function onPlayerConnect(event, ipAddress, port) {
logToConsole(LOG_INFO, `[VRR.Event] Client connecting (IP: ${ipAddress})`);
//if(isIpAddressBanned(ipAddress)) {
// messagePlayerError(client, "You are banned from this server!");
@@ -25,13 +53,17 @@ function onInitialConnectionToServer(ipAddress, port) {
// ===========================================================================
-function onPlayerJoin(client) {
+function onPlayerJoin(event, client) {
logToConsole(LOG_INFO, `[VRR.Event] Client ${getPlayerName(client)}[${getPlayerId(client)}] joining from ${getPlayerIP(client)}`);
if(isFadeCameraSupported()) {
fadeCamera(client, true, 1.0);
}
+ //if(isCustomCameraSupported()) {
+ // showConnectCameraToPlayer(client);
+ //}
+
let messageText = `👋 ${getPlayerName(client)} is connecting to the server ...`;
messageDiscordEventChannel(messageText);
@@ -45,13 +77,13 @@ function onPlayerJoin(client) {
// ===========================================================================
-function onPlayerJoined(client) {
+function onPlayerJoined(event, client) {
}
// ===========================================================================
-function onElementStreamIn(element, client) {
+function onElementStreamIn(event, element, client) {
//if(getPlayerDimension(client) != getElementDimension(element)) {
// event.preventDefault();
//}
@@ -66,13 +98,13 @@ function onElementStreamIn(element, client) {
// ===========================================================================
-function onElementStreamOut(element, client) {
+function onElementStreamOut(event, element, client) {
}
// ===========================================================================
-function onPlayerQuit(client, quitReasonId) {
+function onPlayerQuit(event, client, quitReasonId) {
logToConsole(LOG_INFO, `👋 Client ${getPlayerDisplayForConsole(client)} disconnected (${disconnectReasons[quitReasonId]}[${quitReasonId}])`);
updateConnectionLogOnQuit(client, quitReasonId);
@@ -94,21 +126,18 @@ function onPlayerQuit(client, quitReasonId) {
resetClientStuff(client);
getServerData().clients[getPlayerId(client)] = null;
}
-
- clearTemporaryVehicles();
- clearTemporaryPeds();
}
// ===========================================================================
-async function onPlayerChat(client, messageText) {
+async function onPlayerChat(event, client, messageText) {
processPlayerChat(client, messageText);
event.preventDefault();
}
// ===========================================================================
-function onProcess(deltaTime = 0) {
+function onProcess(event, deltaTime) {
updateServerGameTime();
//checkPlayerSpawning();
//checkPlayerPedState();
@@ -119,12 +148,12 @@ function onProcess(deltaTime = 0) {
// ===========================================================================
-function onEntityProcess(entity) {
+function onEntityProcess(event, entity) {
}
// ===========================================================================
-function onPedEnteringVehicle(ped, vehicle, seat) {
+function onPedEnteringVehicle(event, ped, vehicle, seat) {
if(ped.isType(ELEMENT_PLAYER)) {
let client = getClientFromPlayerElement(ped);
getPlayerData(client).pedState = VRR_PEDSTATE_ENTERINGVEHICLE;
@@ -155,7 +184,7 @@ function onPedEnteringVehicle(ped, vehicle, seat) {
// ===========================================================================
-function onPedExitingVehicle(ped, vehicle) {
+function onPedExitingVehicle(event, ped, vehicle) {
if(!getVehicleData(vehicle)) {
return false;
}
@@ -174,22 +203,22 @@ function onPedExitingVehicle(ped, vehicle) {
// ===========================================================================
-function onResourceStart(resource) {
+function onResourceStart(event, resource) {
logToConsole(LOG_WARN, `[VRR.Event] Resource ${resource.name} started!`);
- if(resource != thisResource) {
- messageAdmins(`{MAINCOLOUR}Resource {ALTCOLOUR}${resource.name}{MAINCOLOUR} started!`);
- }
+ //if(resource != thisResource) {
+ // messageAdmins(`{MAINCOLOUR}Resource {ALTCOLOUR}${resource.name}{MAINCOLOUR} started!`);
+ //}
}
// ===========================================================================
-function onResourceStop(resource) {
+function onResourceStop(event, resource) {
logToConsole(LOG_WARN, `[VRR.Event] Resource ${resource.name} stopped!`);
- if(resource != thisResource) {
- messageAdmins(`{MAINCOLOUR}Resource {ALTCOLOUR}${resource.name}{MAINCOLOUR} stopped!`);
- }
+ //if(resource != thisResource) {
+ // messageAdmins(`{MAINCOLOUR}Resource {ALTCOLOUR}${resource.name}{MAINCOLOUR} stopped!`);
+ //}
if(resource == thisResource) {
kickAllClients();
@@ -497,9 +526,6 @@ function onPlayerSpawn(client) {
//messagePlayerNormal(client, "This server is in early development and may restart at any time for updates.", getColourByName("orange"));
//messagePlayerNormal(client, "Please report any bugs using /bug and suggestions using /idea", getColourByName("yellow"));
- logToConsole(LOG_DEBUG, `[VRR.Event] Updating spawned state for ${getPlayerDisplayForConsole(client)} to true`);
- updatePlayerSpawnedState(client, true);
-
logToConsole(LOG_DEBUG, `[VRR.Event] Setting player interior for ${getPlayerDisplayForConsole(client)} to ${getPlayerCurrentSubAccount(client).interior}`);
setPlayerInterior(client, getPlayerCurrentSubAccount(client).interior);
@@ -599,12 +625,30 @@ function onPlayerSpawn(client) {
sendAllHousesToPlayer(client);
sendAllJobsToPlayer(client);
//sendAllVehiclesToPlayer(client);
-
requestPlayerPedNetworkId(client);
}
+ logToConsole(LOG_DEBUG, `[VRR.Event] Updating spawned state for ${getPlayerDisplayForConsole(client)} to true`);
+ updatePlayerSpawnedState(client, true);
+
getPlayerData(client).payDayTickStart = sdl.ticks;
+ // Stop playing intro music and any other radio
+ stopRadioStreamForPlayer(client);
+
+ // Start playing business/house radio if in one
+ let businessId = getPlayerBusiness(client);
+ let houseId = getPlayerHouse(client);
+ if(businessId != -1) {
+ if(getBusinessData(businessId).streamingRadioStation != -1) {
+ playRadioStreamForPlayer(client, getRadioStationData(getBusinessData(businessId).streamingRadioStation).url, true, getPlayerStreamingRadioVolume(client), null);
+ }
+ } else if(houseId != -1) {
+ if(getHouseData(houseId).streamingRadioStation != -1) {
+ playRadioStreamForPlayer(client, getRadioStationData(getHouseData(houseId).streamingRadioStation).url, true, getPlayerStreamingRadioVolume(client), null);
+ }
+ }
+
messageDiscordEventChannel(`🧍 ${getPlayerName(client)} spawned as ${getCharacterFullName(client)}`);
}
diff --git a/scripts/server/gui.js b/scripts/server/gui.js
index fa814c6c..686a8e13 100644
--- a/scripts/server/gui.js
+++ b/scripts/server/gui.js
@@ -189,7 +189,8 @@ function playerPromptAnswerYes(client) {
getHouseData(houseId).needsSaved = true;
updateHousePickupLabelData(houseId);
- messagePlayerSuccess(client, `You are now the owner of {houseGreen}${getHouseData(houseId).description}`);
+ messageDiscordEventChannel(`🏘️ ${getCharacterFullName(client)} is now the owner of *${getHouseData(houseId).description}*!`);
+ messagePlayerSuccess(client, `🏘️ You are now the owner of {houseGreen}${getHouseData(houseId).description}`);
break;
}
@@ -206,7 +207,7 @@ function playerPromptAnswerYes(client) {
}
if(getPlayerCurrentSubAccount(client).cash < getBusinessData(businessId).buyPrice) {
- messagePlayerError(client, getLocaleString(client, "HousePurchaseNotEnoughMoney"));
+ messagePlayerError(client, getLocaleString(client, "BusinessPurchaseNotEnoughMoney"));
return false;
}
@@ -216,7 +217,8 @@ function playerPromptAnswerYes(client) {
getBusinessData(businessId).needsSaved = true;
updateBusinessPickupLabelData(businessId);
- messagePlayerSuccess(client, `You are now the owner of {businessBlue}${getBusinessData(businessId).name}`);
+ messageDiscordEventChannel(`🏢 ${getCharacterFullName(client)} is now the owner of *${getBusinessData(businessId).name}*!`);
+ messagePlayerSuccess(client, `🏢 You are now the owner of {businessBlue}${getBusinessData(businessId).name}`);
break;
}
@@ -255,12 +257,6 @@ function playerToggledGUI(client) {
// ===========================================================================
-function showPlayerChangePasswordGUI(client) {
- sendNetworkEventToPlayer("vrr.changePassword", client);
-}
-
-// ===========================================================================
-
function showPlayerTwoFactorAuthenticationGUI(client) {
sendNetworkEventToPlayer("vrr.2fa", client);
}
diff --git a/scripts/server/house.js b/scripts/server/house.js
index 5ec8be44..24e4c318 100644
--- a/scripts/server/house.js
+++ b/scripts/server/house.js
@@ -841,10 +841,6 @@ function createAllHouseBlips() {
// ===========================================================================
function createHouseEntrancePickup(houseId) {
- if(!areServerElementsSupported()) {
- return false;
- }
-
if(!getServerConfig().createHousePickups) {
return false;
}
@@ -869,16 +865,25 @@ function createHouseEntrancePickup(houseId) {
pickupModelId = getHouseData(houseId).entrancePickupModel;
}
- let entrancePickup = createGamePickup(pickupModelId, getHouseData(houseId).entrancePosition, getGameConfig().pickupTypes[getGame()].house);
- if(entrancePickup != null) {
- setElementOnAllDimensions(entrancePickup, false);
- setElementDimension(entrancePickup, getHouseData(houseId).entranceDimension);
- setElementStreamInDistance(entrancePickup, getGlobalConfig().housePickupStreamInDistance);
- setElementStreamOutDistance(entrancePickup, getGlobalConfig().housePickupStreamOutDistance);
- setElementTransient(entrancePickup, false);
+ if(areServerElementsSupported()) {
+ let entrancePickup = createGamePickup(pickupModelId, getHouseData(houseId).entrancePosition, getGameConfig().pickupTypes[getGame()].house);
+ if(entrancePickup != null) {
+ setElementOnAllDimensions(entrancePickup, false);
+ setElementDimension(entrancePickup, getHouseData(houseId).entranceDimension);
+ setElementStreamInDistance(entrancePickup, getGlobalConfig().housePickupStreamInDistance);
+ setElementStreamOutDistance(entrancePickup, getGlobalConfig().housePickupStreamOutDistance);
+ setElementTransient(entrancePickup, false);
- getHouseData(houseId).entrancePickup = entrancePickup;
- updateHousePickupLabelData(houseId);
+ getHouseData(houseId).entrancePickup = entrancePickup;
+ updateHousePickupLabelData(houseId);
+ }
+ } else {
+ let pickupModelId = getGameConfig().pickupModels[getGame()].House;
+
+ if(houseData.entrancePickupModel != 0) {
+ pickupModelId = houseData.entrancePickupModel;
+ }
+ sendHouseToPlayer(null, houseId, houseId.description, houseId.entrancePosition, blipModelId, pickupModelId, houseId.hasInterior);
}
}
@@ -912,7 +917,7 @@ function createHouseEntranceBlip(houseId) {
blipModelId = getHouseData(houseId).entranceBlipModel;
}
- let entranceBlip = createGameBlip(houseData.entrancePosition, blipModelId, getColourByName("houseGreen"));
+ let entranceBlip = createGameBlip(houseData.entrancePosition, blipModelId, 1, getColourByName("houseGreen"));
if(entranceBlip != null) {
if(houseData.exitDimension != -1) {
setElementDimension(entranceBlip, houseData.entranceDimension);
diff --git a/scripts/server/item.js b/scripts/server/item.js
index ba3619e1..514fa01c 100644
--- a/scripts/server/item.js
+++ b/scripts/server/item.js
@@ -862,6 +862,8 @@ function playerUseItem(client, hotBarSlot) {
if(getItemData(itemIndex).value <= 0) {
destroyItem(itemIndex);
}
+ } else {
+ messagePlayerError(client, getLocaleString(client, "VehicleRepairFailedTooFar"));
}
break;
}
@@ -1374,8 +1376,11 @@ function setAllItemTypeDataIndexes() {
function cacheAllGroundItems() {
clearArray(getServerData().groundItemCache);
- getServerData().groundItemCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_GROUND);
- //getServerData().groundPlantCache = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_PLANT);
+ for(let i in getServerData().items) {
+ if(getServerData().items[i].ownerType == VRR_ITEM_OWNER_GROUND) {
+ getServerData().groundItemCache.push(i);
+ }
+ }
}
// ===========================================================================
@@ -1411,11 +1416,19 @@ function cachePlayerHotBarItems(client) {
return false;
}
- clearArray(getPlayerData(client).hotBarItems);
- getPlayerData(client).hotBarItems = getServerData().items.filter(item => item.ownerType == VRR_ITEM_OWNER_PLAYER && item.ownerId == getPlayerCurrentSubAccount(client).databaseId);
+ for(let i = 0 ; i < 9 ; i++) {
+ getPlayerData(client).hotBarItems[i] = -1;
+ }
- if(getPlayerData(client).hotBarItems.length < getGlobalConfig().maxPlayerItemSlots) {
- getPlayerData(client).hotBarItems.concat(Array(getGlobalConfig().maxPlayerItemSlots-getPlayerData(client).hotBarItems.length).fill(-1));
+ for(let i in getServerData().items) {
+ if(getItemData(i).ownerType == VRR_ITEM_OWNER_PLAYER) {
+ if(getItemData(i).ownerId == getPlayerCurrentSubAccount(client).databaseId) {
+ let firstSlot = getPlayerFirstEmptyHotBarSlot(client);
+ if(firstSlot != -1) {
+ getPlayerData(client).hotBarItems[firstSlot] = i;
+ }
+ }
+ }
}
}
@@ -1575,18 +1588,20 @@ function getBestItemToTake(client, slot) {
*
*/
function listPlayerInventoryCommand(command, params, client) {
- let targetClient = client;
- if(doesPlayerHaveStaffPermission(client, getStaffFlagValue("BasicModeration"))) {
- if(!areParamsEmpty(client)) {
- if(targetClient == false) {
- sendMessageToPlayer(client, getLocaleString(client, "InvalidPlayer"));
- return false;
- }
- targetClient = getPlayerFromParams(params);
- }
- }
- showPlayerInventoryToPlayer(client, targetClient);
- //showPlayerInventoryToPlayer(client, client);
+ //let targetClient = client;
+ //if(!areParamsEmpty(client)) {
+ // if(doesPlayerHaveStaffPermission(client, getStaffFlagValue("BasicModeration"))) {
+ // if(targetClient == false) {
+ // sendMessageToPlayer(client, getLocaleString(client, "InvalidPlayer"));
+ // return false;
+ // }
+ //
+ // targetClient = getPlayerFromParams(params);
+ // }
+ //}
+ //showPlayerInventoryToPlayer(client, targetClient);
+
+ showPlayerInventoryToPlayer(client, client);
}
// ===========================================================================
@@ -1707,6 +1722,7 @@ function getItemData(itemId) {
if(typeof getServerData().items[itemId] != "undefined") {
return getServerData().items[itemId];
}
+
return false;
}
@@ -1717,7 +1733,11 @@ function getItemData(itemId) {
* @return {ItemTypeData} The item type's data (class instance)
*/
function getItemTypeData(itemTypeId) {
- return getServerData().itemTypes[itemTypeId];
+ if(typeof getServerData().itemTypes[itemTypeId] != "undefined") {
+ return getServerData().itemTypes[itemTypeId];
+ }
+
+ return false;
}
// ===========================================================================
@@ -2268,7 +2288,7 @@ function showItemInventoryToPlayer(client, itemId) {
// ===========================================================================
-function showPlayerInventoryToPlayer(client, targetClient) {
+function showPlayerInventoryToPlayer(showToClient, targetClient) {
resyncWeaponItemAmmo(targetClient);
let itemDisplay = [];
for(let i in getPlayerData(targetClient).hotBarItems) {
@@ -2279,19 +2299,24 @@ function showPlayerInventoryToPlayer(client, targetClient) {
if(getPlayerData(targetClient).hotBarItems[i] == -1) {
itemDisplay.push(`{MAINCOLOUR}${toInteger(i)+1}: ${colour}(Empty)`);
} else {
- itemDisplay.push(`{MAINCOLOUR}${toInteger(i)+1}: ${colour}${getItemTypeData(getItemData(getPlayerData(targetClient).hotBarItems[i]).itemTypeIndex).name}`);
+ let itemTypeData = getItemTypeData(getItemData(getPlayerData(targetClient).hotBarItems[i]).itemTypeIndex);
+ if(itemTypeData != false) {
+ itemDisplay.push(`{MAINCOLOUR}${toInteger(i)+1}: ${colour}${itemTypeData.name}`);
+ } else {
+ itemDisplay.push(`{MAINCOLOUR}${toInteger(i)+1}: ${colour}(Empty)`);
+ }
}
}
- if(client == targetClient) {
- messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderSelfItemList")));
+ if(showToClient == targetClient) {
+ messagePlayerNormal(showToClient, makeChatBoxSectionHeader(getLocaleString(showToClient, "HeaderSelfItemList")));
} else {
- messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPlayerItemList", getCharacterFullName(targetClient))));
+ messagePlayerNormal(showToClient, makeChatBoxSectionHeader(getLocaleString(showToClient, "HeaderPlayerItemList", getCharacterFullName(targetClient))));
}
let chunkedList = splitArrayIntoChunks(itemDisplay, 5);
for(let i in chunkedList) {
- messagePlayerNormal(client, chunkedList[i].join(`{MAINCOLOUR} • `), COLOUR_WHITE);
+ messagePlayerNormal(showToClient, chunkedList[i].join(`{MAINCOLOUR} • `), COLOUR_WHITE);
}
}
diff --git a/scripts/server/job.js b/scripts/server/job.js
index f8d571e7..d35664be 100644
--- a/scripts/server/job.js
+++ b/scripts/server/job.js
@@ -264,16 +264,7 @@ function createAllJobBlips() {
logToConsole(LOG_DEBUG, `[VRR.Job] Spawning all job location blips ...`);
for(let i in getServerData().jobs) {
for(let j in getServerData().jobs[i].locations) {
- getServerData().jobs[i].locations[j].blip = game.createBlip((getServerData().jobs[i].blipModel!=0) ? getServerData().jobs[i].blipModel : 0, getServerData().jobs[i].locations[j].position, 2, getColourByName("yellow"));
- if(getGlobalConfig().jobBlipStreamInDistance == -1 || getGlobalConfig().jobBlipStreamOutDistance == -1) {
- getServerData().jobs[i].locations[j].blip.netFlags.distanceStreaming = false;
- } else {
- setElementStreamInDistance(getServerData().jobs[i].locations[j].blip, getGlobalConfig().jobBlipStreamInDistance);
- setElementStreamOutDistance(getServerData().jobs[i].locations[j].blip, getGlobalConfig().jobBlipStreamOutDistance);
- }
-
- //addToWorld(getServerData().jobs[i].locations[j].blip);
- logToConsole(LOG_DEBUG, `[VRR.Job] Job '${getServerData().jobs[i].name}' location blip ${j} spawned!`);
+ createJobLocationBlip(i, j);
}
}
logToConsole(LOG_DEBUG, `[VRR.Job] All job location blips spawned!`);
@@ -496,7 +487,7 @@ function startWorkingCommand(command, params, client) {
}
messagePlayerSuccess(client, `💼 You are now working for the {jobYellow}${jobData.name}{MAINCOLOUR} job`);
- messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} is now working for the {jobYellow}${jobData.name}{MAINCOLOUR} job`);
+ messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} started working for the {jobYellow}${jobData.name}{MAINCOLOUR} job`);
startWorking(client);
//messagePlayerNewbieTip(client, `Enter a job vehicle to get started!`);
@@ -650,6 +641,7 @@ function stopWorking(client) {
restorePlayerJobLockerItems(client);
respawnJobVehicle(client);
sendPlayerStopJobRoute(client);
+ messageDiscordEventChannel(`💼 ${getPlayerName(client)} has stopped working as a ${getJobData(jobId).name}`);
let jobId = getPlayerJob(client);
switch(getJobType(jobId)) {
@@ -935,6 +927,7 @@ function quitJob(client) {
stopWorking(client);
getPlayerCurrentSubAccount(client).job = 0;
sendPlayerJobType(client, 0);
+ updateJobBlipsForPlayer(client);
}
// ===========================================================================
@@ -942,6 +935,7 @@ function quitJob(client) {
function takeJob(client, jobId) {
getPlayerCurrentSubAccount(client).job = getJobData(jobId).databaseId;
sendPlayerJobType(client, getJobData(jobId).databaseId);
+ updateJobBlipsForPlayer(client);
}
// ===========================================================================
@@ -1760,7 +1754,7 @@ function startJobRoute(client, forceRoute = -1) {
return false;
}
- logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} is starting job route ${jobRoute} for job ${jobId}`);
+ logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} is starting job route ${getJobRouteData(jobId, jobRoute).name} (${jobRoute}) for the ${getJobData(jobId).name} (${jobId}) job`);
getPlayerData(client).jobRoute = jobRoute;
getPlayerData(client).jobRouteLocation = 0;
@@ -1770,6 +1764,12 @@ function startJobRoute(client, forceRoute = -1) {
getPlayerVehicle(client).colour2 = getJobRouteData(jobId, jobRoute).vehicleColour2;
messagePlayerNormal(client, replaceJobRouteStringsInMessage(getJobRouteData(jobId, jobRoute).startMessage, jobId, jobRoute));
+
+ // Don't announce routes that an admin just created
+ if(forceRoute == -1) {
+ messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} started the ${getJobRouteData(jobId, jobRoute).name} route for the ${getJobData(jobId).name} job`);
+ }
+
if(getJobRouteData(jobId, jobRoute).locations.length > 0) {
showCurrentJobLocation(client);
} else {
@@ -1781,9 +1781,10 @@ function startJobRoute(client, forceRoute = -1) {
function stopJobRoute(client, successful = false, alertPlayer = true) {
let jobId = getPlayerJob(client);
+ let routeId = getPlayerJobRoute(client);
if(alertPlayer) {
- messagePlayerAlert(client, replaceJobRouteStringsInMessage(getJobRouteData(jobId, getPlayerJobRoute(client)).finishMessage), jobId, getPlayerJobRoute(client));
+ messagePlayerAlert(client, replaceJobRouteStringsInMessage(getJobRouteData(jobId, routeId).finishMessage, jobId, routeId));
}
if(successful == true) {
@@ -1791,6 +1792,8 @@ function stopJobRoute(client, successful = false, alertPlayer = true) {
return false;
}
+ messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} failed to finish the ${getJobRouteData(jobId, getPlayerJobRoute(client)).name} route for the ${getJobData(jobId).name} job and didn't earn anything.`);
+
stopReturnToJobVehicleCountdown(client);
sendPlayerStopJobRoute(client);
respawnVehicle(getPlayerData(client).jobRouteVehicle);
@@ -2416,24 +2419,46 @@ function createJobLocationBlip(jobId, locationId) {
let tempJobData = getJobData(jobId);
- if(getJobData(jobId).blipModel != -1) {
- let blipModelId = getGameConfig().blipSprites[getGame()].Job;
+ if(getJobData(jobId).blipModel == -1) {
+ return false;
+ }
- if(getJobData(jobId).blipModel != 0) {
- blipModelId = getJobData(jobId).blipModel;
- }
+ let blipModelId = getGameConfig().blipSprites[getGame()].Job;
- if(areServerElementsSupported()) {
- let blip = createGameBlip(tempJobData.locations[locationId].position, blipModelId, getColourByType("jobYellow"));
- if(blip != false) {
- tempJobData.locations[locationId].blip = blip;
+ if(getJobData(jobId).blipModel != 0) {
+ blipModelId = getJobData(jobId).blipModel;
+ }
+
+ if(areServerElementsSupported()) {
+ let blip = createGameBlip(tempJobData.locations[locationId].position, blipModelId, 1, getColourByName("yellow"));
+ if(blip != false) {
+ tempJobData.locations[locationId].blip = blip;
+
+ if(getGlobalConfig().jobBlipStreamInDistance == -1 || getGlobalConfig().jobBlipStreamOutDistance == -1) {
+ blip.netFlags.distanceStreaming = false;
+ } else {
+ setElementStreamInDistance(getServerData().jobs[i].locations[j].blip, getGlobalConfig().jobBlipStreamInDistance);
+ setElementStreamOutDistance(getServerData().jobs[i].locations[j].blip, getGlobalConfig().jobBlipStreamOutDistance);
}
+
setElementOnAllDimensions(blip, false);
setElementDimension(blip, tempJobData.locations[locationId].dimension);
- addToWorld(blip);
- } else {
- sendJobToPlayer(null, jobId, tempJobData.name, tempJobData.locations[locationId].position, blipModelId);
+
+ let clients = getClients();
+ for(let i in clients) {
+ if(getPlayerJob(client) == false) {
+ showElementForPlayer(blip, clients[i]);
+ } else {
+ if(getPlayerJob(clients[i]) == getServerData().jobs[i].databaseId) {
+ showElementForPlayer(blip, clients[i]);
+ } else {
+ hideElementForPlayer(blip, clients[i]);
+ }
+ }
+ }
}
+ } else {
+ sendJobToPlayer(null, jobId, tempJobData.name, tempJobData.locations[locationId].position, blipModelId);
}
}
@@ -3000,6 +3025,7 @@ function finishSuccessfulJobRoute(client) {
let payout = toInteger(applyServerInflationMultiplier(jobRouteData.pay));
getPlayerData(client).payDayAmount = getPlayerData(client).payDayAmount + payout;
+ messageDiscordEventChannel(`💼 ${getCharacterFullName(client)} finished the ${getJobRouteData(jobId, getPlayerJobRoute(client)).name} route for the ${getJobData(jobId).name} job and earned $${getJobRouteData(jobId, jobRouteId).pay}!`);
messagePlayerSuccess(client, replaceJobRouteStringsInMessage(jobRouteData.finishMessage, jobId, jobRouteData.index));
stopReturnToJobVehicleCountdown(client);
@@ -3068,4 +3094,18 @@ function replaceJobRouteStringsInMessage(messageText, jobId, jobRouteId) {
return messageText;
}
+// ===========================================================================
+
+function updateJobBlipsForPlayer(client) {
+ for(let i in getServerData().jobs) {
+ for(let j in getServerData().jobs[i].locations) {
+ if(getPlayerJob(client) == 0 || getPlayerJob(client) == i) {
+ showElementForPlayer(getServerData().jobs[i].locations[j].blip, client);
+ } else {
+ hideElementForPlayer(getServerData().jobs[i].locations[j].blip, client);
+ }
+ }
+ }
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/keybind.js b/scripts/server/keybind.js
index c2a37cfd..3dfaf3ec 100644
--- a/scripts/server/keybind.js
+++ b/scripts/server/keybind.js
@@ -89,9 +89,9 @@ function addPlayerKeyBind(client, keys, command, params, tempKey = false) {
// ===========================================================================
function removePlayerKeyBind(client, keyId) {
- if(isPlayerLoggedIn(client)) {
- quickDatabaseQuery(`DELETE FROM acct_hotkey WHERE acct_hotkey_acct = ${getPlayerData(client).accountData.databaseId} AND acct_hotkey_key = ${keyId}`);
- }
+ //if(isPlayerLoggedIn(client)) {
+ // quickDatabaseQuery(`DELETE FROM acct_hotkey WHERE acct_hotkey_acct = ${getPlayerData(client).accountData.databaseId} AND acct_hotkey_key = ${keyId}`);
+ //}
//for(let i in getPlayerData(client).keyBinds) {
// if(getPlayerData(client).keyBinds[i].key == keyId) {
diff --git a/scripts/server/messaging.js b/scripts/server/messaging.js
index 9e17cdfc..94c91dee 100644
--- a/scripts/server/messaging.js
+++ b/scripts/server/messaging.js
@@ -253,3 +253,13 @@ function messagePlayerHelpContent(client, messageString) {
}
// ===========================================================================
+
+function messagePlayersInRace(raceId, message) {
+ for(let i in clients) {
+ if(getPlayerRace(clients[i]) == raceId) {
+ messagePlayerNormal(clients[i], message);
+ }
+ }
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/misc.js b/scripts/server/misc.js
index d828993e..1ae25e1a 100644
--- a/scripts/server/misc.js
+++ b/scripts/server/misc.js
@@ -301,18 +301,21 @@ function getPlayerInfoCommand(command, params, client) {
let clan = (getPlayerCurrentSubAccount(targetClient).clan != 0) ? `{ALTCOLOUR}${getClanData(getClanIdFromDatabaseId(getPlayerCurrentSubAccount(targetClient).clan)).name}[${getPlayerCurrentSubAccount(targetClient).clan}] (Rank: ${getClanRankData(getPlayerCurrentSubAccount(targetClient).clan, getPlayerCurrentSubAccount(targetClient).clanRank).name}[Level: ${getClanRankData(getPlayerCurrentSubAccount(targetClient).clan, getPlayerCurrentSubAccount(targetClient).clanRank).level}, DBID: ${getClanRankData(getPlayerCurrentSubAccount(targetClient).clan, getPlayerCurrentSubAccount(targetClient).clanRank).databaseId}` : `(None)`;
let job = (getPlayerCurrentSubAccount(targetClient).job != 0) ? `{ALTCOLOUR}${getJobData(getJobIdFromDatabaseId(getPlayerCurrentSubAccount(targetClient).job)).name}[${getPlayerCurrentSubAccount(targetClient).job}] (Rank: ${getPlayerCurrentSubAccount(targetClient).jobRank})` : `(None)`;
- let stats = [
- `{MAINCOLOUR}Account: {ALTCOLOUR}${getPlayerData(targetClient).accountData.name}[${getPlayerData(targetClient).accountData.databaseId}]`,
- `{MAINCOLOUR}Character: {ALTCOLOUR}${getCharacterFullName(targetClient)}[${getPlayerCurrentSubAccount(targetClient).databaseId}]`,
- `{MAINCOLOUR}Connected: {ALTCOLOUR}${getTimeDifferenceDisplay(getCurrentUnixTimestamp(), getPlayerData(targetClient).connectTime)} ago`,
- `{MAINCOLOUR}Registered: ${getPlayerData(targetClient).accountData.registerDate}`,
- `{MAINCOLOUR}Game Version: {ALTCOLOUR}${targetClient.gameVersion}`,
- `{MAINCOLOUR}Client Version: {ALTCOLOUR}${getPlayerData(targetClient).clientVersion}`,
- `{MAINCOLOUR}Skin: {ALTCOLOUR}${getSkinNameFromModel(getPlayerCurrentSubAccount(targetClient).skin)}[${getPlayerCurrentSubAccount(targetClient).skin}]`,
- `{MAINCOLOUR}Clan: {ALTCOLOUR}${clan}`,
- `{MAINCOLOUR}Job: {ALTCOLOUR}${job}`,
+ let tempStats = [
+ ["Account", `${getPlayerData(targetClient).accountData.name}[${getPlayerData(targetClient).accountData.databaseId}]`],
+ ["Character", `${getCharacterFullName(targetClient)}[${getPlayerCurrentSubAccount(targetClient).databaseId}]`],
+ ["Connected", `${getTimeDifferenceDisplay(getCurrentUnixTimestamp(), getPlayerData(targetClient).connectTime)} ago`],
+ ["Registered", `${getPlayerData(targetClient).accountData.registerDate}`],
+ ["Game Version", `${targetClient.gameVersion}`],
+ ["Client Version", `${getPlayerData(targetClient).clientVersion}`],
+ ["Skin", `${getSkinNameFromModel(getPlayerCurrentSubAccount(targetClient).skin)}[${getPlayerCurrentSubAccount(targetClient).skin}]`],
+ ["Clan", `${clan}`],
+ ["Job", `${job}`],
+ ["Cash", `${getPlayerCurrentSubAccount(client).cash}`],
]
+ let stats = tempStats.map(stat => `{MAINCOLOUR}${stat[0]}: {ALTCOLOUR}${stat[1]}{MAINCOLOUR}`);
+
let chunkedList = splitArrayIntoChunks(stats, 6);
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
diff --git a/scripts/server/native/connected-nativeclass.js b/scripts/server/native/connected-nativeclass.js
deleted file mode 100644
index 0e681846..00000000
--- a/scripts/server/native/connected-nativeclass.js
+++ /dev/null
@@ -1,1047 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: connected.js
-// DESC: Provides wrapped natives for GTA Connected and Mafia Connected mods
-// TYPE: Server (JavaScript)
-// ===========================================================================
-
-class CustomNatives {
- getPlayerPosition(client) {
- if(!areServerElementsSupported()) {
- return getPlayerData(client).syncPosition;
- } else {
- if(getPlayerPed(client) != null) {
- return getPlayerPed(client).position;
- }
- }
- };
-
- static setPlayerPosition(client, position) {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s position to ${position.x}, ${position.y}, ${position.z}`);
- sendPlayerSetPosition(client, position);
- }
-
- static getPlayerHeading(client) {
- if(!areServerElementsSupported()) {
- return getPlayerData(client).syncHeading;
- } else {
- if(getPlayerPed(client) != null) {
- return getPlayerPed(client).heading;
- }
- }
- }
- static setPlayerHeading(client, heading) {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s heading to ${heading}`);
- sendPlayerSetHeading(client, heading);
- }
-
- static getPlayerVehicle(client) {
- if(!areServerElementsSupported()) {
- return getPlayerData().syncVehicle;
- } else {
- if(getPlayerPed(client).vehicle) {
- return getPlayerPed(client).vehicle;
- }
- }
- return false;
- }
- static getPlayerDimension(client) {
- if(!areServerElementsSupported()) {
- return getPlayerData(client).syncDimension;
- } else {
- if(getPlayerPed(client) != null) {
- return getPlayerPed(client).dimension;
- }
- }
- }
- static getPlayerInterior(client) {
- return getPlayerCurrentSubAccount(client).interior || 0;
- }
-
- static setPlayerDimension(client, dimension) {
- logToConsole(LOG_VERBOSE, `Setting ${getPlayerDisplayForConsole(client)}'s dimension to ${dimension}`);
- if(!areServerElementsSupported()) {
- getPlayerData(client).syncDimension = dimension;
- } else {
- if(getPlayerPed(client) != null) {
- getPlayerPed(client).dimension = dimension;
- }
- }
- }
-
- static setPlayerInterior(client, interior) {
- logToConsole(LOG_VERBOSE, `Setting ${getPlayerDisplayForConsole(client)}'s interior to ${interior}`);
- sendPlayerSetInterior(client, interior);
- if(isPlayerLoggedIn(client) && isPlayerSpawned(client)) {
- getPlayerCurrentSubAccount(client).interior = interior;
- }
- }
-
- static isPlayerInAnyVehicle(client) {
- if(!areServerElementsSupported()) {
- return (getPlayerData().syncVehicle != null);
- } else {
- return (getPlayerPed(client).vehicle != null);
- }
- }
-
- static getPlayerVehicleSeat(client) {
- if(!isPlayerInAnyVehicle(client)) {
- return false;
- }
-
- if(!areServerElementsSupported()) {
- return getPlayerData().syncVehicleSeat;
- } else {
- for(let i = 0 ; i <= 8 ; i++) {
- if(getPlayerVehicle(client).getOccupant(i) == getPlayerPed(client)) {
- return i;
- }
- }
- }
-
- return false;
- }
-
- static isPlayerSpawned(client) {
- return getPlayerData(client).spawned;
- }
-
- static getVehiclePosition(vehicle) {
- return vehicle.position;
- }
-
- static getVehicleHeading(vehicle) {
- return vehicle.heading;
- }
-
- static setVehicleHeading(vehicle, heading) {
- if(getGame() == VRR_GAME_GTA_IV) {
- return sendNetworkEventToPlayer("vrr.vehPosition", null, getVehicleForNetworkEvent(vehicle), heading);
- }
- return vehicle.heading = heading;
- }
-
- static getElementTransient(element) {
- if(typeof element.transient != "undefined") {
- return element.transient;
- }
- return false;
- }
-
- static setElementTransient(element, state) {
- if(typeof element.transient != "undefined") {
- element.transient = state;
- return true;
- }
- return false;
- }
-
- static getVehicleSyncer(vehicle) {
- return getElementSyncer(vehicle);
- }
-
- static getVehicleForNetworkEvent(vehicle) {
- if(getGame() == VRR_GAME_GTA_IV) {
- if(getVehicleData(vehicle).ivNetworkId != -1) {
- return getVehicleData(vehicle).ivNetworkId;
- }
- return -1;
- }
- return vehicle.id;
- }
-
- static deleteGameElement(element) {
- try {
- if(element != null) {
- destroyElement(element);
- return true;
- }
- } catch(error) {
- return false;
- }
- }
-
- static isPlayerInFrontVehicleSeat(client) {
- return (getPlayerVehicleSeat(client) == 0 || getPlayerVehicleSeat(client) == 1);
- }
-
- static removePlayerFromVehicle(client) {
- logToConsole(LOG_DEBUG, `Removing ${getPlayerDisplayForConsole(client)} from their vehicle`);
- sendPlayerRemoveFromVehicle(client);
- return true;
- }
-
- static setPlayerSkin(client, skinIndex) {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s skin to ${getGameConfig().skins[getGame()][skinIndex][0]} (Index: ${skinIndex}, Name: ${getGameConfig().skins[getGame()][skinIndex][1]})`);
- if(getGame() == VRR_GAME_GTA_IV) {
- triggerNetworkEvent("vrr.localPlayerSkin", client, getGameConfig().skins[getGame()][skinIndex][0]);
- } else {
- getPlayerPed(client).modelIndex = getGameConfig().skins[getGame()][skinIndex][0];
- }
- }
-
- static getPlayerSkin(client) {
- return getSkinIndexFromModel(client.player.modelIndex);
- }
-
- static setPlayerHealth(client, health) {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s health to ${health}`);
- sendPlayerSetHealth(client, health);
- getServerData(client).health = health;
- }
-
- static getPlayerHealth(client) {
- return getPlayerData(client).health;
- }
-
- static setPlayerArmour(client, armour) {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s armour to ${armour}`);
- sendPlayerSetArmour(client, armour);
- //client.player.armour = armour;
- }
-
- static getPlayerArmour(client) {
- if(areServerElementsSupported(client)) {
- return getPlayerPed(client).armour;
- } else {
- return getPlayerData(client).syncArmour;
- }
- }
-
- static setPlayerCash(client, amount) {
- if(client == null) {
- return false;
- }
-
- if(isNaN(amount)) {
- return false;
- }
-
- getPlayerCurrentSubAccount(client).cash = toInteger(amount);
- updatePlayerCash(client);
- }
-
- static givePlayerCash(client, amount) {
- if(client == null) {
- return false;
- }
-
- if(isNaN(amount)) {
- return false;
- }
-
- getPlayerCurrentSubAccount(client).cash = getPlayerCurrentSubAccount(client).cash + toInteger(amount);
- updatePlayerCash(client);
- }
-
- static takePlayerCash(client, amount) {
- if(client == null) {
- return false;
- }
-
- if(isNaN(amount)) {
- return false;
- }
-
- getPlayerCurrentSubAccount(client).cash = getPlayerCurrentSubAccount(client).cash - toInteger(amount);
- updatePlayerCash(client);
- }
-
- static disconnectPlayer(client) {
- logToConsole(LOG_DEBUG, `Disconnecting (kicking) ${getPlayerDisplayForConsole(client)}`);
- disconnectPlayer(client);
- return false;
- }
-
- static getElementSyncer(element) {
- return getClients()[element.syncer];
- }
-
- static getPlayerWeaponAmmo(client) {
- return getPlayerPed(client).weaponAmmunition;
- }
-
- static setPlayerVelocity(client, velocity) {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s velocity to ${velocity.x}, ${velocity.y}, ${velocity.z}`);
- if(typeof getPlayerPed(client).velocity != "undefined") {
- getPlayerPed(client).velocity = velocity;
- }
- }
-
- static getPlayerVelocity(client) {
- if(typeof getPlayerPed(client).velocity != "undefined") {
- return getPlayerPed(client).velocity;
- }
- return toVector3(0.0, 0.0, 0.0);
- }
-
- static getElementDimension(element) {
- if(typeof element.dimension != "undefined") {
- return element.dimension;
- }
- return 0;
- }
-
- static setElementDimension(element, dimension) {
- if(typeof element.dimension != "undefined") {
- logToConsole(LOG_VERBOSE, `Setting element ${element} (${element.id}) dimension to ${dimension}`);
- element.dimension = dimension;
- return true;
- }
- return false;
- }
-
- static setElementRotation(element, rotation) {
- if(typeof element.setRotation != "undefined") {
- element.setRotation(rotation);
- } else {
- return element.rotation = rotation;
- }
- }
-
- static givePlayerHealth(client, amount) {
- if(getPlayerHealth(client)+amount > 100) {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s health to 100`);
- setPlayerHealth(client, 100);
- } else {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s health to ${getPlayerHealth(client)+amount}`);
- setPlayerHealth(client, getPlayerHealth(client)+amount);
- }
- }
-
- static givePlayerArmour(client, amount) {
- if(getPlayerArmour(client)+amount > 100) {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s armour to 100`);
- setPlayerArmour(client, 100);
- } else {
- logToConsole(LOG_DEBUG, `Setting ${getPlayerDisplayForConsole(client)}'s armour to ${getPlayerArmour(client)+amount}`);
- setPlayerArmour(client, getPlayerArmour(client)+amount);
- }
- }
-
- static consolePrint(text) {
- console.log(text);
- }
-
- static consoleWarn(text) {
- console.warn(text);
- }
-
- static consoleError(text) {
- console.error(text);
- }
-
- static getPlayerName(client) {
- return client.name;
- }
-
- static getServerName() {
- return server.name;
- }
-
- static createGamePickup(modelIndex, position, type) {
- if(!isGameFeatureSupported("pickups")) {
- return false;
- }
- return game.createPickup(modelIndex, position, type);
- }
-
- static createGameBlip(position, type = 0, colour = toColour(255, 255, 255, 255)) {
- if(!isGameFeatureSupported("blips")) {
- return false;
- }
- return game.createBlip(type, position, 1, colour);
- }
-
- static createGameObject(modelIndex, position) {
- if(!isGameFeatureSupported("objects")) {
- return false;
- }
- return game.createObject(getGameConfig().objects[getGame()][modelIndex][0], position);
- }
-
- static setElementOnAllDimensions(element, state) {
- if(!isNull(element) && element != false) {
- if(typeof element.netFlags != "undefined") {
- if(typeof element.netFlags.onAllDimensions != "undefined") {
- element.netFlags.onAllDimensions = state;
- }
- } else {
- if(typeof element.onAllDimensions != "undefined") {
- element.onAllDimensions = state;
- }
- }
- }
- }
-
- static destroyGameElement(element) {
- if(!isNull(element) && element != false) {
- destroyElement(element);
- }
- }
-
- static isMeleeWeapon(weaponId, gameId = getGame()) {
- return (getGameConfig().meleeWeapons[gameId].indexOf(weaponId) != -1);
- }
-
- static getPlayerLastVehicle(client) {
- return getPlayerData(client).lastVehicle;
- }
-
- static isVehicleObject(vehicle) {
- if(vehicle == null || vehicle == undefined) {
- return false;
- }
- return (vehicle.type == ELEMENT_VEHICLE);
- }
-
- static repairVehicle(vehicle) {
- vehicle.fix();
- }
-
- static setVehicleLights(vehicle, lights) {
- setEntityData(vehicle, "vrr.lights", lights, true);
- sendNetworkEventToPlayer("vrr.veh.lights", null, vehicle.id, lights);
- }
-
- static setVehicleEngine(vehicle, engine) {
- vehicle.engine = engine;
- setEntityData(vehicle, "vrr.engine", engine, true);
- }
-
- static setVehicleLocked(vehicle, locked) {
- vehicle.locked = locked;
- }
-
- static setVehicleSiren(vehicle, siren) {
- vehicle.siren = siren;
- }
-
- static getVehicleLights(vehicle) {
- return vehicle.lights;
- }
-
- static getVehicleEngine(vehicle) {
- return vehicle.engine;
- }
-
- static getVehicleLocked(vehicle) {
- return vehicle.lockedStatus;
- }
-
- static getVehicleSiren(vehicle) {
- return vehicle.siren;
- }
-
- static setVehicleColours(vehicle, colour1, colour2, colour3 = -1, colour4 = -1) {
- vehicle.colour1 = colour1;
- vehicle.colour2 = colour2;
-
- if(colour3 != -1) {
- vehicle.colour3 = colour3;
- }
-
- if(colour4 != -1) {
- vehicle.colour4 = colour4;
- }
- }
-
- static createGameVehicle(modelIndex, position, heading, toClient = null) {
- if(areServerElementsSupported()) {
- return game.createVehicle(getGameConfig().vehicles[getGame()][modelIndex][0], position, heading);
- }
- }
-
- static createGameCivilian(modelIndex, position, heading, toClient = null) {
- if(areServerElementsSupported()) {
- let civilian = game.createCivilian(getGameConfig().skins[getGame()][modelIndex][0], 0);
- if(!isNull(civilian)) {
- civilian.position = position;
- civilian.heading = heading;
- addToWorld(civilian);
- return civilian;
- }
- }
-
- return false;
- }
-
- static getIsland(position) {
- if(getGame() == VRR_GAME_GTA_III) {
- if(position.x > 616) {
- return VRR_ISLAND_PORTLAND;
- } else if(position.x < -283) {
- return VRR_ISLAND_SHORESIDEVALE;
- }
- return VRR_ISLAND_STAUNTON;
- } else {
- return VRR_ISLAND_NONE;
- }
-
- //return game.getIslandFromPosition(position);
- }
-
- static isValidVehicleModel(model) {
- if(getVehicleModelIndexFromModel(model) != false) {
- return true;
- }
-
- return false;
- }
-
- static setGameTime(hour, minute, minuteDuration = 1000) {
- if(isTimeSupported()) {
- game.time.hour = hour;
- game.time.minute = minute;
- game.time.minuteDuration = minuteDuration;
- }
- }
-
- static setPlayerFightStyle(client, fightStyleId) {
- if(!isPlayerSpawned(client)) {
- return false;
- }
-
- if(!areFightStylesSupported()) {
- return false;
- }
-
- setEntityData(getPlayerElement(client), "vrr.fightStyle", [getGameConfig().fightStyles[getGame()][fightStyleId][1][0], getGameConfig().fightStyles[getGame()][fightStyleId][1][1]]);
- forcePlayerToSyncElementProperties(null, getPlayerElement(client));
- }
-
- static isPlayerAtGym(client) {
- return true;
- }
-
- static getPlayerElement(client) {
- return client.player;
- }
-
- static setElementPosition(element, position) {
- sendNetworkEventToPlayer("vrr.elementPosition", null, element.id, position);
- }
-
- static getElementPosition(element) {
- return element.position;
- }
-
- static getElementHeading(element) {
- return element.heading;
- }
-
- static setElementInterior(element, interior) {
- setEntityData(element, "vrr.interior", interior, true);
- forcePlayerToSyncElementProperties(null, element);
- }
-
- static setElementCollisionsEnabled(element, state) {
- sendNetworkEventToPlayer("vrr.elementCollisions", null, element.id, state);
- }
-
- static isTaxiVehicle(vehicle) {
- if(taxiModels[getGame()].indexOf(vehicle.modelIndex) != -1) {
- return true;
- }
-
- return false;
- }
-
- static getVehicleName(vehicle) {
- let model = getElementModel(vehicle);
- return getVehicleNameFromModel(model) || "Unknown";
- }
-
- static getElementModel(element) {
- if(typeof element.modelIndex != "undefined") {
- return element.modelIndex;
- }
-
- if(typeof element.model != "undefined") {
- return element.model;
- }
- }
-
- static givePlayerWeaponAmmo(client, ammo) {
- givePlayerWeapon(client, getPlayerWeapon(client), getPlayerWeaponAmmo(client) + ammo);
- }
-
- static getPlayerWeapon(client) {
- if(areServerElementsSupported(client)) {
- return getPlayerPed(client).weapon;
- } else {
- return getPlayerData(client).syncWeapon;
- }
- }
-
- static connectToDatabase() {
- if(getDatabaseConfig().usePersistentConnection) {
- if(persistentDatabaseConnection == null) {
- logToConsole(LOG_DEBUG, `[VRR.Database] Initializing database connection ...`);
- persistentDatabaseConnection = module.mysql.connect(getDatabaseConfig().host, getDatabaseConfig().user, getDatabaseConfig().pass, getDatabaseConfig().name, getDatabaseConfig().port);
- if(persistentDatabaseConnection.error) {
- logToConsole(LOG_ERROR, `[VRR.Database] Database connection error: ${persistentDatabaseConnection.error}`);
- persistentDatabaseConnection = null;
- return false;
- }
-
- logToConsole(LOG_DEBUG, `[VRR.Database] Database connection successful!`);
- return persistentDatabaseConnection;
- } else {
- logToConsole(LOG_DEBUG, `[VRR.Database] Using existing database connection.`);
- return persistentDatabaseConnection;
- }
- } else {
- let databaseConnection = module.mysql.connect(getDatabaseConfig().host, getDatabaseConfig().user, getDatabaseConfig().pass, getDatabaseConfig().name, getDatabaseConfig().port);
- if(databaseConnection.error) {
- logToConsole(LOG_ERROR, `[VRR.Database] Database connection error: ${persistentDatabaseConnection.error}`);
- return false;
- } else {
- return databaseConnection;
- }
- }
- }
-
- static disconnectFromDatabase(dbConnection) {
- if(!getDatabaseConfig().usePersistentConnection) {
- try {
- dbConnection.close();
- logToConsole(LOG_DEBUG, `[VRR.Database] Database connection closed successfully`);
- } catch(error) {
- logToConsole(LOG_ERROR, `[VRR.Database] Database connection could not be closed! (Error: ${error})`);
- }
- }
- return true;
- }
-
- static queryDatabase(dbConnection, queryString, useThread = false) {
- logToConsole(LOG_DEBUG, `[VRR.Database] Query string: ${queryString}`);
- if(useThread == true) {
- Promise.resolve().then(() => {
- let queryResult = dbConnection.query(queryString);
- return queryResult;
- });
- } else {
- return dbConnection.query(queryString);
- }
- }
-
- static escapeDatabaseString(dbConnection, unsafeString = "") {
- if(!dbConnection) {
- dbConnection = connectToDatabase();
- }
-
- if(typeof unsafeString == "string") {
- return dbConnection.escapeString(unsafeString);
- }
- return unsafeString;
- }
-
- static getDatabaseInsertId(dbConnection) {
- return dbConnection.insertId;
- }
-
- static getQueryNumRows(dbQuery) {
- return dbQuery.numRows;
- }
-
- static getDatabaseError(dbConnection) {
- return dbConnection.error;
- }
-
- static freeDatabaseQuery(dbQuery) {
- if(dbQuery != null) {
- dbQuery.free();
- }
- return;
- }
-
- static fetchQueryAssoc(dbQuery) {
- return dbQuery.fetchAssoc();
- }
-
- static quickDatabaseQuery(queryString) {
- let dbConnection = connectToDatabase();
- let insertId = 0;
- if(dbConnection) {
- //logToConsole(LOG_DEBUG, `[VRR.Database] Query string: ${queryString}`);
- let dbQuery = queryDatabase(dbConnection, queryString);
- if(getDatabaseInsertId(dbConnection)) {
- insertId = getDatabaseInsertId(dbConnection);
- logToConsole(LOG_DEBUG, `[VRR.Database] Query returned insert id ${insertId}`);
- }
-
- if(dbQuery) {
- try {
- freeDatabaseQuery(dbQuery);
- logToConsole(LOG_DEBUG, `[VRR.Database] Query result free'd successfully`);
- } catch(error) {
- logToConsole(LOG_ERROR, `[VRR.Database] Query result could not be free'd! (Error: ${error})`);
- }
- }
-
- disconnectFromDatabase(dbConnection);
-
- if(insertId != 0) {
- return insertId;
- }
-
- return true;
- }
- return false;
- }
-
- static executeDatabaseQueryCommand(command, params, client) {
- if(areParamsEmpty(params)) {
- messagePlayerSyntax(client, getCommandSyntaxText(command));
- return false;
- }
-
- if(!targetClient) {
- messagePlayerError(client, "That player was not found!");
- return false;
- }
-
- if(targetCode == "") {
- messagePlayerError(client, "You didn't enter any code!");
- return false;
- }
-
- let success = quickDatabaseQuery(params);
-
- if(!success) {
- messagePlayerAlert(client, `Database query failed to execute: {ALTCOLOUR}${query}`);
- } else if(typeof success != "boolean") {
- messagePlayeSuccess(client, `Database query successful: {ALTCOLOUR}${query}`);
- messagePlayerInfo(client, `Returns: ${success}`);
- } else {
- messagePlayerSuccess(client, `Database query successful: {ALTCOLOUR}${query}`);
- }
- return true;
- }
-
- static setConstantsAsGlobalVariablesInDatabase() {
- let dbConnection = connectToDatabase();
- let entries = Object.entries(global);
- for(let i in entries) {
- logToConsole(LOG_DEBUG, `[VRR.Database] Checking entry ${i} (${entries[i]})`);
- if(toString(i).slice(0, 3).indexOf("VRR_") != -1) {
- logToConsole(LOG_DEBUG, `[VRR.Database] Adding ${i} (${entries[i]}) to database global variables`);
- }
- }
- }
-
- static createDatabaseInsertQuery(tableName, data) {
- let fields = [];
- let values = [];
-
- for(let i in data) {
- if(data[i][1] != "undefined" && data[i][1] != NaN && data[i][0] != 'NaN') {
- if(data[i][1] != "undefined" && data[i][1] != NaN && data[i][1] != 'NaN') {
- fields.push(data[i][0]);
-
- if(typeof data[i][1] == "string") {
- if(data[i][1] == "{UNIXTIMESTAMP}") {
- values.push("UNIX_TIMESTAMP()");
- } else {
- values.push(`'${data[i][1]}'`);
- }
- } else {
- values.push(data[i][1]);
- }
- }
- }
- }
-
- let queryString = `INSERT INTO ${tableName} (${fields.join(", ")}) VALUES (${values.join(", ")})`;
- return queryString;
- }
-
- static createDatabaseUpdateQuery(tableName, data, whereClause) {
- let values = [];
-
- for(let i in data) {
- if(data[i][0] != "undefined" && data[i][0] != NaN && data[i][0] != 'NaN') {
- if(data[i][1] != "undefined" && data[i][1] != NaN && data[i][1] != 'NaN') {
- if(typeof data[i][1] == "string") {
- if(data[i][1] == "{UNIXTIMESTAMP}") {
- values.push(`${data[i][0]}=UNIX_TIMESTAMP()`);
- } else {
- values.push(`${data[i][0]}='${data[i][1]}'`);
- }
- } else {
- values.push(`${data[i][0]}=${data[i][1]}`);
- }
- }
- }
- }
-
- let queryString = `UPDATE ${tableName} SET ${values.join(", ")} WHERE ${whereClause}`;
- return queryString;
- }
-
- static sendNetworkEventToPlayer(eventName, client, ...args) {
- let argsArray = [eventName, client];
- argsArray = argsArray.concat(args);
- triggerNetworkEvent.apply(null, argsArray);
- }
-
- static addNetworkEventHandler(eventName, handlerFunction) {
- addNetworkHandler(eventName, handlerFunction);
- }
-
- static getElementId(element) {
- return element.id;
- }
-
- static getClientFromIndex(index) {
- let clients = getClients();
- for(let i in clients) {
- if(clients[i].index == index) {
- return clients[i];
- }
- }
- }
-
- static getClientsInRange(position, distance) {
- return getPlayersInRange(position, distance);
- }
-
- static getCiviliansInRange(position, distance) {
- return getElementsByTypeInRange(ELEMENT_PED, position, distance).filter(x => !x.isType(ELEMENT_PLAYER));
- }
-
- static getPlayersInRange(position, distance) {
- return getClients().filter(x => getDistance(position, getPlayerPosition(x)) <= distance);
- }
-
- static getElementsByTypeInRange(elementType, position, distance) {
- return getElementsByType(elementType).filter(x => getDistance(position, getElementPosition(x)) <= distance);
- }
-
- static getClosestCivilian(position) {
- return getClosestElementByType(ELEMENT_PED, position).filter(ped => !ped.isType(ELEMENT_PLAYER));
- }
-
- static getVehiclesInRange(position, range) {
- if(getGame() == VRR_GAME_GTA_IV) {
- return getServerData().vehicles.reduce((i, j) => (getDistance(position, i.syncPosition) <= getDistance(position, j.syncPosition)) ? i : j);
- }
- return getElementsByTypeInRange(ELEMENT_VEHICLE, position, range);
- }
-
- static getClosestVehicle(position) {
- return getClosestElementByType(ELEMENT_VEHICLE, position);
- }
-
- static getClosestElementByType(elementType, position) {
- return getElementsByType(elementType).reduce((i, j) => (getDistance(position, getElementPosition(i)) <= getDistance(position, getElementPosition(j))) ? i : j);
- }
-
- static getVehicleFirstEmptySeat(vehicle) {
- for(let i = 0; i <= 4; i++) {
- if(vehicle.getOccupant(i) == null) {
- return i;
- }
- }
-
- return false;
- }
-
- static isVehicleTrain(vehicle) {
- if(getGame() == VRR_GAME_GTA_III) {
- if(vehicle.modelIndex == 124) {
- return true;
- }
- }
-
- return false
- }
-
- static warpPedIntoVehicle(ped, vehicle, seatId) {
- ped.warpIntoVehicle(vehicle, seatId);
- }
-
- static getPlayerPing(client) {
- return client.ping
- }
-
- static setVehicleHealth(vehicle, health) {
- vehicle.health = 1000;
- }
-
- static givePlayerWeapon(client, weaponId, ammo, active = true) {
- logToConsole(LOG_DEBUG, `[VRR.Client] Sending signal to ${getPlayerDisplayForConsole(client)} to give weapon (Weapon: ${weaponId}, Ammo: ${ammo})`);
- sendNetworkEventToPlayer("vrr.giveWeapon", client, weaponId, ammo, active);
- }
-
- static setPlayerWantedLevel(client, wantedLevel) {
- sendNetworkEventToPlayer("vrr.wantedLevel", client, wantedLevel);
- return true;
- }
-
- static setElementStreamInDistance(element, distance) {
- if(!isNull(element) && element != false) {
- if(typeof element == "Entity") {
- if(typeof element.streamInDistance != "undefined") {
- element.streamInDistance = distance;
- }
- }
- }
- }
-
- static setElementStreamOutDistance(element, distance) {
- if(!isNull(element) && element != false) {
- if(typeof element == "Entity") {
- if(typeof element.streamOutDistance != "undefined") {
- element.streamOutDistance = distance;
- }
- }
- }
- }
-
- static getPlayerPed(client) {
- if(getGame() == VRR_GAME_GTA_IV) {
- return getPlayerData(client).ped;
- } else {
- return client.player;
- }
- }
-
- static setEntityData(entity, dataName, dataValue, syncToClients = true) {
- if(entity != null) {
- if(areServerElementsSupported()) {
- return entity.setData(dataName, dataValue, syncToClients);
- }
- }
- return false;
- }
-
- static removeEntityData(entity, dataName) {
- if(entity != null) {
- if(areServerElementsSupported()) {
- return entity.removeData(dataName);
- }
- }
- return false;
- }
-
- static doesEntityDataExist(entity, dataName) {
- if(entity != null) {
- if(areServerElementsSupported()) {
- return (entity.getData(dataName) != null);
- } else {
- return false;
- }
- }
- return null;
- }
-
- static disconnectPlayer(client) {
- client.disconnect();
- }
-
- static getPlayerId(client) {
- return client.index;
- }
-
- static getPlayerIP(client) {
- return client.ip;
- }
-
- static getPlayerGameVersion(client) {
- client.gameVersion;
- }
-
- static setPlayerNativeAdminState(client, state) {
- client.administrator = state;
- }
-
- static despawnPlayer(client) {
- client.despawnPlayer();
- }
-
- static getGame() {
- return server.game;
- }
-
- static getCountryNameFromIP(ip) {
- if(module.geoip.getCountryName(ip)) {
- return module.geoip.getCountryName(ip);
- }
- return false;
- }
-
- static getServerPort() {
- return server.port;
- }
-
- static serverBanIP(ip) {
- server.banIP(ip);
- }
-
- static setVehicleTrunkState(vehicle, trunkState) {
- sendNetworkEventToPlayer("vrr.veh.trunk", null, getVehicleForNetworkEvent(vehicle), trunkState);
- }
-
- static addCommandHandler(command, params, client) {
- addCommandHandler(command, params, client);
- }
-
- static removeCommandHandler(command, params, client) {
- removeCommandHandler(command);
- }
-
- static onScriptInit() {
- onScriptInit();
- }
-
- static onScriptExit() {
- onScriptExit();
- }
-
- static onPlayerEnterVehicle() {
- onPlayerEnterVehicle();
- }
-
- static onPlayerExitVehicle() {
- onPlayerExitVehicle();
- }
-};
-
-// ===========================================================================
-
-let builtInCommands = [
- "refresh",
- "restart",
- "stop",
- "start",
- "reconnect",
- "setname",
- "connect",
- "disconnect",
- "say",
- "dumpdoc",
-];
-
-// ===========================================================================
-
-let disconnectReasons = [
- "Lost Connection",
- "Disconnected",
- "Unsupported Client",
- "Wrong Game",
- "Incorrect Password",
- "Unsupported Executable",
- "Disconnected",
- "Banned",
- "Failed",
- "Invalid Name",
- "Crashed",
- "Modified Game"
-];
-
-// ===========================================================================
diff --git a/scripts/server/native/connected.js b/scripts/server/native/connected.js
index c99b47b7..176e9888 100644
--- a/scripts/server/native/connected.js
+++ b/scripts/server/native/connected.js
@@ -477,11 +477,11 @@ function createGamePickup(modelIndex, position, type) {
// ===========================================================================
-function createGameBlip(position, type = 0, colour = toColour(255, 255, 255, 255)) {
+function createGameBlip(position, type = 0, size = 1, colour = toColour(255, 255, 255, 255)) {
if(!isGameFeatureSupported("blips")) {
return false;
}
- return game.createBlip(type, position, 1, colour);
+ return game.createBlip(type, position, size, colour);
}
// ===========================================================================
@@ -619,14 +619,13 @@ function createGameVehicle(modelIndex, position, heading, toClient = null) {
// ===========================================================================
-function createGameCivilian(modelIndex, position, heading, toClient = null) {
+function createGamePed(modelIndex, position, heading, toClient = null) {
if(areServerElementsSupported()) {
- let civilian = game.createCivilian(getGameConfig().skins[getGame()][modelIndex][1], 0);
- if(!isNull(civilian)) {
- civilian.position = position;
- civilian.heading = heading;
- addToWorld(civilian);
- return civilian;
+ let ped = game.createPed(getGameConfig().skins[getGame()][modelIndex][0], position);
+ if(ped) {
+ //ped.position = position;
+ ped.heading = heading;
+ return ped;
}
}
@@ -920,6 +919,103 @@ function quickDatabaseQuery(queryString) {
// ===========================================================================
+function executeDatabaseQueryCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ if(!targetClient) {
+ messagePlayerError(client, "That player was not found!");
+ return false;
+ }
+
+ if(targetCode == "") {
+ messagePlayerError(client, "You didn't enter any code!");
+ return false;
+ }
+
+ let success = quickDatabaseQuery(params);
+
+ if(!success) {
+ messagePlayerAlert(client, `Database query failed to execute: {ALTCOLOUR}${query}`);
+ } else if(typeof success != "boolean") {
+ messagePlayeSuccess(client, `Database query successful: {ALTCOLOUR}${query}`);
+ messagePlayerInfo(client, `Returns: ${success}`);
+ } else {
+ messagePlayerSuccess(client, `Database query successful: {ALTCOLOUR}${query}`);
+ }
+ return true;
+}
+
+// ===========================================================================
+
+function setConstantsAsGlobalVariablesInDatabase() {
+ let dbConnection = connectToDatabase();
+ let entries = Object.entries(global);
+ for(let i in entries) {
+ logToConsole(LOG_DEBUG, `[VRR.Database] Checking entry ${i} (${entries[i]})`);
+ if(toString(i).slice(0, 3).indexOf("VRR_") != -1) {
+ logToConsole(LOG_DEBUG, `[VRR.Database] Adding ${i} (${entries[i]}) to database global variables`);
+ }
+ }
+}
+
+// ===========================================================================
+
+function createDatabaseInsertQuery(tableName, data) {
+ let fields = [];
+ let values = [];
+
+ for(let i in data) {
+ if(data[i][1] != "undefined" && data[i][1] != NaN && data[i][0] != 'NaN') {
+ if(data[i][1] != "undefined" && data[i][1] != NaN && data[i][1] != 'NaN') {
+ fields.push(data[i][0]);
+
+ if(typeof data[i][1] == "string") {
+ if(data[i][1] == "{UNIXTIMESTAMP}") {
+ values.push("UNIX_TIMESTAMP()");
+ } else {
+ values.push(`'${data[i][1]}'`);
+ }
+ } else {
+ values.push(data[i][1]);
+ }
+ }
+ }
+ }
+
+ let queryString = `INSERT INTO ${tableName} (${fields.join(", ")}) VALUES (${values.join(", ")})`;
+ return queryString;
+}
+
+// ===========================================================================
+
+function createDatabaseUpdateQuery(tableName, data, whereClause) {
+ let values = [];
+
+ for(let i in data) {
+ if(data[i][0] != "undefined" && data[i][0] != NaN && data[i][0] != 'NaN') {
+ if(data[i][1] != "undefined" && data[i][1] != NaN && data[i][1] != 'NaN') {
+ if(typeof data[i][1] == "string") {
+ if(data[i][1] == "{UNIXTIMESTAMP}") {
+ values.push(`${data[i][0]}=UNIX_TIMESTAMP()`);
+ } else {
+ values.push(`${data[i][0]}='${data[i][1]}'`);
+ }
+ } else {
+ values.push(`${data[i][0]}=${data[i][1]}`);
+ }
+ }
+ }
+ }
+
+ let queryString = `UPDATE ${tableName} SET ${values.join(", ")} WHERE ${whereClause}`;
+ return queryString;
+}
+
+// ===========================================================================
+
function sendNetworkEventToPlayer(eventName, client, ...args) {
let argsArray = [eventName, client];
argsArray = argsArray.concat(args);
@@ -1178,24 +1274,6 @@ function getCountryNameFromIP(ip) {
// ===========================================================================
-function getSubdivisionNameFromIP(ip) {
- if(module.geoip.getSubdivisionName(ip)) {
- return module.geoip.getSubdivisionName(ip);
- }
- return false;
-}
-
-// ===========================================================================
-
-function getCityNameFromIP(ip) {
- if(module.geoip.getCityNameFromIP(ip)) {
- return module.geoip.getCityNameFromIP(ip);
- }
- return false;
-}
-
-// ===========================================================================
-
function getServerPort() {
return server.port;
}
@@ -1214,6 +1292,7 @@ function setVehicleTrunkState(vehicle, trunkState) {
// ===========================================================================
+/*
function addAllEventHandlers() {
bindServerEventHandler("onResourceStart", onResourceStart)
bindServerEventHandler("onResourceStop", onResourceStart)
@@ -1241,6 +1320,7 @@ function addAllEventHandlers() {
addServerEventHandler("onPedEnteringVehicle", onPedEnteringVehicle);
addServerEventHandler("onPedExitingVehicle", onPedExitingVehicle);
}
+*/
// ===========================================================================
@@ -1270,4 +1350,28 @@ function bindServerEventHandler(eventName, bindTo, handlerFunction) {
});
}
+// ===========================================================================
+
+function setElementName(element, name) {
+ element.name = name;
+}
+
+// ===========================================================================
+
+function hideElementForPlayer(element, client) {
+ element.setExistsFor(client, false);
+}
+
+// ===========================================================================
+
+function showElementForPlayer(element, client) {
+ element.setExistsFor(client, true);
+}
+
+// ===========================================================================
+
+function setElementShownByDefault(element, state) {
+ element.netFlags.defaultExistance = state;
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc.js b/scripts/server/npc.js
index 75012b3d..50ffabb7 100644
--- a/scripts/server/npc.js
+++ b/scripts/server/npc.js
@@ -27,23 +27,23 @@ function getNPCData(npcId) {
// ===========================================================================
-function createNPCCommand(client, command, params) {
+function createNPCCommand(command, params, client) {
if(areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
- let skinId = getSkinModelIndexFromParams(params);
+ let skinIndex = getSkinModelIndexFromParams(params);
- if(!skinId) {
+ if(!skinIndex) {
messagePlayerError(client, getLocaleString(client, "InvalidSkin"));
return false;
}
- let position = getPosInFrontOfPos(getPlayerPosition(client), getPlayerHeading(client), 3);
-
- let npcId = createNPC(skinId, position, getPlayerHeading(client), getPlayerInterior(client), getPlayerDimension());
- messageAdmins(`${getPlayerName(client)}{MAINCOLOUR} created a ${getSkinNameFromIndex(getNPCData(npcId).skin)} NPC!`);
+ let position = getPlayerPosition(client);
+ setPlayerPosition(client, getPosBehindPos(position, getPlayerHeading(client), 1.5))
+ let npcId = createNPC(skinIndex, position, getPlayerHeading(client), getPlayerInterior(client), getPlayerDimension(client));
+ messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created a {ALTCOLOUR}${getSkinNameFromIndex(getNPCData(npcId).skin)}{MAINCOLOUR} NPC!`);
}
// ===========================================================================
@@ -149,23 +149,24 @@ function saveAllNPCsToDatabase() {
function saveNPCToDatabase(npcDataId) {
if(getServerConfig().devServer) {
+ logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} can't be saved because server is running as developer only. Aborting save ...`);
return false;
}
- if(getNPCData(npcDataId) == null) {
- // Invalid NPC data
+ if(getNPCData(npcDataId) == false) {
+ logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} data is invalid. Aborting save ...`);
return false;
}
let tempNPCData = getNPCData(npcDataId);
if(tempNPCData.databaseId == -1) {
- // Temp NPC, no need to save
+ logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} is a temp NPC. Aborting save ...`);
return false;
}
if(!tempNPCData.needsSaved) {
- // NPC hasn't changed. No need to save.
+ logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} hasn't changed data. Aborting save ...`);
return false;
}
@@ -184,17 +185,13 @@ function saveNPCToDatabase(npcDataId) {
}
}
- let safeAnimationName = escapeDatabaseString(tempNPCData.animationName);
- let safeFirstName = escapeDatabaseString(tempNPCData.firstName);
- let safeLastName = escapeDatabaseString(tempNPCData.lastName);
- let safeMiddleName = escapeDatabaseString(tempNPCData.middleName);
+ let safeAnimationName = escapeDatabaseString(dbConnection, tempNPCData.animationName);
+ let safeName = escapeDatabaseString(dbConnection, tempNPCData.name);
let data = [
["npc_server", getServerId()],
- ["npc_skin", toInteger(tempNPCData.model)],
- ["npc_name_first", safeFirstName],
- ["npc_name_middle", safeMiddleName],
- ["npc_name_last", safeLastName],
+ ["npc_skin", toInteger(tempNPCData.skin)],
+ ["npc_name", safeName],
["npc_owner_type", toInteger(tempNPCData.ownerType)],
["npc_owner_id", toInteger(tempNPCData.ownerId)],
["npc_pos_x", toFloat(tempNPCData.position.x)],
@@ -261,13 +258,19 @@ function setNPCDataIndexes() {
// ===========================================================================
function spawnNPC(npcIndex) {
- let civilian = createGameCivilian(getNPCData(npcIndex).model, getNPCData(npcIndex).spawnPosition, getNPCData(npcIndex).spawnRotation);
- if(civilian) {
- civilian.setData("vrr.dataIndex", npcIndex);
- if(getNPCData(npcIndex).animationName != "") {
- civilian.setData("vrr.animation", getNPCData(npcIndex).animationName);
+ let npcData = getNPCData(npcIndex);
+ let ped = createGamePed(npcData.skin, npcData.position, npcData.rotation.z);
+ if(ped) {
+ getNPCData(npcIndex).ped = ped;
+ setEntityData(ped, "vrr.dataIndex", npcIndex, false);
+ if(npcData.animationName != "") {
+ let animationId = getAnimationFromParams(npcData.animationName);
+ if(animationId != false) {
+ setEntityData(ped, "vrr.anim", animationId, true);
+ }
}
- getNPCData(npcIndex).ped = civilian;
+ setElementDimension(ped, npcData.dimension);
+ setElementInterior(ped, npcData.interior);
}
}
@@ -275,18 +278,13 @@ function spawnNPC(npcIndex) {
function spawnAllNPCs() {
for(let i in getServerData().npcs) {
- spawnNPC(npcIndex);
+ spawnNPC(i);
}
}
// ===========================================================================
function deleteNPCCommand(command, params, client) {
- if(areParamsEmpty(params)) {
- messagePlayerSyntax(client, command);
- return false;
- }
-
let closestNPC = getClosestNPC(getPlayerPosition(client));
if(!getNPCData(closestNPC)) {
@@ -297,7 +295,7 @@ function deleteNPCCommand(command, params, client) {
let npcName = getNPCData(closestNPC).name;
deleteNPC(closestNPC);
- messageAdmins(`${getPlayerName(client)}{MAINCOLOUR} deleted NPC {npcPink}${npcName}`);
+ messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} deleted NPC {npcPink}${npcName}`);
}
// ===========================================================================
@@ -319,7 +317,7 @@ function deleteNPC(npcId) {
function setNPCAnimationCommand(command, params, client) {
if(areParamsEmpty(params)) {
- messagePlayerSyntax(client, command);
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -345,8 +343,118 @@ function setNPCAnimationCommand(command, params, client) {
animationPositionOffset = getParam(params, " ", 2);
}
- getNPCData(closestNPC).animationName = animation;
+ getNPCData(closestNPC).animationName = getAnimationData(animationId).name;
+ getNPCData(closestNPC).needsSaved = true;
+
makePedPlayAnimation(getNPCData(closestNPC).ped, animationId, animationPositionOffset);
+ messagePlayerSuccess(client, getLocaleString(client, "NPCAnimationSet", `{ALTCOLOUR}${getNPCData(closestNPC).name}{MAINCOLOUR}`, `{ALTCOLOUR}${getAnimationData(animationId).name}{MAINCOLOUR}`));
+}
+
+// ===========================================================================
+
+function setNPCNameCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let closestNPC = getClosestNPC(getPlayerPosition(client));
+ let name = params;
+
+ if(!getNPCData(closestNPC)) {
+ messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
+ return false;
+ }
+
+ let oldName = getNPCData(closestNPC).name;
+ getNPCData(closestNPC).name = name;
+ getNPCData(closestNPC).needsSaved = true;
+
+ setElementName(getNPCData(closestNPC).ped, name);
+ messagePlayerSuccess(client, getLocaleString(client, "NPCNameSet", `{ALTCOLOUR}${oldName}{MAINCOLOUR}`, `{ALTCOLOUR}${getNPCData(closestNPC).name}{MAINCOLOUR}`));
+}
+
+// ===========================================================================
+
+function toggleNPCLookAtClosestPlayerCommand(command, params, client) {
+ let closestNPC = getClosestNPC(getPlayerPosition(client));
+
+ if(!getNPCData(closestNPC)) {
+ messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
+ return false;
+ }
+
+ getNPCData(closestNPC).lookAtClosestPlayer = !getNPCData(closestNPC).lookAtClosestPlayer;
+ getNPCData(closestNPC).needsSaved = true;
+ setEntityData(getNPCData(closestNPC).ped, "vrr.lookAtClosestPlayer", getNPCData(closestNPC).lookAtClosestPlayer, true);
+ forcePlayerToSyncElementProperties(null, getNPCData(closestNPC).ped);
+ //messagePlayerSuccess(client, getLocaleString(client, "NPCLookAtClosestPlayerSet", `{ALTCOLOUR}${getNPCData(closestNPC).name}{MAINCOLOUR}));
+}
+
+// ===========================================================================
+
+function getNPCInfoCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let closestNPC = getClosestNPC(getPlayerPosition(client));
+
+ if(!getNPCData(closestNPC)) {
+ messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
+ return false;
+ }
+
+ let npcData = getNPCData(closestNPC);
+
+ let ownerName = "Nobody";
+ let ownerType = "None";
+ switch(npcData.ownerType) {
+ case VRR_NPCOWNER_CLAN:
+ ownerName = getClanData(getClanIdFromDatabaseId(npcData.ownerId)).name;
+ ownerType = "clan";
+ break;
+
+ case VRR_NPCOWNER_JOB:
+ ownerName = getJobData(getJobIdFromDatabaseId(npcData.ownerId)).name;
+ ownerType = "job";
+ break;
+
+ case VRR_NPCOWNER_PLAYER:
+ let subAccountData = loadSubAccountFromId(npcData.ownerId);
+ ownerName = `${subAccountData.firstName} ${subAccountData.lastName} [${subAccountData.databaseId}]`;
+ ownerType = "player";
+ break;
+
+ case VRR_NPCOWNER_BIZ:
+ ownerName = getBusinessData(getBusinessIdFromDatabaseId(npcData.ownerId)).name;
+ ownerType = "business";
+ break;
+
+ case VRR_NPCOWNER_PUBLIC:
+ ownerName = "Nobody";
+ ownerType = "public";
+ break;
+
+ default:
+ break;
+ }
+
+ let tempStats = [
+ [`Skin`, `${getGameConfig().skins[npcData.skin][0]} (${getGameConfig().skins[npcData.skin][1]})`],
+ [`ID`, `${npcData.index}/${npcData.databaseId}`],
+ [`Owner`, `${ownerName} (${ownerType})`],
+ [`Animation`, `${npcData.animationName}`],
+ ];
+
+ let stats = tempStats.map(stat => `{MAINCOLOUR}${stat[0]}: {ALTCOLOUR}${stat[1]}{MAINCOLOUR}`);
+
+ messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderNPCInfo")));
+ let chunkedList = splitArrayIntoChunks(stats, 6);
+ for(let i in chunkedList) {
+ messagePlayerInfo(client, chunkedList[i].join(", "));
+ }
}
// ===========================================================================
@@ -355,7 +463,7 @@ function getClosestNPC(position) {
let npcs = getServerData().npcs;
let closest = 0;
for(let i in npcs) {
- if(getDistance(npcs[i].ped.position, position) < getDistance(npcs[i].ped.position, position)) {
+ if(getDistance(npcs[i].ped.position, position) < getDistance(npcs[closest].ped.position, position)) {
closest = i;
}
}
@@ -368,11 +476,12 @@ function getClosestNPC(position) {
function createNPC(skinIndex, position, heading, interior, dimension) {
let tempNPCData = new NPCData(false);
tempNPCData.position = position;
- tempNPCData.heading = heading;
+ tempNPCData.rotation = toVector3(0.0, 0.0, heading);
tempNPCData.skin = skinIndex;
tempNPCData.interior = interior;
tempNPCData.dimension = dimension;
tempNPCData.animationName = "";
+ tempNPCData.needsSaved = true;
let npcIndex = getServerData().npcs.push(tempNPCData);
setNPCDataIndexes();
diff --git a/scripts/server/race.js b/scripts/server/race.js
index b4e2ff68..7862d66f 100644
--- a/scripts/server/race.js
+++ b/scripts/server/race.js
@@ -77,4 +77,73 @@ function createRaceCommand(command, params, client) {
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created race {ALTCOLOUR}${params}`);
}
+// ===========================================================================
+
+function createRaceCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let raceId = createRace(params, getPlayerPosition(client));
+ getRaceData(raceId).enabled = false;
+ initRace(raceId);
+ joinRace(client, raceId);
+ messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created race {ALTCOLOUR}${params}`);
+}
+
+// ===========================================================================
+
+function createRaceLocationCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let raceId = getPlayerRace(client);
+ if(raceId == false) {
+ messagePlayerError(client, "You are not in a race!");
+ return false;
+ }
+
+ let raceLocationName = params;
+ createRaceLocation(raceId, raceLocationName, getPlayerPosition(client));
+
+ messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created race {ALTCOLOUR}${params}`);
+}
+
+// ===========================================================================
+
+function createRaceLocationCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let raceId = getPlayerRace(client);
+ if(raceId == false) {
+ messagePlayerError(client, "You are not in a race!");
+ return false;
+ }
+
+ let raceLocationName = params;
+ createRaceLocation(raceId, raceLocationName, getPlayerPosition(client));
+
+ messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} created race {ALTCOLOUR}${params}`);
+}
+
+// ===========================================================================
+
+function stopRacingCommand(command, params, client) {
+ if(!isPlayerInARace(client)) {
+ messagePlayerError(client, "You aren't in a race!");
+ return false;
+ }
+
+ leaveRace(client);
+ messagePlayerSuccess(client, "You left the race!");
+ messagePlayersInRace(`${getCharacterFullName(client)} left the race!`);
+ checkRemainingPlayersInRace(raceId)
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/radio.js b/scripts/server/radio.js
index b693e4bb..dbaa1b89 100644
--- a/scripts/server/radio.js
+++ b/scripts/server/radio.js
@@ -236,6 +236,10 @@ function setAllRadioStationIndexes() {
// ===========================================================================
+/**
+ * @param {number} radioStationId - The data index of the radio station
+ * @return {RadioStationData} The radio station's data (class instance)
+ */
function getRadioStationData(radioStationId) {
return getServerData().radioStations[radioStationId];
}
diff --git a/scripts/server/staff.js b/scripts/server/staff.js
index d83009b4..ea12b450 100644
--- a/scripts/server/staff.js
+++ b/scripts/server/staff.js
@@ -84,8 +84,8 @@ function setStaffTitleCommand(command, params, client) {
getPlayerData(targetClient).accountData.staffTitle = staffTitle;
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} set {ALTCOLOUR}${getPlayerName(targetClient)}'s{MAINCOLOUR} staff title to ${staffTitle}`);
- messagePlayerAlert(client, `${getPlayerName(client)} set your staff title to ${staffTitle}`);
- targetdisconnectPlayer(client);
+ messagePlayerAlert(targetClient, `${getPlayerName(client)} set your staff title to ${staffTitle}`);
+ //targetdisconnectPlayer(client);
}
// ===========================================================================
diff --git a/scripts/server/trigger.js b/scripts/server/trigger.js
index d6c24653..2cc17c12 100644
--- a/scripts/server/trigger.js
+++ b/scripts/server/trigger.js
@@ -46,6 +46,9 @@ const triggerTypes = [
"onVehicleRepaired",
"onVehicleColourChange",
"onVehicleExtraChange",
+ "onPlayerShout",
+ "onPlayerTalk",
+ "onPlayerWhisper",
];
// ===========================================================================
diff --git a/scripts/server/vehicle.js b/scripts/server/vehicle.js
index 82c8437b..5ed9252b 100644
--- a/scripts/server/vehicle.js
+++ b/scripts/server/vehicle.js
@@ -1002,7 +1002,6 @@ function getVehicleInfoCommand(command, params, client) {
let ownerName = "Nobody";
let ownerType = "None";
- ownerType = toLowerCase(getVehicleOwnerTypeText(vehicleData.ownerType));
switch(vehicleData.ownerType) {
case VRR_VEHOWNER_CLAN:
ownerName = getClanData(getClanIdFromDatabaseId(vehicleData.ownerId)).name;
@@ -1025,11 +1024,40 @@ function getVehicleInfoCommand(command, params, client) {
ownerType = "business";
break;
+ case VRR_VEHOWNER_PUBLIC:
+ ownerName = "Nobody";
+ ownerType = "public";
+ break;
+
default:
break;
}
- messagePlayerNormal(client, `🚗 {vehiclePurple}[Vehicle Info] {MAINCOLOUR}ID: {ALTCOLOUR}${getElementId(vehicle)}, {MAINCOLOUR}Index: {ALTCOLOUR}${vehicleData.index}, {MAINCOLOUR}DatabaseID: {ALTCOLOUR}${vehicleData.databaseId}, {MAINCOLOUR}Owner: {ALTCOLOUR}${ownerName}[ID ${vehicleData.ownerId}] (${ownerType}), {MAINCOLOUR}Type: {ALTCOLOUR}${getVehicleName(vehicle)}[ID: ${vehicle.modelIndex}, Index: ${getVehicleModelIndexFromModel(vehicle.modelIndex)}], {MAINCOLOUR}BuyPrice: {ALTCOLOUR}${vehicleData.buyPrice}, {MAINCOLOUR}RentPrice: {ALTCOLOUR}${vehicleData.rentPrice}`);
+ let tempStats = [
+ [`Type`, `${getGameConfig().vehicles[getGame()][vehicleData.model][1]} (${getGameConfig().vehicles[getGame()][vehicleData.model][0]})`],
+ [`ID`, `${vehicleData.index}/${vehicleData.databaseId}`],
+ [`Owner`, `${ownerName} (${getVehicleOwnerTypeText(vehicleData.ownerType)})`],
+ [`Locked`, `${getYesNoFromBool(vehicleData.locked)}`],
+ [`Engine`, `${getOnOffFromBool(vehicleData.engine)}`],
+ [`Lights`, `${getOnOffFromBool(vehicleData.lights)}`],
+ [`Buy Price`, `${vehicleData.buyPrice}`],
+ [`Rent Price`, `${vehicleData.rentPrice}`],
+ [`Radio Station`, `${(vehicleData.streamingRadioStation == -1) ? "None" : getRadioStationData(vehicleData.streamingRadioStation).name}`],
+ [`Parked`, `${getYesNoFromBool(vehicleData.spawnLocked)}`],
+ [`License Plate`, `${vehicleData.licensePlate}`],
+ [`Colour`, `${getVehicleColourInfoString(vehicleData.colour1, vehicleData.colour1IsRGBA)}, ${getVehicleColourInfoString(vehicleData.colour1, vehicleData.colour1IsRGBA)}`],
+ [`Last Driver`, `${vehicleData.lastDriverName}`],
+ ];
+
+ let stats = tempStats.map(stat => `{MAINCOLOUR}${stat[0]}: {ALTCOLOUR}${stat[1]}{MAINCOLOUR}`);
+
+ messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderVehicleInfo")));
+ let chunkedList = splitArrayIntoChunks(stats, 6);
+ for(let i in chunkedList) {
+ messagePlayerInfo(client, chunkedList[i].join(", "));
+ }
+
+ //messagePlayerNormal(client, `🚗 {vehiclePurple}[Vehicle Info] {MAINCOLOUR}ID: {ALTCOLOUR}${getElementId(vehicle)}, {MAINCOLOUR}Index: {ALTCOLOUR}${vehicleData.index}, {MAINCOLOUR}DatabaseID: {ALTCOLOUR}${vehicleData.databaseId}, {MAINCOLOUR}Owner: {ALTCOLOUR}${ownerName}[ID ${vehicleData.ownerId}] (${ownerType}), {MAINCOLOUR}Type: {ALTCOLOUR}${getVehicleName(vehicle)}[ID: ${vehicle.modelIndex}, Index: ${getVehicleModelIndexFromModel(vehicle.modelIndex)}], {MAINCOLOUR}BuyPrice: {ALTCOLOUR}${vehicleData.buyPrice}, {MAINCOLOUR}RentPrice: {ALTCOLOUR}${vehicleData.rentPrice}`);
}
// ===========================================================================
@@ -1051,7 +1079,6 @@ function getLastVehicleInfoCommand(command, params, client) {
let ownerName = "Nobody";
let ownerType = "None";
- ownerType = toLowerCase(getVehicleOwnerTypeText(vehicleData.ownerType));
switch(vehicleData.ownerType) {
case VRR_VEHOWNER_CLAN:
ownerName = getClanData(vehicleData.ownerId).name;
@@ -1074,7 +1101,14 @@ function getLastVehicleInfoCommand(command, params, client) {
ownerType = "business";
break;
+ case VRR_VEHOWNER_PUBLIC:
+ ownerName = "None";
+ ownerType = "public";
+ break;
+
default:
+ ownerName = "None";
+ ownerType = "unowned";
break;
}
@@ -1273,7 +1307,6 @@ function spawnVehicle(vehicleData) {
let vehicle = createGameVehicle(vehicleData.model, vehicleData.spawnPosition, vehicleData.spawnRotation);
setVehicleHeading(vehicle, vehicleData.spawnRotation);
setElementTransient(vehicle, false);
- addToWorld(vehicle);
if(!vehicle) {
return false;
@@ -1281,7 +1314,6 @@ function spawnVehicle(vehicleData) {
setVehicleHeading(vehicle, vehicleData.spawnRotation);
setElementDimension(vehicle, vehicleData.dimension);
- addToWorld(vehicle);
vehicleData.vehicle = vehicle;
@@ -1320,7 +1352,6 @@ function spawnVehicle(vehicleData) {
forcePlayerToSyncElementProperties(null, vehicle);
-
return vehicle;
}
@@ -1351,6 +1382,9 @@ function getVehicleOwnerTypeText(ownerType) {
case VRR_VEHOWNER_BIZ:
return "business";
+ case VRR_VEHOWNER_PUBLIC:
+ return "public";
+
default:
return "unknown";
}
@@ -1650,4 +1684,15 @@ function removeAllOccupantsFromVehicle(vehicle) {
}
}
+// ===========================================================================
+
+function getVehicleColourInfoString(colour, isRGBA) {
+ if(isRGBA) {
+ let arrayColour = rgbaArrayFromToColour(colour);
+ return `RGBA [${arrayColour[0]}, ${arrayColour[1]}, ${arrayColour[2]}, ${arrayColour[3]}]`;
+ } else {
+ return `GAME [${colour}]`;
+ }
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/shared/const.js b/scripts/shared/const.js
index aaec359f..2abf7090 100644
--- a/scripts/shared/const.js
+++ b/scripts/shared/const.js
@@ -97,7 +97,7 @@ const VRR_VEHBUYSTATE_EXITVEH = 2;
const VRR_VEHBUYSTATE_FARENOUGH = 3;
const VRR_VEHBUYSTATE_WRONGVEH = 4;
-// Body Parts for Skin Select
+// Body Parts for Skin Select (IV for now, but might do other games when I can add accessory objects)
const VRR_SKINSELECT_NONE = 0;
const VRR_SKINSELECT_SKIN = 1;
const VRR_SKINSELECT_HAT = 2;
@@ -111,3 +111,13 @@ const VRR_SKINSELECT_RIGHTWRIST = 10;
const VRR_SKINSELECT_LEFTHAND = 11;
const VRR_SKINSELECT_RIGHTHAND = 12;
const VRR_SKINSELECT_HEAD = 13;
+
+// Action States for NPCs
+const VRR_NPC_ACTION_NONE = 0;
+const VRR_NPC_ACTION_ANIM = 1;
+const VRR_NPC_ACTION_WALKTO = 2;
+const VRR_NPC_ACTION_RUNTO = 3;
+const VRR_NPC_ACTION_SPRINTTO = 4;
+const VRR_NPC_ACTION_FOLLOW = 5;
+const VRR_NPC_ACTION_DEFEND = 6;
+const VRR_NPC_ACTION_GUARD_AREA = 7;
\ No newline at end of file
diff --git a/scripts/shared/gamedata.js b/scripts/shared/gamedata.js
index 02f0a899..106f9685 100644
--- a/scripts/shared/gamedata.js
+++ b/scripts/shared/gamedata.js
@@ -432,7 +432,7 @@ let gameData = {
"Overcast/Cloudy",
"Grey/Cloudy"
],
- [VRR_GAME_GTA_IV_SA]: [ // GTA San Andreas
+ [VRR_GAME_GTA_SA]: [ // GTA San Andreas
"Blue Skies",
"Blue Skies",
"Blue Skies",
@@ -489,10 +489,10 @@ let gameData = {
[VRR_GAME_GTA_SA]: "GTA San Andreas",
[VRR_GAME_GTA_IV]: "GTA IV",
[VRR_GAME_GTA_IV_EFLC]: "GTA IV: Episodes from Liberty City",
- [VRR_GAME_GTA_MAFIA_ONE]: "Mafia: The City of Lost Heaven",
- [VRR_GAME_GTA_MAFIA_TWO]: "Mafia II",
- [VRR_GAME_GTA_MAFIA_THREE]: "Mafia III",
- [VRR_GAME_GTA_MAFIA_ONE_DE]: "Mafia Definitive Edition",
+ [VRR_GAME_MAFIA_ONE]: "Mafia: The City of Lost Heaven",
+ [VRR_GAME_MAFIA_TWO]: "Mafia II",
+ [VRR_GAME_MAFIA_THREE]: "Mafia III",
+ [VRR_GAME_MAFIA_ONE_DE]: "Mafia Definitive Edition",
[VRR_GAME_GTA_V]: "GTA V",
},
vehicleWheelStateNames: [
@@ -580,22 +580,22 @@ let gameData = {
[7 , "Wise Guy" , true ],
[8 , "Taxi Driver" , false],
[9 , "Pimp" , true ],
- [10 , "Mafia Member" , true ],
- [11 , "Mafia Member" , true ],
- [12 , "Triad Member" , true ],
- [13 , "Triad Member" , true ],
- [14 , "Diablo Member" , true ],
- [15 , "Diablo Member" , true ],
- [16 , "Yakuza Member" , true ],
- [17 , "Yakuza Member" , true ],
- [18 , "Yardie Member" , true ],
- [19 , "Yardie Member" , true ],
- [20 , "Cartel Soldier" , true ],
- [21 , "Cartel Soldier" , true ],
+ [10 , "Mafia Member 1" , true ],
+ [11 , "Mafia Member 2" , true ],
+ [12 , "Triad Member 1" , true ],
+ [13 , "Triad Member 2" , true ],
+ [14 , "Diablo Member 1" , true ],
+ [15 , "Diablo Member 2" , true ],
+ [16 , "Yakuza Member 1" , true ],
+ [17 , "Yakuza Member 2" , true ],
+ [18 , "Yardie Member 1" , true ],
+ [19 , "Yardie Member 2" , true ],
+ [20 , "Cartel Soldier 1" , true ],
+ [21 , "Cartel Soldier 2" , true ],
[22 , "Red Jacks Thug" , true ],
[23 , "Purple Nines Thug" , true ],
- [24 , "Street Criminal" , true ],
- [25 , "Street Criminal" , true ],
+ [24 , "Street Criminal 1" , true ],
+ [25 , "Street Criminal 2" , true ],
[30 , "Male Client" , true ],
[31 , "Random Guy" , true ],
[32 , "Vacationist" , true ],
@@ -603,28 +603,28 @@ let gameData = {
[34 , "Young Woman" , true ],
[35 , "Young Woman" , true ],
[36 , "Business Woman" , true ],
- [37 , "Elder Woman" , true ],
- [38 , "Elder Woman" , true ],
- [39 , "Prostitute" , true ],
- [40 , "Prostitute" , true ],
+ [37 , "Elder Woman 1" , true ],
+ [38 , "Elder Woman 2" , true ],
+ [39 , "Prostitute 1" , true ],
+ [40 , "Prostitute 2" , true ],
[41 , "Random Guy" , true ],
[42 , "Diseased Man" , true ],
[43 , "Deseased Woman" , true ],
[44 , "Young Woman" , true ],
- [45 , "Old Man" , true ],
+ [45 , "Old Man 1" , true ],
[46 , "Random Guy" , true ],
- [47 , "Old Woman" , true ],
- [48 , "Old Woman" , true ],
- [49 , "Old Man" , true ],
+ [47 , "Old Woman 1" , true ],
+ [48 , "Old Woman 2" , true ],
+ [49 , "Old Man 2" , true ],
[50 , "Random Guy" , true ],
- [51 , "Old Woman" , true ],
+ [51 , "Old Woman 3" , true ],
[52 , "Young Woman" , true ],
- [53 , "Docks Worker" , true ],
- [54 , "Docks Worker" , true ],
+ [53 , "Docks Worker 1" , true ],
+ [54 , "Docks Worker 2" , true ],
[55 , "Male Street Bum" , true ],
[56 , "Female Street Bum" , true ],
- [57 , "Delivery Guy" , true ],
- [58 , "Delivery Guy" , true ],
+ [57 , "Delivery Guy 1" , true ],
+ [58 , "Delivery Guy 2" , true ],
[59 , "Business Man" , true ],
[60 , "Marty Chonks" , true ],
[61 , "CIA Agent" , true ],
@@ -635,16 +635,16 @@ let gameData = {
[66 , "Female Client" , true ],
[67 , "Male Steward" , true ],
[68 , "Female Steward" , true ],
- [69 , "Male Cocks Fan" , true ],
- [70 , "Male Cocks Fan" , true ],
+ [69 , "Male Cocks Fan 1" , true ],
+ [70 , "Male Cocks Fan 2" , true ],
[71 , "Female Cocks Fan" , true ],
[72 , "Male Paramedics Assistant" , true ],
[73 , "Female Paramedics Assistant", true ],
- [74 , "Construction Worker" , true ],
- [75 , "Construction Worker" , true ],
+ [74 , "Construction Worker 1" , true ],
+ [75 , "Construction Worker 2" , true ],
[76 , "Zip Customer" , true ],
- [77 , "Party Woman" , true ],
- [78 , "Party Woman" , true ],
+ [77 , "Party Woman 1" , true ],
+ [78 , "Party Woman 2" , true ],
[80 , "Female College Student" , true ],
[81 , "Old Man" , true ],
[82 , "Female Jogger" , true ],
@@ -653,39 +653,45 @@ let gameData = {
[85 , "Salvatore's Butler" , true ],
[86 , "Catalina" , true ],
[87 , "Lee Chong" , true ],
- [88 , "Colombian Cartel Member" , true ],
- [89 , "Colombian Cartel Member" , true ],
- [90 , "Colombian Cartel Member" , true ],
- [91 , "Colombian Cartel Member" , true ],
+ [88 , "Colombian Cartel Member 1" , true ],
+ [89 , "Colombian Cartel Member 2" , true ],
+ [90 , "Colombian Cartel Member 3" , true ],
+ [91 , "Colombian Cartel Member 4" , true ],
[92 , "Police Officer" , false],
[93 , "Curly Bob" , true ],
[94 , "Phil Cassidy" , true ],
[95 , "Detective" , true ],
- [96 , "8-Ball" , true ],
- [97 , "8-Ball" , true ],
+ [96 , "8-Ball 1" , true ],
+ [97 , "8-Ball 2" , true ],
[98 , "Salvatore Leone" , true ],
[99 , "Mafia Member" , true ],
- [100, "Joey Leone" , true ],
- [101, "Joey Leone" , true ],
+ [100, "Joey Leone 1" , true ],
+ [101, "Joey Leone 2" , true ],
[102, "Bar Owner" , true ],
[103, "Kenji Kasen" , true ],
[104, "Mike Forelli" , true ],
- [105, "Donald Love" , true ],
- [106, "Donald Love" , true ],
+ [105, "Donald Love 1" , true ],
+ [106, "Donald Love 2" , true ],
[107, "Luigi Goterelli" , true ],
[108, "Maria Latore" , true ],
[109, "Mickey Hamfists" , true ],
[110, "Miguel" , true ],
[111, "Misty" , true ],
- [112, "Old Oriental Gentleman" , true ],
- [113, "Old Oriental Gentleman" , true ],
- [114, "Old Oriental Gentleman" , true ],
+ [112, "Old Oriental Gentleman 1" , true ],
+ [113, "Old Oriental Gentleman 2" , true ],
+ [114, "Old Oriental Gentleman 3" , true ],
[115, "Ray Machowski" , true ],
[116, "Mafia Member" , true ],
+ [117, "Ammunation Clerk" , true ],
[118, "Tanner" , true ],
[119, "Toni Cipriani" , true ],
[120, "Darkel" , true ],
[121, "Chuff Security Officer" , false],
+ [122, "Claude Speed (Prison)" , false],
+ [123, "Busker 1" , false],
+ [124, "Busker 2" , false],
+ [125, "Busker 3" , false],
+ [125, "Busker 4" , false],
],
[VRR_GAME_GTA_VC]: [
[0 , "Tommy Vercetti" , false],
@@ -696,104 +702,104 @@ let gameData = {
[5 , "Paramedic" , false],
[6 , "Fireman" , false],
[7 , "Golfer" , true ],
- [9 , "Random Lady" , true],
- [10 , "Bum" , true],
+ [9 , "Random Lady 1" , true],
+ [10 , "Bum 1" , true],
[11 , "Greaser" , true],
- [12 , "Random Guy" , true],
- [13 , "Random Guy" , true],
+ [12 , "Random Guy 1" , true],
+ [13 , "Random Guy 2" , true],
[14 , "Random Lady" , true],
- [15 , "Random Guy" , true],
- [16 , "Random Guy" , true],
- [17 , "Beach Girl" , true],
+ [15 , "Random Guy 3" , true],
+ [16 , "Random Guy 4" , true],
+ [17 , "Beach Lady 1" , true],
[18 , "Fat Beach Lady" , true ],
- [19 , "Beach Guy" , true ],
+ [19 , "Beach Guy 1" , true ],
[20 , "Fat Beach Guy" , true ],
- [21 , "Random Lady" , true ],
- [22 , "Random Lady" , true ],
- [23 , "Random Lady" , true ],
- [24 , "Prostitute" , true ],
- [25 , "Bum" , true ],
- [26 , "Bum" , true ],
+ [21 , "Random Lady 2" , true ],
+ [22 , "Random Lady 3" , true ],
+ [23 , "Random Lady 4" , true ],
+ [24 , "Prostitute 1" , true ],
+ [25 , "Bum 2" , true ],
+ [26 , "Bum 3" , true ],
[27 , "Random Guy" , true ],
- [28 , "Taxi Driver" , true ],
+ [28 , "Taxi Driver 1" , true ],
[29 , "Haitian" , true ],
[30 , "Criminal" , true ],
- [31 , "Random Lady" , true ],
- [32 , "Random Lady" , true ],
- [33 , "Random Guy" , true ],
- [34 , "Random Guy" , true ],
- [35 , "Random Lady" , true ],
- [36 , "Random Lady" , true ],
- [37 , "Random Guy" , true ],
- [38 , "Beach Lady" , true ],
- [39 , "Beach Guy" , true ],
- [40 , "Beach Lady" , true ],
- [41 , "Beach Guy" , true ],
- [42 , "Random Guy" , true ],
- [43 , "Prostitute" , true ],
- [44 , "Bum" , true ],
- [45 , "Bum" , true ],
- [46 , "Random Guy" , true ],
- [47 , "Random Guy" , true ],
- [48 , "Punk" , true ],
- [49 , "Prostitute" , true ],
+ [31 , "Random Lady 5" , true ],
+ [32 , "Random Lady 6" , true ],
+ [33 , "Random Guy 5" , true ],
+ [34 , "Random Guy 6" , true ],
+ [35 , "Random Lady 7" , true ],
+ [36 , "Random Lady 8" , true ],
+ [37 , "Random Guy 7" , true ],
+ [38 , "Beach Lady 2" , true ],
+ [39 , "Beach Guy 2" , true ],
+ [40 , "Beach Lady 3" , true ],
+ [41 , "Beach Guy 3" , true ],
+ [42 , "Random Guy 8" , true ],
+ [43 , "Prostitute 2" , true ],
+ [44 , "Bum 4" , true ],
+ [45 , "Bum 5" , true ],
+ [46 , "Random Guy 9" , true ],
+ [47 , "Random Guy 9" , true ],
+ [48 , "Punk 1" , true ],
+ [49 , "Prostitute 3" , true ],
[50 , "Random Old Lady" , true ],
- [51 , "Punk" , true ],
- [52 , "Random Guy" , true ],
- [53 , "Random Lady" , true ],
- [54 , "Random Lady" , true ],
- [55 , "Random Guy" , true ],
- [56 , "Random Guy" , true ],
+ [51 , "Punk 2" , true ],
+ [52 , "Random Guy 10" , true ],
+ [53 , "Random Lady 9" , true ],
+ [54 , "Random Lady 10" , true ],
+ [55 , "Random Guy 11" , true ],
+ [56 , "Random Guy 12" , true ],
[57 , "Beach Lady" , true ],
- [58 , "Beach Guy" , true ],
+ [58 , "Beach Guy 13" , true ],
[59 , "Beach Lady" , true ],
- [60 , "Beach Guy" , true ],
+ [60 , "Beach Guy 14" , true ],
[61 , "Construction Worker" , true ],
- [62 , "Golfer" , true ],
- [63 , "Golfer" , true ],
- [64 , "Golfer" , true ],
- [65 , "Beach Lady" , true ],
- [66 , "Beach Guy" , true ],
- [67 , "Random Lady" , true ],
- [68 , "Random Guy" , true ],
- [69 , "Random Guy" , true ],
- [70 , "Prostitute" , true ],
+ [62 , "Golfer 1" , true ],
+ [63 , "Golfer 2" , true ],
+ [64 , "Golfer 3" , true ],
+ [65 , "Beach Lady 4" , true ],
+ [66 , "Beach Guy 4" , true ],
+ [67 , "Random Lady 11" , true ],
+ [68 , "Random Guy 15" , true ],
+ [69 , "Random Guy 16" , true ],
+ [70 , "Prostitute 4" , true ],
[71 , "Bum Lady" , true ],
- [72 , "Random Guy" , true ],
- [73 , "Random Guy" , true ],
- [74 , "Taxi Driver" , true ],
+ [72 , "Random Guy 17" , true ],
+ [73 , "Random Guy 18" , true ],
+ [74 , "Taxi Driver 2" , true ],
[75 , "Random Woman" , true ],
- [76 , "Skater Guy" , true ],
- [77 , "Beach Lady" , true ],
- [78 , "Skater Guy" , true ],
+ [76 , "Skater Guy 1" , true ],
+ [77 , "Beach Lady 5" , true ],
+ [78 , "Skater Guy 2" , true ],
[79 , "Young Woman Shopper" , true ],
[80 , "Old Women Shopper" , true ],
- [81 , "Tourist" , true ],
- [82 , "Tourist" , true ],
- [83 , "Cuban" , true ],
- [84 , "Cuban" , true ],
- [85 , "Haitian" , true ],
- [86 , "Haitian" , true ],
- [87 , "Shark" , true ],
- [88 , "Shark" , true ],
- [89 , "Diaz Guy" , true ],
- [90 , "Diaz Guy" , true ],
- [91 , "Security Guard" , false],
- [92 , "Security Guard" , false],
- [93 , "Biker" , true ],
- [94 , "Biker" , true ],
- [95 , "Vercetti Guy" , true ],
- [96 , "Vercetti Guy" , true ],
- [97 , "Undercover Cop" , false],
- [98 , "Undercover Cop" , false],
- [99 , "Undercover Cop" , false],
- [100, "Undercover Cop " , false],
- [101, "Undercover Cop" , false],
- [102, "Undercover Cop" , false],
+ [81 , "Tourist 1" , true ],
+ [82 , "Tourist 2" , true ],
+ [83 , "Cuban 1" , true ],
+ [84 , "Cuban 2" , true ],
+ [85 , "Haitian 1" , true ],
+ [86 , "Haitian 2" , true ],
+ [87 , "Shark 1" , true ],
+ [88 , "Shark 2" , true ],
+ [89 , "Diaz Guy 1" , true ],
+ [90 , "Diaz Guy 2" , true ],
+ [91 , "Security Guard 1" , false],
+ [92 , "Security Guard 2" , false],
+ [93 , "Biker 1" , true ],
+ [94 , "Biker 2" , true ],
+ [95 , "Vercetti Guy 1" , true ],
+ [96 , "Vercetti Guy 2" , true ],
+ [97 , "Undercover Cop 1" , false],
+ [98 , "Undercover Cop 2" , false],
+ [99 , "Undercover Cop 3" , false],
+ [100, "Undercover Cop 4" , false],
+ [101, "Undercover Cop 5" , false],
+ [102, "Undercover Cop 6" , false],
[103, "Random Guy" , true ],
[104, "Bodyguard" , true ],
- [105, "Prostitute" , true ],
- [106, "Prostitute" , false],
+ [105, "Prostitute 1" , true ],
+ [106, "Prostitute 2" , false],
[107, "Ricardo Diaz" , true ],
[108, "Love Fist Guy" , true ],
[109, "Ken Rosenburg" , true ],
@@ -814,39 +820,39 @@ let gameData = {
[124, "Columbian" , true ],
[125, "Hilary" , true ],
[126, "Mercedes" , true ],
- [127, "Cam" , true ],
- [128, "Cam" , true ],
- [129, "Phil" , true ],
- [130, "Phil" , true ],
+ [127, "Cam 1" , true ],
+ [128, "Cam 2" , true ],
+ [129, "Phil 1" , true ],
+ [130, "Phil 2" , true ],
[131, "Bodyguard" , true ],
[132, "Pizza Worker" , true ],
- [133, "Taxi Driver" , true ],
- [134, "Taxi Driver" , true ],
- [135, "Sailor" , true ],
- [136, "Sailor" , true ],
- [137, "Sailor" , true ],
+ [133, "Taxi Driver 3" , true ],
+ [134, "Taxi Driver 4" , true ],
+ [135, "Sailor 1" , true ],
+ [136, "Sailor 2" , true ],
+ [137, "Sailor 3" , true ],
[138, "Chef" , true ],
[139, "Criminal" , true ],
//[140, "French Guy" , true ],
//[141, "Worker" , true ],
[142, "Haitian" , true ],
[143, "Waitress" , true ],
- [144, "Forelli Member" , true ],
- [145, "Forelli Member" , true ],
- [146, "Forelli Member" , true ],
+ [144, "Forelli Member 1" , true ],
+ [145, "Forelli Member 2" , true ],
+ [146, "Forelli Member 3" , true ],
[147, "Columbian" , true ],
- [148, "Random Guy" , true ],
+ [148, "Random Guy 19" , true ],
[149, "Beach Guy" , true ],
- [150, "Random Guy" , true ],
- [151, "Random Guy" , true ],
- [152, "Random Guy" , true ],
+ [150, "Random Guy 20" , true ],
+ [151, "Random Guy 21" , true ],
+ [152, "Random Guy 22" , true ],
[153, "Drag Queen" , true ],
[154, "Diaz Traitor" , true ],
- [155, "Random Guy" , true ],
- [156, "Random Guy" , true ],
- [157, "Stripper" , true ],
- [158, "Stripper" , true ],
- [159, "Stripper" , true ],
+ [155, "Random Guy 23" , true ],
+ [156, "Random Guy 24" , true ],
+ [157, "Stripper 1" , true ],
+ [158, "Stripper 2" , true ],
+ [159, "Stripper 3" , true ],
[160, "Store Clerk" , true ],
[161, "Tommy Vercetti" , true ],
[162, "Tommy Vercetti (Business Suit)" , true ],
@@ -859,22 +865,22 @@ let gameData = {
[169, "Tommy Vercetti (Striped Suit)" , true ],
[170, "Tommy Vercetti (Black Tracksuit)" , true ],
[171, "Tommy Vercetti (Red Tracksuit)" , true ],
- [172, "Club Bouncer" , true ],
- [173, "Club Bouncer" , true ],
- [174, "Stripclub Dancer" , true ],
- [175, "Random Guy" , true ],
- [176, "Stripclub Dancer" , true ],
- [177, "Stripclub Dancer" , true ],
- [178, "Stripclub Dancer" , true ],
- [179, "Gang Member" , true ],
+ [172, "Club Bouncer 1" , true ],
+ [173, "Club Bouncer 2" , true ],
+ [174, "Stripclub Dancer 1" , true ],
+ [175, "Random Guy 25" , true ],
+ [176, "Stripclub Dancer 2" , true ],
+ [177, "Stripclub Dancer 3" , true ],
+ [178, "Stripclub Dancer 4" , true ],
+ [179, "Gang Member 1" , true ],
[180, "Tommy Vercetti (Endgame T-Shirt)" , true ],
- [181, "Forelli Thug" , true ],
- [182, "Forelli Thug" , true ],
- [183, "Random Lady" , true ],
- [184, "Gang Member" , true ],
+ [181, "Forelli Thug 1" , true ],
+ [182, "Forelli Thug 2" , true ],
+ [183, "Random Lady 12" , true ],
+ [184, "Gang Member 2" , true ],
[185, "Party Waitress" , true ],
[186, "Kent Paul" , true ],
- [187, "Big Head Taxi Driver" , true ],
+ [187, "Big Head Taxi Driver" , false ],
],
[VRR_GAME_GTA_SA]: [
[0 , "Carl 'CJ' Johnson" , false],
@@ -5721,6 +5727,7 @@ let gameData = {
ConcertHall: [toVector3(-925.417, 1053.4, 13.2005), 8, false, -1],
RecordingStudio: [toVector3(-879.767, 1156.88, 17.8115), 9, false, -1],
PrintWorks: [toVector3(-1064.98, -279.093, 12.0882), 18, false, -1],
+ Gas: [toVector3(447.26, 789.09, 12.95), 0, false, -1],
},
[VRR_GAME_GTA_SA]: { // GTA SA
@@ -6244,201 +6251,201 @@ let gameData = {
1208856469
],
},
- vehicleUpgrades: {
- [VRR_GAME_GTA_SA]: { // GTA SA
- 1000: "Pro Spoiler",
- 1001: "Win Spoiler",
- 1002: "Drag Spoiler",
- 1003: "Alpha Spoiler",
- 1004: "Champ Scoop Hood",
- 1005: "Fury Scoop Hood",
- 1006: "Roof Scoop Roof",
- 1007: "Right Sideskirt",
- 1008: "5x Nitro",
- 1009: "2x Nitro",
- 1010: "10x Nitro",
- 1011: "Race Scoop Hood",
- 1012: "Worx Scoop Hood",
- 1013: "Round Fog Lamps",
- 1014: "Champ Spoiler",
- 1015: "Race Spoiler",
- 1016: "Worx Spoiler",
- 1017: "Left Sideskirt",
- 1018: "Upswept Exhaust",
- 1019: "Twin Exhaust",
- 1020: "Large Exhaust",
- 1021: "Medium Exhaust",
- 1022: "Small Exhaust",
- 1023: "Fury Spoiler",
- 1024: "Square Fog Lamps",
- 1025: "Offroad Wheels",
- 1026: "Right Alien Sideskirt",
- 1027: "Left Alien Sideskirt",
- 1028: "Alien Exhaust",
- 1029: "X-Flow Exhaust",
- 1030: "Left X-Flow Sideskirt",
- 1031: "Right X-Flow Sideskirt",
- 1032: "Alien Roof Vent Roof",
- 1033: "X-Flow Roof Vent Roof",
- 1034: "Alien Exhaust",
- 1035: "X-Flow Roof Vent Roof",
- 1036: "Right Alien Sideskirt",
- 1037: "X-Flow Exhaust",
- 1038: "Alien Roof Vent Roof",
- 1039: "Left X-Flow Sideskirt",
- 1040: "Left Alien Sideskirt",
- 1041: "Right X-Flow Sideskirt",
- 1042: "Right Chrome Sideskirt",
- 1043: "Slamin Exhaust",
- 1044: "Chrome Exhaust",
- 1045: "X-Flow Exhaust",
- 1046: "Alien Exhaust",
- 1047: "Right Alien Sideskirt",
- 1048: "Right X-Flow Sideskirt",
- 1049: "Alien Spoiler",
- 1050: "X-Flow Spoiler",
- 1051: "Left Alien Sideskirt",
- 1052: "Left X-Flow Sideskirt",
- 1053: "X-Flow Roof",
- 1054: "Alien Roof",
- 1055: "Alien Roof",
- 1056: "Right Alien Sideskirt",
- 1057: "Right X-Flow Sideskirt",
- 1058: "Alien Spoiler",
- 1059: "X-Flow Exhaust",
- 1060: "X-Flow Spoiler",
- 1061: "X-Flow Roof",
- 1062: "Left Alien Sideskirt",
- 1063: "Left X-Flow Sideskirt",
- 1064: "Alien Exhaust",
- 1065: "Alien Exhaust",
- 1066: "X-Flow Exhaust",
- 1067: "Alien Roof",
- 1068: "X-Flow Roof",
- 1069: "Right Alien Sideskirt",
- 1070: "Right X-Flow Sideskirt",
- 1071: "Left Alien Sideskirt",
- 1072: "Left X-Flow Sideskirt",
- 1073: "Shadow Wheels",
- 1074: "Mega Wheels",
- 1075: "Rimshine Wheels",
- 1076: "Wires Wheels",
- 1077: "Classic Wheels",
- 1078: "Twist Wheels",
- 1079: "Cutter Wheels",
- 1080: "Switch Wheels",
- 1081: "Grove Wheels",
- 1082: "Import Wheels",
- 1083: "Dollar Wheels",
- 1084: "Trance Wheels",
- 1085: "Atomic Wheels",
- 1086: "Stereo Stereo",
- 1087: "Hydraulics Hydraulics",
- 1088: "Alien Roof",
- 1089: "X-Flow Exhaust",
- 1090: "Right Alien Sideskirt",
- 1091: "X-Flow Roof",
- 1092: "Alien Exhaust",
- 1093: "Right X-Flow Sideskirt",
- 1094: "Left Alien Sideskirt",
- 1095: "Right X-Flow Sideskirt",
- 1096: "Ahab Wheels",
- 1097: "Virtual Wheels",
- 1098: "Access Wheels",
- 1099: "Left Chrome Sideskirt",
- 1100: "Chrome Grill Bullbar",
- 1101: "Left Chrome Flames Sideskirt",
- 1102: "Left Chrome Strip Sideskirt",
- 1103: "Covertible Roof",
- 1104: "Chrome Exhaust",
- 1105: "Slamin Exhaust",
- 1106: "Right Chrome Arches Sideskirt",
- 1107: "Left Chrome Strip Sideskirt",
- 1108: "Right Chrome Strip Sideskirt",
- 1109: "Chrome Rear Bullbars",
- 1110: "Slamin Rear Bullbars",
- 1113: "Chrome Exhaust",
- 1114: "Slamin Exhaust",
- 1115: "Chrome Front Bullbars",
- 1116: "Slamin Front Bullbars",
- 1117: "Chrome Front Bumper",
- 1118: "Right Chrome Trim Sideskirt",
- 1119: "Right Wheelcovers Sideskirt",
- 1120: "Left Chrome Trim Sideskirt",
- 1121: "Left Wheelcovers Sideskirt",
- 1122: "Right Chrome Flames Sideskirt",
- 1123: "Chrome Bars Bullbars",
- 1124: "Left Chrome Arches Sideskirt",
- 1125: "Chrome Lights Bullbars",
- 1126: "Chrome Exhaust Exhaust",
- 1127: "Slamin Exhaust Exhaust",
- 1128: "Vinyl Hardtop Roof",
- 1129: "Chrome Exhaust",
- 1130: "Hardtop Roof",
- 1131: "Softtop Roof",
- 1132: "Slamin Exhaust",
- 1133: "Right Chrome Strip Sideskirt",
- 1134: "Right Chrome Strip Sideskirt",
- 1135: "Slamin Exhaust",
- 1136: "Chrome Exhaust",
- 1137: "Left Chrome Strip Sideskirt",
- 1138: "Alien Spoiler",
- 1139: "X-Flow Spoiler",
- 1140: "X-Flow Rear Bumper",
- 1141: "Alien Rear Bumper",
- 1142: "Left Oval Vents Vents",
- 1143: "Right Oval Vents Vents",
- 1144: "Left Square Vents Vents",
- 1145: "Right Square Vents Vents",
- 1146: "X-Flow Spoiler",
- 1147: "Alien Spoiler",
- 1148: "X-Flow Rear Bumper",
- 1149: "Alien Rear Bumper",
- 1150: "Alien Rear Bumper",
- 1151: "X-Flow Rear Bumper",
- 1152: "X-Flow Front Bumper",
- 1153: "Alien Front Bumper",
- 1154: "Alien Rear Bumper",
- 1155: "Alien Front Bumper",
- 1156: "X-Flow Rear Bumper",
- 1157: "X-Flow Front Bumper",
- 1158: "X-Flow Spoiler",
- 1159: "Alien Rear Bumper",
- 1160: "Alien Front Bumper",
- 1161: "X-Flow Rear Bumper",
- 1162: "Alien Spoiler",
- 1163: "X-Flow Spoiler",
- 1164: "Alien Spoiler",
- 1165: "X-Flow Front Bumper",
- 1166: "Alien Front Bumper",
- 1167: "X-Flow Rear Bumper",
- 1168: "Alien Rear Bumper",
- 1169: "Alien Front Bumper",
- 1170: "X-Flow Front Bumper",
- 1171: "Alien Front Bumper",
- 1172: "X-Flow Front Bumper",
- 1173: "X-Flow Front Bumper",
- 1174: "Chrome Front Bumper",
- 1175: "Slamin Rear Bumper",
- 1176: "Chrome Front Bumper",
- 1177: "Slamin Rear Bumper",
- 1178: "Slamin Rear Bumper",
- 1179: "Chrome Front Bumper",
- 1180: "Chrome Rear Bumper",
- 1181: "Slamin Front Bumper",
- 1182: "Chrome Front Bumper",
- 1183: "Slamin Rear Bumper",
- 1184: "Chrome Rear Bumper",
- 1185: "Slamin Front Bumper",
- 1186: "Slamin Rear Bumper",
- 1187: "Chrome Rear Bumper",
- 1188: "Slamin Front Bumper",
- 1189: "Chrome Front Bumper",
- 1190: "Slamin Front Bumper",
- 1191: "Chrome Front Bumper",
- 1192: "Chrome Rear Bumper",
- 1193: "Slamin Rear Bumper"
- },
+ vehicleComponents: {
+ [VRR_GAME_GTA_SA]: [ // GTA SA
+ [1000, "Pro Spoiler"],
+ [1001, "Win Spoiler"],
+ [1002, "Drag Spoiler"],
+ [1003, "Alpha Spoiler"],
+ [1004, "Champ Scoop Hood"],
+ [1005, "Fury Scoop Hood"],
+ [1006, "Roof Scoop Roof"],
+ [1007, "Right Sideskirt"],
+ [1008, "5x Nitro"],
+ [1009, "2x Nitro"],
+ [1010, "10x Nitro"],
+ [1011, "Race Scoop Hood"],
+ [1012, "Worx Scoop Hood"],
+ [1013, "Round Fog Lamps"],
+ [1014, "Champ Spoiler"],
+ [1015, "Race Spoiler"],
+ [1016, "Worx Spoiler"],
+ [1017, "Left Sideskirt"],
+ [1018, "Upswept Exhaust"],
+ [1019, "Twin Exhaust"],
+ [1020, "Large Exhaust"],
+ [1021, "Medium Exhaust"],
+ [1022, "Small Exhaust"],
+ [1023, "Fury Spoiler"],
+ [1024, "Square Fog Lamps"],
+ [1025, "Offroad Wheels"],
+ [1026, "Right Alien Sideskirt"],
+ [1027, "Left Alien Sideskirt"],
+ [1028, "Alien Exhaust"],
+ [1029, "X-Flow Exhaust"],
+ [1030, "Left X-Flow Sideskirt"],
+ [1031, "Right X-Flow Sideskirt"],
+ [1032, "Alien Roof Vent Roof"],
+ [1033, "X-Flow Roof Vent Roof"],
+ [1034, "Alien Exhaust"],
+ [1035, "X-Flow Roof Vent Roof"],
+ [1036, "Right Alien Sideskirt"],
+ [1037, "X-Flow Exhaust"],
+ [1038, "Alien Roof Vent Roof"],
+ [1039, "Left X-Flow Sideskirt"],
+ [1040, "Left Alien Sideskirt"],
+ [1041, "Right X-Flow Sideskirt"],
+ [1042, "Right Chrome Sideskirt"],
+ [1043, "Slamin Exhaust"],
+ [1044, "Chrome Exhaust"],
+ [1045, "X-Flow Exhaust"],
+ [1046, "Alien Exhaust"],
+ [1047, "Right Alien Sideskirt"],
+ [1048, "Right X-Flow Sideskirt"],
+ [1049, "Alien Spoiler"],
+ [1050, "X-Flow Spoiler"],
+ [1051, "Left Alien Sideskirt"],
+ [1052, "Left X-Flow Sideskirt"],
+ [1053, "X-Flow Roof"],
+ [1054, "Alien Roof"],
+ [1055, "Alien Roof"],
+ [1056, "Right Alien Sideskirt"],
+ [1057, "Right X-Flow Sideskirt"],
+ [1058, "Alien Spoiler"],
+ [1059, "X-Flow Exhaust"],
+ [1060, "X-Flow Spoiler"],
+ [1061, "X-Flow Roof"],
+ [1062, "Left Alien Sideskirt"],
+ [1063, "Left X-Flow Sideskirt"],
+ [1064, "Alien Exhaust"],
+ [1065, "Alien Exhaust"],
+ [1066, "X-Flow Exhaust"],
+ [1067, "Alien Roof"],
+ [1068, "X-Flow Roof"],
+ [1069, "Right Alien Sideskirt"],
+ [1070, "Right X-Flow Sideskirt"],
+ [1071, "Left Alien Sideskirt"],
+ [1072, "Left X-Flow Sideskirt"],
+ [1073, "Shadow Wheels"],
+ [1074, "Mega Wheels"],
+ [1075, "Rimshine Wheels"],
+ [1076, "Wires Wheels"],
+ [1077, "Classic Wheels"],
+ [1078, "Twist Wheels"],
+ [1079, "Cutter Wheels"],
+ [1080, "Switch Wheels"],
+ [1081, "Grove Wheels"],
+ [1082, "Import Wheels"],
+ [1083, "Dollar Wheels"],
+ [1084, "Trance Wheels"],
+ [1085, "Atomic Wheels"],
+ [1086, "Stereo Stereo"],
+ [1087, "Hydraulics Hydraulics"],
+ [1088, "Alien Roof"],
+ [1089, "X-Flow Exhaust"],
+ [1090, "Right Alien Sideskirt"],
+ [1091, "X-Flow Roof"],
+ [1092, "Alien Exhaust"],
+ [1093, "Right X-Flow Sideskirt"],
+ [1094, "Left Alien Sideskirt"],
+ [1095, "Right X-Flow Sideskirt"],
+ [1096, "Ahab Wheels"],
+ [1097, "Virtual Wheels"],
+ [1098, "Access Wheels"],
+ [1099, "Left Chrome Sideskirt"],
+ [1100, "Chrome Grill Bullbar"],
+ [1101, "Left Chrome Flames Sideskirt"],
+ [1102, "Left Chrome Strip Sideskirt"],
+ [1103, "Covertible Roof"],
+ [1104, "Chrome Exhaust"],
+ [1105, "Slamin Exhaust"],
+ [1106, "Right Chrome Arches Sideskirt"],
+ [1107, "Left Chrome Strip Sideskirt"],
+ [1108, "Right Chrome Strip Sideskirt"],
+ [1109, "Chrome Rear Bullbars"],
+ [1110, "Slamin Rear Bullbars"],
+ [1113, "Chrome Exhaust"],
+ [1114, "Slamin Exhaust"],
+ [1115, "Chrome Front Bullbars"],
+ [1116, "Slamin Front Bullbars"],
+ [1117, "Chrome Front Bumper"],
+ [1118, "Right Chrome Trim Sideskirt"],
+ [1119, "Right Wheelcovers Sideskirt"],
+ [1120, "Left Chrome Trim Sideskirt"],
+ [1121, "Left Wheelcovers Sideskirt"],
+ [1122, "Right Chrome Flames Sideskirt"],
+ [1123, "Chrome Bars Bullbars"],
+ [1124, "Left Chrome Arches Sideskirt"],
+ [1125, "Chrome Lights Bullbars"],
+ [1126, "Chrome Exhaust Exhaust"],
+ [1127, "Slamin Exhaust Exhaust"],
+ [1128, "Vinyl Hardtop Roof"],
+ [1129, "Chrome Exhaust"],
+ [1130, "Hardtop Roof"],
+ [1131, "Softtop Roof"],
+ [1132, "Slamin Exhaust"],
+ [1133, "Right Chrome Strip Sideskirt"],
+ [1134, "Right Chrome Strip Sideskirt"],
+ [1135, "Slamin Exhaust"],
+ [1136, "Chrome Exhaust"],
+ [1137, "Left Chrome Strip Sideskirt"],
+ [1138, "Alien Spoiler"],
+ [1139, "X-Flow Spoiler"],
+ [1140, "X-Flow Rear Bumper"],
+ [1141, "Alien Rear Bumper"],
+ [1142, "Left Oval Vents Vents"],
+ [1143, "Right Oval Vents Vents"],
+ [1144, "Left Square Vents Vents"],
+ [1145, "Right Square Vents Vents"],
+ [1146, "X-Flow Spoiler"],
+ [1147, "Alien Spoiler"],
+ [1148, "X-Flow Rear Bumper"],
+ [1149, "Alien Rear Bumper"],
+ [1150, "Alien Rear Bumper"],
+ [1151, "X-Flow Rear Bumper"],
+ [1152, "X-Flow Front Bumper"],
+ [1153, "Alien Front Bumper"],
+ [1154, "Alien Rear Bumper"],
+ [1155, "Alien Front Bumper"],
+ [1156, "X-Flow Rear Bumper"],
+ [1157, "X-Flow Front Bumper"],
+ [1158, "X-Flow Spoiler"],
+ [1159, "Alien Rear Bumper"],
+ [1160, "Alien Front Bumper"],
+ [1161, "X-Flow Rear Bumper"],
+ [1162, "Alien Spoiler"],
+ [1163, "X-Flow Spoiler"],
+ [1164, "Alien Spoiler"],
+ [1165, "X-Flow Front Bumper"],
+ [1166, "Alien Front Bumper"],
+ [1167, "X-Flow Rear Bumper"],
+ [1168, "Alien Rear Bumper"],
+ [1169, "Alien Front Bumper"],
+ [1170, "X-Flow Front Bumper"],
+ [1171, "Alien Front Bumper"],
+ [1172, "X-Flow Front Bumper"],
+ [1173, "X-Flow Front Bumper"],
+ [1174, "Chrome Front Bumper"],
+ [1175, "Slamin Rear Bumper"],
+ [1176, "Chrome Front Bumper"],
+ [1177, "Slamin Rear Bumper"],
+ [1178, "Slamin Rear Bumper"],
+ [1179, "Chrome Front Bumper"],
+ [1180, "Chrome Rear Bumper"],
+ [1181, "Slamin Front Bumper"],
+ [1182, "Chrome Front Bumper"],
+ [1183, "Slamin Rear Bumper"],
+ [1184, "Chrome Rear Bumper"],
+ [1185, "Slamin Front Bumper"],
+ [1186, "Slamin Rear Bumper"],
+ [1187, "Chrome Rear Bumper"],
+ [1188, "Slamin Front Bumper"],
+ [1189, "Chrome Front Bumper"],
+ [1190, "Slamin Front Bumper"],
+ [1191, "Chrome Front Bumper"],
+ [1192, "Chrome Rear Bumper"],
+ [1193, "Slamin Rear Bumper"],
+ ]
},
fishingLocations: {
[VRR_GAME_GTA_SA]: [ // GTA San Andreas
@@ -6608,6 +6615,27 @@ let gameData = {
[VRR_GAME_MAFIA_THREE]: 0, // Mafia 3
[VRR_GAME_MAFIA_ONE_DE]: 0, // Mafia Definitive Edition
},
+ properties: {
+ [VRR_GAME_GTA_VC]: {
+ ApartmentBuilding1: {
+ businesses: [
+ ["Manager's Office", 0, 0, toVector3(217.12, -1271.71, 12.09), toVector3(115.48, -823.76, 10.463), 6, null],
+ ],
+ houses: [
+ ["Apartment 101", 0, 200, toVector3(212.33, -1288.79, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
+ ["Apartment 102", 0, 200, toVector3(214.12, -1281.61, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
+ ["Apartment 103", 0, 200, toVector3(218.84, -1275.62, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
+ ["Apartment 104", 0, 200, toVector3(225.40, -1279.77, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
+ ["Apartment 105", 0, 200, toVector3(218.24, -1277.98, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
+ ["Apartment 106", 0, 200, toVector3(209.08, -1275.73, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
+ ["Apartment 107", 0, 200, toVector3(209.76, -1273.40, 19.27), toVector3(26.67, -1328.89, 13.00), 11, null],
+ ],
+ npcs: [
+ ["Front Desk Clerk", 160, toVector(215.11, -1272.65, 12.09), 2.95],
+ ]
+ }
+ }
+ }
};
// ===========================================================================
\ No newline at end of file