diff --git a/meta.xml b/meta.xml
index effdf5eb..7bd670f8 100644
--- a/meta.xml
+++ b/meta.xml
@@ -15,7 +15,6 @@
-
@@ -26,7 +25,7 @@
-
+
@@ -34,10 +33,13 @@
+
+
+
@@ -47,7 +49,6 @@
-
diff --git a/scripts/client/event.js b/scripts/client/event.js
index bfb01abb..a7181e2d 100644
--- a/scripts/client/event.js
+++ b/scripts/client/event.js
@@ -166,6 +166,7 @@ function onLocalPlayerEnteredVehicle(event, vehicle, seat) {
sendNetworkEventToServer("vrr.onPlayerEnterVehicle", getVehicleForNetworkEvent(vehicle), seat);
+ //if (areServerElementsSupported()) {
//if(inVehicleSeat == 0) {
//setVehicleEngine(vehicle, false);
//if(!inVehicle.engine) {
@@ -173,6 +174,7 @@ function onLocalPlayerEnteredVehicle(event, vehicle, seat) {
// parkedVehicleHeading = inVehicle.heading;
//}
//}
+ //}
}
// ===========================================================================
diff --git a/scripts/client/utilities.js b/scripts/client/utilities.js
index f90dba4b..c692b6d5 100644
--- a/scripts/client/utilities.js
+++ b/scripts/client/utilities.js
@@ -208,10 +208,12 @@ function setLocalPlayerInterior(interior) {
//}
}
- let vehicles = getElementsByType(ELEMENT_VEHICLE);
- for (let i in vehicles) {
- if (getEntityData(vehicles[i], "vrr.interior")) {
- vehicles[i].interior = getEntityData(vehicles[i], "vrr.interior");
+ if (areServerElementsSupported() && isGameFeatureSupported("interior")) {
+ let vehicles = getElementsByType(ELEMENT_VEHICLE);
+ for (let i in vehicles) {
+ if (getEntityData(vehicles[i], "vrr.interior")) {
+ vehicles[i].interior = getEntityData(vehicles[i], "vrr.interior");
+ }
}
}
}
diff --git a/scripts/server/account.js b/scripts/server/account.js
index 1313c2f3..ba6b6d1e 100644
--- a/scripts/server/account.js
+++ b/scripts/server/account.js
@@ -7,6 +7,191 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Account Contact Types
+const VRR_CONTACT_NONE = 0;
+const VRR_CONTACT_NEUTRAL = 1; // Contact is neutral. Used for general contacts with no special additional features
+const VRR_CONTACT_FRIEND = 2; // Contact is a friend. Shows when they're online.
+const VRR_CONTACT_BLOCKED = 3; // Contact is blocked. Prevents all communication to/from them except for RP
+
+// ===========================================================================
+
+// Account Authentication Methods
+const VRR_ACCT_AUTHMETHOD_NONE = 0; // None
+const VRR_ACCT_AUTHMETHOD_EMAIL = 1; // Email
+const VRR_ACCT_AUTHMETHOD_PHONENUM = 2; // Phone number
+const VRR_ACCT_AUTHMETHOD_2FA = 3; // Two factor authentication app (authy, google authenticator, etc)
+const VRR_ACCT_AUTHMETHOD_PEBBLE = 4; // Pebble watch (this one's for Vortrex but anybody with a Pebble can use)
+const VRR_ACCT_AUTHMETHOD_PHONEAPP = 5; // The Android/iOS companion app (will initially be a web based thing until I can get the apps created)
+
+// ===========================================================================
+
+// Two-Factor Authentication States
+const VRR_2FA_STATE_NONE = 0; // None
+const VRR_2FA_STATE_CODEINPUT = 1; // Waiting on player to enter code to play
+const VRR_2FA_STATE_SETUP_CODETOAPP = 2; // Providing player with a code to put in their auth app
+const VRR_2FA_STATE_SETUP_CODEFROMAPP = 3; // Waiting on player to enter code from auth app to set up
+
+// ===========================================================================
+
+// Reset Password States
+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
+
+// ===========================================================================
+
+/**
+ * @class Representing an account, loaded/saved in the database
+ */
+class AccountData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.password = "";
+ this.registerDate = 0;
+ this.flags = {
+ moderation: 0,
+ admin: 0,
+ };
+ this.staffTitle = "";
+ this.ircAccount = "";
+ this.discordAccount = 0;
+ this.settings = 0;
+ this.emailAddress = "";
+ this.ipAddress = 0;
+
+ this.notes = [];
+ this.messages = [];
+ this.contacts = [];
+ this.subAccounts = [];
+
+ this.emailVerificationCode = "";
+ this.twoFactorAuthVerificationCode = "";
+
+ this.chatScrollLines = 1;
+
+ this.streamingRadioVolume = 20;
+ this.locale = 0;
+
+ if (dbAssoc) {
+ this.databaseId = dbAssoc["acct_id"];
+ this.name = dbAssoc["acct_name"];
+ this.password = dbAssoc["acct_pass"];
+ this.registerDate = dbAssoc["acct_when_made"];
+ this.flags = {
+ moderation: dbAssoc["acct_svr_mod_flags"],
+ admin: dbAssoc["acct_svr_staff_flags"],
+ };
+ this.staffTitle = dbAssoc["acct_svr_staff_title"];
+ this.ircAccount = dbAssoc["acct_irc"];
+ this.discordAccount = dbAssoc["acct_discord"];
+ this.settings = dbAssoc["acct_svr_settings"];
+ this.emailAddress = dbAssoc["acct_email"];
+ this.whenRegistered = dbAssoc["acct_when_registered"];
+ this.ipAddress = dbAssoc["acct_ip"];
+
+ this.notes = [];
+ this.messages = [];
+ this.contacts = [];
+ this.subAccounts = [];
+
+ this.emailVerificationCode = dbAssoc["acct_code_verifyemail"];
+ this.twoFactorAuthVerificationCode = dbAssoc["acct_code_2fa"];
+ this.chatScrollLines = toInteger(dbAssoc["acct_svr_chat_scroll_lines"]);
+ this.streamingRadioVolume = toInteger(dbAssoc["acct_streaming_radio_volume"]);
+ this.locale = toInteger(dbAssoc["acct_locale"]);
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing an account's contact list, loaded/saved in the database
+ */
+class AccountContactData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.accountId = 0;
+ this.contactAccountId = 0;
+ this.type = 0;
+ this.whenAdded = 0;
+ this.needsSaved = false;
+
+ if (dbAssoc) {
+ this.databaseId = dbAssoc["acct_contact_id"];
+ this.accountId = dbAssoc["acct_contact_acct"];
+ this.contactAccountId = dbAssoc["acct_contact_contact"];
+ this.type = dbAssoc["acct_contact_type"];
+ this.whenAdded = dbAssoc["acct_contact_when_added"];
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing an account's messages, loaded/saved in the database
+ */
+class AccountMessageData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.account = 0;
+ this.whoSent = 0;
+ this.whenSent = 0;
+ this.whenRead = 0;
+ this.deleted = false;
+ this.whenDeleted = 0;
+ this.folder = 0;
+ this.message = "";
+ this.needsSaved = false;
+
+ if (dbAssoc) {
+ this.databaseId = dbAssoc["acct_msg_id"];
+ this.account = dbAssoc["acct_msg_acct"];
+ this.whoSent = dbAssoc["acct_msg_who_sent"];
+ this.whenSent = dbAssoc["acct_msg_when_sent"];
+ this.whenRead = dbAssoc["acct_msg_when_read"];
+ this.deleted = intToBool(dbAssoc["acct_msg_deleted"]);
+ this.whenDeleted = dbAssoc["acct_msg_when_deleted"];
+ this.folder = dbAssoc["acct_msg_folder"];
+ this.message = dbAssoc["acct_msg_message"];
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing an account's staff notes. Visible only to staff and loaded/saved in the database
+ */
+class AccountStaffNoteData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.account = 0;
+ this.whoAdded = 0;
+ this.whenAdded = 0;
+ this.deleted = false;
+ this.whenDeleted = 0;
+ this.serverId = 0;
+ this.note = "";
+ this.needsSaved = false;
+
+ if (dbAssoc) {
+ this.databaseId = dbAssoc["acct_note_id"];
+ this.account = dbAssoc["acct_note_acct"];
+ this.whoAdded = dbAssoc["acct_note_who_added"];
+ this.whenAdded = dbAssoc["acct_note_when_added"];
+ this.deleted = intToBool(dbAssoc["acct_note_deleted"]);
+ this.whenDeleted = dbAssoc["acct_note_when_deleted"];
+ this.serverId = dbAssoc["acct_note_server"];
+ this.note = dbAssoc["acct_note_message"];
+ }
+ }
+};
+
+// ===========================================================================
+
function initAccountScript() {
logToConsole(LOG_DEBUG, "[VRR.Account]: Initializing account script ...");
logToConsole(LOG_DEBUG, "[VRR.Account]: Account script initialized!");
@@ -801,9 +986,10 @@ function createAccount(name, password, email = "") {
// ===========================================================================
-function checkLogin(client, password) {
+async function checkLogin(client, password) {
getPlayerData(client).loginAttemptsRemaining = getPlayerData(client).loginAttemptsRemaining - 1;
if (getPlayerData(client).loginAttemptsRemaining <= 0) {
+ getPlayerData(client).customDisconnectReason = "Kicked - Failed to login";
disconnectPlayer(client);
}
@@ -840,9 +1026,10 @@ function checkLogin(client, password) {
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the login message (GUI disabled) with ${getPlayerData(client).loginAttemptsRemaining} login attempts remaining alert.`);
}
- if (isAccountEmailVerified(getPlayerData(client).accountData) && !isAccountSettingFlagEnabled(getPlayerData(client).accountData, getAccountSettingsFlagValue("AuthAttemptAlert"))) {
- sendAccountLoginFailedNotification(getPlayerData(client).accountData.emailAddress, getPlayerName(client), getPlayerIP(client), getGame());
- }
+ // Disabling email login alerts for now. It hangs the server for a couple seconds. Need a way to thread it.
+ //if (isAccountEmailVerified(getPlayerData(client).accountData) && !isAccountSettingFlagEnabled(getPlayerData(client).accountData, getAccountSettingsFlagValue("AuthAttemptAlert"))) {
+ // await sendAccountLoginFailedNotification(getPlayerData(client).accountData.emailAddress, getPlayerName(client), getPlayerIP(client), getGame());
+ //}
return false;
}
@@ -856,9 +1043,10 @@ function checkLogin(client, password) {
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the login message (GUI disabled) with ${getPlayerData(client).loginAttemptsRemaining} login attempts remaining alert.`);
}
- if (isAccountEmailVerified(getPlayerData(client).accountData) && !isAccountSettingFlagEnabled(getPlayerData(client).accountData, getAccountSettingsFlagValue("AuthAttemptAlert"))) {
- sendAccountLoginFailedNotification(getPlayerData(client).accountData.emailAddress, getPlayerName(client), getPlayerIP(client), getGame());
- }
+ // Disabling email login alerts for now. It hangs the server for a couple seconds. Need a way to thread it.
+ //if (isAccountEmailVerified(getPlayerData(client).accountData) && !isAccountSettingFlagEnabled(getPlayerData(client).accountData, getAccountSettingsFlagValue("AuthAttemptAlert"))) {
+ // await sendAccountLoginFailedNotification(getPlayerData(client).accountData.emailAddress, getPlayerName(client), getPlayerIP(client), getGame());
+ //}
return false;
}
@@ -875,9 +1063,10 @@ function checkLogin(client, password) {
loginSuccess(client);
- if (isAccountEmailVerified(getPlayerData(client).accountData) && !isAccountSettingFlagEnabled(getPlayerData(client).accountData, getAccountSettingsFlagValue("AuthAttemptAlert"))) {
- sendAccountLoginSuccessNotification(getPlayerData(client).accountData.emailAddress, getPlayerName(client), getPlayerIP(client), getGame());
- }
+ // Disabling email login alerts for now. It hangs the server for a couple seconds. Need a way to thread it.
+ //if (isAccountEmailVerified(getPlayerData(client).accountData) && !isAccountSettingFlagEnabled(getPlayerData(client).accountData, getAccountSettingsFlagValue("AuthAttemptAlert"))) {
+ // await sendAccountLoginSuccessNotification(getPlayerData(client).accountData.emailAddress, getPlayerName(client), getPlayerIP(client), getGame());
+ //}
}
// ===========================================================================
@@ -984,6 +1173,7 @@ function checkRegistration(client, password, confirmPassword = "", emailAddress
if (doesServerHaveTesterOnlyEnabled() && !isPlayerATester(client)) {
setTimeout(function () {
+ getPlayerData(client).customDisconnectReason = "Kicked - Not a tester";
disconnectPlayer(client);
}, 5000);
@@ -1029,22 +1219,23 @@ function checkAccountResetPasswordRequest(client, inputText) {
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 ...`);
+ logToConsole(LOG_INFO, `${getPlayerDisplayForConsole(client)} submitted successful email for password reset. Sending email and awaiting verification code input (${passwordResetCode}) ...`);
break;
}
case VRR_RESETPASS_STATE_CODEINPUT: {
+ logToConsole(LOG_INFO, `${getPlayerDisplayForConsole(client)} submitted code for password reset (${inputText}) ...`);
if (inputText != "") {
if (getPlayerData(client).passwordResetCode == toUpperCase(inputText)) {
getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_SETPASS;
- showPlayerChangePasswordGUI(client, getLocaleString(client));
+ showPlayerChangePasswordGUI(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 ...)`);
+ getPlayerData(client).customDisconnectReason = "Kicked - Failed to login";
disconnectPlayer(client);
return false;
}
@@ -1191,8 +1382,8 @@ function initClient(client) {
sendPlayerGUIInit(client);
updatePlayerSnowState(client);
- logToConsole(LOG_DEBUG, `[VRR.Account] Showing connect camera to ${getPlayerDisplayForConsole(client)} ...`);
- showConnectCameraToPlayer(client);
+ //logToConsole(LOG_DEBUG, `[VRR.Account] Showing connect camera to ${getPlayerDisplayForConsole(client)} ...`);
+ //showConnectCameraToPlayer(client);
messageClient(`Please wait ...`, client, getColourByName("softGreen"));
@@ -1541,7 +1732,7 @@ function sendAccountLoginSuccessNotification(emailAddress, name, ip, game = getG
emailBodyText = emailBodyText.replace("{SERVERNAME}", getServerName());
emailBodyText = emailBodyText.replace("{TIMESTAMP}", new Date().toLocaleString('en-US'));
- sendEmail(emailAddress, name, `Login failed on ${getServerName()}`, emailBodyText);
+ sendEmail(emailAddress, name, `Login successful on ${getServerName()}`, emailBodyText);
return true;
}
@@ -1567,6 +1758,7 @@ function checkPlayerTwoFactorAuthentication(client, authCode) {
}
}
+ getPlayerData(client).customDisconnectReason = "Kicked - Failed to login";
disconnectPlayer(client);
return false;
}
diff --git a/scripts/server/ban.js b/scripts/server/ban.js
index 6f42cd31..9c983e05 100644
--- a/scripts/server/ban.js
+++ b/scripts/server/ban.js
@@ -7,6 +7,36 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Ban Types
+const VRR_BANTYPE_NONE = 0;
+const VRR_BANTYPE_ACCOUNT = 1;
+const VRR_BANTYPE_SUBACCOUNT = 2;
+const VRR_BANTYPE_IPADDRESS = 3;
+const VRR_BANTYPE_SUBNET = 4;
+
+// ===========================================================================
+
+class BanData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.type = VRR_BANTYPE_NONE;
+ this.detail = "";
+ this.ipAddress = "";
+ this.name = "";
+ this.reason = "";
+
+ if (dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["ban_id"]);
+ this.type = dbAssoc["ban_type"];
+ this.detail = toInteger(dbAssoc["ban_detail"]);
+ this.ipAddress = toInteger(dbAssoc["ban_ip"]);
+ this.reason = toInteger(dbAssoc["ban_reason"]);
+ }
+ }
+}
+
+// ===========================================================================
+
function initBanScript() {
logToConsole(LOG_INFO, "[VRR.Ban]: Initializing ban script ...");
logToConsole(LOG_INFO, "[VRR.Ban]: Ban script initialized!");
@@ -15,7 +45,7 @@ function initBanScript() {
// ===========================================================================
function accountBanCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -24,28 +54,30 @@ function accountBanCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let reason = splitParams.slice(1).join(" ");
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, "That player is not connected!")
return false;
}
// Prevent banning admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, "ManageServer") || doesPlayerHaveStaffPermission(targetClient, "Developer")) {
+ if (doesPlayerHaveStaffPermission(targetClient, "ManageServer") || doesPlayerHaveStaffPermission(targetClient, "Developer")) {
messagePlayerError(client, getLocaleString(client, "CantBanPlayer"));
return false;
}
logToConsole(LOG_WARN, `[VRR.Ban]: ${getPlayerDisplayForConsole(targetClient)} (${getPlayerData(targetClient).accountData.name}) account was banned by ${getPlayerDisplayForConsole(client)}. Reason: ${reason}`);
- announceAdminAction(`PlayerAccountBanned`, `{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR}`);
+ announceAdminAction(`PlayerAccountBanned`, `{ALTCOLOUR}${getPlayerName(targetClient)}{MAINCOLOUR}`);
banAccount(getPlayerData(targetClient).accountData.databaseId, getPlayerData(client).accountData.databaseId, reason);
- disconnectPlayer(client);
+
+ getPlayerData(targetClient).customDisconnectReason = `Banned - ${reason}`;
+ disconnectPlayer(targetClient);
}
// ===========================================================================
function subAccountBanCommand(command, params, client, fromDiscord) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -54,29 +86,30 @@ function subAccountBanCommand(command, params, client, fromDiscord) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let reason = splitParams.slice(1).join(" ");
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, "That player is not connected!")
return false;
}
// Prevent banning admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, "ManageServer") || doesPlayerHaveStaffPermission(targetClient, "Developer")) {
+ if (doesPlayerHaveStaffPermission(targetClient, "ManageServer") || doesPlayerHaveStaffPermission(targetClient, "Developer")) {
messagePlayerError(client, getLocaleString(client, "CantBanPlayer"));
return false;
}
logToConsole(LOG_WARN, `[VRR.Ban]: ${getPlayerDisplayForConsole(targetClient)} (${getPlayerData(targetClient).accountData.name})'s subaccount was banned by ${getPlayerDisplayForConsole(client)}. Reason: ${reason}`);
- announceAdminAction(`PlayerCharacterBanned`, `{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR}`);
+ announceAdminAction(`PlayerCharacterBanned`, `{ALTCOLOUR}${getPlayerName(targetClient)}{MAINCOLOUR}`);
banSubAccount(getPlayerData(targetClient).currentSubAccountData.databaseId, getPlayerData(client).accountData.databaseId, reason);
- disconnectPlayer(client);
+ getPlayerData(targetClient).customDisconnectReason = `Banned - ${reason}`;
+ disconnectPlayer(targetClient);
}
// ===========================================================================
function ipBanCommand(command, params, client, fromDiscord) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -85,13 +118,13 @@ function ipBanCommand(command, params, client, fromDiscord) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let reason = splitParams.slice(1).join(" ");
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, "That player is not connected!")
return false;
}
// Prevent banning admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, "ManageServer") || doesPlayerHaveStaffPermission(targetClient, "Developer")) {
+ if (doesPlayerHaveStaffPermission(targetClient, "ManageServer") || doesPlayerHaveStaffPermission(targetClient, "Developer")) {
messagePlayerError(client, getLocaleString(client, "CantBanPlayer"));
return false;
}
@@ -99,6 +132,7 @@ function ipBanCommand(command, params, client, fromDiscord) {
announceAdminAction(`PlayerIPBanned`, `{ALTCOLOUR}${getPlayerName(targetClient)}{MAINCOLOUR}`);
banIPAddress(getPlayerIP(targetClient), getPlayerData(client).accountData.databaseId, reason);
+ getPlayerData(targetClient).customDisconnectReason = `IP Banned - ${reason}`;
serverBanIP(getPlayerIP(targetClient));
disconnectPlayer(targetClient);
}
@@ -106,7 +140,7 @@ function ipBanCommand(command, params, client, fromDiscord) {
// ===========================================================================
function subNetBanCommand(command, params, client, fromDiscord) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -116,13 +150,13 @@ function subNetBanCommand(command, params, client, fromDiscord) {
let octetAmount = Number(getParam(params, " ", 2));
let reason = splitParams.slice(2).join(" ");
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, "That player is not connected!")
return false;
}
// Prevent banning admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, "ManageServer") || doesPlayerHaveStaffPermission(targetClient, "Developer")) {
+ if (doesPlayerHaveStaffPermission(targetClient, "ManageServer") || doesPlayerHaveStaffPermission(targetClient, "Developer")) {
messagePlayerError(client, getLocaleString(client, "CantBanPlayer"));
return false;
}
@@ -130,6 +164,7 @@ function subNetBanCommand(command, params, client, fromDiscord) {
announceAdminAction(`PlayerSubNetBanned`, `{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR}`);
banSubNet(getPlayerIP(targetClient), getSubNet(getPlayerIP(targetClient), octetAmount), getPlayerData(client).accountData.databaseId, reason);
+ getPlayerData(client).customDisconnectReason = `IP Subnet Banned - ${reason}`;
serverBanIP(getPlayerIP(targetClient));
}
@@ -137,7 +172,7 @@ function subNetBanCommand(command, params, client, fromDiscord) {
function banAccount(accountId, adminAccountId, reason) {
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let safeReason = dbConnection.escapetoString(reason);
let dbQuery = queryDatabase(dbConnection, `INSERT INTO ban_main (ban_type, ban_detail, ban_who_banned, ban_reason) VALUES (${VRR_BANTYPE_ACCOUNT}, ${accountId}, ${adminAccountId}, '${safeReason}');`);
freeDatabaseQuery(dbQuery);
@@ -152,7 +187,7 @@ function banAccount(accountId, adminAccountId, reason) {
function banSubAccount(subAccountId, adminAccountId, reason) {
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let safeReason = dbConnection.escapetoString(reason);
let dbQuery = queryDatabase(dbConnection, `INSERT INTO ban_main (ban_type, ban_detail, ban_who_banned, ban_reason) VALUES (${VRR_BANTYPE_SUBACCOUNT}, ${subAccountId}, ${adminAccountId}, '${safeReason}');`);
freeDatabaseQuery(dbQuery);
@@ -167,7 +202,7 @@ function banSubAccount(subAccountId, adminAccountId, reason) {
function banIPAddress(ipAddress, adminAccountId, reason) {
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let safeReason = dbConnection.escapetoString(reason);
let dbQuery = queryDatabase(dbConnection, `INSERT INTO ban_main (ban_type, ban_detail, ban_who_banned, ban_reason) VALUES (${VRR_BANTYPE_IPADDRESS}, INET_ATON(${ipAddress}), ${adminAccountId}, '${safeReason}');`);
freeDatabaseQuery(dbQuery);
@@ -182,7 +217,7 @@ function banIPAddress(ipAddress, adminAccountId, reason) {
function banSubNet(ipAddressStart, ipAddressEnd, adminAccountId, reason) {
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let safeReason = dbConnection.escapetoString(reason);
let dbQuery = queryDatabase(dbConnection, `INSERT INTO ban_main (ban_type, ban_ip_start, ban_ip_end, ban_who_banned, ban_reason) VALUES (${VRR_BANTYPE_SUBNET}, INET_ATON(${ipAddressStart}), INET_ATON(${ipAddressEnd}), ${adminAccountId}, '${safeReason}');`);
freeDatabaseQuery(dbQuery);
@@ -197,7 +232,7 @@ function banSubNet(ipAddressStart, ipAddressEnd, adminAccountId, reason) {
function unbanAccount(accountId, adminAccountId) {
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let dbQuery = queryDatabase(dbConnection, `UPDATE ban_main SET ban_who_removed=${adminAccountId}, ban_removed=1 WHERE ban_type=${VRR_BANTYPE_ACCOUNT} AND ban_detail=${accountId}`);
freeDatabaseQuery(dbQuery);
dbConnection.close();
@@ -211,7 +246,7 @@ function unbanAccount(accountId, adminAccountId) {
function unbanSubAccount(subAccountId, adminAccountId) {
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let dbQuery = queryDatabase(dbConnection, `UPDATE ban_main SET ban_who_removed=${adminAccountId}, ban_removed=1 WHERE ban_type=${VRR_BANTYPE_SUBACCOUNT} AND ban_detail=${subAccountId}`);
freeDatabaseQuery(dbQuery);
dbConnection.close();
@@ -225,7 +260,7 @@ function unbanSubAccount(subAccountId, adminAccountId) {
function unbanIPAddress(ipAddress, adminAccountId) {
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let dbQuery = queryDatabase(dbConnection, `UPDATE ban_main SET ban_who_removed=${adminAccountId}, ban_removed=1 WHERE ban_type=${VRR_BANTYPE_IPADDRESS} AND ban_detail=INET_ATON(${ipAddress})`);
freeDatabaseQuery(dbQuery);
dbConnection.close();
@@ -239,7 +274,7 @@ function unbanIPAddress(ipAddress, adminAccountId) {
function unbanSubNet(ipAddressStart, ipAddressEnd, adminAccountId) {
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let dbQuery = queryDatabase(dbConnection, `UPDATE ban_main SET ban_who_removed=${adminAccountId}, ban_removed=1 WHERE ban_type=${VRR_BANTYPE_SUBNET} AND ban_ip_start=INET_ATON(${ipAddressStart}) AND ban_ip_end=INET_ATON(${ipAddressEnd})`);
freeDatabaseQuery(dbQuery);
dbConnection.close();
@@ -253,7 +288,7 @@ function unbanSubNet(ipAddressStart, ipAddressEnd, adminAccountId) {
function isAccountBanned(accountId) {
let bans = getServerData().bans.filter(ban => ban.type === VRR_BANTYPE_ACCOUNT && ban.detail === accountId);
- if(bans.length > 0) {
+ if (bans.length > 0) {
return true;
}
@@ -264,7 +299,7 @@ function isAccountBanned(accountId) {
function isSubAccountBanned(subAccountId) {
let bans = getServerData().bans.filter(ban => ban.type === VRR_BANTYPE_SUBACCOUNT && ban.detail === subAccountId);
- if(bans.length > 0) {
+ if (bans.length > 0) {
return true;
}
@@ -275,7 +310,7 @@ function isSubAccountBanned(subAccountId) {
function isIpAddressBanned(ipAddress) {
let bans = getServerData().bans.filter(ban => ban.type === VRR_BANTYPE_IPADDRESS && ban.detail === ipAddress);
- if(bans.length > 0) {
+ if (bans.length > 0) {
return true;
}
diff --git a/scripts/server/business.js b/scripts/server/business.js
index 084b04f4..909289bf 100644
--- a/scripts/server/business.js
+++ b/scripts/server/business.js
@@ -7,10 +7,171 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Business Types
+const VRR_BIZ_TYPE_NONE = 0; // None (invalid)
+const VRR_BIZ_TYPE_NORMAL = 1; // Normal business (sells items)
+const VRR_BIZ_TYPE_BANK = 2; // Bank
+const VRR_BIZ_TYPE_PUBLIC = 3; // Public business (Government, public service, etc)
+
+// ===========================================================================
+
+// Business Location Types
+const VRR_BIZLOC_NONE = 0; // None
+const VRR_BIZLOC_GATE = 1; // Center of any moveable gate that belongs to the biz
+const VRR_BIZLOC_GARAGE = 2; // Location for attached garage (pos1 = outside, pos2 = inside). Use pos to teleport or spawn veh/ped
+const VRR_BIZLOC_FUEL = 3; // Fuel pump
+const VRR_BIZLOC_DRIVETHRU = 4; // Drivethrough
+const VRR_BIZLOC_VENDMACHINE = 5; // Vending machine
+
+// ===========================================================================
+
+// Business Owner Types
+const VRR_BIZOWNER_NONE = 0; // Not owned
+const VRR_BIZOWNER_PLAYER = 1; // Owned by a player (character/subaccount)
+const VRR_BIZOWNER_JOB = 2; // Owned by a job
+const VRR_BIZOWNER_CLAN = 3; // Owned by a clan
+const VRR_BIZOWNER_FACTION = 4; // Owned by a faction (not used at the moment)
+const VRR_BIZOWNER_PUBLIC = 5; // Public Business. Used for goverment/official places like police, fire, city hall, DMV, etc
+
+// ===========================================================================
+
+/**
+ * @class Representing a businesses' data. Loaded and saved in the database
+ */
+class BusinessData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.ownerType = VRR_BIZOWNER_NONE;
+ this.ownerId = 0;
+ this.buyPrice = 0;
+ this.locked = false;
+ this.hasInterior = false;
+ this.index = -1;
+ this.needsSaved = false;
+ this.interiorLights = true;
+
+ this.floorItemCache = [];
+ this.storageItemCache = [];
+ this.locations = [];
+ this.gameScripts = [];
+
+ this.entrancePosition = false;
+ this.entranceRotation = 0.0;
+ this.entranceInterior = 0;
+ this.entranceDimension = 0;
+ this.entrancePickupModel = -1;
+ this.entranceBlipModel = -1;
+ this.entrancePickup = null;
+ this.entranceBlip = null;
+
+ this.exitPosition = false;
+ this.exitRotation = 0.0;
+ this.exitInterior = 0;
+ this.exitDimension = 0;
+ this.exitPickupModel = -1;
+ this.exitBlipModel = -1;
+ this.exitPickup = null;
+ this.exitBlip = null;
+
+ this.entranceFee = 0;
+ this.till = 0;
+
+ this.streamingRadioStation = -1;
+
+ this.labelHelpType = VRR_PROPLABEL_INFO_NONE;
+
+ if (dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["biz_id"]);
+ this.name = toString(dbAssoc["biz_name"]);
+ this.ownerType = toInteger(dbAssoc["biz_owner_type"]);
+ this.ownerId = toInteger(dbAssoc["biz_owner_id"]);
+ this.buyPrice = toInteger(dbAssoc["biz_buy_price"]);
+ this.locked = intToBool(toInteger(dbAssoc["biz_locked"]));
+ this.hasInterior = intToBool(toInteger(dbAssoc["biz_has_interior"]));
+ this.interiorLights = intToBool(toInteger(dbAssoc["biz_interior_lights"]));
+
+ this.entrancePosition = toVector3(toFloat(dbAssoc["biz_entrance_pos_x"]), toFloat(dbAssoc["biz_entrance_pos_y"]), toFloat(dbAssoc["biz_entrance_pos_z"]));
+ this.entranceRotation = toInteger(dbAssoc["biz_entrance_rot_z"]);
+ this.entranceInterior = toInteger(dbAssoc["biz_entrance_int"]);
+ this.entranceDimension = toInteger(dbAssoc["biz_entrance_vw"]);
+ this.entrancePickupModel = toInteger(dbAssoc["biz_entrance_pickup"]);
+ this.entranceBlipModel = toInteger(dbAssoc["biz_entrance_blip"]);
+
+ this.exitPosition = toVector3(dbAssoc["biz_exit_pos_x"], dbAssoc["biz_exit_pos_y"], dbAssoc["biz_exit_pos_z"]);
+ this.exitRotation = toInteger(dbAssoc["biz_exit_rot_z"]);
+ this.exitInterior = toInteger(dbAssoc["biz_exit_int"]);
+ this.exitDimension = toInteger(dbAssoc["biz_exit_vw"]);
+ this.exitPickupModel = toInteger(dbAssoc["biz_exit_pickup"]);
+ this.exitBlipModel = toInteger(dbAssoc["biz_exit_blip"]);
+
+ this.entranceFee = toInteger(dbAssoc["biz_entrance_fee"]);
+ this.till = toInteger(dbAssoc["biz_till"]);
+
+ this.labelHelpType = toInteger(dbAssoc["biz_label_help_type"]);
+ this.streamingRadioStation = toInteger(dbAssoc["biz_radiostation"]);
+ }
+ };
+};
+
+/**
+ * @class Representing a business's location data. Multiple can be used for a single business. Used for things like doors, fuel pumps, drive thru positions, etc. Loaded and saved in the database
+ */
+class BusinessLocationData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.type = 0;
+ this.business = 0;
+ this.enabled = false;
+ this.index = -1;
+ this.businessIndex = -1;
+ this.needsSaved = false;
+
+ this.position = toVector3(0.0, 0.0, 0.0);
+ this.interior = 0;
+ this.dimension = 0;
+
+ if (dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["biz_loc_id"]);
+ this.name = toString(dbAssoc["biz_loc_name"]);
+ this.type = toInteger(dbAssoc["biz_loc_type"]);
+ this.business = toInteger(dbAssoc["biz_loc_biz"]);
+ this.enabled = intToBool(toInteger(dbAssoc["biz_loc_enabled"]));
+
+ this.position = toVector3(toFloat(dbAssoc["biz_loc_pos_x"]), toFloat(dbAssoc["biz_loc_pos_y"]), toFloat(dbAssoc["biz_loc_pos_z"]));
+ this.interior = toInteger(dbAssoc["biz_loc_int"]);
+ this.dimension = toInteger(dbAssoc["biz_loc_vw"]);
+ }
+ }
+};
+
+/**
+ * @class Representing a business's game scripts. Multiple can be used for a single business. Used for things like bar and club NPCs and other actions
+ */
+class BusinessGameScriptData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.business = 0;
+ this.enabled = false;
+ this.index = -1;
+ this.businessIndex = -1;
+ this.needsSaved = false;
+
+ if (dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["biz_script_id"]);
+ this.name = toString(dbAssoc["biz_script_name"]);
+ this.state = toInteger(dbAssoc["biz_script_state"]);
+ this.business = toInteger(dbAssoc["biz_script_biz"]);
+ }
+ }
+};
+
+// ===========================================================================
+
function initBusinessScript() {
logToConsole(LOG_INFO, "[VRR.Business]: Initializing business script ...");
-
-
logToConsole(LOG_INFO, "[VRR.Business]: Business script initialized successfully!");
return true;
}
@@ -44,7 +205,7 @@ function loadBusinessesFromDatabase() {
let dbAssoc;
if (dbConnection) {
- dbQuery = queryDatabase(dbConnection, `SELECT * FROM biz_main WHERE biz_server = ${getServerId()}`);
+ dbQuery = queryDatabase(dbConnection, `SELECT * FROM biz_main WHERE biz_deleted = 0 AND biz_server = ${getServerId()}`);
if (dbQuery) {
if (dbQuery.numRows > 0) {
while (dbAssoc = fetchQueryAssoc(dbQuery)) {
diff --git a/scripts/server/clan.js b/scripts/server/clan.js
index e409f65b..bab3ffdb 100644
--- a/scripts/server/clan.js
+++ b/scripts/server/clan.js
@@ -7,6 +7,103 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+/**
+ * @class Representing a clan's data. Loaded and saved in the database
+ */
+ class ClanData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.ownerId = 0;
+ this.tag = "";
+ this.enabled = false;
+ this.index = -1;
+ this.colour = COLOUR_WHITE;
+ this.colours = [];
+ this.initialRank = 0;
+ this.members = [];
+ this.ranks = [];
+ this.needsSaved = false;
+ this.motd = false;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["clan_id"]);
+ this.name = dbAssoc["clan_name"];
+ this.owner = toInteger(dbAssoc["clan_owner"]);
+ this.tag = dbAssoc["clan_tag"];
+ this.enabled = intToBool(toInteger(dbAssoc["clan_enabled"]));
+ this.colour = toColour(toInteger(dbAssoc["clan_col_r"]), toInteger(dbAssoc["clan_col_g"]), toInteger(dbAssoc["clan_col_b"]));
+ this.colours = [toInteger(dbAssoc["clan_col_r"]), toInteger(dbAssoc["clan_col_g"]), toInteger(dbAssoc["clan_col_b"])];
+ this.motd = dbAssoc["clan_motd"];
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing a clan rank's data. Loaded and saved in the database
+ */
+class ClanRankData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.clan = 0;
+ this.name = "";
+ this.level = 0;
+ this.flags = 0;
+ this.customTag = "";
+ this.enabled = true;
+ this.index = -1;
+ this.clanIndex = -1;
+ this.needsSaved = false;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["clan_rank_id"]);
+ this.clan = toInteger(dbAssoc["clan_rank_clan"]);
+ this.name = dbAssoc["clan_rank_name"];
+ this.level = toInteger(dbAssoc["clan_rank_level"]);
+ this.flags = toInteger(dbAssoc["clan_rank_flags"]);
+ this.tag = dbAssoc["clan_rank_tag"];
+ this.enabled = intToBool(toInteger(dbAssoc["clan_rank_enabled"]));
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing a clan member's data. Loaded and saved in the database
+ */
+class ClanMemberData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.clan = 0;
+ this.subAccount = 0;
+ this.flags = 0;
+ this.customTitle = "";
+ this.customTag = "";
+ this.rank = 0;
+ this.enabled = false;
+ this.index = -1;
+ this.clanIndex = -1;
+ this.rankIndex = -1;
+ this.needsSaved = false;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["clan_member_id"]);
+ this.subAccount = toInteger(dbAssoc["clan_member_sacct"]);
+ this.clan = toInteger(dbAssoc["clan_member_clan"]);
+ this.name = dbAssoc["clan_member_name"];
+ this.rank = toInteger(dbAssoc["clan_member_rank"]);
+ this.flags = toInteger(dbAssoc["clan_member_flags"]);
+ this.customTag = dbAssoc["clan_member_tag"];
+ this.customTitle = dbAssoc["clan_member_title"];
+ }
+ }
+};
+
+// ===========================================================================
+
function initClanScript() {
logToConsole(LOG_INFO, "[VRR.Clan]: Initializing clans script ...");
logToConsole(LOG_INFO, "[VRR.Clan]: Clan script initialized successfully!");
diff --git a/scripts/server/class.js b/scripts/server/class.js
deleted file mode 100644
index 314b2d5a..00000000
--- a/scripts/server/class.js
+++ /dev/null
@@ -1,1724 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: class.js
-// DESC: Provides classes
-// TYPE: Server (JavaScript)
-// ===========================================================================
-
-function initClassScript() {
- logToConsole(LOG_INFO, "[VRR.Class]: Initializing class script ...");
- logToConsole(LOG_INFO, "[VRR.Class]: Class script initialized successfully!");
-}
-
-// ===========================================================================
-
-/**
- * @class Representing data for server configuration
- */
-class ServerConfigData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.needsSaved = false;
-
- this.newCharacter = {
- spawnPosition: toVector3(0.0, 0.0, 0.0),
- spawnHeading: 0.0,
- spawnInterior: 0,
- spawnDimension: 0,
- money: 0,
- bank: 0,
- skin: 0,
- };
-
- this.connectCameraPosition = toVector3(0.0, 0.0, 0.0);
- this.connectCameraLookAt = toVector3(0.0, 0.0, 0.0);
-
- this.characterSelectCameraPosition = toVector3(0.0, 0.0, 0.0);
- this.characterSelectCameraLookAt = toVector3(0.0, 0.0, 0.0);
- this.characterSelectPedPosition = toVector3(0.0, 0.0, 0.0);
- this.characterSelectPedHeading = 0.0;
- this.characterSelectInterior = 0;
- this.characterSelectDimension = 0;
-
- this.hour = 0;
- this.minute = 0
- this.minuteDuration = 1000;
- this.weather = 0
- this.fallingSnow = false;
- this.groundSnow = false;
- this.useGUI = true;
- this.guiColourPrimary = [200, 200, 200];
- this.guiColourSecondary = [200, 200, 200];
- this.guiTextColourPrimary = [0, 0, 0];
- this.guiTextColourSecondary = [0, 0, 0];
- this.showLogo = true;
- this.inflationMultiplier = 1;
- this.testerOnly = false;
- this.devServer = false;
- this.nameTagDistance = 50.0;
-
- this.antiCheat = {
- enabled: false,
- //checkGameScripts: false,
- //gameScriptWhiteListEnabled: false,
- //gameScriptBlackListEnabled: false,
- //gameScriptWhiteList: [],
- //gameScriptBlackList: [],
- };
-
- this.discordBotToken = "";
- this.discordEnabled = false;
-
- this.createJobPickups = false;
- this.createBusinessPickups = false;
- this.createHousePickups = false;
- this.createJobBlips = false;
- this.createBusinessBlips = false;
- this.createHouseBlips = false;
-
- this.introMusicURL = "";
-
- this.pauseSavingToDatabase = false;
-
- this.useRealTime = false;
- this.realTimeZone = 0;
-
- this.discordConfig = {
- sendEvents: true,
- sendChat: true,
- sendAdmin: true,
- };
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["svr_id"];
- this.newCharacter = {
- spawnPosition: toVector3(dbAssoc["svr_newchar_pos_x"], dbAssoc["svr_newchar_pos_y"], dbAssoc["svr_newchar_pos_z"]),
- spawnHeading: dbAssoc["svr_newchar_rot_z"],
- money: dbAssoc["svr_newchar_money"],
- bank: dbAssoc["svr_newchar_bank"],
- skin: dbAssoc["svr_newchar_skin"],
- };
-
- //this.connectCameraPosition = toVector3(dbAssoc["svr_connectcam_pos_x"], dbAssoc["svr_connectcam_pos_y"], dbAssoc["svr_connectcam_pos_z"]);
- //this.connectCameraLookAt = toVector3(dbAssoc["svr_connectcam_lookat_x"], dbAssoc["svr_connectcam_lookat_y"], dbAssoc["svr_connectcam_lookat_z"]);
-
- this.hour = toInteger(dbAssoc["svr_start_time_hour"]);
- this.minute = toInteger(dbAssoc["svr_start_time_min"]);
- this.minuteDuration = toInteger(dbAssoc["svr_time_min_duration"]);
- this.weather = toInteger(dbAssoc["svr_start_weather"]);
- this.fallingSnow = intToBool(toInteger(dbAssoc["svr_snow_falling"]));
- this.groundSnow = intToBool(toInteger(dbAssoc["svr_snow_ground"]));
- this.useGUI = intToBool(toInteger(dbAssoc["svr_gui"]));
- //this.showLogo = intToBool(toInteger(dbAssoc["svr_logo"]));
- this.createJobPickups = intToBool(toInteger(dbAssoc["svr_job_pickups"]));
- this.createBusinessPickups = intToBool(toInteger(dbAssoc["svr_biz_pickups"]));
- this.createHousePickups = intToBool(toInteger(dbAssoc["svr_house_pickups"]));
- this.createJobBlips = intToBool(toInteger(dbAssoc["svr_job_blips"]));
- this.createBusinessBlips = intToBool(toInteger(dbAssoc["svr_biz_blips"]));
- this.createHouseBlips = intToBool(toInteger(dbAssoc["svr_house_blips"]));
- this.createPlayerBlips = intToBool(toInteger(dbAssoc["svr_player_blips"]));
- this.guiColourPrimary = [toInteger(dbAssoc["svr_gui_col1_r"]), toInteger(dbAssoc["svr_gui_col1_g"]), toInteger(dbAssoc["svr_gui_col1_b"])];
- this.guiColourSecondary = [toInteger(dbAssoc["svr_gui_col2_r"]), toInteger(dbAssoc["svr_gui_col2_g"]), toInteger(dbAssoc["svr_gui_col2_b"])];
- this.guiTextColourPrimary = [toInteger(dbAssoc["svr_gui_textcol1_r"]), toInteger(dbAssoc["svr_gui_textcol1_g"]), toInteger(dbAssoc["svr_gui_textcol1_b"])];
- this.guiTextColourSecondary = [toInteger(dbAssoc["svr_gui_textcol2_r"]), toInteger(dbAssoc["svr_gui_textcol2_g"]), toInteger(dbAssoc["svr_gui_textcol2_b"])];
- this.inflationMultiplier = toFloat(dbAssoc["svr_inflation_multiplier"]);
- this.nameTagDistance = toFloat(dbAssoc["svr_nametag_distance"]);
- this.discordBotToken = intToBool(dbAssoc["svr_discord_bot_token"]);
- this.introMusicURL = dbAssoc["svr_intro_music"];
-
- //this.useRealTime = intToBool(toInteger(dbAssoc["svr_real_time_enabled"]));
- //this.realTimeZone = dbAssoc["svr_real_time_timezone"];
-
- this.discord = {
- sendEvents: intToBool(dbAssoc["svr_discord_send_events"]),
- 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")));
- }
- }
-};
-
-/**
- * @class Representing extra data for a client
- */
-class ClientData {
- constructor(client, accountData, subAccounts) {
- this.accountData = accountData;
- this.subAccounts = subAccounts; // Characters
- this.client = client;
- this.currentSubAccount = -1;
- this.loggedIn = false;
- this.index = -1;
- this.connectTime = 0;
- this.clientVersion = "0.0.0";
- this.loginAttemptsRemaining = 3;
- this.passwordResetAttemptsRemaining = 3;
- this.afk = false;
-
- this.jobRoute = -1;
- this.jobRouteLocation = -1;
- this.jobRouteVehicle = false;
-
- this.spawned = false;
-
- this.rentingVehicle = false;
- this.buyingVehicle = false;
-
- this.lastVehicle = false;
-
- this.returnToJobVehicleTick = 0;
- this.returnToJobVehicleTimer = null;
-
- this.switchingCharacter = false;
-
- this.tutorialStep = -1;
- this.tutorialItem = null;
- this.tutorialVehicle = null;
-
- this.hotBarItems = new Array(9).fill(-1);
- this.activeHotBarSlot = -1;
- this.toggleUseItem = false;
-
- this.jobLockerCache = new Array(9).fill(-1);
- this.jobEquipmentCache = [];
- this.jobUniform = 0;
-
- this.itemActionState = VRR_ITEM_ACTION_NONE;
- this.itemActionItem = -1;
-
- this.alcoholLevel = 0;
-
- this.pedState = VRR_PEDSTATE_NONE;
- this.promptType = VRR_PROMPT_NONE;
-
- this.businessOrderAmount = 0;
- this.businessOrderBusiness = -1;
- this.businessOrderItem = -1;
- this.businessOrderValue = -1;
-
- this.syncPosition = null;
- this.syncHeading = null;
- this.syncVehicle = null;
- this.syncVehicleSeat = null;
-
- this.twoFactorAuthenticationState = VRR_2FA_STATE_NONE;
- this.twoFactorAuthenticationCode = 0;
-
- this.payDayAmount = 0;
- this.payDayTickStart = 0;
-
- this.creatingCharacter = false;
- this.creatingCharacterSkin = -1;
-
- this.streamingRadioStation = -1;
- this.streamingRadioElement = false;
-
- this.returnToPosition = null;
- this.returnToHeading = null;
- this.returnToInterior = null;
- this.returnToDimension = null;
- this.returnToHouse = null;
- this.returnToBusiness = null;
- this.returnToType = VRR_RETURNTO_TYPE_NONE;
-
- this.changingCharacterName = false;
- this.currentPickup = false;
- this.usingSkinSelect = false;
- this.keyBinds = [];
- this.sessionId = 0;
- this.incomingDamageMultiplier = 1;
- this.weaponDamageEvent = VRR_WEAPON_DAMAGE_EVENT_NORMAL;
-
- this.currentAnimation = -1;
- this.currentAnimationPositionOffset = false;
- this.currentAnimationPositionReturnTo = false;
- this.animationStart = 0;
- this.animationForced = false;
-
- this.passwordResetState = VRR_RESETPASS_STATE_NONE;
- this.passwordResetCode = "";
-
- this.lastJobVehicle = null;
- this.health = 100;
- this.locale = 0;
-
- this.enteringVehicle = null;
-
- this.customDisconnectReason = "";
-
- this.interiorCutscene = -1;
-
- this.playerBlip = false;
- }
-};
-
-/**
- * @class Representing an account, loaded/saved in the database
- */
-class AccountData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.password = "";
- this.registerDate = 0;
- this.flags = {
- moderation: 0,
- admin: 0,
- };
- this.staffTitle = "";
- this.ircAccount = "";
- this.discordAccount = 0,
- this.settings = 0,
- this.emailAddress = "";
- this.ipAddress = 0,
-
- this.notes = [];
- this.messages = [];
- this.contacts = [];
- this.subAccounts = [];
-
- this.emailVerificationCode = "";
- this.twoFactorAuthVerificationCode = "";
-
- this.chatScrollLines = 1;
- this.chatAutoHideDelay = 0;
-
- this.streamingRadioVolume = 20;
- this.locale = 0;
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["acct_id"];
- this.name = dbAssoc["acct_name"];
- this.password = dbAssoc["acct_pass"];
- this.registerDate = dbAssoc["acct_when_made"];
- this.flags = {
- moderation: dbAssoc["acct_svr_mod_flags"],
- admin: dbAssoc["acct_svr_staff_flags"],
- };
- this.staffTitle = dbAssoc["acct_svr_staff_title"];
- this.ircAccount = dbAssoc["acct_irc"];
- this.discordAccount = dbAssoc["acct_discord"];
- this.settings = dbAssoc["acct_svr_settings"];
- this.emailAddress = dbAssoc["acct_email"];
- this.whenRegistered = dbAssoc["acct_when_registered"];
- this.ipAddress = dbAssoc["acct_ip"];
-
- this.notes = [];
- this.messages = [];
- this.contacts = [];
- this.subAccounts = [];
-
- this.emailVerificationCode = dbAssoc["acct_code_verifyemail"];
- this.twoFactorAuthVerificationCode = dbAssoc["acct_code_2fa"];
- this.chatScrollLines = toInteger(dbAssoc["acct_svr_chat_scroll_lines"]);
- this.chatAutoHideDelay = toInteger(dbAssoc["acct_svr_chat_auto_hide_delay"]);
- this.streamingRadioVolume = toInteger(dbAssoc["acct_streaming_radio_volume"]);
- this.locale = toInteger(dbAssoc["acct_locale"]);
- }
- }
-};
-
-/**
- * @class Representing an account's contact list, loaded/saved in the database
- */
-class AccountContactData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.accountId = 0;
- this.contactAccountId = 0;
- this.type = 0;
- this.whenAdded = 0;
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["acct_contact_id"];
- this.accountId = dbAssoc["acct_contact_acct"];
- this.contactAccountId = dbAssoc["acct_contact_contact"];
- this.type = dbAssoc["acct_contact_type"];
- this.whenAdded = dbAssoc["acct_contact_when_added"];
- }
- }
-};
-
-/**
- * @class Representing an account's messages, loaded/saved in the database
- */
-class AccountMessageData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.account = 0;
- this.whoSent = 0;
- this.whenSent = 0;
- this.whenRead = 0;
- this.deleted = false;
- this.whenDeleted = 0;
- this.folder = 0;
- this.message = "";
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["acct_msg_id"];
- this.account = dbAssoc["acct_msg_acct"];
- this.whoSent = dbAssoc["acct_msg_who_sent"];
- this.whenSent = dbAssoc["acct_msg_when_sent"];
- this.whenRead = dbAssoc["acct_msg_when_read"];
- this.deleted = intToBool(dbAssoc["acct_msg_deleted"]);
- this.whenDeleted = dbAssoc["acct_msg_when_deleted"];
- this.folder = dbAssoc["acct_msg_folder"];
- this.message = dbAssoc["acct_msg_message"];
- }
- }
-};
-
-/**
- * @class Representing an account's staff notes. Visible only to staff and loaded/saved in the database
- */
-class AccountStaffNoteData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.account = 0;
- this.whoAdded = 0;
- this.whenAdded = 0;
- this.deleted = false;
- this.whenDeleted = 0;
- this.serverId = 0;
- this.note = "";
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["acct_note_id"];
- this.account = dbAssoc["acct_note_acct"];
- this.whoAdded = dbAssoc["acct_note_who_added"];
- this.whenAdded = dbAssoc["acct_note_when_added"];
- this.deleted = intToBool(dbAssoc["acct_note_deleted"]);
- this.whenDeleted = dbAssoc["acct_note_when_deleted"];
- this.serverId = dbAssoc["acct_note_server"];
- this.note = dbAssoc["acct_note_message"];
- }
- }
-};
-
-/**
- * @class Representing a character's (subaccount) data. Loaded and saved in the database
- */
-class SubAccountData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.serverId = 0;
- this.firstName = "John";
- this.lastName = "Doe";
- this.middleName = "Q";
- this.account = 0;
- this.skin = 0;
- this.cash = 0;
- this.spawnPosition = toVector3(0.0, 0.0, 0.0);
- this.spawnHeading = 0.0;
- this.lastLogin = 0;
- this.clan = 0;
- this.clanFlags = 0;
- this.clanRank = 0;
- this.clanTitle = 0;
- this.isWorking = false;
- this.jobUniform = this.skin;
- this.job = 0;
- this.jobRank = 0;
- this.weapons = [];
- this.inJail = false;
- this.interior = 0;
- this.dimension = 0;
- this.pedScale = toVector3(1.0, 1.0, 1.0);
- this.walkStyle = 0;
- this.fightStyle = 0;
- this.health = 100;
- this.armour = 100;
- this.inHouse = 0;
- this.inBusiness = 0;
- this.accent = "";
-
- this.bodyParts = {
- hair: [0, 0],
- head: [0, 0],
- upper: [0, 0],
- lower: [0, 0],
- };
-
- this.bodyProps = {
- hair: [0, 0],
- eyes: [0, 0],
- head: [0, 0],
- leftHand: [0, 0],
- rightHand: [0, 0],
- leftWrist: [0, 0],
- rightWrist: [0, 0],
- hip: [0, 0],
- leftFoot: [0, 0],
- rightFoot: [0, 0],
- };
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["sacct_id"];
- this.serverId = toInteger(dbAssoc["sacct_server"]);
- this.firstName = dbAssoc["sacct_name_first"];
- this.lastName = dbAssoc["sacct_name_last"];
- this.middleName = dbAssoc["sacct_name_middle"] || "";
- this.account = toInteger(dbAssoc["sacct_acct"]);
- this.skin = toInteger(dbAssoc["sacct_svr_skin"]);
- this.cash = toInteger(dbAssoc["sacct_cash"]);
- this.spawnPosition = toVector3(toFloat(dbAssoc["sacct_pos_x"]), toFloat(dbAssoc["sacct_pos_y"]), toFloat(dbAssoc["sacct_pos_z"]));
- this.spawnHeading = toFloat(dbAssoc["sacct_rot_z"]);
- this.lastLogin = toInteger(dbAssoc["sacct_when_lastlogin"]);
- this.clan = toInteger(dbAssoc["sacct_svr_clan"]);
- this.clanFlags = toInteger(dbAssoc["sacct_svr_clan_flags"]);
- this.clanRank = toInteger(dbAssoc["sacct_svr_clan_rank"]);
- this.clanTitle = toInteger(dbAssoc["sacct_svr_clan_title"]);
- this.job = toInteger(dbAssoc["sacct_svr_job"]);
- this.jobRank = toInteger(dbAssoc["sacct_svr_job_rank"]);
- this.interior = toInteger(dbAssoc["sacct_int"]);
- this.dimension = toInteger(dbAssoc["sacct_vw"]);
- this.pedScale = toVector3(toFloat(dbAssoc["sacct_svr_scale_x"]), toFloat(dbAssoc["sacct_svr_scale_y"]), toFloat(dbAssoc["sacct_svr_scale_z"]));
- this.walkStyle = toInteger(dbAssoc["sacct_svr_walkstyle"]);
- this.fightStyle = toInteger(dbAssoc["sacct_svr_fightstyle"]);
- this.health = toInteger(dbAssoc["sacct_health"]);
- this.armour = toInteger(dbAssoc["sacct_armour"]);
- this.inHouse = toInteger(dbAssoc["sacct_inhouse"]);
- this.inBusiness = toInteger(dbAssoc["sacct_inbusiness"]);
- this.accent = toString(dbAssoc["sacct_accent"]);
-
- this.bodyParts = {
- hair: [toInteger(dbAssoc["sacct_svr_hd_part_hair_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_hair_texture"]) || 0],
- head: [toInteger(dbAssoc["sacct_svr_hd_part_head_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_head_texture"]) || 0],
- upper: [toInteger(dbAssoc["sacct_svr_hd_part_upper_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_upper_texture"]) || 0],
- lower: [toInteger(dbAssoc["sacct_svr_hd_part_lower_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_lower_texture"]) || 0],
- };
-
- this.bodyProps = {
- hair: [toInteger(dbAssoc["sacct_svr_hd_prop_hair_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_hair_texture"]) || 0],
- eyes: [toInteger(dbAssoc["sacct_svr_hd_prop_eyes_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_eyes_texture"]) || 0],
- head: [toInteger(dbAssoc["sacct_svr_hd_prop_head_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_head_texture"]) || 0],
- leftHand: [toInteger(dbAssoc["sacct_svr_hd_prop_lefthand_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_lefthand_texture"]) || 0],
- rightHand: [toInteger(dbAssoc["sacct_svr_hd_prop_righthand_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_righthand_texture"]) || 0],
- leftWrist: [toInteger(dbAssoc["sacct_svr_hd_prop_leftwrist_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_leftwrist_texture"]) || 0],
- rightWrist: [toInteger(dbAssoc["sacct_svr_hd_prop_rightwrist_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_rightwrist_texture"]) || 0],
- hip: [toInteger(dbAssoc["sacct_svr_hd_prop_hip_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_hip_texture"]) || 0],
- leftFoot: [toInteger(dbAssoc["sacct_svr_hd_prop_leftfoot_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_leftfoot_texture"]) || 0],
- rightFoot: [toInteger(dbAssoc["sacct_svr_hd_prop_rightfoot_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_rightfoot_texture"]) || 0],
- };
- }
- }
-};
-
-/**
- * @class Representing a businesses' data. Loaded and saved in the database
- */
-class BusinessData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.ownerType = VRR_BIZOWNER_NONE;
- this.ownerId = 0;
- this.buyPrice = 0;
- this.locked = false;
- this.hasInterior = false;
- this.index = -1;
- this.needsSaved = false;
- this.interiorLights = true;
-
- this.floorItemCache = [];
- this.storageItemCache = [];
- this.locations = [];
- this.gameScripts = [];
-
- this.entrancePosition = false;
- this.entranceRotation = 0.0;
- this.entranceInterior = 0;
- this.entranceDimension = 0;
- this.entrancePickupModel = -1;
- this.entranceBlipModel = -1;
- this.entrancePickup = null;
- this.entranceBlip = null;
- this.entranceCutscene = -1;
-
- this.exitPosition = false;
- this.exitRotation = 0.0;
- this.exitInterior = 0;
- this.exitDimension = 0;
- this.exitPickupModel = -1;
- this.exitBlipModel = -1;
- this.exitPickup = null;
- this.exitBlip = null;
- this.exitCutscene = -1;
-
- this.entranceFee = 0;
- this.till = 0;
-
- this.streamingRadioStation = -1;
-
- this.labelHelpType = VRR_PROPLABEL_INFO_NONE;
-
- this.triggers = [];
-
- this.customInterior = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["biz_id"]);
- this.name = toString(dbAssoc["biz_name"]);
- this.ownerType = toInteger(dbAssoc["biz_owner_type"]);
- this.ownerId = toInteger(dbAssoc["biz_owner_id"]);
- this.buyPrice = toInteger(dbAssoc["biz_buy_price"]);
- this.locked = intToBool(toInteger(dbAssoc["biz_locked"]));
- this.hasInterior = intToBool(toInteger(dbAssoc["biz_has_interior"]));
- this.interiorLights = intToBool(toInteger(dbAssoc["biz_interior_lights"]));
-
- this.entrancePosition = toVector3(toFloat(dbAssoc["biz_entrance_pos_x"]), toFloat(dbAssoc["biz_entrance_pos_y"]), toFloat(dbAssoc["biz_entrance_pos_z"]));
- this.entranceRotation = toInteger(dbAssoc["biz_entrance_rot_z"]);
- this.entranceInterior = toInteger(dbAssoc["biz_entrance_int"]);
- this.entranceDimension = toInteger(dbAssoc["biz_entrance_vw"]);
- this.entrancePickupModel = toInteger(dbAssoc["biz_entrance_pickup"]);
- this.entranceBlipModel = toInteger(dbAssoc["biz_entrance_blip"]);
- this.entranceCutscene = toInteger(dbAssoc["biz_entrance_cutscene"]);
-
- this.exitPosition = toVector3(dbAssoc["biz_exit_pos_x"], dbAssoc["biz_exit_pos_y"], dbAssoc["biz_exit_pos_z"]);
- this.exitRotation = toInteger(dbAssoc["biz_exit_rot_z"]);
- this.exitInterior = toInteger(dbAssoc["biz_exit_int"]);
- this.exitDimension = toInteger(dbAssoc["biz_exit_vw"]);
- this.exitPickupModel = toInteger(dbAssoc["biz_exit_pickup"]);
- this.exitBlipModel = toInteger(dbAssoc["biz_exit_blip"]);
- this.exitCutscene = toInteger(dbAssoc["biz_exit_cutscene"]);
-
- this.entranceFee = toInteger(dbAssoc["biz_entrance_fee"]);
- this.till = toInteger(dbAssoc["biz_till"]);
-
- this.labelHelpType = toInteger(dbAssoc["biz_label_help_type"]);
- this.streamingRadioStation = toInteger(dbAssoc["biz_radiostation"]);
- this.customInterior = intToBool(toInteger(dbAssoc["biz_custom_interior"]));
- }
- };
-};
-
-/**
- * @class Representing a business's location data. Multiple can be used for a single business. Used for things like doors, fuel pumps, drive thru positions, etc. Loaded and saved in the database
- */
-class BusinessLocationData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.type = 0;
- this.business = 0;
- this.enabled = false;
- this.index = -1;
- this.businessIndex = -1;
- this.needsSaved = false;
-
- this.position = toVector3(0.0, 0.0, 0.0);
- this.interior = 0;
- this.dimension = 0;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["biz_loc_id"]);
- this.name = toString(dbAssoc["biz_loc_name"]);
- this.type = toInteger(dbAssoc["biz_loc_type"]);
- this.business = toInteger(dbAssoc["biz_loc_biz"]);
- this.enabled = intToBool(toInteger(dbAssoc["biz_loc_enabled"]));
-
- this.position = toVector3(toFloat(dbAssoc["biz_loc_pos_x"]), toFloat(dbAssoc["biz_loc_pos_y"]), toFloat(dbAssoc["biz_loc_pos_z"]));
- this.interior = toInteger(dbAssoc["biz_loc_int"]);
- this.dimension = toInteger(dbAssoc["biz_loc_vw"]);
- }
- }
-};
-
-/**
- * @class Representing a business's game scripts. Multiple can be used for a single business. Used for things like bar and club NPCs and other actions
- */
-class BusinessGameScriptData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.business = 0;
- this.enabled = false;
- this.index = -1;
- this.businessIndex = -1;
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["biz_script_id"]);
- this.name = toString(dbAssoc["biz_script_name"]);
- this.state = toInteger(dbAssoc["biz_script_state"]);
- this.business = toInteger(dbAssoc["biz_script_biz"]);
- }
- }
-};
-
-/**
- * @class Representing a house's data. Loaded and saved in the database
- */
-class HouseData {
- constructor(dbAssoc = false) {
- this.databaseId = 0
- this.description = "";
- this.ownerType = VRR_HOUSEOWNER_NONE;
- this.ownerId = 0;
- this.buyPrice = 0;
- this.rentPrice = 0;
- this.renter = 0;
- this.locked = false;
- this.hasInterior = false;
- this.index = -1;
- this.needsSaved = false;
- this.interiorLights = true;
-
- this.itemCache = [];
- this.locations = [];
- //this.gameScripts = [];
-
- this.entrancePosition = false;
- this.entranceRotation = 0.0;
- this.entranceInterior = 0;
- this.entranceDimension = 0;
- this.entrancePickupModel = -1;
- this.entranceBlipModel = -1;
- this.entrancePickup = null;
- this.entranceBlip = null;
-
- this.exitPosition = false;
- this.exitRotation = 0.0;
- this.exitInterior = 0;
- this.exitDimension = -1;
- this.exitPickupModel = -1;
- this.exitBlipModel = -1;
- this.exitPickup = null;
- this.exitBlip = null;
-
- this.streamingRadioStation = -1;
-
- this.triggers = [];
-
- this.customInterior = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["house_id"]);
- this.description = toString(dbAssoc["house_description"]);
- this.ownerType = toInteger(dbAssoc["house_owner_type"]);
- this.ownerId = toInteger(dbAssoc["house_owner_id"]);
- this.buyPrice = toInteger(dbAssoc["house_buy_price"]);
- this.rentPrice = toInteger(dbAssoc["house_rent_price"]);
- this.renter = toInteger(dbAssoc["house_renter"]);
- this.locked = intToBool(toInteger(dbAssoc["house_locked"]));
- this.hasInterior = intToBool(toInteger(dbAssoc["house_has_interior"]));
- this.interiorLights = intToBool(toInteger(dbAssoc["house_interior_lights"]));
-
- this.entrancePosition = toVector3(toFloat(dbAssoc["house_entrance_pos_x"]), toFloat(dbAssoc["house_entrance_pos_y"]), toFloat(dbAssoc["house_entrance_pos_z"]));
- this.entranceRotation = toFloat(dbAssoc["house_entrance_rot_z"]);
- this.entranceInterior = toInteger(dbAssoc["house_entrance_int"]);
- this.entranceDimension = toInteger(dbAssoc["house_entrance_vw"]);
- this.entrancePickupModel = toInteger(dbAssoc["house_entrance_pickup"]);
- this.entranceBlipModel = toInteger(dbAssoc["house_entrance_blip"]);
- this.entranceCutscene = toInteger(dbAssoc["house_entrance_cutscene"]);
-
- this.exitPosition = toVector3(toFloat(dbAssoc["house_exit_pos_x"]), toFloat(dbAssoc["house_exit_pos_y"]), toFloat(dbAssoc["house_exit_pos_z"]));
- this.exitRotation = toFloat(dbAssoc["house_exit_rot_z"]);
- this.exitInterior = toInteger(dbAssoc["house_exit_int"]);
- this.exitDimension = toInteger(dbAssoc["house_exit_vw"]);
- this.exitPickupModel = toInteger(dbAssoc["house_exit_pickup"]);
- this.exitBlipModel = toInteger(dbAssoc["house_exit_blip"]);
- this.exitCutscene = toInteger(dbAssoc["house_exit_cutscene"]);
-
- this.customInterior = intToBool(toInteger(dbAssoc["house_custom_interior"]));
- }
- }
-};
-
-/**
- * @class Representing a houses's location data. Multiple can be used for a single house. Used for things like doors, garage entry/exit/vehspawn, gates, etc. Loaded and saved in the database
- */
-class HouseLocationData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.type = 0;
- this.house = 0;
- this.enabled = false;
- this.index = -1;
- this.houseIndex = -1;
- this.needsSaved = false;
-
- this.position = toVector3(0.0, 0.0, 0.0);
- this.interior = 0;
- this.dimension = 0;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["house_loc_id"]);
- this.name = toString(dbAssoc["house_loc_name"]);
- this.type = toInteger(dbAssoc["house_loc_type"]);
- this.house = toInteger(dbAssoc["house_loc_house"]);
- this.enabled = intToBool(toInteger(dbAssoc["house_loc_enabled"]));
- this.index = -1;
-
- this.position = toVector3(toFloat(dbAssoc["house_loc_pos_x"]), toFloat(dbAssoc["house_loc_pos_y"]), toFloat(dbAssoc["house_loc_pos_z"]));
- this.interior = toInteger(dbAssoc["house_loc_int"]);
- this.dimension = toInteger(dbAssoc["house_loc_vw"]);
- }
- };
-
- //saveToDatabase = () => {
- // saveHouseLocationToDatabase(this.houseIndex, this.index);
- //}
-};
-
-/**
- * @class Representing a house's game scripts. Multiple can be used for a single house
- */
-class HouseGameScriptData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.business = 0;
- this.state = false;
- this.index = -1;
- this.houseIndex = -1;
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["house_script_id"]);
- this.name = toString(dbAssoc["house_script_name"]);
- this.state = toInteger(dbAssoc["house_script_state"]);
- this.business = toInteger(dbAssoc["house_script_biz"]);
- }
- }
-};
-
-/**
- * @class Representing a clan's data. Loaded and saved in the database
- */
-class ClanData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.ownerId = 0;
- this.tag = "";
- this.enabled = false;
- this.index = -1;
- this.colour = COLOUR_WHITE;
- this.colours = [];
- this.initialRank = 0;
- this.members = [];
- this.ranks = [];
- this.needsSaved = false;
- this.motd = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["clan_id"]);
- this.name = dbAssoc["clan_name"];
- this.owner = toInteger(dbAssoc["clan_owner"]);
- this.tag = dbAssoc["clan_tag"];
- this.enabled = intToBool(toInteger(dbAssoc["clan_enabled"]));
- this.colour = toColour(toInteger(dbAssoc["clan_col_r"]), toInteger(dbAssoc["clan_col_g"]), toInteger(dbAssoc["clan_col_b"]));
- this.colours = [toInteger(dbAssoc["clan_col_r"]), toInteger(dbAssoc["clan_col_g"]), toInteger(dbAssoc["clan_col_b"])];
- this.motd = dbAssoc["clan_motd"];
- }
- }
-};
-
-/**
- * @class Representing a clan rank's data. Loaded and saved in the database
- */
-class ClanRankData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.clan = 0;
- this.name = "";
- this.level = 0;
- this.flags = 0;
- this.customTag = "";
- this.enabled = true;
- this.index = -1;
- this.clanIndex = -1;
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["clan_rank_id"]);
- this.clan = toInteger(dbAssoc["clan_rank_clan"]);
- this.name = dbAssoc["clan_rank_name"];
- this.level = toInteger(dbAssoc["clan_rank_level"]);
- this.flags = toInteger(dbAssoc["clan_rank_flags"]);
- this.tag = dbAssoc["clan_rank_tag"];
- this.enabled = intToBool(toInteger(dbAssoc["clan_rank_enabled"]));
- }
- }
-};
-
-/**
- * @class Representing a clan member's data. Loaded and saved in the database
- */
-class ClanMemberData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.clan = 0;
- this.subAccount = 0;
- this.flags = 0;
- this.customTitle = "";
- this.customTag = "";
- this.rank = 0;
- this.enabled = false;
- this.index = -1;
- this.clanIndex = -1;
- this.rankIndex = -1;
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["clan_member_id"]);
- this.subAccount = toInteger(dbAssoc["clan_member_sacct"]);
- this.clan = toInteger(dbAssoc["clan_member_clan"]);
- this.name = dbAssoc["clan_member_name"];
- this.rank = toInteger(dbAssoc["clan_member_rank"]);
- this.flags = toInteger(dbAssoc["clan_member_flags"]);
- this.customTag = dbAssoc["clan_member_tag"];
- this.customTitle = dbAssoc["clan_member_title"];
- }
- }
-};
-
-/**
- * @class Representing a vehicle's data. Loaded and saved in the database
- */
-class VehicleData {
- constructor(dbAssoc = false, vehicle = false) {
- // General Info
- this.databaseId = 0;
- this.serverId = getServerId();
- this.model = (vehicle != false) ? getVehicleModelIndexFromModel(vehicle.modelIndex) : 0;
- this.vehicle = vehicle;
- this.index = -1;
- this.needsSaved = false;
-
- // GTA IV
- this.ivNetworkId = -1;
- this.syncPosition = toVector3(0.0, 0.0, 0.0);
- this.syncHeading = 0.0;
-
- // Ownership
- this.ownerType = VRR_VEHOWNER_NONE;
- this.ownerId = 0;
- this.buyPrice = 0;
- this.rentPrice = 0;
- this.rentedBy = false;
- this.rentStart = 0;
-
- // Position and Rotation
- this.spawnPosition = (vehicle) ? vehicle.position : toVector3(0.0, 0.0, 0.0);
- this.spawnRotation = (vehicle) ? vehicle.heading : 0.0;
- this.spawnLocked = false;
-
- // Colour Info
- this.colour1IsRGBA = 0;
- this.colour2IsRGBA = 0;
- this.colour3IsRGBA = 0;
- this.colour4IsRGBA = 0;
- this.colour1 = (vehicle) ? vehicle.colour1 : 1;
- this.colour2 = (vehicle) ? vehicle.colour2 : 1;
- this.colour3 = (vehicle) ? vehicle.colour3 : 1;
- this.colour4 = (vehicle) ? vehicle.colour4 : 1;
- this.livery = 3;
-
- this.mods = [];
-
- // Vehicle Attributes
- this.locked = false;
- this.engine = false;
- this.lights = false;
- this.health = 1000;
- this.engineDamage = 0;
- this.visualDamage = 0;
- this.dirtLevel = 0;
-
- this.trunkItemCache = [];
- this.dashItemCache = [];
-
- this.streamingRadioStation = -1;
-
- // Other/Misc
- this.insuranceAccount = 0;
- this.fuel = 0;
- this.flags = 0;
- this.needsSaved = false;
- this.whoAdded = 0;
- this.whenAdded = 0;
- this.licensePlate = "";
-
- this.interior = 0;
- this.dimension = 0;
-
- this.lastActiveTime = false;
-
- this.triggers = [];
-
- if (dbAssoc) {
- // General Info
- this.databaseId = toInteger(dbAssoc["veh_id"]);
- this.serverId = toInteger(dbAssoc["veh_server"]);
- this.model = toInteger(dbAssoc["veh_model"]);
-
- // Ownership
- this.ownerType = toInteger(dbAssoc["veh_owner_type"]);
- this.ownerId = toInteger(dbAssoc["veh_owner_id"]);
- this.buyPrice = toInteger(dbAssoc["veh_buy_price"]);
- this.rentPrice = toInteger(dbAssoc["veh_rent_price"]);
-
- // Position and Rotation
- this.spawnPosition = toVector3(dbAssoc["veh_pos_x"], dbAssoc["veh_pos_y"], dbAssoc["veh_pos_z"]);
- this.spawnRotation = toInteger(dbAssoc["veh_rot_z"]);
- this.spawnLocked = intToBool(toInteger(dbAssoc["veh_spawn_lock"]));
-
- // Colour Info
- this.colour1IsRGBA = intToBool(toInteger(dbAssoc["veh_col1_isrgba"]));
- this.colour2IsRGBA = intToBool(toInteger(dbAssoc["veh_col2_isrgba"]));
- this.colour3IsRGBA = intToBool(toInteger(dbAssoc["veh_col3_isrgba"]));
- this.colour4IsRGBA = intToBool(toInteger(dbAssoc["veh_col4_isrgba"]));
- this.colour1 = toInteger(dbAssoc["veh_col1"]);
- this.colour2 = toInteger(dbAssoc["veh_col2"]);
- this.colour3 = toInteger(dbAssoc["veh_col3"]);
- this.colour4 = toInteger(dbAssoc["veh_col4"]);
- this.livery = toInteger(dbAssoc["veh_livery"]);
-
- // Vehicle Attributes
- this.locked = intToBool(toInteger(dbAssoc["veh_locked"]));
- this.engine = intToBool(toInteger(dbAssoc["veh_engine"]));
- this.lights = intToBool(toInteger(dbAssoc["veh_lights"]));
- this.health = toInteger(dbAssoc["veh_damage_normal"]);
- this.engineDamage = toInteger(dbAssoc["veh_damage_engine"]);
- this.visualDamage = toInteger(dbAssoc["veh_damage_visual"]);
- this.dirtLevel = toInteger(dbAssoc["veh_dirt_level"]);
-
- // Other/Misc
- this.insuranceAccount = toInteger(0);
- this.fuel = toInteger(0);
- this.flags = toInteger(0);
- 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"]);
- }
- }
-};
-
-/**
- * @class Representing a command's data.
- */
-class CommandData {
- enable() {
- this.enabled = true;
- }
-
- disable() {
- this.enabled = false;
- }
-
- toggleEnabled() {
- this.enabled = !this.enabled;
- }
-
- constructor(command, handlerFunction, syntaxString = "", requiredStaffFlags = 0, requireLogin = true, allowOnDiscord = false, helpDescription = "") {
- this.command = command;
- this.handlerFunction = handlerFunction;
- this.syntaxString = syntaxString;
- this.requiredStaffFlags = requiredStaffFlags;
- this.enabled = true;
- this.requireLogin = requireLogin;
- this.allowOnDiscord = allowOnDiscord;
- this.helpDescription = helpDescription;
- this.aliases = [];
- }
-};
-
-/**
- * @class Representing a crime's data. Loaded and saved in the database
- */
-class CrimeData {
- constructor(suspectId, crimeType, reporterId = 0) {
- this.crimeType = crimeType;
- this.suspectId = suspectId;
- this.reporterId = reporterId;
- this.whenCommitted = 0;
- this.whenReported = 0;
- this.databaseId = 0;
- }
-};
-
-/**
- * @class Representing a job's data. Loaded and saved in the database
- */
-class JobData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.serverId = 0;
- this.type = VRR_JOB_NONE;
- this.name = "Unnamed";
- this.enabled = true;
- this.blipModel = -1
- this.pickupModel = -1
- this.colour = toColour(0, 0, 0, 255);
- this.whiteListEnabled = false;
- this.blackListEnabled = false;
- this.walkieTalkieFrequency = 0;
- this.index = -1;
- this.needsSaved = false;
-
- this.equipment = [];
- this.uniforms = [];
- this.locations = [];
- this.whiteList = [];
- this.blackList = [];
- this.routes = [];
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["job_id"];
- this.serverId = dbAssoc["job_server"];
- this.type = dbAssoc["job_type"];
- this.name = dbAssoc["job_name"];
- this.enabled = dbAssoc["job_enabled"];
- this.blipModel = dbAssoc["job_blip"];
- this.pickupModel = dbAssoc["job_pickup"];
- this.colour = toColour(dbAssoc["job_colour_r"], dbAssoc["job_colour_g"], dbAssoc["job_colour_b"], 255);
- this.whiteListEnabled = dbAssoc["job_wl"];
- this.blackListEnabled = dbAssoc["job_bl"];
- this.walkieTalkieFrequency = dbAssoc["job_walkietalkiefreq"];
-
- this.equipment = [];
- this.uniforms = [];
- this.locations = [];
- this.whiteList = [];
- this.blackList = [];
- this.routes = [];
- }
- }
-};
-
-/**
- * @class Representing a job equipment set's data. Loaded and saved in the database
- */
-class JobEquipmentData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.job = 0;
- this.name = "Unnamed";
- this.requiredRank = 0;
- this.enabled = false;
- this.index = -1;
- this.jobIndex = -1;
- this.needsSaved = false;
- this.items = [];
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["job_equip_id"];
- this.job = dbAssoc["job_equip_job"];
- this.name = dbAssoc["job_equip_name"];
- this.requiredRank = dbAssoc["job_equip_minrank"];
- this.enabled = dbAssoc["job_equip_enabled"];
- }
- }
-};
-
-/**
- * @class Representing a job equipment set item's data. Loaded and saved in the database
- */
-class JobEquipmentItemData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.equipmentId = 0;
- this.itemType = 0;
- this.value = 0;
- this.enabled = false;
- this.index = -1;
- this.jobIndex = -1;
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["job_equip_item_id"];
- this.equipmentId = dbAssoc["job_equip_item_equip"];
- this.itemType = dbAssoc["job_equip_item_type"];
- this.value = dbAssoc["job_equip_item_value"];
- this.enabled = dbAssoc["job_equip_item_enabled"];
- }
- }
-};
-
-/**
- * @class Representing a job uniform's data. Loaded and saved in the database
- */
-class JobUniformData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.job = 0;
- this.name = "Unnamed";
- this.requiredRank = 0
- this.skin = -1;
- this.enabled = false;
- this.index = -1;
- this.jobIndex = -1;
- this.needsSaved = false;
-
- this.bodyParts = {
- hair: [0, 0],
- head: [0, 0],
- upper: [0, 0],
- lower: [0, 0],
- };
-
- this.bodyProps = {
- hair: [0, 0],
- eyes: [0, 0],
- head: [0, 0],
- leftHand: [0, 0],
- rightHand: [0, 0],
- leftWrist: [0, 0],
- rightWrist: [0, 0],
- hip: [0, 0],
- leftFoot: [0, 0],
- rightFoot: [0, 0],
- };
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["job_uniform_id"];
- this.job = dbAssoc["job_uniform_job"];
- this.name = dbAssoc["job_uniform_name"];
- this.requiredRank = dbAssoc["job_uniform_minrank"];
- this.skin = dbAssoc["job_uniform_skin"];
- this.enabled = intToBool(dbAssoc["job_uniform_enabled"]);
-
- this.bodyParts = {
- hair: [toInteger(dbAssoc["job_uniform_hd_part_hair_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_part_hair_texture"]) || 0],
- head: [toInteger(dbAssoc["job_uniform_hd_part_head_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_part_head_texture"]) || 0],
- upper: [toInteger(dbAssoc["job_uniform_hd_part_upper_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_part_upper_texture"]) || 0],
- lower: [toInteger(dbAssoc["job_uniform_hd_part_lower_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_part_lower_texture"]) || 0],
- };
-
- this.bodyProps = {
- hair: [toInteger(dbAssoc["job_uniform_hd_prop_hair_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_hair_texture"]) || 0],
- eyes: [toInteger(dbAssoc["job_uniform_hd_prop_eyes_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_eyes_texture"]) || 0],
- head: [toInteger(dbAssoc["job_uniform_hd_prop_head_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_head_texture"]) || 0],
- leftHand: [toInteger(dbAssoc["job_uniform_hd_prop_lefthand_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_lefthand_texture"]) || 0],
- rightHand: [toInteger(dbAssoc["job_uniform_hd_prop_righthand_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_righthand_texture"]) || 0],
- leftWrist: [toInteger(dbAssoc["job_uniform_hd_prop_leftwrist_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_leftwrist_texture"]) || 0],
- rightWrist: [toInteger(dbAssoc["job_uniform_hd_prop_rightwrist_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_rightwrist_texture"]) || 0],
- hip: [toInteger(dbAssoc["job_uniform_hd_prop_hip_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_hip_texture"]) || 0],
- leftFoot: [toInteger(dbAssoc["job_uniform_hd_prop_leftfoot_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_leftfoot_texture"]) || 0],
- rightFoot: [toInteger(dbAssoc["job_uniform_hd_prop_rightfoot_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_rightfoot_texture"]) || 0],
- };
- }
- }
-};
-
-/**
- * @class JobLocationData Representing a job uniform's data. Loaded and saved in the database
- */
-class JobLocationData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.jobId = 0;
- this.position = toVector3(0.0, 0.0, 0.0);
- this.blip = false;
- this.pickup = false;
- this.enabled = false;
- this.interior = 0;
- this.dimension = 0;
- this.index = -1;
- this.jobIndex = -1;
- this.needsSaved = false;
- this.routeCache = [];
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["job_loc_id"]);
- this.jobId = toInteger(dbAssoc["job_loc_job"]);
- this.position = toVector3(toFloat(dbAssoc["job_loc_pos_x"]), toFloat(dbAssoc["job_loc_pos_y"]), toFloat(dbAssoc["job_loc_pos_z"]));
- this.enabled = toInteger(dbAssoc["job_loc_enabled"]);
- this.interior = toInteger(dbAssoc["job_loc_int"]);
- this.dimension = toInteger(dbAssoc["job_loc_vw"]);
- }
- }
-};
-
-class JobWhiteListData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.job = 0;
- this.subAccount = 0
- this.enabled = false;
- this.index = -1;
- this.jobIndex = -1;
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["job_wl_id"];
- this.job = dbAssoc["job_wl_job"];
- this.subAccount = dbAssoc["job_wl_sacct"]
- this.enabled = dbAssoc["job_wl_enabled"];
- }
- }
-};
-
-class JobBlackListData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.job = 0;
- this.subAccount = 0
- this.enabled = false;
- this.index = -1;
- this.jobIndex = -1;
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["job_bl_id"];
- this.job = dbAssoc["job_bl_job"];
- this.subAccount = dbAssoc["job_bl_sacct"]
- this.enabled = dbAssoc["job_bl_enabled"];
- }
- }
-};
-
-class KeyBindData {
- constructor(dbAssoc = false, key = 0, commandString = "", keyState = VRR_KEYSTATE_UP) {
- this.databaseId = 0;
- this.key = key;
- this.account = 0;
- this.commandString = commandString;
- this.whenAdded = 0;
- this.enabled = true;
- this.keyState = false;
- this.index = -1;
- this.needsSaved = false;
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["acct_hotkey_id"];
- this.key = toInteger(dbAssoc["acct_hotkey_key"]);
- this.account = toInteger(dbAssoc["acct_hotkey_acct"]);
- this.commandString = dbAssoc["acct_hotkey_cmdstr"];
- this.whenAdded = dbAssoc["acct_hotkey_when_added"];
- this.enabled = intToBool(dbAssoc["acct_hotkey_enabled"]);
- this.keyState = intToBool(dbAssoc["acct_hotkey_down"]);
- }
- }
-};
-
-class RadioStationData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.url = "";
- this.genre = "";
- this.codec = "";
- this.index = -1;
-
- if (dbAssoc) {
- this.databaseId = dbAssoc["radio_id"];
- this.name = dbAssoc["radio_name"];
- this.url = dbAssoc["radio_url"];
- this.genre = dbAssoc["radio_genre"];
- this.codec = dbAssoc["radio_codec"];
- }
- }
-};
-
-class ItemData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.index = 0;
- this.itemTypeIndex = 0;
- this.itemType = 0;
- this.ownerType = VRR_ITEM_OWNER_NONE;
- this.ownerId = 0;
- this.ownerIndex = -1;
- this.position = toVector3(0.0, 0.0, 0.0);
- this.interior = 0;
- this.dimension = 0;
- this.object = null;
- this.buyPrice = 0;
- this.needsSaved = false;
- this.amount = 0;
- this.value = 0;
- this.enabled = false;
- this.extra = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["item_id"]);
- this.index = 0;
- this.itemTypeIndex = 0;
- this.itemType = toInteger(dbAssoc["item_type"]);
- this.ownerType = toInteger(dbAssoc["item_owner_type"]);;
- this.ownerId = toInteger(dbAssoc["item_owner_id"]);
- this.position = toVector3(toFloat(dbAssoc["item_pos_x"]), toFloat(dbAssoc["item_pos_y"]), toFloat(dbAssoc["item_pos_z"]));
- this.interior = toInteger(dbAssoc["item_int"]);
- this.dimension = toInteger(dbAssoc["item_vw"]);
- this.buyPrice = toInteger(dbAssoc["item_buy_price"]);
- this.amount = toInteger(dbAssoc["item_amount"]);
- this.value = toInteger(dbAssoc["item_value"]);
- this.enabled = intToBool(toInteger(dbAssoc["item_enabled"]));
- }
- }
-};
-
-class ItemTypeData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.serverId = 0;
- this.index = 0;
- this.name = "Unknown";
- this.enabled = false;
- this.useType = VRR_ITEM_USETYPE_NONE;
- this.useId = 0;
- this.useValue = 0;
- this.maxValue = 0;
- this.dropType = VRR_ITEM_DROPTYPE_NONE;
- this.useId = 0;
- this.dropPosition = toVector3(0.0, 0.0, 0.0);
- this.dropRotation = toVector3(0.0, 0.0, 0.0);
- this.dropScale = toVector3(0.0, 0.0, 0.0);
- this.dropModel = 0;
- this.orderPrice = 0;
- this.orderValue = 0;
- this.demandMultiplier = 1;
- this.supplyMultiplier = 1;
- this.riskMultiplier = 1;
- this.needsSaved = false;
- this.useDelay = 0;
- this.switchDelay = 0;
- this.pickupDelay = 0;
- this.putDelay = 0;
- this.takeDelay = 0;
- this.giveDelay = 0;
- this.dropDelay = 0;
- this.useAnimationName = "";
- this.dropAnimationName = "";
- this.pickupAnimationName = "";
- this.giveAnimationName = "";
- this.putAnimationName = "";
- this.takeAnimationName = "";
- this.switchAnimationName = "";
- this.useAnimationIndex = false;
- this.dropAnimationIndex = false;
- this.pickupAnimationIndex = false;
- this.giveAnimationIndex = false;
- this.putAnimationIndex = false;
- this.takeAnimationIndex = false;
- this.switchAnimationIndex = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["item_type_id"]);
- this.serverId = toInteger(dbAssoc["item_type_server"]);
- this.name = dbAssoc["item_type_name"];
- this.enabled = intToBool(toInteger(dbAssoc["item_type_enabled"]));
- this.useType = toInteger(dbAssoc["item_type_use_type"]);
- this.dropType = toInteger(dbAssoc["item_type_drop_type"]);
- this.useId = toInteger(dbAssoc["item_type_use_id"]);
- this.dropPosition = toVector3(toFloat(dbAssoc["item_type_drop_pos_x"]), toFloat(dbAssoc["item_type_drop_pos_y"]), toFloat(dbAssoc["item_type_drop_pos_z"]));
- this.dropRotation = toVector3(toFloat(dbAssoc["item_type_drop_rot_x"]), toFloat(dbAssoc["item_type_drop_rot_y"]), toFloat(dbAssoc["item_type_drop_rot_z"]));
- this.dropScale = toVector3(toFloat(dbAssoc["item_type_drop_scale_x"]), toFloat(dbAssoc["item_type_drop_scale_y"]), toFloat(dbAssoc["item_type_drop_scale_z"]));
- this.dropModel = toInteger(dbAssoc["item_type_drop_model"]);
- this.useId = toInteger(dbAssoc["item_type_use_id"]);
- this.useValue = toInteger(dbAssoc["item_type_use_value"]);
- this.maxValue = toInteger(dbAssoc["item_type_max_value"]);
- this.orderPrice = toInteger(dbAssoc["item_type_order_price"]);
- this.orderValue = toInteger(dbAssoc["item_type_order_value"]);
- this.demandMultiplier = toFloat(dbAssoc["item_type_demand_multiplier"]);
- this.supplyMultiplier = toFloat(dbAssoc["item_type_supply_multiplier"]);
- this.riskMultiplier = toFloat(dbAssoc["item_type_risk_multiplier"]);
- this.size = toInteger(dbAssoc["item_type_size"]);
- this.capacity = toInteger(dbAssoc["item_type_capacity"]);
- this.useDelay = toInteger(dbAssoc["item_type_delay_use"]);
- this.switchDelay = toInteger(dbAssoc["item_type_delay_switch"]);
- this.pickupDelay = toInteger(dbAssoc["item_type_delay_pickup"]);
- this.putDelay = toInteger(dbAssoc["item_type_delay_put"]);
- this.takeDelay = toInteger(dbAssoc["item_type_delay_take"]);
- this.giveDelay = toInteger(dbAssoc["item_type_delay_give"]);
- this.dropDelay = toInteger(dbAssoc["item_type_delay_drop"]);
- this.useAnimationName = toInteger(dbAssoc["item_type_anim_use"]);
- this.switchAnimationName = toInteger(dbAssoc["item_type_anim_switch"]);
- this.pickupAnimationName = toInteger(dbAssoc["item_type_anim_pickup"]);
- this.putAnimationName = toInteger(dbAssoc["item_type_anim_put"]);
- this.takeAnimationName = toInteger(dbAssoc["item_type_anim_take"]);
- this.giveAnimationName = toInteger(dbAssoc["item_type_anim_give"]);
- this.dropAnimationName = toInteger(dbAssoc["item_type_anim_drop"]);
- }
- }
-};
-
-class NPCData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.serverId = 0;
- this.name = "NPC";
- this.skin = 0;
- this.cash = 0;
- this.position = toVector3(0.0, 0.0, 0.0);
- this.rotation = toVector3(0.0, 0.0, 0.0);
- this.scale = toVector3(1.0, 1.0, 1.0);
- this.heading = 0.0;
- this.clan = 0;
- this.isWorking = false;
- this.jobUniform = this.skin;
- this.lastJobVehicle = null;
- this.job = 0;
- this.weapons = [];
- this.interior = 0;
- this.dimension = 0;
- this.walkStyle = 0;
- this.fightStyle = 0;
- this.health = 100;
- this.armour = 100;
- 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],
- head: [0, 0],
- upper: [0, 0],
- lower: [0, 0],
- };
-
- this.bodyProps = {
- hair: [0, 0],
- eyes: [0, 0],
- head: [0, 0],
- leftHand: [0, 0],
- rightHand: [0, 0],
- leftWrist: [0, 0],
- rightWrist: [0, 0],
- hip: [0, 0],
- leftFoot: [0, 0],
- rightFoot: [0, 0],
- };
-
- this.triggers = [];
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["npc_id"]);
- this.serverId = toInteger(dbAssoc["npc_server"]);
- 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"]));
- this.rotation = toVector3(toFloat(dbAssoc["npc_rot_x"]), toFloat(dbAssoc["npc_rot_y"]), toFloat(dbAssoc["npc_rot_z"]));
- this.scale = toVector3(toFloat(dbAssoc["npc_scale_x"]), toFloat(dbAssoc["npc_scale_y"]), toFloat(dbAssoc["npc_scale_z"]));
- this.heading = toFloat(dbAssoc["npc_rot_z"]);
- this.lastLogin = toInteger(dbAssoc["npc_when_lastlogin"]);
- this.rank = toInteger(dbAssoc["npc_rank"]);
- this.title = toInteger(dbAssoc["npc_title"]);
- this.job = toInteger(dbAssoc["npc_job"]);
- this.interior = toInteger(dbAssoc["npc_int"]);
- this.dimension = toInteger(dbAssoc["npc_vw"]);
- this.walkStyle = toInteger(dbAssoc["npc_walkstyle"]);
- this.fightStyle = toInteger(dbAssoc["npc_fightstyle"]);
- this.health = toInteger(dbAssoc["npc_health"]);
- this.armour = toInteger(dbAssoc["npc_armour"]);
- this.typeFlags = toInteger(dbAssoc["npc_type_flags"]);
- 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],
- head: [toInteger(dbAssoc["npc_hd_part_head_model"]) || 0, toInteger(dbAssoc["npc_hd_part_head_texture"]) || 0],
- upper: [toInteger(dbAssoc["npc_hd_part_upper_model"]) || 0, toInteger(dbAssoc["npc_hd_part_upper_texture"]) || 0],
- lower: [toInteger(dbAssoc["npc_hd_part_lower_model"]) || 0, toInteger(dbAssoc["npc_hd_part_lower_texture"]) || 0],
- };
-
- this.bodyProps = {
- hair: [toInteger(dbAssoc["npc_hd_prop_hair_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_hair_texture"]) || 0],
- eyes: [toInteger(dbAssoc["npc_hd_prop_eyes_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_eyes_texture"]) || 0],
- head: [toInteger(dbAssoc["npc_hd_prop_head_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_head_texture"]) || 0],
- leftHand: [toInteger(dbAssoc["npc_hd_prop_lefthand_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_lefthand_texture"]) || 0],
- rightHand: [toInteger(dbAssoc["npc_hd_prop_righthand_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_righthand_texture"]) || 0],
- leftWrist: [toInteger(dbAssoc["npc_hd_prop_leftwrist_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_leftwrist_texture"]) || 0],
- rightWrist: [toInteger(dbAssoc["npc_hd_prop_rightwrist_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_rightwrist_texture"]) || 0],
- hip: [toInteger(dbAssoc["npc_hd_prop_hip_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_hip_texture"]) || 0],
- leftFoot: [toInteger(dbAssoc["npc_hd_prop_leftfoot_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_leftfoot_texture"]) || 0],
- rightFoot: [toInteger(dbAssoc["npc_hd_prop_rightfoot_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_rightfoot_texture"]) || 0],
- };
- }
- }
-};
-
-class NPCTriggerData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.npcId = 0;
- this.index = 0;
- this.npc = 0;
- this.npcIndex = -1;
- this.triggerType = 0;
- this.conditions = [];
- this.responses = [];
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["npc_trig_id"]);
- this.npc = toInteger(dbAssoc["npc_trig_npc"]);
- this.triggerType = toInteger(dbAssoc["npc_trig_type"]);
- }
- }
-};
-
-class NPCTriggerConditionData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.triggerId = 0;
- this.index = 0;
- this.triggerIndex = 0;
- this.conditionType = 0;
- this.conditionValue = false;
- this.matchType = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["npc_trig_cond_id"]);
- this.npc = toInteger(dbAssoc["npc_trig_cond_trig"]);
- this.conditionType = toInteger(dbAssoc["npc_trig_cond_type"]);
- this.conditionValue = toInteger(dbAssoc["npc_trig_cond_val"]);
- this.matchType = toInteger(dbAssoc["npc_trig_cond_val"]);
- }
- }
-};
-
-class NPCTriggerResponseData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.triggerId = 0;
- this.index = 0;
- this.triggerIndex = 0;
- this.responseType = 0;
- this.responseValue = false;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["npc_trig_resp_id"]);
- this.npc = toInteger(dbAssoc["npc_trig_resp_trig"]);
- this.responseType = toInteger(dbAssoc["npc_trig_resp_type"]);
- this.responseValue = toInteger(dbAssoc["npc_trig_resp_val"]);
- }
- }
-};
-
-class BanData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.type = VRR_BANTYPE_NONE;
- this.detail = "";
- this.ipAddress = "";
- this.name = "";
- this.reason = "";
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["ban_id"]);
- this.type = dbAssoc["ban_type"];
- this.detail = toInteger(dbAssoc["ban_detail"]);
- this.ipAddress = toInteger(dbAssoc["ban_ip"]);
- this.reason = toInteger(dbAssoc["ban_reason"]);
- }
- }
-}
-
-class JobRouteData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.jobId = 0;
- this.locationId = 0;
- this.enabled = false;
- this.index = -1;
- this.jobIndex = -1;
- this.locationIndex = -1;
- this.needsSaved = false;
- this.pay = 0;
- this.vehicleColour1 = 1;
- this.vehicleColour2 = 1;
- this.detail = 0;
- this.startMessage = "";
- this.finishMessage = "";
- this.locationArriveMessage = "";
- this.locationNextMessage = "";
- this.locations = [];
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["job_route_id"]);
- this.name = toString(dbAssoc["job_route_name"]);
- this.jobId = toInteger(dbAssoc["job_route_job"]);
- this.locationId = toInteger(dbAssoc["job_route_job_loc"]);
- this.enabled = intToBool(toInteger(dbAssoc["job_route_enabled"]));
- this.pay = toInteger(dbAssoc["job_route_pay"]);
- this.startMessage = toString(dbAssoc["job_route_start_msg"]);
- this.finishMessage = toString(dbAssoc["job_route_finish_msg"]);
- this.locationArriveMessage = toString(dbAssoc["job_route_loc_arrive_msg"]);
- this.locationNextMessage = toString(dbAssoc["job_route_loc_next_msg"]);
- this.vehicleColour1 = toInteger(dbAssoc["job_route_veh_colour1"]);
- this.vehicleColour2 = toInteger(dbAssoc["job_route_veh_colour2"]);
- this.detail = toInteger(dbAssoc["job_route_detail"]);
- }
- }
-};
-
-class JobRouteLocationData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.routeId = 0;
- this.enabled = false;
- this.index = -1;
- this.jobIndex = -1;
- this.routeIndex = -1;
- this.needsSaved = false;
- this.position = toVector3(0.0, 0.0, 0.0);
- this.stopDelay = 0;
- this.pay = 0;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["job_route_loc_id"]);
- this.name = toString(dbAssoc["job_route_loc_name"]);
- this.routeId = toInteger(dbAssoc["job_route_loc_route"]);
- this.enabled = intToBool(toInteger(dbAssoc["job_route_loc_enabled"]));
- this.position = toVector3(toFloat(dbAssoc["job_route_loc_x"]), toFloat(dbAssoc["job_route_loc_y"]), toFloat(dbAssoc["job_route_loc_z"]));
- this.stopDelay = toInteger(dbAssoc["job_route_loc_delay"]);
- this.pay = toInteger(dbAssoc["job_route_loc_pay"]);
- }
- }
-};
-
-class GateData {
- constructor(dbAssoc = false) {
- this.databaseId = 0;
- this.name = "";
- this.scriptName = "";
- this.enabled = false;
- this.position = toVector3(0.0, 0.0, 0.0);
- this.locked = true;
- this.ownerType = VRR_GATEOWNER_NONE;
- this.ownerId = 0;
-
- if (dbAssoc) {
- this.databaseId = toInteger(dbAssoc["gate_id"]);
- this.name = toString(dbAssoc["gate_name"]);
- this.scriptName = toString(dbAssoc["gate_script_name"]);
- this.enabled = intToBool(toInteger(dbAssoc["gate_enabled"]));
- this.position = toVector3(toFloat(dbAssoc["gate_pos_x"]), toFloat(dbAssoc["gate_pos_y"]), toFloat(dbAssoc["gate_pos_z"]));
- this.ownerType = toInteger(dbAssoc["gate_owner_type"]);
- this.ownerId = toInteger(dbAssoc["gate_owner_id"]);
- }
- }
-}
\ No newline at end of file
diff --git a/scripts/server/command.js b/scripts/server/command.js
index 8c448de8..f0badb16 100644
--- a/scripts/server/command.js
+++ b/scripts/server/command.js
@@ -7,6 +7,41 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+/**
+ * @class Representing a command's data. Loaded and saved in the database
+ */
+class CommandData {
+ enable() {
+ this.enabled = true;
+ }
+
+ disable() {
+ this.enabled = false;
+ }
+
+ toggleEnabled() {
+ this.enabled = !this.enabled;
+ }
+
+ constructor(command, handlerFunction, syntaxString, requiredStaffFlags, requireLogin, allowOnDiscord, helpDescription) {
+ this.command = command;
+ this.handlerFunction = handlerFunction;
+ this.syntaxString = syntaxString;
+ this.requiredStaffFlags = requiredStaffFlags;
+ this.enabled = true;
+ this.requireLogin = requireLogin;
+ this.allowOnDiscord = allowOnDiscord;
+ this.helpDescription = helpDescription;
+ this.aliases = [];
+ }
+};
+
+// ===========================================================================
+
+let serverCommands = [];
+
+// ===========================================================================
+
function initCommandScript() {
logToConsole(LOG_INFO, "[VRR.Command]: Initializing commands script ...");
logToConsole(LOG_INFO, "[VRR.Command]: Initialized commands script!");
@@ -612,8 +647,8 @@ function loadCommands() {
function addAllCommandHandlers() {
let commandCount = 0;
let commands = getCommands();
- for(let i in commands) {
- for(let j in commands[i]) {
+ for (let i in commands) {
+ for (let j in commands[i]) {
logToConsole(LOG_DEBUG, `[VRR.Command] Adding command handler for ${i} - ${commands[i][j].command}`);
addCommandHandler(commands[i][j].command, processPlayerCommand);
commandCount++;
@@ -627,10 +662,10 @@ function addAllCommandHandlers() {
function getCommand(command) {
let commandGroups = getCommands()
- for(let i in commandGroups) {
+ for (let i in commandGroups) {
let commandGroup = commandGroups[i];
- for(let j in commandGroup) {
- if(toLowerCase(commandGroup[j].command) == toLowerCase(command)) {
+ for (let j in commandGroup) {
+ if (toLowerCase(commandGroup[j].command) == toLowerCase(command)) {
return commandGroup[j];
}
}
@@ -684,14 +719,14 @@ function isCommandAllowedOnDiscord(command) {
// ===========================================================================
function disableCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
params = toLowerCase(params);
- if(!getCommand(params)) {
+ if (!getCommand(params)) {
messagePlayerError(client, `The command {ALTCOLOUR}/${params} {MAINCOLOUR} does not exist!`);
return false;
}
@@ -704,14 +739,14 @@ function disableCommand(command, params, client) {
// ===========================================================================
function enableCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
params = toLowerCase(params);
- if(!getCommand(params)) {
+ if (!getCommand(params)) {
messagePlayerError(client, `The command {ALTCOLOUR}/${params} {MAINCOLOUR} does not exist!`);
return false;
}
@@ -724,19 +759,19 @@ function enableCommand(command, params, client) {
// ===========================================================================
function disableAllCommandsByType(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
params = toLowerCase(params);
- if(isNull(getServerData().commands[params])) {
+ if (isNull(getServerData().commands[params])) {
messagePlayerError(client, `Command type {ALTCOLOUR}${params} {MAINCOLOUR}does not exist!`);
return false;
}
- for(let i in getServerData().commands[params]) {
+ for (let i in getServerData().commands[params]) {
getServerData().commands[params][i].enabled = false;
}
@@ -747,19 +782,19 @@ function disableAllCommandsByType(command, params, client) {
// ===========================================================================
function enableAllCommandsByType(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
params = toLowerCase(params);
- if(isNull(getServerData().commands[params])) {
+ if (isNull(getServerData().commands[params])) {
messagePlayerError(client, `Command type {ALTCOLOUR}${params} {MAINCOLOUR}does not exist!`);
return false;
}
- for(let i in getServerData().commands[params]) {
+ for (let i in getServerData().commands[params]) {
getServerData().commands[params][i].enabled = true;
}
@@ -776,22 +811,22 @@ function enableAllCommandsByType(command, params, client) {
// ===========================================================================
function processPlayerCommand(command, params, client) {
- if(builtInCommands.indexOf(toLowerCase(command)) != -1) {
+ if (builtInCommands.indexOf(toLowerCase(command)) != -1) {
return true;
}
let commandData = getCommand(toLowerCase(command));
let paramsDisplay = params;
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
paramsDisplay = "";
}
- if(!doesCommandExist(toLowerCase(command))) {
+ if (!doesCommandExist(toLowerCase(command))) {
logToConsole(LOG_WARN, `[VRR.Command] ${getPlayerDisplayForConsole(client)} attempted to use command, but failed (invalid command): /${command} ${paramsDisplay}`);
let possibleCommand = getCommandFromParams(command);
- if(possibleCommand != false && doesPlayerHaveStaffPermission(client, getCommandRequiredPermissions(toLowerCase(possibleCommand.command)))) {
+ if (possibleCommand != false && doesPlayerHaveStaffPermission(client, getCommandRequiredPermissions(toLowerCase(possibleCommand.command)))) {
messagePlayerError(client, getLocaleString(client, "InvalidCommandPossibleMatchTip", `{ALTCOLOUR}/${command}{MAINCOLOUR}`, `{ALTCOLOUR}${toLowerCase(possibleCommand.command)}{MAINCOLOUR}`));
} else {
messagePlayerError(client, getLocaleString(client, "InvalidCommandHelpTip", `{ALTCOLOUR}/${command}{MAINCOLOUR}`, `{ALTCOLOUR}/help{MAINCOLOUR}`));
@@ -799,31 +834,31 @@ function processPlayerCommand(command, params, client) {
return false;
}
- if(!commandData.enabled) {
+ if (!commandData.enabled) {
logToConsole(LOG_WARN, `[VRR.Command] ${getPlayerDisplayForConsole(client)} attempted to use command, but failed (command is disabled): /${command} ${paramsDisplay}`);
messagePlayerError(client, `The command {ALTCOLOUR}/${command}{MAINCOLOUR} is disabled!`);
messagePlayerError(client, getLocaleString(client, "CommandDisabled", `{ALTCOLOUR}/${command}{MAINCOLOUR}`));
return false;
}
- if(doesCommandRequireLogin(toLowerCase(command))) {
- if(!isPlayerLoggedIn(client)) {
+ if (doesCommandRequireLogin(toLowerCase(command))) {
+ if (!isPlayerLoggedIn(client)) {
logToConsole(LOG_WARN, `[VRR.Command] ${getPlayerDisplayForConsole(client)} attempted to use command, but failed (requires login first): /${command} ${paramsDisplay}`);
messagePlayerError(client, getLocaleString(client, "CommandRequiresLogin", `{ALTCOLOUR}/${command}{MAINCOLOUR}`));
return false;
}
}
- if(isClientFromDiscord(client)) {
- if(!isCommandAllowedOnDiscord(command)) {
- logToConsole(LOG_WARN, `[VRR.Command] ${getPlayerDisplayForConsole(client)} attempted to use command from discord, but failed (not available on discord): /${command} ${paramsDisplay}`);
+ if (isClientFromDiscord(client)) {
+ if (!isCommandAllowedOnDiscord(command)) {
+ logToConsole(LOG_WARN, `[VRR.Command] ${getPlayerDisplayForConsole(client)} attempted to use command from discord, but failed (not available on discord): /${command} ${paramsDisplay}`);
messagePlayerError(client, `The {ALTCOLOUR}/${command}{MAINCOLOUR} command isn't available on discord!`);
return false;
}
}
- if(!isConsole(client)) {
- if(!doesPlayerHaveStaffPermission(client, getCommandRequiredPermissions(toLowerCase(command)))) {
+ 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, getLocaleString(client, "CommandNoPermissions", `{ALTCOLOUR}/${toLowerCase(command)}{MAINCOLOUR}`));
return false;
@@ -836,8 +871,8 @@ function processPlayerCommand(command, params, client) {
// ===========================================================================
-addCommandHandler("cmd", function(command, params, client) {
- if(!isConsole(client)) {
+addCommandHandler("cmd", function (command, params, client) {
+ if (!isConsole(client)) {
return false;
}
@@ -852,8 +887,8 @@ addCommandHandler("cmd", function(command, params, client) {
function listAllCommands() {
let commands = getCommands();
- for(let i in commands) {
- for(let j in commands[i]) {
+ for (let i in commands) {
+ for (let j in commands[i]) {
logToConsole(LOG_DEBUG, commands[i][j].command);
}
}
@@ -864,8 +899,8 @@ function listAllCommands() {
function getAllCommandsInSingleArray() {
let tempCommands = [];
let commands = getCommands();
- for(let i in commands) {
- for(let j in commands[i]) {
+ for (let i in commands) {
+ for (let j in commands[i]) {
tempCommands.push(commands[i][j].command);
}
}
@@ -878,8 +913,8 @@ function getAllCommandsInSingleArray() {
function getAllCommandsInGroupInSingleArray(groupName, staffFlag = "None") {
let tempCommands = [];
let commands = getCommands();
- for(let i in commands[groupName]) {
- if(getCommandRequiredPermissions(commands[groupName][i].command) == 0) {
+ for (let i in commands[groupName]) {
+ if (getCommandRequiredPermissions(commands[groupName][i].command) == 0) {
tempCommands.push(commands[groupName][i].command);
}
}
@@ -892,10 +927,10 @@ function getAllCommandsInGroupInSingleArray(groupName, staffFlag = "None") {
function getAllCommandsForStaffFlagInSingleArray(staffFlagName) {
let tempCommands = [];
let commands = getCommands();
- for(let i in commands) {
- for(let j in commands[i]) {
- if(getCommandRequiredPermissions(commands[i][j].command) != 0) {
- if(hasBitFlag(getCommandRequiredPermissions(commands[i][j].command), getStaffFlagValue(staffFlagName))) {
+ for (let i in commands) {
+ for (let j in commands[i]) {
+ if (getCommandRequiredPermissions(commands[i][j].command) != 0) {
+ if (hasBitFlag(getCommandRequiredPermissions(commands[i][j].command), getStaffFlagValue(staffFlagName))) {
tempCommands.push(commands[i][j].command);
}
}
@@ -908,7 +943,7 @@ function getAllCommandsForStaffFlagInSingleArray(staffFlagName) {
// ===========================================================================
function doesCommandExist(command) {
- if(getCommandData(command)) {
+ if (getCommandData(command)) {
return true;
}
@@ -919,11 +954,11 @@ function doesCommandExist(command) {
function cacheAllCommandsAliases() {
let commands = getCommands();
- for(let i in commands) {
- for(let j in commands[i]) {
- for(let k in commands) {
- for(let m in commands[k]) {
- if(commands[i][j].handlerFunction == commands[k][m].handlerFunction) {
+ for (let i in commands) {
+ for (let j in commands[i]) {
+ for (let k in commands) {
+ for (let m in commands[k]) {
+ if (commands[i][j].handlerFunction == commands[k][m].handlerFunction) {
commands[i][j].aliases.push(commands[k][m]);
commands[k][m].aliases.push(commands[i][j]);
}
@@ -937,7 +972,7 @@ function cacheAllCommandsAliases() {
function getCommandAliasesNames(command) {
let commandAliases = [];
- for(let i in command.aliases) {
+ for (let i in command.aliases) {
commandAliases.push(command.aliases[i].name);
}
@@ -947,7 +982,7 @@ function getCommandAliasesNames(command) {
// ===========================================================================
function areParamsEmpty(params) {
- if(!params || params == "" || params.length == 0 || typeof params == "undefined") {
+ if (!params || params == "" || params.length == 0 || typeof params == "undefined") {
return true;
}
@@ -969,16 +1004,16 @@ function areThereEnoughParams(params, requiredAmount, delimiter = " ") {
// ===========================================================================
function getParam(params, delimiter, index) {
- return params.split(delimiter)[index-1];
+ return params.split(delimiter)[index - 1];
}
// ===========================================================================
function getCommandFromParams(params) {
let commands = getCommands();
- for(let i in commands) {
- for(let j in commands[i]) {
- if(toLowerCase(commands[i][j].command).indexOf(toLowerCase(params)) != -1) {
+ for (let i in commands) {
+ for (let j in commands[i]) {
+ if (toLowerCase(commands[i][j].command).indexOf(toLowerCase(params)) != -1) {
return commands[i][j];
}
}
diff --git a/scripts/server/config.js b/scripts/server/config.js
index e9ece596..e2276cb4 100644
--- a/scripts/server/config.js
+++ b/scripts/server/config.js
@@ -7,6 +7,127 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+/**
+ * @class Representing data for server configuration
+ */
+class ServerConfigData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.needsSaved = false;
+
+ this.newCharacter = {
+ spawnPosition: toVector3(0.0, 0.0, 0.0),
+ spawnHeading: 0.0,
+ spawnInterior: 0,
+ spawnDimension: 0,
+ money: 0,
+ bank: 0,
+ skin: 0,
+ };
+
+ this.connectCameraPosition = toVector3(0.0, 0.0, 0.0);
+ this.connectCameraLookAt = toVector3(0.0, 0.0, 0.0);
+
+ this.characterSelectCameraPosition = toVector3(0.0, 0.0, 0.0);
+ this.characterSelectCameraLookAt = toVector3(0.0, 0.0, 0.0);
+ this.characterSelectPedPosition = toVector3(0.0, 0.0, 0.0);
+ this.characterSelectPedHeading = 0.0;
+ this.characterSelectInterior = 0;
+ this.characterSelectDimension = 0;
+
+ this.hour = 0;
+ this.minute = 0
+ this.minuteDuration = 1000;
+ this.weather = 0
+ this.fallingSnow = false;
+ this.groundSnow = false;
+ this.useGUI = true;
+ this.guiColourPrimary = [200, 200, 200];
+ this.guiColourSecondary = [200, 200, 200];
+ this.guiTextColourPrimary = [0, 0, 0];
+ this.guiTextColourSecondary = [0, 0, 0];
+ this.showLogo = true;
+ this.inflationMultiplier = 1;
+ this.testerOnly = false;
+ this.settings = 0;
+
+ this.antiCheat = {
+ enabled: false,
+ //checkGameScripts: false,
+ //gameScriptWhiteListEnabled: false,
+ //gameScriptBlackListEnabled: false,
+ //gameScriptWhiteList: [],
+ //gameScriptBlackList: [],
+ };
+
+ this.discordBotToken = "";
+ this.discordEnabled = false;
+
+ this.createJobPickups = false;
+ this.createBusinessPickups = false;
+ this.createHousePickups = false;
+ this.createJobBlips = false;
+ this.createBusinessBlips = false;
+ this.createHouseBlips = false;
+
+ this.introMusicURL = "";
+
+ this.pauseSavingToDatabase = false;
+
+ this.useRealTime = false;
+ this.realTimeZone = 0;
+
+ this.discordConfig = {
+ eventChannelWebHookURL: "",
+ chatChannelWebHookURL: "",
+ adminChannelWebHookURL: "",
+ sendEvents: true,
+ sendChat: true,
+ sendAdminEvents: true,
+ };
+
+ if (dbAssoc) {
+ this.databaseId = dbAssoc["svr_id"];
+ this.newCharacter = {
+ spawnPosition: toVector3(dbAssoc["svr_newchar_pos_x"], dbAssoc["svr_newchar_pos_y"], dbAssoc["svr_newchar_pos_z"]),
+ spawnHeading: dbAssoc["svr_newchar_rot_z"],
+ money: dbAssoc["svr_newchar_money"],
+ bank: dbAssoc["svr_newchar_bank"],
+ skin: dbAssoc["svr_newchar_skin"],
+ },
+ this.settings = toInteger(dbAssoc["svr_settings"]);
+
+ this.connectCameraPosition = toVector3(dbAssoc["svr_connectcam_pos_x"], dbAssoc["svr_connectcam_pos_y"], dbAssoc["svr_connectcam_pos_z"]);
+ this.connectCameraLookAt = toVector3(dbAssoc["svr_connectcam_lookat_x"], dbAssoc["svr_connectcam_lookat_y"], dbAssoc["svr_connectcam_lookat_z"]);
+
+ this.hour = toInteger(dbAssoc["svr_start_time_hour"]);
+ this.minute = toInteger(dbAssoc["svr_start_time_min"]);
+ this.minuteDuration = toInteger(dbAssoc["svr_time_min_duration"]);
+ this.weather = toInteger(dbAssoc["svr_start_weather"]);
+ this.guiColourPrimary = [toInteger(dbAssoc["svr_gui_col1_r"]), toInteger(dbAssoc["svr_gui_col1_g"]), toInteger(dbAssoc["svr_gui_col1_b"])];
+ this.guiColourSecondary = [toInteger(dbAssoc["svr_gui_col2_r"]), toInteger(dbAssoc["svr_gui_col2_g"]), toInteger(dbAssoc["svr_gui_col2_b"])];
+ this.guiTextColourPrimary = [toInteger(dbAssoc["svr_gui_textcol1_r"]), toInteger(dbAssoc["svr_gui_textcol1_g"]), toInteger(dbAssoc["svr_gui_textcol1_b"])];
+ //this.guiTextColourSecondary = [toInteger(dbAssoc["svr_gui_textcol2_r"]), toInteger(dbAssoc["svr_gui_textcol2_g"]), toInteger(dbAssoc["svr_gui_textcol2_b"])];
+ this.inflationMultiplier = toFloat(dbAssoc["svr_inflation_multiplier"]);
+
+ this.discordBotToken = intToBool(dbAssoc["svr_discord_bot_token"]);
+ this.introMusicURL = dbAssoc["svr_intro_music"];
+ this.realTimeZone = dbAssoc["svr_time_realtime_timezone"];
+
+ this.discordConfig = {
+ eventChannelWebHookURL: dbAssoc["svr_discord_event_webhook"],
+ chatChannelWebHookURL: dbAssoc["svr_discord_chat_webhook"],
+ adminChannelWebHookURL: dbAssoc["svr_discord_admin_webhook"],
+ sendEvents: true,
+ sendChat: true,
+ sendAdminEvents: true,
+ };
+ }
+ }
+};
+
+// ===========================================================================
+
let serverConfig = false;
let gameConfig = false;
@@ -653,7 +774,7 @@ function toggleServerGUICommand(command, params, client) {
getServerConfig().needsSaved = true;
- announceAdminAction(`ServerGUISet`, `${getPlayerName(client)}{MAINCOLOUR}`, `{adminOrange}${getPlayerName(client)}{MAINCOLOUR}`, `${getBoolRedGreenInlineColour(getServerConfig().useGUI)}${toUpperCase(getOnOffFromBool(getServerConfig().useGUI))}{MAINCOLOUR}`);
+ announceAdminAction(`ServerGUISet`, `${getPlayerName(client)}{MAINCOLOUR}`, `${getBoolRedGreenInlineColour(getServerConfig().useGUI)}${toUpperCase(getOnOffFromBool(getServerConfig().useGUI))}{MAINCOLOUR}`);
updateServerRules();
return true;
}
@@ -961,6 +1082,8 @@ function loadServerConfig() {
logToConsole(LOG_ERROR, `[VRR.Config] Could not load server configuration for game ${getGame()} and port ${getServerPort}`);
thisResource.stop();
}
+
+ logToConsole(LOG_DEBUG | LOG_WARN, `Server ID: ${serverConfig.databaseId}`);
}
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/const.js b/scripts/server/const.js
deleted file mode 100644
index adf23695..00000000
--- a/scripts/server/const.js
+++ /dev/null
@@ -1,371 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: const.js
-// DESC: Provides constants
-// TYPE: Server (JavaScript)
-// ===========================================================================
-
-// Prompts (used for client GUI prompt responses)
-const VRR_PROMPT_NONE = 0;
-const VRR_PROMPT_CREATEFIRSTCHAR = 1;
-const VRR_PROMPT_BIZORDER = 2;
-const VRR_PROMPT_VEHGIVETOCLAN = 3;
-const VRR_PROMPT_HOUSEGIVETOCLAN = 4;
-const VRR_PROMPT_BIZGIVETOCLAN = 5;
-const VRR_PROMPT_HOUSEBUY = 6;
-const VRR_PROMPT_BIZBUY = 7;
-
-// Job Types
-const VRR_JOB_NONE = 0;
-const VRR_JOB_POLICE = 1;
-const VRR_JOB_MEDICAL = 2;
-const VRR_JOB_FIRE = 3;
-const VRR_JOB_BUS = 4;
-const VRR_JOB_TAXI = 5;
-const VRR_JOB_GARBAGE = 6;
-const VRR_JOB_WEAPON = 7;
-const VRR_JOB_DRUG = 8;
-const VRR_JOB_PIZZA = 9;
-const VRR_JOB_GENERIC = 10;
-
-// Pickup Types
-const VRR_PICKUP_NONE = 0;
-const VRR_PICKUP_JOB = 1;
-const VRR_PICKUP_BUSINESS_ENTRANCE = 2;
-const VRR_PICKUP_BUSINESS_EXIT = 3;
-const VRR_PICKUP_HOUSE_ENTRANCE = 4;
-const VRR_PICKUP_HOUSE_EXIT = 5;
-const VRR_PICKUP_EXIT = 6;
-
-// Vehicle Owner Types
-const VRR_VEHOWNER_NONE = 0; // Not owned
-const VRR_VEHOWNER_PLAYER = 1; // Owned by a player (character/subaccount)
-const VRR_VEHOWNER_JOB = 2; // Owned by a job
-const VRR_VEHOWNER_CLAN = 3; // Owned by a clan
-const VRR_VEHOWNER_FACTION = 4; // Owned by a faction (not used at the moment)
-const VRR_VEHOWNER_PUBLIC = 5; // Public vehicle. Anybody can drive it.
-const VRR_VEHOWNER_BIZ = 6; // Owned by a business (also includes dealerships since they're businesses)
-
-// Business Owner Types
-const VRR_BIZOWNER_NONE = 0; // Not owned
-const VRR_BIZOWNER_PLAYER = 1; // Owned by a player (character/subaccount)
-const VRR_BIZOWNER_JOB = 2; // Owned by a job
-const VRR_BIZOWNER_CLAN = 3; // Owned by a clan
-const VRR_BIZOWNER_FACTION = 4; // Owned by a faction (not used at the moment)
-const VRR_BIZOWNER_PUBLIC = 5; // Public Business. Used for goverment/official places like police, fire, city hall, DMV, etc
-
-// House Owner Types
-const VRR_HOUSEOWNER_NONE = 0; // Not owned
-const VRR_HOUSEOWNER_PLAYER = 1; // Owner is a player (character/subaccount)
-const VRR_HOUSEOWNER_JOB = 2; // Owned by a job
-const VRR_HOUSEOWNER_CLAN = 3; // Owned by a clan
-const VRR_HOUSEOWNER_FACTION = 4; // Owned by a faction
-const VRR_HOUSEOWNER_PUBLIC = 5; // Is a public house. Technically not owned. This probably won't be used.
-const VRR_HOUSEOWNER_BIZ = 6; // Owned by a business. Used for apartment buildings where rent goes to business.
-
-// Gate Owner Types
-const VRR_GATEOWNER_NONE = 0; // Not owned
-const VRR_GATEOWNER_PLAYER = 1; // Owner is a player (character/subaccount)
-const VRR_GATEOWNER_JOB = 2; // Owned by a job
-const VRR_GATEOWNER_CLAN = 3; // Owned by a clan
-const VRR_GATEOWNER_FACTION = 4; // Owned by a faction
-const VRR_GATEOWNER_PUBLIC = 5; // Public gate. Technically not owned. This probably won't be used.
-const VRR_GATEOWNER_BUSINESS = 6; // Owned by a business. Back lots, unloading areas, and other stuff like that
-const VRR_GATEOWNER_HOUSE = 7; // Owned by a house. Like for mansions with closed private areas.
-
-// Business Location Types
-const VRR_BIZLOC_NONE = 0; // None
-const VRR_BIZLOC_GATE = 1; // Center of any moveable gate that belongs to the biz
-const VRR_BIZLOC_GARAGE = 2; // Location for attached garage (pos1 = outside, pos2 = inside). Use pos to teleport or spawn veh/ped
-const VRR_BIZLOC_FUEL = 3; // Fuel pump
-const VRR_BIZLOC_DRIVETHRU = 4; // Drivethrough
-const VRR_BIZLOC_VENDMACHINE = 5; // Vending machine
-
-// House Location Types
-const VRR_HOUSELOC_NONE = 0; // None
-const VRR_HOUSELOC_GATE = 1; // Center of any moveable gate that belongs to the house
-const VRR_HOUSELOC_GARAGE = 2; // Location for garage (pos1 = outside, pos2 = inside). Use pos to teleport or spawn veh/ped
-
-// Account Contact Types
-const VRR_CONTACT_NONE = 0;
-const VRR_CONTACT_NEUTRAL = 1; // Contact is neutral. Used for general contacts with no special additional features
-const VRR_CONTACT_FRIEND = 2; // Contact is a friend. Shows when they're online.
-const VRR_CONTACT_BLOCKED = 3; // Contact is blocked. Prevents all communication to/from them except for RP
-
-// Job Work Types (Currently Unused)
-const VRR_JOBWORKTYPE_NONE = 0;
-const VRR_JOBWORKTYPE_ROUTE = 1; // Jobs that use routes. Bus, trash collector, mail, etc
-const VRR_JOBWORKTYPE_SELL = 2; // Jobs that sell items to other players and NPCs. Drugs, guns, etc
-const VRR_JOBWORKTYPE_SERVICE = 3; // Services to other players and NPCs. Taxi ride, mechanic fix, etc
-
-// Vehicle Seats
-const VRR_VEHSEAT_DRIVER = 0;
-const VRR_VEHSEAT_FRONTPASSENGER = 1;
-const VRR_VEHSEAT_REARLEFTPASSENGER = 2;
-const VRR_VEHSEAT_REARRIGHTPASSENGER = 3;
-
-// Ban Types
-const VRR_BANTYPE_NONE = 0;
-const VRR_BANTYPE_ACCOUNT = 1;
-const VRR_BANTYPE_SUBACCOUNT = 2;
-const VRR_BANTYPE_IPADDRESS = 3;
-const VRR_BANTYPE_SUBNET = 4;
-
-// Blip Owner Types
-const VRR_BLIP_NONE = 0;
-const VRR_BLIP_JOB = 1;
-const VRR_BLIP_BUSINESS_ENTRANCE = 2;
-const VRR_BLIP_BUSINESS_EXIT = 3;
-const VRR_BLIP_HOUSE_ENTRANCE = 4;
-const VRR_BLIP_HOUSE_EXIT = 5;
-const VRR_BLIP_EXIT = 6;
-
-// Insurance Account Owner Types
-const VRR_INS_ACCT_OWNER_NONE = 0; // None
-const VRR_INS_ACCT_OWNER_PLAYER = 1; // Player owns insurance company
-const VRR_INS_ACCT_OWNER_BIZ = 2; // Business owns insurance company
-const VRR_INS_ACCT_OWNER_CLAN = 3; // Clan owns insurance company
-
-// Insurance Account Entity Types
-const VRR_INS_ACCT_ENTITY_NONE = 0; // None
-const VRR_INS_ACCT_ENTITY_PLAYER_HEALTH = 1; // Health Insurance
-const VRR_INS_ACCT_ENTITY_PLAYER_LIFE = 2; // Life Insurance
-const VRR_INS_ACCT_ENTITY_VEH = 3; // Vehicle Insurance
-const VRR_INS_ACCT_ENTITY_BIZ = 4; // Business Insurance
-const VRR_INS_ACCT_ENTITY_HOUSE = 5; // House Insurance
-
-// Insurance Account History Types
-const VRR_INS_ACCT_HISTORY_NONE = 0; // None
-const VRR_INS_ACCT_HISTORY_PLAYER_MEDICAL = 1; // Medical insurance was used (player disease/injury)
-const VRR_INS_ACCT_HISTORY_PLAYER_DEATH = 2; // Life insurance was used (player death)
-const VRR_INS_ACCT_HISTORY_VEH_DAMAGE = 3; // Vehicle was damaged, but not destroyed
-const VRR_INS_ACCT_HISTORY_VEH_WRECKED = 4; // Vehicle was completely destroyed
-const VRR_INS_ACCT_HISTORY_VEH_THEFT = 5; // Vehicle was stolen
-const VRR_INS_ACCT_HISTORY_BIZ_DAMAGE = 6; // Business was damaged (broken items/window/door)
-const VRR_INS_ACCT_HISTORY_BIZ_THEFT = 7; // Business was stolen from
-const VRR_INS_ACCT_HISTORY_HOUSE_DAMAGE = 8; // House was damaged
-const VRR_INS_ACCT_HISTORY_HOUSE_THEFT = 9; // House was stolen from
-
-// Islands
-const VRR_ISLAND_NONE = 0; // None
-const VRR_ISLAND_PORTLAND = 0; // Portland Island
-const VRR_ISLAND_STAUNTON = 1; // Staunton Island
-const VRR_ISLAND_SHORESIDEVALE = 2; // Shoreside Vale
-const VRR_ISLAND_VICEWEST = 0; // Western Island of VC
-const VRR_ISLAND_VICEEAST = 1; // Eastern Island of VC
-const VRR_ISLAND_LOSSANTOS = 0; // Los Santos
-const VRR_ISLAND_LASVENTURAS = 1; // Las Venturas
-const VRR_ISLAND_SANFIERRO = 2; // San Fierro
-const VRR_ISLAND_REDCOUNTYNORTH = 4; // Red County North (spans all the way from Palamino/shore on the east east to border of Flint County on the west)
-const VRR_ISLAND_BONECOUNTYNORTH = 5; // Bone County North (usually called Tierra Robada)
-const VRR_ISLAND_BONECOUNTYSOUTH = 6; // Bone County South
-
-// Item Owners
-const VRR_ITEM_OWNER_NONE = 0; // None
-const VRR_ITEM_OWNER_PLAYER = 1; // Item is in a player's inventory
-const VRR_ITEM_OWNER_VEHTRUNK = 2; // Item is in a vehicle's trunk
-const VRR_ITEM_OWNER_VEHDASH = 3; // Item is in a vehicle's glove compartment
-const VRR_ITEM_OWNER_BIZFLOOR = 4; // Item is in the public area of a business (on the floor = ready to buy)
-const VRR_ITEM_OWNER_BIZSTORAGE = 5; // Item is in a business's storage area (stock room)
-const VRR_ITEM_OWNER_HOUSE = 6; // Item is in a house
-const VRR_ITEM_OWNER_SAFE = 7; // Item is in a safe (safes can be anywhere)
-const VRR_ITEM_OWNER_ITEM = 8; // Item is in another item (trashbag, briefcase, wallet, suitcase, crate/box, barrel, etc)
-const VRR_ITEM_OWNER_GROUND = 9; // Item is on the ground
-const VRR_ITEM_OWNER_JOBLOCKER = 10; // Item is in player's job locker
-const VRR_ITEM_OWNER_LOCKER = 10; // Item is in player's locker
-
-// Item Use Types
-const VRR_ITEM_USETYPE_NONE = 0; // Has no effect
-const VRR_ITEM_USETYPE_WEAPON = 1; // Equips weapon
-const VRR_ITEM_USETYPE_AMMO_CLIP = 2; // Magazine for weapon. If in inventory, R will load it into gun
-const VRR_ITEM_USETYPE_PHONE = 3; // Pulls out phone
-const VRR_ITEM_USETYPE_GPS = 4; // Not sure how I want this to work yet
-const VRR_ITEM_USETYPE_MAP = 5; // Shows minimap on HUD
-const VRR_ITEM_USETYPE_SKIN = 6; // Changes skin (uses skin changer)
-const VRR_ITEM_USETYPE_PEDPART = 7; // Changes ped part (clothing, skin, hair, etc) (UNUSED)
-const VRR_ITEM_USETYPE_PEDPROP = 8; // Changes ped prop (watches, glasses, hats, etc) (UNUSED)
-const VRR_ITEM_USETYPE_STORAGE = 9; // Shows stored items. Backpack, crate, briefcase, wallet, etc
-const VRR_ITEM_USETYPE_VEHKEY = 10; // Locks/unlocks a vehicle and allows starting engine without hotwire
-const VRR_ITEM_USETYPE_BIZKEY = 11; // Locks/unlocks a business
-const VRR_ITEM_USETYPE_HOUSEKEY = 12; // Locks/unlocks a house
-const VRR_ITEM_USETYPE_SEED = 13; // Plants a seed
-const VRR_ITEM_USETYPE_WEED = 14; // Light drug effect (short term relief of addiction symptoms?)
-const VRR_ITEM_USETYPE_COKE = 15; // Medium drug effect (medium term relief of addiction symptoms?)
-const VRR_ITEM_USETYPE_METH = 16; // Heavy drug effect (extended term relief of addiction symptoms?)
-const VRR_ITEM_USETYPE_CIGAR = 17; // Just for appearance. Makes people look cool I guess
-const VRR_ITEM_USETYPE_WATER = 18; // Replenishes small amount of health
-const VRR_ITEM_USETYPE_FOOD = 19; // Eat food. Replenishes a small amount of health
-const VRR_ITEM_USETYPE_BEER = 20; // Subtle drunk effect. Replenishes small amount of health.
-const VRR_ITEM_USETYPE_WINE = 21; // Moderate drunk effect. Replenishes moderate amount of health.
-const VRR_ITEM_USETYPE_LIQUOR = 22; // Heavy drunk effect. Replenishes large amount of health.
-const VRR_ITEM_USETYPE_COFFEE = 23; // Replenishes moderate amount of health.
-const VRR_ITEM_USETYPE_AMMO_ROUND = 23; // Bullet. Loads into magazine. Not used at the moment
-const VRR_ITEM_USETYPE_HANDCUFF = 24; //
-const VRR_ITEM_USETYPE_ROPE = 25; //
-const VRR_ITEM_USETYPE_BLINDFOLD = 26; //
-const VRR_ITEM_USETYPE_TAZER = 27; //
-const VRR_ITEM_USETYPE_ARMOUR = 28; //
-const VRR_ITEM_USETYPE_HEALTH = 29; //
-const VRR_ITEM_USETYPE_AED = 30; //
-const VRR_ITEM_USETYPE_WALKIETALKIE = 31; //
-const VRR_ITEM_USETYPE_AREARADIO = 32; //
-const VRR_ITEM_USETYPE_PERSONALRADIO = 33; //
-const VRR_ITEM_USETYPE_BADGE = 34; //
-const VRR_ITEM_USETYPE_DRINK = 35; // Drinkable item. Action output shows "Player_Name drinks some (drink name)"
-const VRR_ITEM_USETYPE_EXTINGUISHER = 36; // Extinguisher item. Allows putting out fires
-const VRR_ITEM_USETYPE_SPRAYPAINT = 37; // Spraypaint item. Allows spraying custom clan tags on walls
-const VRR_ITEM_USETYPE_PEPPERSPRAY = 38; // Pepper spray item. Incapacitates nearby player
-const VRR_ITEM_USETYPE_FLASHLIGHT = 39; // Flashlight item. Unusable for now, but plan to cast a custom light beam
-const VRR_ITEM_USETYPE_AIRPLANETICKET = 40; // Airplane ticket. Allows a character to move to another server
-const VRR_ITEM_USETYPE_TRAINTICKET = 41; // Train ticket. Allows a character to move to another server
-const VRR_ITEM_USETYPE_VEHUPGRADE_PART = 42; // Vehicle update part item. Allows adding custom parts like spoilers, side skirts, roof scoops, etc
-const VRR_ITEM_USETYPE_VEHTIRE = 43; // Vehicle tire item. Allows changing the tire/rim types
-const VRR_ITEM_USETYPE_FUELCAN = 44; // Fuel can item. Allows refueling of a nearby vehicle anywhere
-const VRR_ITEM_USETYPE_VEHCOLOUR = 45; // Vehicle colour item. Changes primary and secondary vehicle colours
-const VRR_ITEM_USETYPE_VEHLIVERY = 46; // Vehicle livery/paintjob item. Applies decals and special paint jobs
-const VRR_ITEM_USETYPE_VEHREPAIR = 47; // Vehicle repair item. Much longer use time
-const VRR_ITEM_USETYPE_SMOKEDRUG = 48; // Smokable drug. Action output shows "Player_Name smokes some (drug)"
-const VRR_ITEM_USETYPE_SNORTDRUG = 49; // Snortable drug. Action output shows "Player_Name snorts some (drug)"
-const VRR_ITEM_USETYPE_PLANT = 50; // Plantable item. Pot plants, coke plants, etc
-const VRR_ITEM_USETYPE_MEGAPHONE = 51; // Megaphone item. Allows shouting over greater distances. Also called a bullhorn
-const VRR_ITEM_USETYPE_INJECTDRUG = 52; // Injectable drug. Action output shows "Player_Name injects some (drug)"
-const VRR_ITEM_USETYPE_ALCOHOL = 53; // Alcohol. Applies an intoxication/drunkness effect
-const VRR_ITEM_USETYPE_LOTTOTICKET = 54; // Lotto ticket. Allows a character to enter the lottery
-
-// Item Drop Types
-const VRR_ITEM_DROPTYPE_NONE = 0; // Can't be dropped
-const VRR_ITEM_DROPTYPE_OBJECT = 1; // Drops as an object on the ground
-const VRR_ITEM_DROPTYPE_PICKUP = 2; // Drops as a pickup
-const VRR_ITEM_DROPTYPE_OBJECTLIGHT = 3; // Object that produces an area light effect (lamp, flashlight, etc)
-const VRR_ITEM_DROPTYPE_DESTROY = 4; // Will destroy the item on drop (keys mostly but for any tiny object)
-const VRR_ITEM_DROPTYPE_OBJECTSTACK = 5; // Stackable objects (crates and such). Will sit on top of closest other stackable
-
-// Forensic Types
-const VRR_FORENSICS_NONE = 0;
-const VRR_FORENSICS_BULLET = 1; // Bullet. The actual tip that hits a target. Has rifling and ballistics information of the weapon.
-const VRR_FORENSICS_BLOOD = 2; // Blood. Automatically applied to ground and bullets that hit when somebody is shot
-const VRR_FORENSICS_BODY = 3; // Body. A dead body lol
-const VRR_FORENSICS_HAIR = 4; // Hair. Automatically applied to
-const VRR_FORENSICS_SWEAT = 5; // Sweat. Automatically applied to clothing when worn
-const VRR_FORENSICS_SALIVA = 6; // Saliva. Automatically applied to drinks when drank
-const VRR_FORENSICS_BULLETCASINGS = 7; // Bullet casings. Automatically dropped when fired from a weapon except when used in a vehicle (driveby)
-
-// Account Authentication Methods
-const VRR_ACCT_AUTHMETHOD_NONE = 0; // None
-const VRR_ACCT_AUTHMETHOD_EMAIL = 1; // Email
-const VRR_ACCT_AUTHMETHOD_PHONENUM = 2; // Phone number
-const VRR_ACCT_AUTHMETHOD_2FA = 3; // Two factor authentication app (authy, google authenticator, etc)
-const VRR_ACCT_AUTHMETHOD_PEBBLE = 4; // Pebble watch (this one's for Vortrex but anybody with a Pebble can use)
-const VRR_ACCT_AUTHMETHOD_PHONEAPP = 5; // The Android/iOS companion app (will initially be a web based thing until I can get the apps created)
-
-// Police Patrol Types
-const VRR_PATROLTYPE_NONE = 0; // None
-const VRR_PATROLTYPE_FOOT = 1; // Foot patrol. Officer takes a vehicle to get to their designated area and then walks a beat. More common in LC games
-const VRR_PATROLTYPE_VEHICLE = 2; // Vehicle patrol. More common in VC/LS/SF/LV cities.
-
-// Job Route States
-const VRR_JOBROUTESTATE_NONE = 0; // None
-const VRR_JOBROUTESTATE_INPROGRESS = 1; // Route is in progress. Player is in between stops but not at the last one.
-const VRR_JOBROUTESTATE_LASTSTOP = 2; // Player is heading to the last stop on the route
-const VRR_JOBROUTESTATE_PAUSED = 3; // Route is paused for some reason. For police, this could be player accepted callout and once finished, patrol route will resume
-const VRR_JOBROUTESTATE_ATSTOP = 4; // For bus/trash stops that freeze player, this is the state when they're at one
-
-// Item Occupied States
-const VRR_ITEM_ACTION_NONE = 0; // None
-const VRR_ITEM_ACTION_USE = 1; // Using item
-const VRR_ITEM_ACTION_PICKUP = 2; // Picking up item
-const VRR_ITEM_ACTION_DROP = 3; // Dropping item
-const VRR_ITEM_ACTION_SWITCH = 4; // Switching item
-const VRR_ITEM_ACTION_PUT = 5; // Putting item (into trunk, dash, crate, etc)
-const VRR_ITEM_ACTION_TAKE = 6; // Taking item (from trunk, dash, crate, etc)
-
-// Ped States
-const VRR_PEDSTATE_NONE = 2; // None
-const VRR_PEDSTATE_READY = 1; // Ready
-const VRR_PEDSTATE_DRIVER = 2; // Driving a vehicle
-const VRR_PEDSTATE_PASSENGER = 3; // In a vehicle as passenger
-const VRR_PEDSTATE_DEAD = 4; // Dead
-const VRR_PEDSTATE_ENTERINGPROPERTY = 5; // Entering a property
-const VRR_PEDSTATE_EXITINGPROPERTY = 6; // Exiting a property
-const VRR_PEDSTATE_ENTERINGVEHICLE = 7; // Entering a vehicle
-const VRR_PEDSTATE_EXITINGVEHICLE = 8; // Exiting a vehicle
-const VRR_PEDSTATE_BINDED = 9; // Binded by rope or handcuffs
-const VRR_PEDSTATE_TAZED = 10; // Under incapacitating effect of tazer
-const VRR_PEDSTATE_INTRUNK = 11; // In vehicle trunk
-const VRR_PEDSTATE_INITEM = 12; // In item (crate, box, etc)
-const VRR_PEDSTATE_HANDSUP = 13; // Has hands up (surrendering)
-const VRR_PEDSTATE_SPAWNING = 14; // Spawning
-
-// Two-Factor Authentication States
-const VRR_2FA_STATE_NONE = 0; // None
-const VRR_2FA_STATE_CODEINPUT = 1; // Waiting on player to enter code to play
-const VRR_2FA_STATE_SETUP_CODETOAPP = 2; // Providing player with a code to put in their auth app
-const VRR_2FA_STATE_SETUP_CODEFROMAPP = 3; // Waiting on player to enter code from auth app to set up
-
-// Reset Password States
-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)
-const VRR_NPC_COND_MATCH_EQ = 1; // Must be equal to
-const VRR_NPC_COND_MATCH_GT = 2; // Must be greater than
-const VRR_NPC_COND_MATCH_LT = 3; // Must be less than
-const VRR_NPC_COND_MATCH_GTEQ = 4; // Must be greater than or equal to
-const VRR_NPC_COND_MATCH_LTEQ = 5; // Must be less than or equal to
-const VRR_NPC_COND_MATCH_CONTAINS = 6; // Must contain string (case insensitive)
-const VRR_NPC_COND_MATCH_CONTAINS_CASE = 7; // Must contain string (case sensitive)
-const VRR_NPC_COND_MATCH_EXACT = 8; // Must match string exactly (case insensitive)
-const VRR_NPC_COND_MATCH_EXACT_CASE = 9; // Must match string exactly (case insensitive)
-
-// Business Types
-const VRR_BIZ_TYPE_NONE = 0; // None (invalid)
-const VRR_BIZ_TYPE_NORMAL = 1; // Normal business (sells items)
-const VRR_BIZ_TYPE_BANK = 2; // Bank
-const VRR_BIZ_TYPE_PUBLIC = 3; // Public business (Government, public service, etc)
-
-// Return-To types (for when a player is teleported)
-const VRR_RETURNTO_TYPE_NONE = 0; // "Return to" data is invalid
-const VRR_RETURNTO_TYPE_ADMINGET = 1; // "Return to" data is from admin teleporting
-const VRR_RETURNTO_TYPE_SKINSELECT = 2; // "Return to" data is from skin select
-
-// Card Game Types
-const VRR_DECKCARD_GAME_NONE = 0; // None (invalid)
-const VRR_DECKCARD_GAME_BLACKJACK = 1; // Blackjack
-const VRR_DECKCARD_GAME_TEXASHOLDEM = 2; // Texas Hold-em
-const VRR_DECKCARD_GAME_FIVECARDDRAW = 3; // Five Card Draw
-const VRR_DECKCARD_GAME_FIVECARDSTUD = 4; // Five Card Stud
-const VRR_DECKCARD_GAME_HIGHLOW = 5; // High-Low (Also known as War)
-
-// Card Suits
-const VRR_DECKCARD_SUIT_NONE = 0; // None (invalid)
-const VRR_DECKCARD_SUIT_SPADE = 1; // Spades
-const VRR_DECKCARD_SUIT_CLUB = 2; // Clubs
-const VRR_DECKCARD_SUIT_HEART = 3; // Hearts
-const VRR_DECKCARD_SUIT_DIAMOND = 4; // Diamonds
-
-// GPS State Types
-const VRR_GPS_TYPE_NONE = 0; // None (invalid)
-const VRR_GPS_TYPE_BUSINESS = 1; // Business
-const VRR_GPS_TYPE_POLICE = 2; // Police Station
-const VRR_GPS_TYPE_HOSPITAL = 3; // Hospital
-const VRR_GPS_TYPE_JOB = 4; // Job
-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;
-
-// 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/crime.js b/scripts/server/crime.js
new file mode 100644
index 00000000..1df467c3
--- /dev/null
+++ b/scripts/server/crime.js
@@ -0,0 +1,22 @@
+// ===========================================================================
+// Vortrex's Roleplay Resource
+// https://github.com/VortrexFTW/gtac_roleplay
+// ===========================================================================
+// FILE: crime.js
+// DESC: Provides crime data structures, functions, and operations
+// TYPE: Server (JavaScript)
+// ===========================================================================
+
+/**
+ * @class Representing a crime's data. Loaded and saved in the database
+ */
+ class CrimeData {
+ constructor(suspectId, crimeType, reporterId = 0) {
+ this.crimeType = crimeType;
+ this.suspectId = suspectId;
+ this.reporterId = reporterId;
+ this.whenCommitted = 0;
+ this.whenReported = 0;
+ this.databaseId = 0;
+ }
+};
\ No newline at end of file
diff --git a/scripts/server/discord.js b/scripts/server/discord.js
index 39f1877c..66c17e76 100644
--- a/scripts/server/discord.js
+++ b/scripts/server/discord.js
@@ -53,7 +53,7 @@ function messageDiscordUser(discordUser, messageText) {
// ===========================================================================
function sendDiscordSocketData(socketData) {
- if(!getDiscordSocket()) {
+ if (!getDiscordSocket()) {
return false;
}
@@ -63,11 +63,11 @@ function sendDiscordSocketData(socketData) {
// ===========================================================================
function isClientFromDiscord(client) {
- if(client == null) {
+ if (client == null) {
return false;
}
- if(client instanceof Client) {
+ if (client instanceof Client) {
return false;
} else {
return true;
@@ -89,58 +89,82 @@ function getDiscordUserData(discordUserId) {
// ===========================================================================
function messageDiscordChatChannel(messageString) {
- if(getServerConfig().devServer == true) {
+ if (getServerConfig().devServer == true) {
return false;
}
- if(!getGlobalConfig().discord.sendChat) {
+ if (!getGlobalConfig().discord.sendChat) {
return false;
}
- if(!getServerConfig().discord.sendChat) {
+ if (!getServerConfig().discord.sendChat) {
return false;
}
messageString = removeColoursInMessage(messageString);
- triggerWebHook(messageString, getServerId(), VRR_DISCORD_WEBHOOK_LOG);
+ triggerDiscordWebHook(messageString, getServerId(), VRR_DISCORD_WEBHOOK_LOG);
}
// ===========================================================================
function messageDiscordEventChannel(messageString) {
- if(getServerConfig().devServer == true) {
+ if (getServerConfig().devServer == true) {
return false;
}
- if(!getGlobalConfig().discord.sendEvents) {
+ if (!getGlobalConfig().discord.sendEvents) {
return false;
}
- if(!getServerConfig().discord.sendEvents) {
+ if (!getServerConfig().discord.sendEvents) {
return false;
}
messageString = removeColoursInMessage(messageString);
- triggerWebHook(messageString, getServerId(), VRR_DISCORD_WEBHOOK_LOG);
+ triggerDiscordWebHook(messageString, getServerId(), VRR_DISCORD_WEBHOOK_LOG);
}
// ===========================================================================
function messageDiscordAdminChannel(messageString) {
- if(getServerConfig().devServer == true) {
+ if (getServerConfig().devServer == true) {
return false;
}
- if(!getGlobalConfig().discord.sendAdmin) {
+ if (!getGlobalConfig().discord.sendAdmin) {
return false;
}
- if(!getServerConfig().discord.sendAdmin) {
+ if (!getServerConfig().discord.sendAdmin) {
return false;
}
messageString = removeColoursInMessage(messageString);
- triggerWebHook(messageString, getServerId(), VRR_DISCORD_WEBHOOK_ADMIN);
+ triggerDiscordWebHook(messageString, getServerId(), VRR_DISCORD_WEBHOOK_ADMIN);
+}
+
+// ===========================================================================
+
+function triggerDiscordWebHook(messageString, serverId = getServerId(), type = VRR_DISCORD_WEBHOOK_LOG) {
+ if (!getGlobalConfig().discord.webhook.enabled) {
+ return false;
+ }
+
+ let tempURL = getGlobalConfig().discord.webhook.webhookBaseURL;
+ tempURL = tempURL.replace("{0}", encodeURI(messageString));
+ tempURL = tempURL.replace("{1}", serverId);
+ tempURL = tempURL.replace("{2}", type);
+ tempURL = tempURL.replace("{3}", getGlobalConfig().discord.webhook.pass);
+
+ httpGet(
+ tempURL,
+ "",
+ function (data) {
+
+ },
+ function (data) {
+ }
+ );
}
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/economy.js b/scripts/server/economy.js
index e42479cb..c320b850 100644
--- a/scripts/server/economy.js
+++ b/scripts/server/economy.js
@@ -15,13 +15,13 @@ function initEconomyScript() {
// ===========================================================================
function getTimeDisplayUntilPlayerPayDay(client) {
- return getTimeDifferenceDisplay(sdl.ticks-getPlayerData(client).payDayTickStart);
+ return getTimeDifferenceDisplay(sdl.ticks - getPlayerData(client).payDayTickStart);
}
// ===========================================================================
function applyServerInflationMultiplier(value) {
- return toInteger(Math.round(value*getServerConfig().inflationMultiplier))
+ return toInteger(Math.round(value * getServerConfig().inflationMultiplier))
}
// ===========================================================================
@@ -31,28 +31,28 @@ function playerPayDay(client) {
let grossIncome = getPlayerData(client).payDayAmount;
// Passive income
- grossIncome = grossIncome + getGlobalConfig().economy.passiveIncomePerPayDay;
+ grossIncome = Math.round(grossIncome + getGlobalConfig().economy.passiveIncomePerPayDay);
// Payday bonus
- grossIncome = grossIncome*getGlobalConfig().economy.grossIncomeMultiplier;
+ grossIncome = Math.round(grossIncome * getGlobalConfig().economy.grossIncomeMultiplier);
// Double bonus
- if(isDoubleBonusActive()) {
- grossIncome = grossIncome*2;
+ if (isDoubleBonusActive()) {
+ grossIncome = Math.round(grossIncome * 2);
}
let incomeTaxAmount = Math.round(calculateIncomeTax(wealth));
- let netIncome = grossIncome-incomeTaxAmount;
+ let netIncome = Math.round(grossIncome - incomeTaxAmount);
messagePlayerAlert(client, "== Payday! =============================");
messagePlayerInfo(client, `Paycheck: {ALTCOLOUR}$${grossIncome}`);
messagePlayerInfo(client, `Taxes: {ALTCOLOUR}$${incomeTaxAmount}`);
messagePlayerInfo(client, `You receive: {ALTCOLOUR}$${netIncome}`);
- if(netIncome < incomeTaxAmount) {
+ if (netIncome < incomeTaxAmount) {
let totalCash = getPlayerCash(client);
- let canPayNow = totalCash+netIncome;
- if(incomeTaxAmount <= canPayNow) {
+ let canPayNow = totalCash + netIncome;
+ if (incomeTaxAmount <= canPayNow) {
takePlayerCash(client, canPayNow);
messagePlayerInfo(client, `{orange}${getLocaleString(client, "RemainingTaxPaidInCash", `{ALTCOLOUR}${canPayNow}{MAINCOLOUR}`)}`);
messagePlayerAlert(client, `{orange}${getLocaleString(client, "LostMoneyFromTaxes")}`);
@@ -65,12 +65,12 @@ function playerPayDay(client) {
let houseCount = getAllHousesOwnedByPlayer(client).length;
let businessCount = getAllBusinessesOwnedByPlayer(client).length;
- attemptRepossession(client, incomeTaxAmount-canPayNow);
+ attemptRepossession(client, incomeTaxAmount - canPayNow);
let newVehicleCount = getAllVehiclesOwnedByPlayer(client).length;
let newHouseCount = getAllHousesOwnedByPlayer(client).length;
let newBusinessCount = getAllBusinessesOwnedByPlayer(client).length;
- messagePlayerInfo(client, `{orange}${getLocaleString(client, "AssetsRepossessedForTaxes", newVehicleCount-vehicleCount, newHouseCount-houseCount, newBusinessCount-businessCount)}`);
+ messagePlayerInfo(client, `{orange}${getLocaleString(client, "AssetsRepossessedForTaxes", newVehicleCount - vehicleCount, newHouseCount - houseCount, newBusinessCount - businessCount)}`);
}
}
@@ -84,29 +84,29 @@ function calculateWealth(client) {
let houses = getAllHousesOwnedByPlayer(client);
let businesses = getAllBusinessesOwnedByPlayer(client);
- let vehicleUpKeep = applyServerInflationMultiplier(vehicles.length*getGlobalConfig().economy.upKeepCosts.upKeepPerVehicle);
- let houseUpKeep = applyServerInflationMultiplier(houses.length*getGlobalConfig().economy.upKeepCosts.upKeepPerHouse);
- let businessUpKeep = applyServerInflationMultiplier(businesses.length*getGlobalConfig().economy.upKeepCosts.upKeepPerBusiness);
+ let vehicleUpKeep = applyServerInflationMultiplier(vehicles.length * getGlobalConfig().economy.upKeepCosts.upKeepPerVehicle);
+ let houseUpKeep = applyServerInflationMultiplier(houses.length * getGlobalConfig().economy.upKeepCosts.upKeepPerHouse);
+ let businessUpKeep = applyServerInflationMultiplier(businesses.length * getGlobalConfig().economy.upKeepCosts.upKeepPerBusiness);
- return vehicleUpKeep+houseUpKeep+businessUpKeep;
+ return vehicleUpKeep + houseUpKeep + businessUpKeep;
}
// ===========================================================================
function calculateIncomeTax(amount) {
- return amount*getGlobalConfig().economy.incomeTaxRate;
+ return amount * getGlobalConfig().economy.incomeTaxRate;
}
// ===========================================================================
function forcePlayerPayDayCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, "That player is not connected!");
return false;
}
@@ -118,21 +118,21 @@ function forcePlayerPayDayCommand(command, params, client) {
// ===========================================================================
function setPayDayBonusMultiplier(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let newMultiplier = params;
- if(isNaN(newMultiplier)) {
+ if (isNaN(newMultiplier)) {
messagePlayerError(client, getLocaleString(client, "AmountNotNumber"));
return false;
}
getGlobalConfig().economy.grossIncomeMultiplier = newMultiplier;
- announceAdminAction(`PaydayBonusSet`, `{adminOrange}${getPlayerName(client)}{MAINCOLOUR}`, `{ALTCOLOUR}${newMultiplier*100}%{MAINCOLOUR}`);
+ announceAdminAction(`PaydayBonusSet`, `{adminOrange}${getPlayerName(client)}{MAINCOLOUR}`, `{ALTCOLOUR}${newMultiplier * 100}%{MAINCOLOUR}`);
}
// ===========================================================================
@@ -155,7 +155,7 @@ function wealthInfoCommand(command, params, client) {
function attemptRepossession(client, totalToPay) {
let leftToPay = totalToPay;
- while(leftToPay > 0) {
+ while (leftToPay > 0) {
let repossessionValue = repossessFirstAsset(client);
leftToPay = leftToPay - repossessionValue;
}
@@ -166,19 +166,19 @@ function attemptRepossession(client, totalToPay) {
function repossessFirstAsset(client) {
let vehicles = getAllVehiclesOwnedByPlayer(client);
- if(vehicles.length > 0) {
- deleteVehicle(vehicles[0])
+ if (vehicles.length > 0) {
+ deleteVehicle(vehicles[0]);
return getGlobalConfig().economy.upKeepCosts.upKeepPerVehicle;
}
let houses = getAllHousesOwnedByPlayer(client);
- if(houses.length > 0) {
+ if (houses.length > 0) {
deleteHouse(houses[0].index);
return getGlobalConfig().economy.upKeepCosts.upKeepPerHouse;
}
let businesses = getAllBusinessesOwnedByPlayer(client);
- if(businesses.length > 0) {
+ if (businesses.length > 0) {
deleteBusiness(businesses[0].index);
return getGlobalConfig().economy.upKeepCosts.upKeepPerBusiness;
}
@@ -205,7 +205,7 @@ function getAllHousesOwnedByPlayer(client) {
// ===========================================================================
function isDoubleBonusActive() {
- if(isWeekend()) {
+ if (isWeekend()) {
return true;
}
diff --git a/scripts/server/email.js b/scripts/server/email.js
index d9593512..689c546e 100644
--- a/scripts/server/email.js
+++ b/scripts/server/email.js
@@ -14,23 +14,26 @@ function initEmailScript() {
// ===========================================================================
-function sendEmail(toEmail, toName, subject, body) {
- if(!checkForSMTPModule()) {
+async function sendEmail(toEmail, toName, subject, body) {
+ if (!checkForSMTPModule()) {
return false;
}
- module.smtp.send(
- getEmailConfig().smtp.host,
- getEmailConfig().smtp.port,
- intToBool(getEmailConfig().smtp.useTLS),
- getEmailConfig().smtp.username,
- getEmailConfig().smtp.password,
- toEmail,
- toName,
- subject,
- body,
- getEmailConfig().smtp.from,
- getEmailConfig().smtp.fromName);
+ Promise.resolve().then(() => {
+ module.smtp.send(
+ getEmailConfig().smtp.host,
+ getEmailConfig().smtp.port,
+ intToBool(getEmailConfig().smtp.useTLS),
+ getEmailConfig().smtp.username,
+ getEmailConfig().smtp.password,
+ toEmail,
+ toName,
+ subject,
+ body,
+ getEmailConfig().smtp.from,
+ getEmailConfig().smtp.fromName
+ );
+ });
}
// ===========================================================================
diff --git a/scripts/server/event.js b/scripts/server/event.js
index aa4a99de..ffdf3e9d 100644
--- a/scripts/server/event.js
+++ b/scripts/server/event.js
@@ -109,8 +109,10 @@ function onPlayerQuit(event, client, quitReasonId) {
updateConnectionLogOnQuit(client, quitReasonId);
let reasonText = disconnectReasons[quitReasonId];
- if (getPlayerData(client).customDisconnectReason != "" && getPlayerData(client).customDisconnectReason != undefined && getPlayerData(client).customDisconnectReason != false && getPlayerData(client).customDisconnectReason != null) {
- reasonText = getPlayerData(client).customDisconnectReason;
+ if (getPlayerData(client) != false) {
+ if (getPlayerData(client).customDisconnectReason != "") {
+ reasonText = getPlayerData(client).customDisconnectReason;
+ }
}
messageDiscordEventChannel(`👋 ${getPlayerName(client)} has left the server (${reasonText})`);
@@ -488,6 +490,7 @@ async function onPlayerSpawn(client) {
logToConsole(LOG_DEBUG, `[VRR.Event] Checking ${getPlayerDisplayForConsole(client)}'s player data`);
if (!getPlayerData(client)) {
logToConsole(LOG_DEBUG, `[VRR.Event] ${getPlayerDisplayForConsole(client)}'s player data is invalid. Kicking them from server.`);
+ getPlayerData(targetClient).customDisconnectReason = `Kicked - Spawn bug. Data invalid.`;
disconnectPlayer(client);
return false;
}
@@ -495,6 +498,7 @@ async function onPlayerSpawn(client) {
logToConsole(LOG_DEBUG, `[VRR.Event] Checking ${getPlayerDisplayForConsole(client)}'s login status`);
if (!isPlayerLoggedIn(client)) {
logToConsole(LOG_DEBUG, `[VRR.Event] ${getPlayerDisplayForConsole(client)} is NOT logged in. Despawning their player.`);
+ getPlayerData(targetClient).customDisconnectReason = `Kicked - Tried to force spawn without logging in.`;
disconnectPlayer(client);
return false;
}
@@ -502,6 +506,7 @@ async function onPlayerSpawn(client) {
logToConsole(LOG_DEBUG, `[VRR.Event] Checking ${getPlayerDisplayForConsole(client)}'s selected character status`);
if (getPlayerData(client).currentSubAccount == -1) {
logToConsole(LOG_DEBUG, `[VRR.Event] ${getPlayerDisplayForConsole(client)} has NOT selected a character. Despawning their player.`);
+ getPlayerData(targetClient).customDisconnectReason = `Kicked - Tried to force spawn without selecting a character.`;
disconnectPlayer(client);
return false;
}
@@ -649,7 +654,7 @@ async function onPlayerSpawn(client) {
getPlayerData(client).payDayTickStart = sdl.ticks;
- sendPlayerLocaleStrings(client);
+ //sendPlayerLocaleStrings(client);
// Stop playing intro music and any other radio
stopRadioStreamForPlayer(client);
diff --git a/scripts/server/forensics.js b/scripts/server/forensics.js
new file mode 100644
index 00000000..840a969f
--- /dev/null
+++ b/scripts/server/forensics.js
@@ -0,0 +1,20 @@
+// ===========================================================================
+// Vortrex's Roleplay Resource
+// https://github.com/VortrexFTW/gtac_roleplay
+// ===========================================================================
+// FILE: forensics.js
+// DESC: Provides forensics functions and commands (bullet casings, blood, etc)
+// TYPE: Server (JavaScript)
+// ===========================================================================
+
+// Forensic Types
+const VRR_FORENSICS_NONE = 0;
+const VRR_FORENSICS_BULLET = 1; // Bullet. The actual tip that hits a target. Has rifling and ballistics information of the weapon.
+const VRR_FORENSICS_BLOOD = 2; // Blood. Automatically applied to ground and bullets that hit when somebody is shot
+const VRR_FORENSICS_BODY = 3; // Body. A dead body lol
+const VRR_FORENSICS_HAIR = 4; // Hair. Automatically applied to
+const VRR_FORENSICS_SWEAT = 5; // Sweat. Automatically applied to clothing when worn
+const VRR_FORENSICS_SALIVA = 6; // Saliva. Automatically applied to drinks when drank
+const VRR_FORENSICS_BULLETCASINGS = 7; // Bullet casings. Automatically dropped when fired from a weapon except when used in a vehicle (driveby)
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/gate.js b/scripts/server/gate.js
index c0565345..29f5e511 100644
--- a/scripts/server/gate.js
+++ b/scripts/server/gate.js
@@ -7,6 +7,43 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Gate Owner Types
+const VRR_GATEOWNER_NONE = 0; // Not owned
+const VRR_GATEOWNER_PLAYER = 1; // Owner is a player (character/subaccount)
+const VRR_GATEOWNER_JOB = 2; // Owned by a job
+const VRR_GATEOWNER_CLAN = 3; // Owned by a clan
+const VRR_GATEOWNER_FACTION = 4; // Owned by a faction
+const VRR_GATEOWNER_PUBLIC = 5; // Public gate. Technically not owned. This probably won't be used.
+const VRR_GATEOWNER_BUSINESS = 6; // Owned by a business. Back lots, unloading areas, and other stuff like that
+const VRR_GATEOWNER_HOUSE = 7; // Owned by a house. Like for mansions with closed private areas.
+
+// ===========================================================================
+
+class GateData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.scriptName = "";
+ this.enabled = false;
+ this.position = toVector3(0.0, 0.0, 0.0);
+ this.locked = true;
+ this.ownerType = VRR_GATEOWNER_NONE;
+ this.ownerId = 0;
+
+ if (dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["gate_id"]);
+ this.name = toString(dbAssoc["gate_name"]);
+ this.scriptName = toString(dbAssoc["gate_script_name"]);
+ this.enabled = intToBool(toInteger(dbAssoc["gate_enabled"]));
+ this.position = toVector3(toFloat(dbAssoc["gate_pos_x"]), toFloat(dbAssoc["gate_pos_y"]), toFloat(dbAssoc["gate_pos_z"]));
+ this.ownerType = toInteger(dbAssoc["gate_owner_type"]);
+ this.ownerId = toInteger(dbAssoc["gate_owner_id"]);
+ }
+ }
+}
+
+// ===========================================================================
+
function initGateScript() {
logToConsole(LOG_INFO, `[VRR.Gate]: Initializing gate script ...`);
logToConsole(LOG_INFO, `[VRR.Gate]: Gate script initialized successfully!`);
@@ -17,66 +54,66 @@ function initGateScript() {
function doesPlayerHaveGateKeys(client, vehicle) {
let gateData = getGateData(vehicle);
- if(gateData.ownerType == VRR_GATEOWNER_PUBLIC) {
+ if (gateData.ownerType == VRR_GATEOWNER_PUBLIC) {
return true;
}
- if(gateData.ownerType == VRR_GATEOWNER_PLAYER) {
- if(gateData.ownerId == getPlayerCurrentSubAccount(client).databaseId) {
+ if (gateData.ownerType == VRR_GATEOWNER_PLAYER) {
+ if (gateData.ownerId == getPlayerCurrentSubAccount(client).databaseId) {
return true;
}
}
- if(gateData.ownerType == VRR_GATEOWNER_CLAN) {
- if(doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageClans"))) {
+ if (gateData.ownerType == VRR_GATEOWNER_CLAN) {
+ if (doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageClans"))) {
return true;
}
- if(gateData.ownerId == getPlayerCurrentSubAccount(client).clan) {
- if(gateData.clanRank <= getPlayerCurrentSubAccount(client).clanRank) {
+ if (gateData.ownerId == getPlayerCurrentSubAccount(client).clan) {
+ if (gateData.clanRank <= getPlayerCurrentSubAccount(client).clanRank) {
return true;
}
}
}
- if(gateData.ownerType == VRR_GATEOWNER_FACTION) {
- if(doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageFactions"))) {
+ if (gateData.ownerType == VRR_GATEOWNER_FACTION) {
+ if (doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageFactions"))) {
return true;
}
- if(gateData.ownerId == getPlayerCurrentSubAccount(client).faction) {
- if(gateData.factionRank <= getPlayerCurrentSubAccount(client).factionRank) {
+ if (gateData.ownerId == getPlayerCurrentSubAccount(client).faction) {
+ if (gateData.factionRank <= getPlayerCurrentSubAccount(client).factionRank) {
return true;
}
}
}
- if(gateData.ownerType == VRR_GATEOWNER_JOB) {
- if(doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageJobs"))) {
+ if (gateData.ownerType == VRR_GATEOWNER_JOB) {
+ if (doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageJobs"))) {
return true;
}
- if(gateData.ownerId == getPlayerCurrentSubAccount(client).job) {
+ if (gateData.ownerId == getPlayerCurrentSubAccount(client).job) {
return true;
}
}
- if(gateData.ownerType == VRR_GATEOWNER_BUSINESS) {
- if(doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageBusinesses"))) {
+ if (gateData.ownerType == VRR_GATEOWNER_BUSINESS) {
+ if (doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageBusinesses"))) {
return true;
}
- if(canPlayerManageBusiness(client, getBusinessIdFromDatabaseId(gateData.ownerId))) {
+ if (canPlayerManageBusiness(client, getBusinessIdFromDatabaseId(gateData.ownerId))) {
return true;
}
}
- if(gateData.ownerType == VRR_GATEOWNER_HOUSE) {
- if(doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageHouses"))) {
+ if (gateData.ownerType == VRR_GATEOWNER_HOUSE) {
+ if (doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageHouses"))) {
return true;
}
- if(canPlayerManageHouse(client, getHouseIdFromDatabaseId(gateData.ownerId))) {
+ if (canPlayerManageHouse(client, getHouseIdFromDatabaseId(gateData.ownerId))) {
return true;
}
}
@@ -87,7 +124,7 @@ function doesPlayerHaveGateKeys(client, vehicle) {
// ===========================================================================
function getGateData(gateId) {
- if(typeof getServerData().gates[gateId] != "undefined") {
+ if (typeof getServerData().gates[gateId] != "undefined") {
return getServerData().gates[gateId];
}
@@ -98,8 +135,8 @@ function getGateData(gateId) {
function getClosestGate(position) {
let closest = 0;
- for(let i in getServerData().gates[getGame()]) {
- if(getDistance(getServerData().gates[i].position, position) < getDistance(getServerData().gates[closest].position, position)) {
+ for (let i in getServerData().gates[getGame()]) {
+ if (getDistance(getServerData().gates[i].position, position) < getDistance(getServerData().gates[closest].position, position)) {
closest = i;
}
}
@@ -112,11 +149,11 @@ function getClosestGate(position) {
function triggerGateCommand(command, params, client) {
let closestGate = getClosestGate(getPlayerPosition(client));
- if(!getGateData(closestGate)) {
+ if (!getGateData(closestGate)) {
messagePlayerError(client, getLocaleString(client, "InvalidGate"));
}
- if(!doesPlayerHaveGateKeys(client, closestGate)) {
+ if (!doesPlayerHaveGateKeys(client, closestGate)) {
messagePlayerError(client, getLocaleString(client, "NoGateAccess"));
return false;
}
@@ -127,11 +164,11 @@ function triggerGateCommand(command, params, client) {
// ===========================================================================
function saveAllGatesToDatabase() {
- if(getServerConfig().devServer) {
+ if (getServerConfig().devServer) {
return false;
}
- for(let i in getServerData().gates) {
+ for (let i in getServerData().gates) {
saveGateToDatabase(i);
}
}
@@ -139,26 +176,26 @@ function saveAllGatesToDatabase() {
// ===========================================================================
function saveGateToDatabase(gateId) {
- if(getGateData(gateId) == null) {
+ if (getGateData(gateId) == null) {
// Invalid gate data
return false;
}
let tempGateData = getGateData(gateId);
- if(tempGateData.databaseId == -1) {
+ if (tempGateData.databaseId == -1) {
// Temp gate, no need to save
return false;
}
- if(!tempGateData.needsSaved) {
+ if (!tempGateData.needsSaved) {
// Gate hasn't changed. No need to save.
return false;
}
logToConsole(LOG_VERBOSE, `[VRR.Gate]: Saving gate ${tempGateData.databaseId} to database ...`);
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let safeGateName = escapeDatabaseString(tempGateData.name);
let safeGateScriptName = escapeDatabaseString(tempGateData.scriptName);
@@ -175,7 +212,7 @@ function saveGateToDatabase(gateId) {
];
let dbQuery = null;
- if(tempGateData.databaseId == 0) {
+ if (tempGateData.databaseId == 0) {
let queryString = createDatabaseInsertQuery("gate_main", data);
dbQuery = queryDatabase(dbConnection, queryString);
tempGateData.databaseId = getDatabaseInsertId(dbConnection);
@@ -204,11 +241,11 @@ function loadGatesFromDatabase() {
let dbConnection = connectToDatabase();
let dbAssoc;
- if(dbConnection) {
+ if (dbConnection) {
let dbQuery = queryDatabase(dbConnection, `SELECT * FROM gate_main WHERE gate_server = ${getServerId()}`);
- if(dbQuery) {
- if(dbQuery.numRows > 0) {
- while(dbAssoc = fetchQueryAssoc(dbQuery)) {
+ if (dbQuery) {
+ if (dbQuery.numRows > 0) {
+ while (dbAssoc = fetchQueryAssoc(dbQuery)) {
let tempGateData = new GateData(dbAssoc);
tempGates.push(tempGateData);
logToConsole(LOG_DEBUG, `[VRR.Gate]: Gate '${tempGateData.name}' loaded from database successfully!`);
diff --git a/scripts/server/gps.js b/scripts/server/gps.js
new file mode 100644
index 00000000..69d47321
--- /dev/null
+++ b/scripts/server/gps.js
@@ -0,0 +1,148 @@
+// ===========================================================================
+// Vortrex's Roleplay Resource
+// https://github.com/VortrexFTW/gtac_roleplay
+// ===========================================================================
+// FILE: gps.js
+// DESC: Provides GPS functions and commands
+// TYPE: Server (JavaScript)
+// ===========================================================================
+
+// GPS State Types
+const VRR_GPS_TYPE_NONE = 0; // None (invalid)
+const VRR_GPS_TYPE_BUSINESS = 1; // Business
+const VRR_GPS_TYPE_POLICE = 2; // Police Station
+const VRR_GPS_TYPE_HOSPITAL = 3; // Hospital
+const VRR_GPS_TYPE_JOB = 4; // Job
+const VRR_GPS_TYPE_GAMELOC = 5; // Game Location
+
+// ===========================================================================
+
+function gpsCommand(command, params, client) {
+ messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderBusinessList")));
+
+ let locationType = VRR_GPS_TYPE_NONE;
+ let useType = VRR_ITEM_USETYPE_NONE;
+ let blipColour = "white";
+
+ switch(toLowerCase(params)) {
+ case "police":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_POLICE;
+ break;
+
+ case "hospital":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_HOSPITAL;
+ break;
+
+ case "job":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_JOB;
+ break;
+
+ case "skin":
+ case "skins":
+ case "clothes":
+ case "player":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_BUSINESS;
+ useType = VRR_ITEM_USETYPE_SKIN;
+ break;
+
+ case "gun":
+ case "guns":
+ case "weapon":
+ case "weapons":
+ case "wep":
+ case "weps":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_BUSINESS;
+ useType = VRR_ITEM_USETYPE_WEAPON;
+ break;
+
+ case "food":
+ case "eat":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_BUSINESS;
+ useType = VRR_ITEM_USETYPE_FOOD;
+ break;
+
+ case "drink":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_BUSINESS;
+ useType = VRR_ITEM_USETYPE_DRINK;
+ break;
+
+ case "alcohol":
+ case "booze":
+ case "bar":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_BUSINESS;
+ useType = VRR_ITEM_USETYPE_ALCOHOL;
+ break;
+
+ case "repair":
+ case "carrepair":
+ case "vehrepair":
+ case "spray":
+ case "fix":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_BUSINESS;
+ useType = VRR_ITEM_USETYPE_VEHREPAIR;
+ break;
+
+ case "vehiclecolour":
+ case "vehcolour":
+ case "carcolour":
+ case "colour":
+ blipColour = "businessBlue"
+ locationType = VRR_GPS_TYPE_BUSINESS;
+ useType = VRR_ITEM_USETYPE_VEHCOLOUR;
+ break;
+
+ default: {
+ let itemTypeId = getItemTypeFromParams(params);
+ if(getItemTypeData(itemTypeId) != false) {
+ locationType = VRR_GPS_TYPE_BUSINESS;
+ blipColour = "businessBlue";
+ useType = getItemTypeData(itemTypeId).useType;
+ } else {
+ let gameLocationId = getGameLocationFromParams(params);
+ if(gameLocationId != false) {
+ position = getGameConfig().locations[getServerGame()][gameLocationId][1]
+ }
+ }
+ }
+ }
+
+ if(locationType == VRR_GPS_TYPE_NONE) {
+ messagePlayerError(client, getLocaleString(client, "InvalidGPSLocation"));
+ return false;
+ }
+
+ if(locationType == VRR_GPS_TYPE_BUSINESS) {
+ let businessId = getClosestBusinessWithBuyableItemOfUseType(useType);
+ if(!businessId) {
+ messagePlayerError(client, getLocaleString(client, "NoBusinessWithItemType"));
+ return false;
+ }
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, getLocaleString(client, "NoBusinessWithItemType"));
+ return false;
+ }
+
+ hideAllBlipsForPlayerGPS(client);
+ blinkGenericGPSBlipForPlayer(client, getBusinessData(businessId).entrancePosition, getBusinessData(businessId).entranceBlipModel, getColourByType(blipColour), 10);
+ messagePlayerSuccess(client, "Look for the blinking icon on your mini map");
+ }
+
+ if(locationType == VRR_GPS_TYPE_GAMELOC) {
+ hideAllBlipsForPlayerGPS(client);
+ blinkGenericGPSBlipForPlayer(client, position, 0, getColourByType(blipColour), 10);
+ messagePlayerSuccess(client, "Look for the blinking icon on your mini map");
+ return true;
+ }
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/gui.js b/scripts/server/gui.js
index 686a8e13..0afb3020 100644
--- a/scripts/server/gui.js
+++ b/scripts/server/gui.js
@@ -7,6 +7,13 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Prompts (used for client GUI prompt responses)
+const VRR_PROMPT_NONE = 0;
+const VRR_PROMPT_CREATEFIRSTCHAR = 1;
+const VRR_PROMPT_BIZORDER = 2;
+
+// ===========================================================================
+
function initGUIScript() {
logToConsole(LOG_INFO, "[VRR.GUI]: Initializing GUI script ...");
logToConsole(LOG_INFO, "[VRR.GUI]: GUI script initialized successfully!");
@@ -15,31 +22,32 @@ function initGUIScript() {
// ===========================================================================
function playerPromptAnswerNo(client) {
- if(getPlayerData(client).promptType == VRR_PROMPT_NONE) {
+ if (getPlayerData(client).promptType == VRR_PROMPT_NONE) {
return false;
}
logToConsole(LOG_DEBUG, `[VRR.GUI] ${getPlayerDisplayForConsole(client)} answered NO to their prompt (${getPlayerData(client).promptType})`);
- switch(getPlayerData(client).promptType) {
+ switch (getPlayerData(client).promptType) {
case VRR_PROMPT_CREATEFIRSTCHAR:
logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} chose not to create a first character. Kicking them from the server ...`);
showPlayerErrorGUI(client, "You don't have a character to play. Goodbye!", "No Characters");
- setTimeout(function() { disconnectPlayer(client); }, 5000);
+ getPlayerData(targetClient).customDisconnectReason = `Kicked - Didn't create a character`;
+ setTimeout(function () { disconnectPlayer(client); }, 5000);
break;
- case VRR_PROMPT_BIZORDER:
- if(getPlayerData(client).businessOrderAmount > 0) {
- if(canPlayerUseGUI(client)) {
- showPlayerErrorGUI(client, "You canceled the order.", "Business Order Canceled");
- } else {
- logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} canceled the order of ${getPlayerData(client).businessOrderAmount} ${getPlayerData(client).businessOrderItem} at ${getPlayerData(client).businessOrderCost/getPlayerData(client).businessOrderAmount} each for business ${getBusinessData(getPlayerData(client).businessOrderBusiness)}`);
- messagePlayerError(client, "You canceled the order!");
- }
+ case VRR_PROMPT_BIZORDER:
+ if (getPlayerData(client).businessOrderAmount > 0) {
+ if (canPlayerUseGUI(client)) {
+ showPlayerErrorGUI(client, "You canceled the order.", "Business Order Canceled");
} else {
- showPlayerErrorGUI(client, "You aren't ordering anything for a business!", "Business Order Canceled");
+ logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} canceled the order of ${getPlayerData(client).businessOrderAmount} ${getPlayerData(client).businessOrderItem} at ${getPlayerData(client).businessOrderCost / getPlayerData(client).businessOrderAmount} each for business ${getBusinessData(getPlayerData(client).businessOrderBusiness)}`);
+ messagePlayerError(client, "You canceled the order!");
}
- break;
+ } else {
+ showPlayerErrorGUI(client, "You aren't ordering anything for a business!", "Business Order Canceled");
+ }
+ break;
default:
break;
@@ -51,29 +59,29 @@ function playerPromptAnswerNo(client) {
// ===========================================================================
function playerPromptAnswerYes(client) {
- if(getPlayerData(client).promptType == VRR_PROMPT_NONE) {
+ if (getPlayerData(client).promptType == VRR_PROMPT_NONE) {
return false;
}
logToConsole(LOG_DEBUG, `[VRR.GUI] ${getPlayerDisplayForConsole(client)} answered YES to their prompt (${getPlayerData(client).promptType})`);
- switch(getPlayerData(client).promptType) {
+ switch (getPlayerData(client).promptType) {
case VRR_PROMPT_CREATEFIRSTCHAR: {
showPlayerNewCharacterGUI(client);
break;
}
case VRR_PROMPT_BIZORDER: {
- if(getPlayerData(client).businessOrderAmount > 0) {
- if(getBusinessData(getPlayerData(client).businessOrderBusiness).till < getPlayerData(client).businessOrderCost) {
- logToConsole(LOG_DEBUG, `[VRR.GUI] ${getPlayerDisplayForConsole(client)} failed to order ${getPlayerData(client).businessOrderAmount} ${getItemTypeData(getPlayerData(client).businessOrderItem).name} at ${getPlayerData(client).businessOrderCost/getPlayerData(client).businessOrderAmount} each for business ${getBusinessData(getPlayerData(client).businessOrderBusiness).name} (Reason: Not enough money in business till)`);
+ if (getPlayerData(client).businessOrderAmount > 0) {
+ if (getBusinessData(getPlayerData(client).businessOrderBusiness).till < getPlayerData(client).businessOrderCost) {
+ logToConsole(LOG_DEBUG, `[VRR.GUI] ${getPlayerDisplayForConsole(client)} failed to order ${getPlayerData(client).businessOrderAmount} ${getItemTypeData(getPlayerData(client).businessOrderItem).name} at ${getPlayerData(client).businessOrderCost / getPlayerData(client).businessOrderAmount} each for business ${getBusinessData(getPlayerData(client).businessOrderBusiness).name} (Reason: Not enough money in business till)`);
showPlayerErrorGUI(client, "This business doesn't have enough money! Deposit some using /bizdeposit", "Business Order Canceled");
getPlayerData(client).businessOrderAmount = 0;
getPlayerData(client).businessOrderBusiness = false;
getPlayerData(client).businessOrderItem = -1;
getPlayerData(client).businessOrderValue = -1;
} else {
- logToConsole(LOG_DEBUG, `[VRR.GUI] ${getPlayerDisplayForConsole(client)} successfully ordered ${getPlayerData(client).businessOrderAmount} ${getItemTypeData(getPlayerData(client).businessOrderItem).name} at ${getPlayerData(client).businessOrderCost/getPlayerData(client).businessOrderAmount} each for business ${getBusinessData(getPlayerData(client).businessOrderBusiness).name}`);
+ logToConsole(LOG_DEBUG, `[VRR.GUI] ${getPlayerDisplayForConsole(client)} successfully ordered ${getPlayerData(client).businessOrderAmount} ${getItemTypeData(getPlayerData(client).businessOrderItem).name} at ${getPlayerData(client).businessOrderCost / getPlayerData(client).businessOrderAmount} each for business ${getBusinessData(getPlayerData(client).businessOrderBusiness).name}`);
showPlayerInfoGUI(client, `You ordered ${getPlayerData(client).businessOrderAmount} ${getItemTypeData(getPlayerData(client).businessOrderItem).name} (${getItemValueDisplay(getPlayerData(client).businessOrderItem, getPlayerData(client).businessOrderValue)}) for ${getPlayerData(client).businessOrderCost}!`, "Business Order Successful");
createItem(getPlayerData(client).businessOrderItem, getPlayerData(client).businessOrderValue, VRR_ITEM_OWNER_BIZFLOOR, getBusinessData(getPlayerData(client).businessOrderBusiness).databaseId, getPlayerData(client).businessOrderAmount);
cacheBusinessItems(getPlayerData(client).businessOrderBusiness);
@@ -91,22 +99,22 @@ function playerPromptAnswerYes(client) {
}
case VRR_PROMPT_GIVEVEHTOCLAN: {
- if(!isPlayerInAnyVehicle(client)) {
+ if (!isPlayerInAnyVehicle(client)) {
messagePlayerError(client, getLocaleString(client, "MustBeInVehicle"));
return false;
}
- if(!getVehicleData(getPlayerVehicle(client))) {
+ if (!getVehicleData(getPlayerVehicle(client))) {
messagePlayerError(client, getLocaleString(client, "RandomVehicleCommandsDisabled"));
return false;
}
- if(getVehicleData(getPlayerVehicle(client)).ownerType != VRR_VEHOWNER_PLAYER) {
+ if (getVehicleData(getPlayerVehicle(client)).ownerType != VRR_VEHOWNER_PLAYER) {
messagePlayerError(client, getLocaleString(client, "MustOwnVehicle"));
return false;
}
- if(getVehicleData(getPlayerVehicle(client)).ownerId != getPlayerCurrentSubAccount(client).databaseId) {
+ if (getVehicleData(getPlayerVehicle(client)).ownerId != getPlayerCurrentSubAccount(client).databaseId) {
messagePlayerError(client, getLocaleString(client, "MustOwnVehicle"));
return false;
}
@@ -120,17 +128,17 @@ function playerPromptAnswerYes(client) {
case VRR_PROMPT_GIVEHOUSETOCLAN: {
let houseId = getPlayerHouse(client);
- if(!houseId) {
+ if (!houseId) {
messagePlayerError(client, getLocaleString(client, "InvalidHouse"));
return false;
}
- if(getHouseData(houseId).ownerType != VRR_VEHOWNER_PLAYER) {
+ if (getHouseData(houseId).ownerType != VRR_VEHOWNER_PLAYER) {
messagePlayerError(client, getLocaleString(client, "MustOwnHouse"));
return false;
}
- if(getHouseData(houseId).ownerId != getPlayerCurrentSubAccount(client).databaseId) {
+ if (getHouseData(houseId).ownerId != getPlayerCurrentSubAccount(client).databaseId) {
messagePlayerError(client, getLocaleString(client, "MustOwnHouse"));
return false;
}
@@ -144,17 +152,17 @@ function playerPromptAnswerYes(client) {
case VRR_PROMPT_GIVEBIZTOCLAN: {
let businessId = getPlayerBusiness(client);
- if(!businessId) {
+ if (!businessId) {
messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
- if(getBusinessData(businessId).ownerType != VRR_VEHOWNER_PLAYER) {
+ if (getBusinessData(businessId).ownerType != VRR_VEHOWNER_PLAYER) {
messagePlayerError(client, getLocaleString(client, "MustOwnBusiness"));
return false;
}
- if(getBusinessData(businessId).ownerId != getPlayerCurrentSubAccount(client).databaseId) {
+ if (getBusinessData(businessId).ownerId != getPlayerCurrentSubAccount(client).databaseId) {
messagePlayerError(client, getLocaleString(client, "MustOwnBusiness"));
return false;
}
@@ -168,17 +176,17 @@ function playerPromptAnswerYes(client) {
case VRR_PROMPT_BUYHOUSE: {
let houseId = getPlayerHouse(client);
- if(!houseId) {
+ if (!houseId) {
messagePlayerError(client, getLocaleString(client, "InvalidHouse"));
return false;
}
- if(getHouseData(houseId).buyPrice <= 0) {
+ if (getHouseData(houseId).buyPrice <= 0) {
messagePlayerError(client, getLocaleString(client, "HouseNotForSale"));
return false;
}
- if(getPlayerCurrentSubAccount(client).cash < getHouseData(houseId).buyPrice) {
+ if (getPlayerCurrentSubAccount(client).cash < getHouseData(houseId).buyPrice) {
messagePlayerError(client, getLocaleString(client, "HousePurchaseNotEnoughMoney"));
return false;
}
@@ -196,17 +204,17 @@ function playerPromptAnswerYes(client) {
case VRR_PROMPT_BUYBIZ: {
let businessId = getPlayerBusiness(client);
- if(!businessId) {
+ if (!businessId) {
messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
- if(getBusinessData(businessId).buyPrice <= 0) {
+ if (getBusinessData(businessId).buyPrice <= 0) {
messagePlayerError(client, getLocaleString(client, "BusinessNotForSale"));
return false;
}
- if(getPlayerCurrentSubAccount(client).cash < getBusinessData(businessId).buyPrice) {
+ if (getPlayerCurrentSubAccount(client).cash < getBusinessData(businessId).buyPrice) {
messagePlayerError(client, getLocaleString(client, "BusinessPurchaseNotEnoughMoney"));
return false;
}
diff --git a/scripts/server/house.js b/scripts/server/house.js
index 37f0ad93..656ad61a 100644
--- a/scripts/server/house.js
+++ b/scripts/server/house.js
@@ -7,6 +7,159 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// House Location Types
+const VRR_HOUSELOC_NONE = 0; // None
+const VRR_HOUSELOC_GATE = 1; // Center of any moveable gate that belongs to the house
+const VRR_HOUSELOC_GARAGE = 2; // Location for garage (pos1 = outside, pos2 = inside). Use pos to teleport or spawn veh/ped
+
+// ===========================================================================
+
+// House Owner Types
+const VRR_HOUSEOWNER_NONE = 0; // Not owned
+const VRR_HOUSEOWNER_PLAYER = 1; // Owner is a player (character/subaccount)
+const VRR_HOUSEOWNER_JOB = 2; // Owned by a job
+const VRR_HOUSEOWNER_CLAN = 3; // Owned by a clan
+const VRR_HOUSEOWNER_FACTION = 4; // Owned by a faction
+const VRR_HOUSEOWNER_PUBLIC = 5; // Is a public house. Technically not owned. This probably won't be used.
+
+// ===========================================================================
+
+/**
+ * @class Representing a house's data. Loaded and saved in the database
+ */
+ class HouseData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0
+ this.description = "";
+ this.ownerType = VRR_HOUSEOWNER_NONE;
+ this.ownerId = 0;
+ this.buyPrice = 0;
+ this.rentPrice = 0;
+ this.renter = 0;
+ this.locked = false;
+ this.hasInterior = false;
+ this.index = -1;
+ this.needsSaved = false;
+ this.interiorLights = true;
+
+ this.itemCache = [];
+ this.locations = [];
+ //this.gameScripts = [];
+
+ this.entrancePosition = false;
+ this.entranceRotation = 0.0;
+ this.entranceInterior = 0;
+ this.entranceDimension = 0;
+ this.entrancePickupModel = -1;
+ this.entranceBlipModel = -1;
+ this.entrancePickup = null;
+ this.entranceBlip = null;
+
+ this.exitPosition = false;
+ this.exitRotation = 0.0;
+ this.exitInterior = 0;
+ this.exitDimension = -1;
+ this.exitPickupModel = -1;
+ this.exitBlipModel = -1;
+ this.exitPickup = null;
+ this.exitBlip = null;
+
+ this.streamingRadioStation = -1;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["house_id"]);
+ this.description = toString(dbAssoc["house_description"]);
+ this.ownerType = toInteger(dbAssoc["house_owner_type"]);
+ this.ownerId = toInteger(dbAssoc["house_owner_id"]);
+ this.buyPrice = toInteger(dbAssoc["house_buy_price"]);
+ this.rentPrice = toInteger(dbAssoc["house_rent_price"]);
+ this.renter = toInteger(dbAssoc["house_renter"]);
+ this.locked = intToBool(toInteger(dbAssoc["house_locked"]));
+ this.hasInterior = intToBool(toInteger(dbAssoc["house_has_interior"]));
+ this.interiorLights = intToBool(toInteger(dbAssoc["house_interior_lights"]));
+
+ this.entrancePosition = toVector3(toFloat(dbAssoc["house_entrance_pos_x"]), toFloat(dbAssoc["house_entrance_pos_y"]), toFloat(dbAssoc["house_entrance_pos_z"]));
+ this.entranceRotation = toFloat(dbAssoc["house_entrance_rot_z"]);
+ this.entranceInterior = toInteger(dbAssoc["house_entrance_int"]);
+ this.entranceDimension = toInteger(dbAssoc["house_entrance_vw"]);
+ this.entrancePickupModel = toInteger(dbAssoc["house_entrance_pickup"]);
+ this.entranceBlipModel = toInteger(dbAssoc["house_entrance_blip"]);
+
+ this.exitPosition = toVector3(toFloat(dbAssoc["house_exit_pos_x"]), toFloat(dbAssoc["house_exit_pos_y"]), toFloat(dbAssoc["house_exit_pos_z"]));
+ this.exitRotation = toFloat(dbAssoc["house_exit_rot_z"]);
+ this.exitInterior = toInteger(dbAssoc["house_exit_int"]);
+ this.exitDimension = toInteger(dbAssoc["house_exit_vw"]);
+ this.exitPickupModel = toInteger(dbAssoc["house_exit_pickup"]);
+ this.exitBlipModel = toInteger(dbAssoc["house_exit_blip"]);
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing a houses's location data. Multiple can be used for a single house. Used for things like doors, garage entry/exit/vehspawn, gates, etc. Loaded and saved in the database
+ */
+class HouseLocationData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.type = 0;
+ this.house = 0;
+ this.enabled = false;
+ this.index = -1;
+ this.houseIndex = -1;
+ this.needsSaved = false;
+
+ this.position = toVector3(0.0, 0.0, 0.0);
+ this.interior = 0;
+ this.dimension = 0;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["house_loc_id"]);
+ this.name = toString(dbAssoc["house_loc_name"]);
+ this.type = toInteger(dbAssoc["house_loc_type"]);
+ this.house = toInteger(dbAssoc["house_loc_house"]);
+ this.enabled = intToBool(toInteger(dbAssoc["house_loc_enabled"]));
+ this.index = -1;
+
+ this.position = toVector3(toFloat(dbAssoc["house_loc_pos_x"]), toFloat(dbAssoc["house_loc_pos_y"]), toFloat(dbAssoc["house_loc_pos_z"]));
+ this.interior = toInteger(dbAssoc["house_loc_int"]);
+ this.dimension = toInteger(dbAssoc["house_loc_vw"]);
+ }
+ };
+
+ //saveToDatabase = () => {
+ // saveHouseLocationToDatabase(this.houseIndex, this.index);
+ //}
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing a house's game scripts. Multiple can be used for a single house
+ */
+class HouseGameScriptData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.business = 0;
+ this.state = false;
+ this.index = -1;
+ this.houseIndex = -1;
+ this.needsSaved = false;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["house_script_id"]);
+ this.name = toString(dbAssoc["house_script_name"]);
+ this.state = toInteger(dbAssoc["house_script_state"]);
+ this.business = toInteger(dbAssoc["house_script_biz"]);
+ }
+ }
+};
+
+// ===========================================================================
+
function initHouseScript() {
logToConsole(LOG_INFO, "[VRR.House]: Initializing house script ...");
logToConsole(LOG_INFO, "[VRR.House]: House script initialized successfully!");
@@ -22,7 +175,7 @@ function loadHousesFromDatabase() {
let dbAssoc;
if (dbConnection) {
- let dbQuery = queryDatabase(dbConnection, `SELECT * FROM house_main WHERE house_server = ${getServerId()}`);
+ let dbQuery = queryDatabase(dbConnection, `SELECT * FROM house_main WHERE house_deleted = 0 AND house_server = ${getServerId()}`);
if (dbQuery) {
if (dbQuery.numRows > 0) {
while (dbAssoc = fetchQueryAssoc(dbQuery)) {
diff --git a/scripts/server/insurance.js b/scripts/server/insurance.js
new file mode 100644
index 00000000..35aee21f
--- /dev/null
+++ b/scripts/server/insurance.js
@@ -0,0 +1,40 @@
+// ===========================================================================
+// Vortrex's Roleplay Resource
+// https://github.com/VortrexFTW/gtac_roleplay
+// ===========================================================================
+// FILE: insurance.js
+// DESC: Provides insurance commands, functions, and usage
+// TYPE: Server (JavaScript)
+// ===========================================================================
+
+// Insurance Account Owner Types
+const VRR_INS_ACCT_OWNER_NONE = 0; // None
+const VRR_INS_ACCT_OWNER_PLAYER = 1; // Player owns insurance company
+const VRR_INS_ACCT_OWNER_BIZ = 2; // Business owns insurance company
+const VRR_INS_ACCT_OWNER_CLAN = 3; // Clan owns insurance company
+
+// ===========================================================================
+
+// Insurance Account Entity Types
+const VRR_INS_ACCT_ENTITY_NONE = 0; // None
+const VRR_INS_ACCT_ENTITY_PLAYER_HEALTH = 1; // Health Insurance
+const VRR_INS_ACCT_ENTITY_PLAYER_LIFE = 2; // Life Insurance
+const VRR_INS_ACCT_ENTITY_VEH = 3; // Vehicle Insurance
+const VRR_INS_ACCT_ENTITY_BIZ = 4; // Business Insurance
+const VRR_INS_ACCT_ENTITY_HOUSE = 5; // House Insurance
+
+// ===========================================================================
+
+// Insurance Account History Types
+const VRR_INS_ACCT_HISTORY_NONE = 0; // None
+const VRR_INS_ACCT_HISTORY_PLAYER_MEDICAL = 1; // Medical insurance was used (player disease/injury)
+const VRR_INS_ACCT_HISTORY_PLAYER_DEATH = 2; // Life insurance was used (player death)
+const VRR_INS_ACCT_HISTORY_VEH_DAMAGE = 3; // Vehicle was damaged, but not destroyed
+const VRR_INS_ACCT_HISTORY_VEH_WRECKED = 4; // Vehicle was completely destroyed
+const VRR_INS_ACCT_HISTORY_VEH_THEFT = 5; // Vehicle was stolen
+const VRR_INS_ACCT_HISTORY_BIZ_DAMAGE = 6; // Business was damaged (broken items/window/door)
+const VRR_INS_ACCT_HISTORY_BIZ_THEFT = 7; // Business was stolen from
+const VRR_INS_ACCT_HISTORY_HOUSE_DAMAGE = 8; // House was damaged
+const VRR_INS_ACCT_HISTORY_HOUSE_THEFT = 9; // House was stolen from
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/item.js b/scripts/server/item.js
index e324123d..de440744 100644
--- a/scripts/server/item.js
+++ b/scripts/server/item.js
@@ -7,6 +7,229 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Item Owners
+const VRR_ITEM_OWNER_NONE = 0; // None
+const VRR_ITEM_OWNER_PLAYER = 1; // Item is in a player's inventory
+const VRR_ITEM_OWNER_VEHTRUNK = 2; // Item is in a vehicle's trunk
+const VRR_ITEM_OWNER_VEHDASH = 3; // Item is in a vehicle's glove compartment
+const VRR_ITEM_OWNER_BIZFLOOR = 4; // Item is in the public area of a business (on the floor = ready to buy)
+const VRR_ITEM_OWNER_BIZSTORAGE = 5; // Item is in a business's storage area (stock room)
+const VRR_ITEM_OWNER_HOUSE = 6; // Item is in a house
+const VRR_ITEM_OWNER_SAFE = 7; // Item is in a safe (safes can be anywhere)
+const VRR_ITEM_OWNER_ITEM = 8; // Item is in another item (trashbag, briefcase, wallet, suitcase, crate/box, barrel, etc)
+const VRR_ITEM_OWNER_GROUND = 9; // Item is on the ground
+const VRR_ITEM_OWNER_JOBLOCKER = 10; // Item is in player's job locker
+const VRR_ITEM_OWNER_LOCKER = 10; // Item is in player's locker
+
+// ===========================================================================
+
+// Item Use Types
+const VRR_ITEM_USETYPE_NONE = 0; // Has no effect
+const VRR_ITEM_USETYPE_WEAPON = 1; // Equips weapon
+const VRR_ITEM_USETYPE_AMMO_CLIP = 2; // Magazine for weapon. If in inventory, R will load it into gun
+const VRR_ITEM_USETYPE_PHONE = 3; // Pulls out phone
+const VRR_ITEM_USETYPE_GPS = 4; // Not sure how I want this to work yet
+const VRR_ITEM_USETYPE_MAP = 5; // Shows minimap on HUD
+const VRR_ITEM_USETYPE_SKIN = 6; // Changes skin (uses skin changer)
+const VRR_ITEM_USETYPE_PEDPART = 7; // Changes ped part (clothing, skin, hair, etc) (UNUSED)
+const VRR_ITEM_USETYPE_PEDPROP = 8; // Changes ped prop (watches, glasses, hats, etc) (UNUSED)
+const VRR_ITEM_USETYPE_STORAGE = 9; // Shows stored items. Backpack, crate, briefcase, wallet, etc
+const VRR_ITEM_USETYPE_VEHKEY = 10; // Locks/unlocks a vehicle and allows starting engine without hotwire
+const VRR_ITEM_USETYPE_BIZKEY = 11; // Locks/unlocks a business
+const VRR_ITEM_USETYPE_HOUSEKEY = 12; // Locks/unlocks a house
+const VRR_ITEM_USETYPE_SEED = 13; // Plants a seed
+const VRR_ITEM_USETYPE_WEED = 14; // Light drug effect (short term relief of addiction symptoms?)
+const VRR_ITEM_USETYPE_COKE = 15; // Medium drug effect (medium term relief of addiction symptoms?)
+const VRR_ITEM_USETYPE_METH = 16; // Heavy drug effect (extended term relief of addiction symptoms?)
+const VRR_ITEM_USETYPE_CIGAR = 17; // Just for appearance. Makes people look cool I guess
+const VRR_ITEM_USETYPE_WATER = 18; // Replenishes small amount of health
+const VRR_ITEM_USETYPE_FOOD = 19; // Eat food. Replenishes a small amount of health
+const VRR_ITEM_USETYPE_BEER = 20; // Subtle drunk effect. Replenishes small amount of health.
+const VRR_ITEM_USETYPE_WINE = 21; // Moderate drunk effect. Replenishes moderate amount of health.
+const VRR_ITEM_USETYPE_LIQUOR = 22; // Heavy drunk effect. Replenishes large amount of health.
+const VRR_ITEM_USETYPE_COFFEE = 23; // Replenishes moderate amount of health.
+const VRR_ITEM_USETYPE_AMMO_ROUND = 23; // Bullet. Loads into magazine. Not used at the moment
+const VRR_ITEM_USETYPE_HANDCUFF = 24; //
+const VRR_ITEM_USETYPE_ROPE = 25; //
+const VRR_ITEM_USETYPE_BLINDFOLD = 26; //
+const VRR_ITEM_USETYPE_TAZER = 27; //
+const VRR_ITEM_USETYPE_ARMOUR = 28; //
+const VRR_ITEM_USETYPE_HEALTH = 29; //
+const VRR_ITEM_USETYPE_AED = 30; //
+const VRR_ITEM_USETYPE_WALKIETALKIE = 31; //
+const VRR_ITEM_USETYPE_BOOMBOX = 32; //
+const VRR_ITEM_USETYPE_EARBUDS = 33; //
+const VRR_ITEM_USETYPE_BADGE = 34; //
+const VRR_ITEM_USETYPE_DRINK = 35; // Drinkable item. Action output shows "Player_Name drinks some (drink name)"
+const VRR_ITEM_USETYPE_EXTINGUISHER = 36; // Extinguisher item. Allows putting out fires
+const VRR_ITEM_USETYPE_SPRAYPAINT = 37; // Spraypaint item. Allows spraying custom clan tags on walls
+const VRR_ITEM_USETYPE_PEPPERSPRAY = 38; // Pepper spray item. Incapacitates nearby player
+const VRR_ITEM_USETYPE_FLASHLIGHT = 39; // Flashlight item. Unusable for now, but plan to cast a custom light beam
+const VRR_ITEM_USETYPE_AIRPLANETICKET = 40; // Airplane ticket. Allows a character to move to another server
+const VRR_ITEM_USETYPE_TRAINTICKET = 41; // Train ticket. Allows a character to move to another server
+const VRR_ITEM_USETYPE_VEHUPGRADE_PART = 42; // Vehicle update part item. Allows adding custom parts like spoilers, side skirts, roof scoops, etc
+const VRR_ITEM_USETYPE_VEHTIRE = 43; // Vehicle tire item. Allows changing the tire/rim types
+const VRR_ITEM_USETYPE_FUELCAN = 44; // Fuel can item. Allows refueling of a nearby vehicle anywhere
+const VRR_ITEM_USETYPE_VEHCOLOUR = 45; // Vehicle colour item. Changes primary and secondary vehicle colours
+const VRR_ITEM_USETYPE_VEHLIVERY = 46; // Vehicle livery/paintjob item. Applies decals and special paint jobs
+const VRR_ITEM_USETYPE_VEHREPAIR = 47; // Vehicle repair item. Much longer use time
+const VRR_ITEM_USETYPE_SMOKEDRUG = 48; // Smokable drug. Action output shows "Player_Name smokes some (drug)"
+const VRR_ITEM_USETYPE_SNORTDRUG = 49; // Snortable drug. Action output shows "Player_Name snorts some (drug)"
+const VRR_ITEM_USETYPE_PLANT = 50; // Plantable item. Pot plants, coke plants, etc
+const VRR_ITEM_USETYPE_MEGAPHONE = 51; // Megaphone item. Allows shouting over greater distances. Also called a bullhorn
+const VRR_ITEM_USETYPE_INJECTDRUG = 52; // Injectable drug. Action output shows "Player_Name injects some (drug)"
+const VRR_ITEM_USETYPE_ALCOHOL = 53; // Alcohol. Applies an intoxication/drunkness effect
+
+// ===========================================================================
+
+// Item Drop Types
+const VRR_ITEM_DROPTYPE_NONE = 0; // Can't be dropped
+const VRR_ITEM_DROPTYPE_OBJECT = 1; // Drops as an object on the ground
+const VRR_ITEM_DROPTYPE_PICKUP = 2; // Drops as a pickup
+const VRR_ITEM_DROPTYPE_OBJECTLIGHT = 3; // Object that produces an area light effect (lamp, flashlight, etc)
+const VRR_ITEM_DROPTYPE_DESTROY = 4; // Will destroy the item on drop (keys mostly but for any tiny object)
+const VRR_ITEM_DROPTYPE_OBJECTSTACK = 5; // Stackable objects (crates and such). Will sit on top of closest other stackable
+
+// ===========================================================================
+
+// Item Occupied States
+const VRR_ITEM_ACTION_NONE = 0; // None
+const VRR_ITEM_ACTION_USE = 1; // Using item
+const VRR_ITEM_ACTION_PICKUP = 2; // Picking up item
+const VRR_ITEM_ACTION_DROP = 3; // Dropping item
+const VRR_ITEM_ACTION_SWITCH = 4; // Switching item
+const VRR_ITEM_ACTION_PUT = 5; // Putting item (into trunk, dash, crate, etc)
+const VRR_ITEM_ACTION_TAKE = 6; // Taking item (from trunk, dash, crate, etc)
+
+// ===========================================================================
+
+class ItemData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.index = 0;
+ this.itemTypeIndex = 0;
+ this.itemType = 0;
+ this.ownerType = VRR_ITEM_OWNER_NONE;
+ this.ownerId = 0;
+ this.ownerIndex = -1;
+ this.position = toVector3(0.0, 0.0, 0.0);
+ this.interior = 0;
+ this.dimension = 0;
+ this.object = null;
+ this.buyPrice = 0;
+ this.needsSaved = false;
+ this.amount = 0;
+ this.value = 0;
+ this.enabled = false;
+ this.extra = false;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["item_id"]);
+ this.index = 0;
+ this.itemTypeIndex = 0;
+ this.itemType = toInteger(dbAssoc["item_type"]);
+ this.ownerType = toInteger(dbAssoc["item_owner_type"]);;
+ this.ownerId = toInteger(dbAssoc["item_owner_id"]);
+ this.position = toVector3(toFloat(dbAssoc["item_pos_x"]), toFloat(dbAssoc["item_pos_y"]), toFloat(dbAssoc["item_pos_z"]));
+ this.interior = toInteger(dbAssoc["item_int"]);
+ this.dimension = toInteger(dbAssoc["item_vw"]);
+ this.buyPrice = toInteger(dbAssoc["item_buy_price"]);
+ this.amount = toInteger(dbAssoc["item_amount"]);
+ this.value = toInteger(dbAssoc["item_value"]);
+ this.enabled = intToBool(toInteger(dbAssoc["item_enabled"]));
+ }
+ }
+};
+
+// ===========================================================================
+
+class ItemTypeData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.serverId = 0;
+ this.index = 0;
+ this.name = "Unknown";
+ this.enabled = false;
+ this.useType = VRR_ITEM_USETYPE_NONE;
+ this.useId = 0;
+ this.useValue = 0;
+ this.maxValue = 0;
+ this.dropType = VRR_ITEM_DROPTYPE_NONE;
+ this.useId = 0;
+ this.dropPosition = toVector3(0.0, 0.0, 0.0);
+ this.dropRotation = toVector3(0.0, 0.0, 0.0);
+ this.dropScale = toVector3(0.0, 0.0, 0.0);
+ this.dropModel = 0;
+ this.orderPrice = 0;
+ this.orderValue = 0;
+ this.demandMultiplier = 1;
+ this.supplyMultiplier = 1;
+ this.riskMultiplier = 1;
+ this.needsSaved = false;
+ this.useDelay = 0;
+ this.switchDelay = 0;
+ this.pickupDelay = 0;
+ this.putDelay = 0;
+ this.takeDelay = 0;
+ this.giveDelay = 0;
+ this.dropDelay = 0;
+ this.useAnimationName = "";
+ this.dropAnimationName = "";
+ this.pickupAnimationName = "";
+ this.giveAnimationName = "";
+ this.putAnimationName = "";
+ this.takeAnimationName = "";
+ this.switchAnimationName = "";
+ this.useAnimationIndex = false;
+ this.dropAnimationIndex = false;
+ this.pickupAnimationIndex = false;
+ this.giveAnimationIndex = false;
+ this.putAnimationIndex = false;
+ this.takeAnimationIndex = false;
+ this.switchAnimationIndex = false;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["item_type_id"]);
+ this.serverId = toInteger(dbAssoc["item_type_server"]);
+ this.name = dbAssoc["item_type_name"];
+ this.enabled = intToBool(toInteger(dbAssoc["item_type_enabled"]));
+ this.useType = toInteger(dbAssoc["item_type_use_type"]);
+ this.dropType = toInteger(dbAssoc["item_type_drop_type"]);
+ this.useId = toInteger(dbAssoc["item_type_use_id"]);
+ this.dropPosition = toVector3(toFloat(dbAssoc["item_type_drop_pos_x"]), toFloat(dbAssoc["item_type_drop_pos_y"]), toFloat(dbAssoc["item_type_drop_pos_z"]));
+ this.dropRotation = toVector3(toFloat(dbAssoc["item_type_drop_rot_x"]), toFloat(dbAssoc["item_type_drop_rot_y"]), toFloat(dbAssoc["item_type_drop_rot_z"]));
+ this.dropScale = toVector3(toFloat(dbAssoc["item_type_drop_scale_x"]), toFloat(dbAssoc["item_type_drop_scale_y"]), toFloat(dbAssoc["item_type_drop_scale_z"]));
+ this.dropModel = toInteger(dbAssoc["item_type_drop_model"]);
+ this.useId = toInteger(dbAssoc["item_type_use_id"]);
+ this.useValue = toInteger(dbAssoc["item_type_use_value"]);
+ this.maxValue = toInteger(dbAssoc["item_type_max_value"]);
+ this.orderPrice = toInteger(dbAssoc["item_type_order_price"]);
+ this.orderValue = toInteger(dbAssoc["item_type_order_value"]);
+ this.demandMultiplier = toFloat(dbAssoc["item_type_demand_multiplier"]);
+ this.supplyMultiplier = toFloat(dbAssoc["item_type_supply_multiplier"]);
+ this.riskMultiplier = toFloat(dbAssoc["item_type_risk_multiplier"]);
+ this.size = toInteger(dbAssoc["item_type_size"]);
+ this.capacity = toInteger(dbAssoc["item_type_capacity"]);
+ this.useDelay = toInteger(dbAssoc["item_type_delay_use"]);
+ this.switchDelay = toInteger(dbAssoc["item_type_delay_switch"]);
+ this.pickupDelay = toInteger(dbAssoc["item_type_delay_pickup"]);
+ this.putDelay = toInteger(dbAssoc["item_type_delay_put"]);
+ this.takeDelay = toInteger(dbAssoc["item_type_delay_take"]);
+ this.giveDelay = toInteger(dbAssoc["item_type_delay_give"]);
+ this.dropDelay = toInteger(dbAssoc["item_type_delay_drop"]);
+ this.useAnimationName = toInteger(dbAssoc["item_type_anim_use"]);
+ this.switchAnimationName = toInteger(dbAssoc["item_type_anim_switch"]);
+ this.pickupAnimationName = toInteger(dbAssoc["item_type_anim_pickup"]);
+ this.putAnimationName = toInteger(dbAssoc["item_type_anim_put"]);
+ this.takeAnimationName = toInteger(dbAssoc["item_type_anim_take"]);
+ this.giveAnimationName = toInteger(dbAssoc["item_type_anim_give"]);
+ this.dropAnimationName = toInteger(dbAssoc["item_type_anim_drop"]);
+ }
+ }
+};
+
+// ===========================================================================
+
function initItemScript() {
logToConsole(LOG_INFO, "[VRR.Item]: Initializing item script ...");
logToConsole(LOG_INFO, "[VRR.Item]: Item script initialized successfully!");
@@ -20,7 +243,7 @@ function loadItemsFromDatabase() {
let dbConnection = connectToDatabase();
let dbFetchAssoc;
if (dbConnection) {
- let dbQuery = queryDatabase(dbConnection, `SELECT * FROM item_main WHERE item_server = ${getServerId()}`);
+ let dbQuery = queryDatabase(dbConnection, `SELECT * FROM item_main WHERE item_deleted = 0 AND item_server = ${getServerId()}`);
if (dbQuery) {
if (dbQuery.numRows > 0) {
while (dbFetchAssoc = fetchQueryAssoc(dbQuery)) {
@@ -42,7 +265,7 @@ function loadItemTypesFromDatabase() {
let dbConnection = connectToDatabase();
let dbFetchAssoc;
if (dbConnection) {
- let dbQuery = queryDatabase(dbConnection, `SELECT * FROM item_type WHERE item_type_enabled = 1 AND item_type_server = ${getServerId()}`);
+ let dbQuery = queryDatabase(dbConnection, `SELECT * FROM item_type WHERE item_type_deleted = 0 AND item_type_enabled = 1 AND item_type_server = ${getServerId()}`);
if (dbQuery) {
if (getQueryNumRows(dbQuery) > 0) {
while (dbFetchAssoc = fetchQueryAssoc(dbQuery)) {
@@ -561,15 +784,16 @@ function setItemTypeDropModelCommand(command, params, client) {
}
let itemTypeIndex = getItemTypeFromParams(splitParams.slice(0, -1).join(" "));
- let modelId = splitParams[splitParams.length - 1];
+ let modelIndex = getObjectModelIndexFromParams(splitParams.slice(-1).join(" "));
if (!getItemTypeData(itemTypeIndex)) {
messagePlayerError(client, getLocaleString(client, "InvalidItemType"));
return false;
}
- getItemTypeData(itemTypeIndex).dropModel = modelId;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name} dropped object model to ${modelId}`);
+ getItemTypeData(itemTypeIndex).dropModel = modelIndex;
+ getItemTypeData(itemTypeIndex).needsSaved = true;
+ messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}'s dropped object model index to ${modelIndex}`);
}
// ===========================================================================
@@ -598,6 +822,7 @@ function setItemTypeOrderPriceCommand(command, params, client) {
}
getItemTypeData(itemTypeIndex).orderPrice = orderPrice;
+ getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name} {MAINCOLOUR}base price to {ALTCOLOUR}$${orderPrice}`);
}
@@ -627,7 +852,8 @@ function setItemTypeRiskMultiplierCommand(command, params, client) {
}
getItemTypeData(itemTypeIndex).riskMultiplier = riskMultiplier;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name} {MAINCOLOUR}risk multilier to {ALTCOLOUR}$${riskMultiplier}`);
+ getItemTypeData(itemTypeIndex).needsSaved = true;
+ messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} risk multiplier to {ALTCOLOUR}$${riskMultiplier}`);
}
// ===========================================================================
@@ -655,6 +881,7 @@ function toggleItemTypeEnabledCommand(command, params, client) {
}
getItemTypeData(itemTypeIndex).enabled = !getItemTypeData(itemTypeIndex).enabled;
+ getItemTypeData(itemTypeIndex).needsSaved = true;
messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} ${getEnabledDisabledFromBool(getItemTypeData(itemTypeIndex).enabled)} item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}`);
}
@@ -684,7 +911,8 @@ function setItemTypeUseTypeCommand(command, params, client) {
}
getItemTypeData(itemTypeIndex).useType = useType;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name} {MAINCOLOUR}use type to {ALTCOLOUR}$${useType}`);
+ getItemTypeData(itemTypeIndex).needsSaved = true;
+ messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} use type to {ALTCOLOUR}$${useType}`);
}
// ===========================================================================
@@ -713,7 +941,8 @@ function setItemTypeUseValueCommand(command, params, client) {
}
getItemTypeData(itemTypeIndex).useValue = useValue;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name} {MAINCOLOUR}use value to {ALTCOLOUR}$${useValue}`);
+ getItemTypeData(itemTypeIndex).needsSaved = true;
+ messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} set item type {ALTCOLOUR}${getItemTypeData(itemTypeIndex).name}{MAINCOLOUR} use value to {ALTCOLOUR}$${useValue}`);
}
// ===========================================================================
@@ -722,6 +951,7 @@ function playerUseItem(client, hotBarSlot) {
let itemIndex = getPlayerData(client).hotBarItems[hotBarSlot];
if (itemIndex == -1) {
+ logToConsole(LOG_DEBUG | LOG_WARN, `[VRR.Item] ${getPlayerDisplayForConsole(client)} tried to use an empty hotbar slot ${hotBarSlot}`);
return false;
}
@@ -732,10 +962,12 @@ function playerUseItem(client, hotBarSlot) {
}
let itemData = getItemData(itemIndex);
- let itemTypeData = getItemTypeData(itemIndex);
+ let itemTypeData = getItemTypeData(itemData.itemTypeIndex);
let hotBarItems = getPlayerData(client).hotBarItems;
- switch (itemTypeData.useType) {
+ logToConsole(LOG_DEBUG, `[VRR.Item] ${getPlayerDisplayForConsole(client)} used a ${itemTypeData.name} (use type ${itemTypeData.useType} - ${typeof itemTypeData.useType}) item (ID: ${itemData.index}/${itemData.databaseId}, TypeID: ${itemTypeData.index}/${itemTypeData.databaseId})`);
+
+ switch (toInteger(itemTypeData.useType)) {
case VRR_ITEM_USETYPE_SKIN: {
getPlayerData(client).itemActionItem = itemIndex;
forcePlayerIntoSkinSelect(client);
@@ -746,9 +978,9 @@ function playerUseItem(client, hotBarSlot) {
for (let i in hotBarItems) {
if (hotBarItems[i] != -1) {
if (getItemData(hotBarItems[i]) != false) {
- if (getItemData(getItemData(hotBarItems[i]).itemTypeIndex).useType == VRR_ITEM_USETYPE_AMMO_CLIP) {
+ if (getItemTypeData(getItemData(hotBarItems[i]).itemTypeIndex).useType == VRR_ITEM_USETYPE_AMMO_CLIP) {
let ammoItemData = getItemData(hotBarItems[i]);
- let ammoItemTypeData = getItemData(ammoItemData.itemTypeIndex);
+ let ammoItemTypeData = getItemTypeData(ammoItemData.itemTypeIndex);
if (ammoItemTypeData.useId == itemTypeData.databaseId) {
givePlayerWeaponAmmo(client, ammoItemData.value);
itemData.value = itemData.value + ammoItemData.value;
@@ -869,11 +1101,6 @@ function playerUseItem(client, hotBarSlot) {
break;
}
- case VRR_ITEM_USETYPE_NONE: {
- messagePlayerError(client, `The ${getItemName(itemIndex)} doesn't do anything when you try to use it.`);
- break;
- }
-
case VRR_ITEM_USETYPE_VEHREPAIR: {
let vehicle = getClosestVehicle(getPlayerPosition(client));
if (getDistance(getPlayerPosition(client), getVehiclePosition(vehicle)) <= getGlobalConfig().vehicleRepairDistance) {
@@ -1059,25 +1286,31 @@ function playerUseItem(client, hotBarSlot) {
}
case VRR_ITEM_USETYPE_LOTTOTICKET: {
+ messagePlayerError(client, getLocaleString(client, "ItemDoesntDoAnythingOnUse", itemTypeData.name));
break;
}
case VRR_ITEM_USETYPE_AREARADIO: {
itemData.enabled = !itemData.enabled;
meActionToNearbyPlayers(client, `turns ${getOnOffFromBool(itemData.enabled)} the boombox radio`);
- messagePlayerAlert(client, `Use /radiostation to set the radio station and drop it on the ground to play`);
+ messagePlayerAlert(client, getLocaleString(client, "ItemRadioStationTip", `{ALTCOLOUR}/radiostation{MAINCOLOUR}`));
break;
}
case VRR_ITEM_USETYPE_PERSONALRADIO: {
itemData.enabled = !itemData.enabled;
- meActionToNearbyPlayers(client, `turns ${getOnOffFromBool(itemData.enabled)} the boombox radio`);
- messagePlayerAlert(client, `Use /radiostation to set the radio station`);
+ meActionToNearbyPlayers(client, `turns ${getOnOffFromBool(itemData.enabled)} their personal radio`);
+ messagePlayerAlert(client, getLocaleString(client, "ItemRadioStationTip", `{ALTCOLOUR}/radiostation{MAINCOLOUR}`));
+ break;
+ }
+
+ case VRR_ITEM_USETYPE_NONE: {
+ messagePlayerError(client, getLocaleString(client, "ItemDoesntDoAnythingOnUse", itemTypeData.name));
break;
}
default: {
- messagePlayerError(client, `The ${itemTypeData.name} doesn't do anything when you try to use it.`);
+ messagePlayerError(client, getLocaleString(client, "ItemDoesntDoAnythingOnUse", itemTypeData.name));
break;
}
}
@@ -1455,7 +1688,7 @@ function cachePlayerHotBarItems(client) {
// ===========================================================================
-function deleteItem(itemId) {
+function deleteItem(itemId, whoDeleted = -1) {
let owner = -1;
let ownerTypeString = "Unknown";
switch (getItemData(itemId).ownerType) {
@@ -1526,7 +1759,7 @@ function deleteItem(itemId) {
logToConsole(LOG_DEBUG, `Deleted item ${itemId} (DBID: ${getItemData(itemId).databaseId}, Owner Type: ${ownerTypeString}, Owner ID: ${getItemData(itemId).ownerId})`);
if (getItemData(itemId).databaseId > 0) {
- quickDatabaseQuery(`DELETE FROM item_main WHERE item_id = ${getItemData(itemId).databaseId}`);
+ quickDatabaseQuery(`UPDATE item_main SET item_deleted = 1, item_when_deleted = UNIX_TIMESTAMP() WHERE item_id = ${getItemData(itemId).databaseId}`);
}
getServerData().items[itemId] = false;
setAllItemDataIndexes();
@@ -2234,9 +2467,54 @@ function getOrderPriceForItemType(itemType) {
// ===========================================================================
function clearPlayerItemActionState(client) {
+ if (getPlayerData(client).itemActionItem != -1) {
+ switch (getPlayerData(client).itemActionState) {
+ case VRR_ITEM_ACTION_DROP: {
+ if (getItemTypeData(getItemData(getPlayerData(client).itemActionItem).itemTypeIndex).dropAnimationIndex != -1) {
+ makePlayerStopAnimation(client);
+ }
+ break;
+ }
+
+ case VRR_ITEM_ACTION_USE: {
+ if (getItemTypeData(getItemData(getPlayerData(client).itemActionItem).itemTypeIndex).useAnimationIndex != -1) {
+ makePlayerStopAnimation(client);
+ }
+ break;
+ }
+
+ case VRR_ITEM_ACTION_PICKUP: {
+ if (getItemTypeData(getItemData(getPlayerData(client).itemActionItem).itemTypeIndex).pickupAnimationIndex != -1) {
+ makePlayerStopAnimation(client);
+ }
+ break;
+ }
+
+ case VRR_ITEM_ACTION_TAKE: {
+ if (getItemTypeData(getItemData(getPlayerData(client).itemActionItem).itemTypeIndex).takeAnimationIndex != -1) {
+ makePlayerStopAnimation(client);
+ }
+ break;
+ }
+
+ case VRR_ITEM_ACTION_PUT: {
+ if (getItemTypeData(getItemData(getPlayerData(client).itemActionItem).itemTypeIndex).putAnimationIndex != -1) {
+ makePlayerStopAnimation(client);
+ }
+ break;
+ }
+
+ case VRR_ITEM_ACTION_SWITCH: {
+ if (getItemTypeData(getItemData(getPlayerData(client).itemActionItem).itemTypeIndex).switchAnimationIndex != -1) {
+ makePlayerStopAnimation(client);
+ }
+ break;
+ }
+ }
+ }
+
getPlayerData(client).itemActionState = VRR_ITEM_ACTION_NONE;
getPlayerData(client).itemActionItem = -1;
- makePlayerStopAnimation(client);
}
// ===========================================================================
diff --git a/scripts/server/job.js b/scripts/server/job.js
index 06e0402f..b48580f0 100644
--- a/scripts/server/job.js
+++ b/scripts/server/job.js
@@ -7,6 +7,346 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Job Types
+const VRR_JOB_NONE = 0;
+const VRR_JOB_POLICE = 1;
+const VRR_JOB_MEDICAL = 2;
+const VRR_JOB_FIRE = 3;
+const VRR_JOB_BUS = 4;
+const VRR_JOB_TAXI = 5;
+const VRR_JOB_GARBAGE = 6;
+const VRR_JOB_WEAPON = 7;
+const VRR_JOB_DRUG = 8;
+const VRR_JOB_PIZZA = 9;
+const VRR_JOB_GENERIC = 10;
+
+// ===========================================================================
+
+// Job Route States
+const VRR_JOBROUTESTATE_NONE = 0; // None
+const VRR_JOBROUTESTATE_INPROGRESS = 1; // Route is in progress. Player is in between stops but not at the last one.
+const VRR_JOBROUTESTATE_LASTSTOP = 2; // Player is heading to the last stop on the route
+const VRR_JOBROUTESTATE_PAUSED = 3; // Route is paused for some reason. For police, this could be player accepted callout and once finished, patrol route will resume
+const VRR_JOBROUTESTATE_ATSTOP = 4; // For bus/trash stops that freeze player, this is the state when they're at one
+
+// ===========================================================================
+
+/**
+ * @class Representing a job's data. Loaded and saved in the database
+ */
+ class JobData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.serverId = 0;
+ this.type = VRR_JOB_NONE;
+ this.name = "Unnamed";
+ this.enabled = true;
+ this.blipModel = -1
+ this.pickupModel = -1
+ this.colour = toColour(0, 0, 0, 255);
+ this.whiteListEnabled = false;
+ this.blackListEnabled = false;
+ this.walkieTalkieFrequency = 0;
+ this.index = -1;
+ this.needsSaved = false;
+
+ this.equipment = [];
+ this.uniforms = [];
+ this.locations = [];
+ this.whiteList = [];
+ this.blackList = [];
+ this.routes = [];
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["job_id"];
+ this.serverId = dbAssoc["job_server"];
+ this.type = dbAssoc["job_type"];
+ this.name = dbAssoc["job_name"];
+ this.enabled = dbAssoc["job_enabled"];
+ this.blipModel = dbAssoc["job_blip"];
+ this.pickupModel = dbAssoc["job_pickup"];
+ this.colour = toColour(dbAssoc["job_colour_r"], dbAssoc["job_colour_g"], dbAssoc["job_colour_b"], 255);
+ this.whiteListEnabled = dbAssoc["job_wl"];
+ this.blackListEnabled = dbAssoc["job_bl"];
+ this.walkieTalkieFrequency = dbAssoc["job_walkietalkiefreq"];
+
+ this.equipment = [];
+ this.uniforms = [];
+ this.locations = [];
+ this.whiteList = [];
+ this.blackList = [];
+ this.routes = [];
+ }
+ }
+};
+
+// ===========================================================================
+
+class JobRouteData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.jobId = 0;
+ this.locationId = 0;
+ this.enabled = false;
+ this.index = -1;
+ this.jobIndex = -1;
+ this.locationIndex = -1;
+ this.needsSaved = false;
+ this.pay = 0;
+ this.vehicleColour1 = 1;
+ this.vehicleColour2 = 1;
+ this.detail = 0;
+ this.startMessage = "";
+ this.finishMessage = "";
+ this.locationArriveMessage = "";
+ this.locationNextMessage = "";
+ this.locations = [];
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["job_route_id"]);
+ this.name = toString(dbAssoc["job_route_name"]);
+ this.jobId = toInteger(dbAssoc["job_route_job"]);
+ this.locationId = toInteger(dbAssoc["job_route_job_loc"]);
+ this.enabled = intToBool(toInteger(dbAssoc["job_route_enabled"]));
+ this.pay = toInteger(dbAssoc["job_route_pay"]);
+ this.startMessage = toString(dbAssoc["job_route_start_msg"]);
+ this.finishMessage = toString(dbAssoc["job_route_finish_msg"]);
+ this.locationArriveMessage = toString(dbAssoc["job_route_loc_arrive_msg"]);
+ this.locationNextMessage = toString(dbAssoc["job_route_loc_next_msg"]);
+ this.vehicleColour1 = toInteger(dbAssoc["job_route_veh_colour1"]);
+ this.vehicleColour2 = toInteger(dbAssoc["job_route_veh_colour2"]);
+ this.detail = toInteger(dbAssoc["job_route_detail"]);
+ }
+ }
+};
+
+// ===========================================================================
+
+class JobRouteLocationData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.routeId = 0;
+ this.enabled = false;
+ this.index = -1;
+ this.jobIndex = -1;
+ this.routeIndex = -1;
+ this.needsSaved = false;
+ this.position = toVector3(0.0, 0.0, 0.0);
+ this.stopDelay = 0;
+ this.pay = 0;
+
+ if(dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["job_route_loc_id"]);
+ this.name = toString(dbAssoc["job_route_loc_name"]);
+ this.routeId = toInteger(dbAssoc["job_route_loc_route"]);
+ this.enabled = intToBool(toInteger(dbAssoc["job_route_loc_enabled"]));
+ this.position = toVector3(toFloat(dbAssoc["job_route_loc_x"]), toFloat(dbAssoc["job_route_loc_y"]), toFloat(dbAssoc["job_route_loc_z"]));
+ this.stopDelay = toInteger(dbAssoc["job_route_loc_delay"]);
+ this.pay = toInteger(dbAssoc["job_route_loc_pay"]);
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing a job equipment set's data. Loaded and saved in the database
+ */
+class JobEquipmentData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.job = 0;
+ this.name = "Unnamed";
+ this.requiredRank = 0;
+ this.enabled = false;
+ this.index = -1;
+ this.jobIndex = -1;
+ this.needsSaved = false;
+ this.items = [];
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["job_equip_id"];
+ this.job = dbAssoc["job_equip_job"];
+ this.name = dbAssoc["job_equip_name"];
+ this.requiredRank = dbAssoc["job_equip_minrank"];
+ this.enabled = dbAssoc["job_equip_enabled"];
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing a job equipment set item's data. Loaded and saved in the database
+ */
+class JobEquipmentItemData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.equipmentId = 0;
+ this.itemType = 0;
+ this.value = 0;
+ this.enabled = false;
+ this.index = -1;
+ this.jobIndex = -1;
+ this.needsSaved = false;
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["job_equip_item_id"];
+ this.equipmentId = dbAssoc["job_equip_item_equip"];
+ this.itemType = dbAssoc["job_equip_item_type"];
+ this.value = dbAssoc["job_equip_item_value"];
+ this.enabled = dbAssoc["job_equip_item_enabled"];
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class Representing a job uniform's data. Loaded and saved in the database
+ */
+class JobUniformData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.job = 0;
+ this.name = "Unnamed";
+ this.requiredRank = 0
+ this.skin = -1;
+ this.enabled = false;
+ this.index = -1;
+ this.jobIndex = -1;
+ this.needsSaved = false;
+
+ this.bodyParts = {
+ hair: [0,0],
+ head: [0,0],
+ upper: [0,0],
+ lower: [0,0],
+ };
+
+ this.bodyProps = {
+ hair: [0,0],
+ eyes: [0,0],
+ head: [0,0],
+ leftHand: [0,0],
+ rightHand: [0,0],
+ leftWrist: [0,0],
+ rightWrist: [0,0],
+ hip: [0,0],
+ leftFoot: [0,0],
+ rightFoot: [0,0],
+ };
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["job_uniform_id"];
+ this.job = dbAssoc["job_uniform_job"];
+ this.name = dbAssoc["job_uniform_name"];
+ this.requiredRank = dbAssoc["job_uniform_minrank"];
+ this.skin = dbAssoc["job_uniform_skin"];
+ this.enabled = intToBool(dbAssoc["job_uniform_enabled"]);
+
+ this.bodyParts = {
+ hair: [toInteger(dbAssoc["job_uniform_hd_part_hair_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_part_hair_texture"]) || 0],
+ head: [toInteger(dbAssoc["job_uniform_hd_part_head_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_part_head_texture"]) || 0],
+ upper: [toInteger(dbAssoc["job_uniform_hd_part_upper_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_part_upper_texture"]) || 0],
+ lower: [toInteger(dbAssoc["job_uniform_hd_part_lower_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_part_lower_texture"]) || 0],
+ };
+
+ this.bodyProps = {
+ hair: [toInteger(dbAssoc["job_uniform_hd_prop_hair_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_hair_texture"]) || 0],
+ eyes: [toInteger(dbAssoc["job_uniform_hd_prop_eyes_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_eyes_texture"]) || 0],
+ head: [toInteger(dbAssoc["job_uniform_hd_prop_head_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_head_texture"]) || 0],
+ leftHand: [toInteger(dbAssoc["job_uniform_hd_prop_lefthand_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_lefthand_texture"]) || 0],
+ rightHand: [toInteger(dbAssoc["job_uniform_hd_prop_righthand_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_righthand_texture"]) || 0],
+ leftWrist: [toInteger(dbAssoc["job_uniform_hd_prop_leftwrist_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_leftwrist_texture"]) || 0],
+ rightWrist: [toInteger(dbAssoc["job_uniform_hd_prop_rightwrist_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_rightwrist_texture"]) || 0],
+ hip: [toInteger(dbAssoc["job_uniform_hd_prop_hip_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_hip_texture"]) || 0],
+ leftFoot: [toInteger(dbAssoc["job_uniform_hd_prop_leftfoot_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_leftfoot_texture"]) || 0],
+ rightFoot: [toInteger(dbAssoc["job_uniform_hd_prop_rightfoot_model"]) || 0, toInteger(dbAssoc["job_uniform_hd_prop_rightfoot_texture"]) || 0],
+ };
+ }
+ }
+};
+
+// ===========================================================================
+
+/**
+ * @class JobLocationData Representing a job uniform's data. Loaded and saved in the database
+ */
+class JobLocationData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.jobId = 0;
+ this.position = toVector3(0.0, 0.0, 0.0);
+ this.blip = false;
+ this.pickup = false;
+ this.enabled = false;
+ this.interior = 0;
+ this.dimension = 0;
+ this.index = -1;
+ this.jobIndex = -1;
+ this.needsSaved = false;
+ this.routeCache = [];
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["job_loc_id"];
+ this.jobId = dbAssoc["job_loc_job"];
+ this.position = toVector3(dbAssoc["job_loc_pos_x"], dbAssoc["job_loc_pos_y"], dbAssoc["job_loc_pos_z"]);
+ this.blip = false;
+ this.pickup = false;
+ this.enabled = dbAssoc["job_loc_enabled"];
+ this.interior = dbAssoc["job_loc_int"];
+ this.dimension = dbAssoc["job_loc_vw"];
+ }
+ }
+};
+
+// ===========================================================================
+
+class JobWhiteListData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.job = 0;
+ this.subAccount = 0
+ this.enabled = false;
+ this.index = -1;
+ this.jobIndex = -1;
+ this.needsSaved = false;
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["job_wl_id"];
+ this.job = dbAssoc["job_wl_job"];
+ this.subAccount = dbAssoc["job_wl_sacct"]
+ this.enabled = dbAssoc["job_wl_enabled"];
+ }
+ }
+};
+
+// ===========================================================================
+
+class JobBlackListData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.job = 0;
+ this.subAccount = 0
+ this.enabled = false;
+ this.index = -1;
+ this.jobIndex = -1;
+ this.needsSaved = false;
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["job_bl_id"];
+ this.job = dbAssoc["job_bl_job"];
+ this.subAccount = dbAssoc["job_bl_sacct"]
+ this.enabled = dbAssoc["job_bl_enabled"];
+ }
+ }
+};
+
+// ===========================================================================
+
function initJobScript() {
logToConsole(LOG_INFO, "[VRR.Job]: Initializing job script ...");
logToConsole(LOG_INFO, "[VRR.Job]: Job script initialized successfully!");
@@ -24,7 +364,7 @@ function loadJobsFromDatabase() {
let dbAssoc;
if (dbConnection) {
- dbQuery = queryDatabase(dbConnection, `SELECT * FROM job_main WHERE job_enabled = 1 AND job_server = ${getServerId()}`);
+ dbQuery = queryDatabase(dbConnection, `SELECT * FROM job_main WHERE job_deleted = 0 AND job_enabled = 1 AND job_server = ${getServerId()}`);
if (dbQuery) {
if (dbQuery.numRows > 0) {
while (dbAssoc = fetchQueryAssoc(dbQuery)) {
@@ -89,7 +429,7 @@ function loadJobRoutesFromDatabase(jobDatabaseId) {
let dbAssoc;
if (dbConnection) {
- dbQuery = queryDatabase(dbConnection, `SELECT * FROM job_route WHERE job_route_enabled = 1 AND job_route_job = ${jobDatabaseId}`);
+ dbQuery = queryDatabase(dbConnection, `SELECT * FROM job_route WHERE job_route_deleted = 0 AND job_route_enabled = 1 AND job_route_job = ${jobDatabaseId}`);
if (dbQuery) {
if (dbQuery.numRows > 0) {
while (dbAssoc = fetchQueryAssoc(dbQuery)) {
@@ -119,7 +459,7 @@ function loadJobRouteLocationsFromDatabase(jobRouteId) {
let dbAssoc;
if (dbConnection) {
- dbQuery = queryDatabase(dbConnection, `SELECT * FROM job_route_loc WHERE job_route_loc_enabled = 1 AND job_route_loc_route = ${jobRouteId}`);
+ dbQuery = queryDatabase(dbConnection, `SELECT * FROM job_route_loc WHERE job_route_loc_deleted = 0 AND job_route_loc_enabled = 1 AND job_route_loc_route = ${jobRouteId}`);
if (dbQuery) {
if (dbQuery.numRows > 0) {
while (dbAssoc = fetchQueryAssoc(dbQuery)) {
@@ -148,7 +488,7 @@ function loadJobEquipmentsFromDatabase(jobDatabaseId) {
let dbAssoc;
if (dbConnection) {
- dbQuery = queryDatabase(dbConnection, "SELECT * FROM `job_equip` WHERE `job_equip_enabled` = 1 AND `job_equip_job` = " + toString(jobDatabaseId));
+ dbQuery = queryDatabase(dbConnection, `SELECT * FROM job_equip WHERE job_equip_deleted = 0 AND job_equip_enabled = 1 AND job_equip_job = ${jobDatabaseId}`);
if (dbQuery) {
if (dbQuery.numRows > 0) {
while (dbAssoc = fetchQueryAssoc(dbQuery)) {
@@ -178,7 +518,7 @@ function loadJobLocationsFromDatabase(jobDatabaseId) {
let dbAssoc;
if (dbConnection) {
- dbQuery = queryDatabase(dbConnection, "SELECT * FROM `job_loc` WHERE `job_loc_enabled` = 1 AND `job_loc_job` = " + toString(jobDatabaseId));
+ dbQuery = queryDatabase(dbConnection, `SELECT * FROM job_loc WHERE job_loc_deleted = 0 AND job_loc_enabled = 1 AND job_loc_job = ${jobDatabaseId}`);
if (dbQuery) {
if (dbQuery.numRows > 0) {
while (dbAssoc = fetchQueryAssoc(dbQuery)) {
@@ -950,8 +1290,8 @@ function reloadAllJobsCommand(command, params, client) {
Promise.resolve().then(() => {
getServerData().jobs = loadJobsFromDatabase();
- createJobLocationPickup(i, j);
- createJobLocationBlip(i, j);
+ createAllJobPickups();
+ createAllJobBlips();
});
announceAdminAction("AllJobsReloaded");
@@ -3106,6 +3446,10 @@ function replaceJobRouteStringsInMessage(messageText, jobId, jobRouteId) {
// ===========================================================================
function updateJobBlipsForPlayer(client) {
+ if (!areServerElementsSupported()) {
+ return false;
+ }
+
for (let i in getServerData().jobs) {
for (let j in getServerData().jobs[i].locations) {
if (getPlayerJob(client) == 0 || getPlayerJob(client) == i) {
diff --git a/scripts/server/keybind.js b/scripts/server/keybind.js
index e941f4d4..abe1699a 100644
--- a/scripts/server/keybind.js
+++ b/scripts/server/keybind.js
@@ -8,6 +8,32 @@
// ===========================================================================
+class KeyBindData {
+ constructor(dbAssoc = false, key = 0, commandString = "", keyState = VRR_KEYSTATE_UP) {
+ this.databaseId = 0;
+ this.key = key;
+ this.account = 0;
+ this.commandString = commandString;
+ this.whenAdded = 0;
+ this.enabled = true;
+ this.keyState = false;
+ this.index = -1;
+ this.needsSaved = false;
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["acct_hotkey_id"];
+ this.key = toInteger(dbAssoc["acct_hotkey_key"]);
+ this.account = toInteger(dbAssoc["acct_hotkey_acct"]);
+ this.commandString = dbAssoc["acct_hotkey_cmdstr"];
+ this.whenAdded = dbAssoc["acct_hotkey_when_added"];
+ this.enabled = intToBool(dbAssoc["acct_hotkey_enabled"]);
+ this.keyState = intToBool(dbAssoc["acct_hotkey_down"]);
+ }
+ }
+};
+
+// ===========================================================================
+
function initKeyBindScript() {
logToConsole(LOG_INFO, "[VRR.KeyBind]: Initializing key bind script ...");
logToConsole(LOG_INFO, "[VRR.KeyBind]: Key bind script initialized!");
diff --git a/scripts/server/misc.js b/scripts/server/misc.js
index af6a1c41..11caadcb 100644
--- a/scripts/server/misc.js
+++ b/scripts/server/misc.js
@@ -7,6 +7,45 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Pickup Types
+const VRR_PICKUP_NONE = 0;
+const VRR_PICKUP_JOB = 1;
+const VRR_PICKUP_BUSINESS_ENTRANCE = 2;
+const VRR_PICKUP_BUSINESS_EXIT = 3;
+const VRR_PICKUP_HOUSE_ENTRANCE = 4;
+const VRR_PICKUP_HOUSE_EXIT = 5;
+const VRR_PICKUP_EXIT = 6;
+
+// ===========================================================================
+
+// Blip Owner Types
+const VRR_BLIP_NONE = 0;
+const VRR_BLIP_JOB = 1;
+const VRR_BLIP_BUSINESS_ENTRANCE = 2;
+const VRR_BLIP_BUSINESS_EXIT = 3;
+const VRR_BLIP_HOUSE_ENTRANCE = 4;
+const VRR_BLIP_HOUSE_EXIT = 5;
+const VRR_BLIP_EXIT = 6;
+
+// ===========================================================================
+
+// Ped States
+const VRR_PEDSTATE_NONE = 2; // None
+const VRR_PEDSTATE_READY = 1; // Ready
+const VRR_PEDSTATE_DRIVER = 2; // Driving a vehicle
+const VRR_PEDSTATE_PASSENGER = 3; // In a vehicle as passenger
+const VRR_PEDSTATE_DEAD = 4; // Dead
+const VRR_PEDSTATE_ENTERINGPROPERTY = 5; // Entering a property
+const VRR_PEDSTATE_EXITINGPROPERTY = 6; // Exiting a property
+const VRR_PEDSTATE_ENTERINGVEHICLE = 7; // Entering a vehicle
+const VRR_PEDSTATE_EXITINGVEHICLE = 8; // Exiting a vehicle
+const VRR_PEDSTATE_BINDED = 9; // Binded by rope or handcuffs
+const VRR_PEDSTATE_TAZED = 10; // Under incapacitating effect of tazer
+const VRR_PEDSTATE_INTRUNK = 11; // In vehicle trunk
+const VRR_PEDSTATE_INITEM = 12; // In item (crate, box, etc)
+const VRR_PEDSTATE_HANDSUP = 13; // Has hands up (surrendering)
+const VRR_PEDSTATE_SPAWNING = 14; // Spawning
+
// ===========================================================================
function initMiscScript() {
@@ -218,10 +257,10 @@ function enterExitPropertyCommand(command, params, client) {
setTimeout(function () {
setPlayerInCutsceneInterior(client, closestProperty.exitCutscene);
- setPlayerPosition(client, closestProperty.exitPosition);
- setPlayerHeading(client, closestProperty.exitRotation);
setPlayerDimension(client, closestProperty.exitDimension);
setPlayerInterior(client, closestProperty.exitInterior);
+ setPlayerPosition(client, closestProperty.exitPosition);
+ setPlayerHeading(client, closestProperty.exitRotation);
setTimeout(function () {
if (isFadeCameraSupported()) {
fadeCamera(client, true, 1.0);
@@ -417,146 +456,6 @@ function listOnlineAdminsCommand(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 gpsCommand(command, params, client) {
- messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderBusinessList")));
-
- let locationType = VRR_GPS_TYPE_NONE;
- let useType = VRR_ITEM_USETYPE_NONE;
- let blipColour = "white";
-
- switch (toLowerCase(params)) {
- case "police":
- case "policestation":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_POLICE;
- break;
-
- case "hospital":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_HOSPITAL;
- break;
-
- case "job":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_JOB;
- break;
-
- case "skin":
- case "skins":
- case "clothes":
- case "player":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_BUSINESS;
- useType = VRR_ITEM_USETYPE_SKIN;
- break;
-
- case "gun":
- case "guns":
- case "weapon":
- case "weapons":
- case "wep":
- case "weps":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_BUSINESS;
- useType = VRR_ITEM_USETYPE_WEAPON;
- break;
-
- case "food":
- case "eat":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_BUSINESS;
- useType = VRR_ITEM_USETYPE_FOOD;
- break;
-
- case "drink":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_BUSINESS;
- useType = VRR_ITEM_USETYPE_DRINK;
- break;
-
- case "alcohol":
- case "booze":
- case "bar":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_BUSINESS;
- useType = VRR_ITEM_USETYPE_ALCOHOL;
- break;
-
- case "repair":
- case "carrepair":
- case "vehrepair":
- case "spray":
- case "fix":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_BUSINESS;
- useType = VRR_ITEM_USETYPE_VEHREPAIR;
- break;
-
- case "vehiclecolour":
- case "vehcolour":
- case "carcolour":
- case "colour":
- blipColour = "mediumGrey"
- locationType = VRR_GPS_TYPE_BUSINESS;
- useType = VRR_ITEM_USETYPE_VEHCOLOUR;
- break;
-
- default: {
- let itemTypeId = getItemTypeFromParams(params);
- if (getItemTypeData(itemTypeId) != false) {
- locationType = VRR_GPS_TYPE_BUSINESS;
- blipColour = "mediumGrey";
- useType = getItemTypeData(itemTypeId).useType;
- } else {
- let gameLocationId = getGameLocationFromParams(params);
- if (gameLocationId != false) {
- position = getGameConfig().locations[getGame()][gameLocationId][1]
- }
- }
- }
- }
-
- if (locationType == VRR_GPS_TYPE_NONE) {
- messagePlayerError(client, getLocaleString(client, "InvalidGPSLocation"));
- return false;
- }
-
- if (locationType == VRR_GPS_TYPE_BUSINESS) {
- let businessId = getClosestBusinessWithBuyableItemOfUseType(useType);
- if (!businessId) {
- messagePlayerError(client, getLocaleString(client, "NoBusinessWithItemType"));
- return false;
- }
-
- if (!getBusinessData(businessId)) {
- messagePlayerError(client, getLocaleString(client, "NoBusinessWithItemType"));
- return false;
- }
-
- hideAllBlipsForPlayerGPS(client);
- blinkGenericGPSBlipForPlayer(client, getBusinessData(businessId).entrancePosition, getBusinessData(businessId).entranceBlipModel, getColourByType(blipColour), 10);
- messagePlayerSuccess(client, "Look for the blinking icon on your mini map");
- }
-
- if (locationType == VRR_GPS_TYPE_GAMELOC) {
- hideAllBlipsForPlayerGPS(client);
- blinkGenericGPSBlipForPlayer(client, position, 0, getColourByType(blipColour), 10);
- messagePlayerSuccess(client, "Look for the blinking icon on your mini map");
- return true;
- }
-}
-
-// ===========================================================================
-
/**
* This is a command handler function.
*
@@ -881,9 +780,9 @@ function deletePlayerBlip(client) {
return false;
}
- if (getPlayerData(client).playerBlip != false) {
- destroyElement(getPlayerData(client).playerBlip);
- getPlayerData(client).playerBlip = false;
+ if (getPlayerData(client).playerBlip != null) {
+ deleteGameElement(getPlayerData(client).playerBlip);
+ getPlayerData(client).playerBlip = null;
}
}
diff --git a/scripts/server/netevents.js b/scripts/server/netevents.js
index c3f200b9..f2c61dd3 100644
--- a/scripts/server/netevents.js
+++ b/scripts/server/netevents.js
@@ -7,6 +7,124 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Return-To types (for when a player is teleported)
+const VRR_RETURNTO_TYPE_NONE = 0; // "Return to" data is invalid
+const VRR_RETURNTO_TYPE_ADMINGET = 1; // "Return to" data is from admin teleporting
+const VRR_RETURNTO_TYPE_SKINSELECT = 2; // "Return to" data is from skin select
+
+// ===========================================================================
+
+/**
+ * @class Representing extra data for a client
+ */
+class ClientData {
+ constructor(client, accountData, subAccounts) {
+ /** @member {AccountData} accountData */
+ this.accountData = accountData;
+
+ /** @member {Array.} subAccounts */
+ this.subAccounts = subAccounts; // Characters
+ this.client = client;
+ this.currentSubAccount = -1;
+ this.loggedIn = false;
+ this.index = -1;
+ this.connectTime = 0;
+ this.clientVersion = "0.0.0";
+ this.loginAttemptsRemaining = 3;
+ this.afk = false;
+
+ this.jobRoute = -1;
+ this.jobRouteLocation = -1;
+ this.jobRouteVehicle = false;
+
+ this.spawned = false;
+
+ this.rentingVehicle = false;
+ this.buyingVehicle = false;
+
+ this.lastVehicle = false;
+
+ this.returnToJobVehicleTick = 0;
+ this.returnToJobVehicleTimer = null;
+
+ this.switchingCharacter = false;
+
+ this.tutorialStep = -1;
+ this.tutorialItem = null;
+ this.tutorialVehicle = null;
+
+ this.hotBarItems = new Array(9).fill(-1);
+ this.activeHotBarSlot = -1;
+ this.toggleUseItem = false;
+
+ this.jobLockerCache = new Array(9).fill(-1);
+ this.jobEquipmentCache = [];
+ this.jobUniform = 0;
+
+ this.itemActionState = VRR_ITEM_ACTION_NONE;
+ this.itemActionItem = -1;
+
+ this.alcoholLevel = 0;
+
+ this.pedState = VRR_PEDSTATE_NONE;
+ this.promptType = VRR_PROMPT_NONE;
+
+ this.businessOrderAmount = 0;
+ this.businessOrderBusiness = -1;
+ this.businessOrderItem = -1;
+ this.businessOrderValue = -1;
+
+ this.syncPosition = null;
+ this.syncHeading = null;
+ this.syncVehicle = null;
+ this.syncVehicleSeat = null;
+
+ this.twoFactorAuthenticationState = VRR_2FA_STATE_NONE;
+ this.twoFactorAuthenticationCode = 0;
+
+ this.payDayAmount = 0;
+ this.payDayTickStart = 0;
+
+ this.creatingCharacter = false;
+ this.creatingCharacterSkin = -1;
+
+ this.streamingRadioStation = -1;
+ this.streamingRadioElement = false;
+
+ this.returnToPosition = null;
+ this.returnToHeading = null;
+ this.returnToInterior = null;
+ this.returnToDimension = null;
+ this.returnToHouse = null;
+ this.returnToBusiness = null;
+ this.returnToType = VRR_RETURNTO_TYPE_NONE;
+
+ this.changingCharacterName = false;
+ this.currentPickup = false;
+ this.usingSkinSelect = false;
+ this.keyBinds = [];
+ this.sessionId = 0;
+ this.incomingDamageMultiplier = 1;
+ this.weaponDamageEvent = VRR_WEAPON_DAMAGE_EVENT_NORMAL;
+ this.currentAnimation = -1;
+ this.currentAnimationPositionOffset = false;
+ this.currentAnimationPositionReturnTo = false;
+ this.animationStart = 0;
+ this.animationForced = false;
+ this.passwordResetState = VRR_RESETPASS_STATE_NONE;
+ this.passwordResetCode = "";
+ this.lastJobVehicle = null;
+ this.health = 100;
+ this.locale = 0;
+ this.enteringVehicle = null;
+ this.customDisconnectReason = "";
+ this.interiorCutscene = -1;
+ this.playerBlip = null;
+ }
+};
+
+// ===========================================================================
+
function initNetworkEventsScript() {
logToConsole(LOG_DEBUG, "[VRR.Client]: Initializing client script ...");
addAllNetworkEventHandlers();
diff --git a/scripts/server/npc.js b/scripts/server/npc.js
index bb646408..0e061bcb 100644
--- a/scripts/server/npc.js
+++ b/scripts/server/npc.js
@@ -7,6 +7,198 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// NPC Trigger Condition Match Types
+const VRR_NPC_COND_MATCH_NONE = 0; // None (invalid)
+const VRR_NPC_COND_MATCH_EQ = 1; // Must be equal to
+const VRR_NPC_COND_MATCH_GT = 2; // Must be greater than
+const VRR_NPC_COND_MATCH_LT = 3; // Must be less than
+const VRR_NPC_COND_MATCH_GTEQ = 4; // Must be greater than or equal to
+const VRR_NPC_COND_MATCH_LTEQ = 5; // Must be less than or equal to
+const VRR_NPC_COND_MATCH_CONTAINS = 6; // Must contain string (case insensitive)
+const VRR_NPC_COND_MATCH_CONTAINS_CASE = 7; // Must contain string (case sensitive)
+const VRR_NPC_COND_MATCH_EXACT = 8; // Must match string exactly (case insensitive)
+const VRR_NPC_COND_MATCH_EXACT_CASE = 9; // Must match string exactly (case insensitive)
+
+// NPC Owner Types
+const VRR_NPC_OWNER_NONE = 0; // Not owned
+const VRR_NPC_OWNER_PLAYER = 1; // Owned by a player (character/subaccount)
+const VRR_NPC_OWNER_JOB = 2; // Owned by a job
+const VRR_NPC_OWNER_CLAN = 3; // Owned by a clan
+const VRR_NPC_OWNER_FACTION = 4; // Owned by a faction (not used at the moment)
+const VRR_NPC_OWNER_PUBLIC = 5; // Public NPC. Anybody can do stuff with it.
+const VRR_NPC_OWNER_BIZ = 6; // Owned by a business
+
+// ===========================================================================
+
+class NPCData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.serverId = 0;
+ this.name = "NPC";
+ this.skin = 0;
+ this.cash = 0;
+ this.position = toVector3(0.0, 0.0, 0.0);
+ this.rotation = toVector3(0.0, 0.0, 0.0);
+ this.scale = toVector3(1.0, 1.0, 1.0);
+ this.heading = 0.0;
+ this.clan = 0;
+ this.isWorking = false;
+ this.jobUniform = this.skin;
+ this.lastJobVehicle = null;
+ this.job = 0;
+ this.weapons = [];
+ this.interior = 0;
+ this.dimension = 0;
+ this.walkStyle = 0;
+ this.fightStyle = 0;
+ this.health = 100;
+ this.armour = 100;
+ 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_NPC_OWNER_NONE;
+ this.ownerId = 0;
+
+ this.bodyParts = {
+ hair: [0, 0],
+ head: [0, 0],
+ upper: [0, 0],
+ lower: [0, 0],
+ };
+
+ this.bodyProps = {
+ hair: [0, 0],
+ eyes: [0, 0],
+ head: [0, 0],
+ leftHand: [0, 0],
+ rightHand: [0, 0],
+ leftWrist: [0, 0],
+ rightWrist: [0, 0],
+ hip: [0, 0],
+ leftFoot: [0, 0],
+ rightFoot: [0, 0],
+ };
+
+ this.triggers = [];
+
+ if (dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["npc_id"]);
+ this.serverId = toInteger(dbAssoc["npc_server"]);
+ 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"]));
+ this.rotation = toVector3(toFloat(dbAssoc["npc_rot_x"]), toFloat(dbAssoc["npc_rot_y"]), toFloat(dbAssoc["npc_rot_z"]));
+ this.scale = toVector3(toFloat(dbAssoc["npc_scale_x"]), toFloat(dbAssoc["npc_scale_y"]), toFloat(dbAssoc["npc_scale_z"]));
+ this.heading = toFloat(dbAssoc["npc_rot_z"]);
+ this.lastLogin = toInteger(dbAssoc["npc_when_lastlogin"]);
+ this.rank = toInteger(dbAssoc["npc_rank"]);
+ this.title = toInteger(dbAssoc["npc_title"]);
+ this.job = toInteger(dbAssoc["npc_job"]);
+ this.interior = toInteger(dbAssoc["npc_int"]);
+ this.dimension = toInteger(dbAssoc["npc_vw"]);
+ this.walkStyle = toInteger(dbAssoc["npc_walkstyle"]);
+ this.fightStyle = toInteger(dbAssoc["npc_fightstyle"]);
+ this.health = toInteger(dbAssoc["npc_health"]);
+ this.armour = toInteger(dbAssoc["npc_armour"]);
+ this.typeFlags = toInteger(dbAssoc["npc_type_flags"]);
+ 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],
+ head: [toInteger(dbAssoc["npc_hd_part_head_model"]) || 0, toInteger(dbAssoc["npc_hd_part_head_texture"]) || 0],
+ upper: [toInteger(dbAssoc["npc_hd_part_upper_model"]) || 0, toInteger(dbAssoc["npc_hd_part_upper_texture"]) || 0],
+ lower: [toInteger(dbAssoc["npc_hd_part_lower_model"]) || 0, toInteger(dbAssoc["npc_hd_part_lower_texture"]) || 0],
+ };
+
+ this.bodyProps = {
+ hair: [toInteger(dbAssoc["npc_hd_prop_hair_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_hair_texture"]) || 0],
+ eyes: [toInteger(dbAssoc["npc_hd_prop_eyes_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_eyes_texture"]) || 0],
+ head: [toInteger(dbAssoc["npc_hd_prop_head_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_head_texture"]) || 0],
+ leftHand: [toInteger(dbAssoc["npc_hd_prop_lefthand_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_lefthand_texture"]) || 0],
+ rightHand: [toInteger(dbAssoc["npc_hd_prop_righthand_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_righthand_texture"]) || 0],
+ leftWrist: [toInteger(dbAssoc["npc_hd_prop_leftwrist_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_leftwrist_texture"]) || 0],
+ rightWrist: [toInteger(dbAssoc["npc_hd_prop_rightwrist_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_rightwrist_texture"]) || 0],
+ hip: [toInteger(dbAssoc["npc_hd_prop_hip_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_hip_texture"]) || 0],
+ leftFoot: [toInteger(dbAssoc["npc_hd_prop_leftfoot_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_leftfoot_texture"]) || 0],
+ rightFoot: [toInteger(dbAssoc["npc_hd_prop_rightfoot_model"]) || 0, toInteger(dbAssoc["npc_hd_prop_rightfoot_texture"]) || 0],
+ };
+ }
+ }
+};
+
+// ===========================================================================
+
+class NPCTriggerData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.npcId = 0;
+ this.index = 0;
+ this.npc = 0;
+ this.npcIndex = -1;
+ this.triggerType = 0;
+ this.conditions = [];
+ this.responses = [];
+
+ if (dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["npc_trig_id"]);
+ this.npc = toInteger(dbAssoc["npc_trig_npc"]);
+ this.triggerType = toInteger(dbAssoc["npc_trig_type"]);
+ }
+ }
+};
+
+// ===========================================================================
+
+class NPCTriggerConditionData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.triggerId = 0;
+ this.index = 0;
+ this.triggerIndex = 0;
+ this.conditionType = 0;
+ this.conditionValue = false;
+ this.matchType = false;
+
+ if (dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["npc_trig_cond_id"]);
+ this.npc = toInteger(dbAssoc["npc_trig_cond_trig"]);
+ this.conditionType = toInteger(dbAssoc["npc_trig_cond_type"]);
+ this.conditionValue = toInteger(dbAssoc["npc_trig_cond_val"]);
+ this.matchType = toInteger(dbAssoc["npc_trig_cond_val"]);
+ }
+ }
+};
+
+// ===========================================================================
+
+class NPCTriggerResponseData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.triggerId = 0;
+ this.index = 0;
+ this.triggerIndex = 0;
+ this.responseType = 0;
+ this.responseValue = false;
+
+ if (dbAssoc) {
+ this.databaseId = toInteger(dbAssoc["npc_trig_resp_id"]);
+ this.npc = toInteger(dbAssoc["npc_trig_resp_trig"]);
+ this.responseType = toInteger(dbAssoc["npc_trig_resp_type"]);
+ this.responseValue = toInteger(dbAssoc["npc_trig_resp_val"]);
+ }
+ }
+};
+
+// ===========================================================================
+
function initNPCScript() {
logToConsole(LOG_INFO, "[VRR.NPC]: Initializing NPC script ...");
logToConsole(LOG_INFO, "[VRR.NPC]: NPC script initialized successfully!");
@@ -19,7 +211,7 @@ function initNPCScript() {
* @return {NPCData} The NPC's data (class instancee)
*/
function getNPCData(npcId) {
- if(typeof getServerData().npcs[npcId] != "undefined") {
+ if (typeof getServerData().npcs[npcId] != "undefined") {
return getServerData().npcs[npcId];
}
return false;
@@ -28,14 +220,14 @@ function getNPCData(npcId) {
// ===========================================================================
function createNPCCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let skinIndex = getSkinModelIndexFromParams(params);
- if(!skinIndex) {
+ if (!skinIndex) {
messagePlayerError(client, getLocaleString(client, "InvalidSkin"));
return false;
}
@@ -53,11 +245,11 @@ function loadNPCsFromDatabase() {
let dbConnection = connectToDatabase();
let tempNPCs = [];
let dbAssoc;
- if(dbConnection) {
+ if (dbConnection) {
let dbQueryString = `SELECT * FROM npc_main WHERE npc_server = ${getServerId()} AND npc_enabled = 1`;
let dbQuery = queryDatabase(dbConnection, dbQueryString);
- if(dbQuery) {
- while(dbAssoc = fetchQueryAssoc(dbQuery)) {
+ if (dbQuery) {
+ while (dbAssoc = fetchQueryAssoc(dbQuery)) {
let tempNPCData = new NPCData(dbAssoc);
tempNPCData.triggers = loadNPCTriggersFromDatabase(tempNPCData.databaseId);
tempNPCs.push(tempNPCData);
@@ -78,11 +270,11 @@ function loadNPCTriggersFromDatabase(npcDatabaseId) {
let dbConnection = connectToDatabase();
let tempNPCTriggers = [];
let dbAssoc;
- if(dbConnection) {
+ if (dbConnection) {
let dbQueryString = `SELECT * FROM npc_trig WHERE npc_trig_npc = ${npcDatabaseId} AND npc_trig_enabled = 1`;
let dbQuery = queryDatabase(dbConnection, dbQueryString);
- if(dbQuery) {
- while(dbAssoc = fetchQueryAssoc(dbQuery)) {
+ if (dbQuery) {
+ while (dbAssoc = fetchQueryAssoc(dbQuery)) {
let tempNPCTriggerData = new NPCTriggerData(dbAssoc);
tempNPCTriggerData.conditions = loadNPCTriggerConditionsFromDatabase(tempNPCTriggerData.databaseId);
tempNPCTriggerData.responses = loadNPCTriggerResponsesFromDatabase(tempNPCTriggerData.databaseId);
@@ -104,11 +296,11 @@ function loadNPCTriggerConditionsFromDatabase(npcTriggerDatabaseId) {
let dbConnection = connectToDatabase();
let tempNPCTriggerConditions = [];
let dbAssoc;
- if(dbConnection) {
+ if (dbConnection) {
let dbQueryString = `SELECT * FROM npc_cond WHERE npc_cond_trig = ${npcTriggerDatabaseId} AND npc_cond_enabled = 1`;
let dbQuery = queryDatabase(dbConnection, dbQueryString);
- if(dbQuery) {
- while(dbAssoc = fetchQueryAssoc(dbQuery)) {
+ if (dbQuery) {
+ while (dbAssoc = fetchQueryAssoc(dbQuery)) {
let tempNPCTriggerConditionData = new NPCTriggerConditionData(dbAssoc);
tempNPCTriggerConditions.push(tempNPCTriggerConditionData);
}
@@ -128,11 +320,11 @@ function loadNPCTriggerResponsesFromDatabase(npcTriggerDatabaseId) {
let dbConnection = connectToDatabase();
let tempNPCTriggerResponses = [];
let dbAssoc;
- if(dbConnection) {
+ if (dbConnection) {
let dbQueryString = `SELECT * FROM npc_resp WHERE npc_resp_trig = ${npcTriggerDatabaseId} AND npc_resp_enabled = 1`;
let dbQuery = queryDatabase(dbConnection, dbQueryString);
- if(dbQuery) {
- while(dbAssoc = fetchQueryAssoc(dbQuery)) {
+ if (dbQuery) {
+ while (dbAssoc = fetchQueryAssoc(dbQuery)) {
let tempNPCTriggerResponseData = new NPCTriggerResponseData(dbAssoc);
tempNPCTriggerResponses.push(tempNPCTriggerResponseData);
}
@@ -148,11 +340,11 @@ function loadNPCTriggerResponsesFromDatabase(npcTriggerDatabaseId) {
// ===========================================================================
function saveAllNPCsToDatabase() {
- if(getServerConfig().devServer) {
+ if (getServerConfig().devServer) {
return false;
}
- for(let i in getServerData().npcs) {
+ for (let i in getServerData().npcs) {
saveNPCToDatabase(i);
}
}
@@ -160,34 +352,34 @@ function saveAllNPCsToDatabase() {
// ===========================================================================
function saveNPCToDatabase(npcDataId) {
- if(getServerConfig().devServer) {
+ 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) == false) {
+ 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) {
+ if (tempNPCData.databaseId == -1) {
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} is a temp NPC. Aborting save ...`);
return false;
}
- if(!tempNPCData.needsSaved) {
+ if (!tempNPCData.needsSaved) {
logToConsole(LOG_VERBOSE, `[VRR.NPC]: NPC ${npcDataId} hasn't changed data. Aborting save ...`);
return false;
}
logToConsole(LOG_VERBOSE, `[VRR.NPC]: Saving NPC ${tempNPCData.databaseId} to database ...`);
let dbConnection = connectToDatabase();
- if(dbConnection) {
- if(tempNPCData.ped != false) {
- if(!tempNPCData.spawnLocked) {
- if(areServerElementsSupported()) {
+ if (dbConnection) {
+ if (tempNPCData.ped != false) {
+ if (!tempNPCData.spawnLocked) {
+ if (areServerElementsSupported()) {
tempNPCData.position = tempNPCData.ped.position;
tempNPCData.heading = tempNPCData.ped.heading;
} else {
@@ -224,7 +416,7 @@ function saveNPCToDatabase(npcDataId) {
];
let dbQuery = null;
- if(tempNPCData.databaseId == 0) {
+ if (tempNPCData.databaseId == 0) {
let queryString = createDatabaseInsertQuery("npc_main", data);
dbQuery = queryDatabase(dbConnection, queryString);
tempNPCData.databaseId = getDatabaseInsertId(dbConnection);
@@ -247,19 +439,19 @@ function saveNPCToDatabase(npcDataId) {
// ===========================================================================
function setNPCDataIndexes() {
- for(let i in getServerData().npcs) {
+ for (let i in getServerData().npcs) {
getServerData().npcs[i].index = i;
- for(let j in getServerData().npcs[i].triggers) {
+ for (let j in getServerData().npcs[i].triggers) {
getServerData().npcs[i].triggers[j].index = j;
getServerData().npcs[i].triggers[j].npcIndex = i;
- for(let k in getServerData().npcs[i].triggers[j].conditions) {
+ for (let k in getServerData().npcs[i].triggers[j].conditions) {
getServerData().npcs[i].triggers[j].conditions[k].index = k;
getServerData().npcs[i].triggers[j].conditions[m].triggerIndex = j;
}
- for(let m in getServerData().npcs[i].triggers[j].responses) {
+ for (let m in getServerData().npcs[i].triggers[j].responses) {
getServerData().npcs[i].triggers[j].responses[m].index = m;
getServerData().npcs[i].triggers[j].responses[m].triggerIndex = j;
}
@@ -272,12 +464,12 @@ function setNPCDataIndexes() {
function spawnNPC(npcIndex) {
let npcData = getNPCData(npcIndex);
let ped = createGamePed(npcData.skin, npcData.position, npcData.rotation.z);
- if(ped) {
+ if (ped) {
getNPCData(npcIndex).ped = ped;
setEntityData(ped, "vrr.dataIndex", npcIndex, false);
- if(npcData.animationName != "") {
+ if (npcData.animationName != "") {
let animationId = getAnimationFromParams(npcData.animationName);
- if(animationId != false) {
+ if (animationId != false) {
setEntityData(ped, "vrr.anim", animationId, true);
}
}
@@ -289,7 +481,7 @@ function spawnNPC(npcIndex) {
// ===========================================================================
function spawnAllNPCs() {
- for(let i in getServerData().npcs) {
+ for (let i in getServerData().npcs) {
spawnNPC(i);
}
}
@@ -297,9 +489,9 @@ function spawnAllNPCs() {
// ===========================================================================
function deleteNPCCommand(command, params, client) {
- let closestNPC = getClosestNPC(getPlayerPosition(client));
+ let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
- if(!getNPCData(closestNPC)) {
+ if (!getNPCData(closestNPC)) {
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
return false;
}
@@ -315,8 +507,8 @@ function deleteNPCCommand(command, params, client) {
function deleteNPC(npcId) {
quickDatabaseQuery(`DELETE FROM npc_main WHERE npc_id=${getNPCData(npcId).databaseId}`);
- if(getNPCData(npcId)) {
- if(getNPCData(npcId).ped != false) {
+ if (getNPCData(npcId)) {
+ if (getNPCData(npcId).ped != false) {
deleteEntity(getNPCData(npcId).ped);
}
getServerData().npcs.splice(npcId, 1);
@@ -328,27 +520,27 @@ function deleteNPC(npcId) {
// ===========================================================================
function setNPCAnimationCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
- let closestNPC = getClosestNPC(getPlayerPosition(client));
+ let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
let animationId = getAnimationFromParams(getParam(params, " ", 1));
let animationPositionOffset = 1;
- if(!getNPCData(closestNPC)) {
+ if (!getNPCData(closestNPC)) {
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
return false;
}
- if(!getAnimationData(animationId)) {
+ if (!getAnimationData(animationId)) {
messagePlayerError(client, getLocaleString(client, "InvalidAnimation"));
return false;
}
- if(areThereEnoughParams(params, 2, " ")) {
- if(toInteger(animationPositionOffset) < 0 || toInteger(animationPositionOffset) > 3) {
+ if (areThereEnoughParams(params, 2, " ")) {
+ if (toInteger(animationPositionOffset) < 0 || toInteger(animationPositionOffset) > 3) {
messagePlayerError(client, getLocaleString(client, "InvalidAnimationDistance"));
return false;
}
@@ -365,15 +557,15 @@ function setNPCAnimationCommand(command, params, client) {
// ===========================================================================
function setNPCNameCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
- let closestNPC = getClosestNPC(getPlayerPosition(client));
+ let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
let name = params;
- if(!getNPCData(closestNPC)) {
+ if (!getNPCData(closestNPC)) {
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
return false;
}
@@ -389,9 +581,9 @@ function setNPCNameCommand(command, params, client) {
// ===========================================================================
function toggleNPCLookAtClosestPlayerCommand(command, params, client) {
- let closestNPC = getClosestNPC(getPlayerPosition(client));
+ let closestNPC = getClosestNPC(getPlayerPosition(client), getPlayerDimension(client), getPlayerInterior(client));
- if(!getNPCData(closestNPC)) {
+ if (!getNPCData(closestNPC)) {
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
return false;
}
@@ -406,14 +598,14 @@ function toggleNPCLookAtClosestPlayerCommand(command, params, client) {
// ===========================================================================
function getNPCInfoCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let closestNPC = getClosestNPC(getPlayerPosition(client));
- if(!getNPCData(closestNPC)) {
+ if (!getNPCData(closestNPC)) {
messagePlayerError(client, getLocaleString(client, "InvalidNPC"));
return false;
}
@@ -422,29 +614,29 @@ function getNPCInfoCommand(command, params, client) {
let ownerName = "Nobody";
let ownerType = "None";
- switch(npcData.ownerType) {
- case VRR_NPCOWNER_CLAN:
+ switch (npcData.ownerType) {
+ case VRR_NPC_OWNER_CLAN:
ownerName = getClanData(getClanIdFromDatabaseId(npcData.ownerId)).name;
ownerType = "clan";
break;
- case VRR_NPCOWNER_JOB:
+ case VRR_NPC_OWNER_JOB:
ownerName = getJobData(getJobIdFromDatabaseId(npcData.ownerId)).name;
ownerType = "job";
break;
- case VRR_NPCOWNER_PLAYER:
+ case VRR_NPC_OWNER_PLAYER:
let subAccountData = loadSubAccountFromId(npcData.ownerId);
ownerName = `${subAccountData.firstName} ${subAccountData.lastName} [${subAccountData.databaseId}]`;
ownerType = "player";
break;
- case VRR_NPCOWNER_BIZ:
+ case VRR_NPC_OWNER_BIZ:
ownerName = getBusinessData(getBusinessIdFromDatabaseId(npcData.ownerId)).name;
ownerType = "business";
break;
- case VRR_NPCOWNER_PUBLIC:
+ case VRR_NPC_OWNER_PUBLIC:
ownerName = "Nobody";
ownerType = "public";
break;
@@ -464,22 +656,19 @@ function getNPCInfoCommand(command, params, client) {
messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderNPCInfo")));
let chunkedList = splitArrayIntoChunks(stats, 6);
- for(let i in chunkedList) {
+ for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
}
// ===========================================================================
-function getClosestNPC(position) {
+function getClosestNPC(position, interior, dimension) {
let npcs = getServerData().npcs;
- let interior = getPlayerInterior(client);
- let dimension = getPlayerDimension(client);
-
let closest = 0;
- for(let i in npcs) {
- if(getDistance(npcs[i].ped.position, position) < getDistance(npcs[closest].ped.position, position) && npcs[closest].interior == interior && npcs[closest].dimension == dimension) {
+ for (let i in npcs) {
+ if (getDistance(npcs[i].ped.position, position) < getDistance(npcs[closest].ped.position, position) && npcs[closest].interior == interior && npcs[closest].dimension == dimension) {
closest = i;
}
}
@@ -502,9 +691,9 @@ function createNPC(skinIndex, position, heading, interior, dimension) {
let npcIndex = getServerData().npcs.push(tempNPCData);
setNPCDataIndexes();
- spawnNPC(npcIndex-1);
+ spawnNPC(npcIndex - 1);
- return npcIndex-1;
+ return npcIndex - 1;
}
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc/biker.js b/scripts/server/npc/biker.js
deleted file mode 100644
index 42bd940b..00000000
--- a/scripts/server/npc/biker.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: biker.js
-// DESC: Provides biker NPC interaction and functionality
-// TYPE: Server (JavaScript)
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc/drugdealer.js b/scripts/server/npc/drugdealer.js
deleted file mode 100644
index c9fffbe2..00000000
--- a/scripts/server/npc/drugdealer.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: drugdealer.js
-// DESC: Provides drug dealer NPC interaction and functionality
-// TYPE: Server (JavaScript)
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc/firefighter.js b/scripts/server/npc/firefighter.js
deleted file mode 100644
index 76b6df10..00000000
--- a/scripts/server/npc/firefighter.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: firefighter.js
-// DESC: Provides firefighter NPC interaction and functionality
-// TYPE: Server (JavaScript)
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc/gang.js b/scripts/server/npc/gang.js
deleted file mode 100644
index 1f26972d..00000000
--- a/scripts/server/npc/gang.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: gangsta.js
-// DESC: Provides street gang/hoodlum NPC interaction and functionality
-// TYPE: Server (JavaScript)
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc/mafia.js b/scripts/server/npc/mafia.js
deleted file mode 100644
index b9e814cc..00000000
--- a/scripts/server/npc/mafia.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: mafia.js
-// DESC: Provides mafia/mafioso NPC interaction and functionality
-// TYPE: Server (JavaScript)
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc/normal.js b/scripts/server/npc/normal.js
deleted file mode 100644
index 52b15464..00000000
--- a/scripts/server/npc/normal.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: normal.js
-// DESC: Provides normal/generic civilian NPC interaction and functionality
-// TYPE: Server (JavaScript)
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc/paramedic.js b/scripts/server/npc/paramedic.js
deleted file mode 100644
index 1571a464..00000000
--- a/scripts/server/npc/paramedic.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: paramedic.js
-// DESC: Provides paramedic NPC interaction and functionality
-// TYPE: Server (JavaScript)
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc/police.js b/scripts/server/npc/police.js
deleted file mode 100644
index 5f878909..00000000
--- a/scripts/server/npc/police.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: police.js
-// DESC: Provides police officer NPC interaction and functionality
-// TYPE: Server (JavaScript)
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/npc/taxi.js b/scripts/server/npc/taxi.js
deleted file mode 100644
index df95c91d..00000000
--- a/scripts/server/npc/taxi.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: taxi.js
-// DESC: Provides taxi driver NPC interaction and functionality
-// TYPE: Server (JavaScript)
-// ===========================================================================
-
-function attemptToSignalToNearbyTaxi(client) {
- if(!isPlayerLoggedIn(client)) {
- return false;
- }
-
- if(!isPlayerSpawned(client)) {
- return false;
- }
-
- let nearbyTaxis = getElementsByType(ELEMENT_VEHICLE).filter((v) > getPlayerPosition(client).distance(v.position) <= 15 && isTaxiVehicle(v));
-
- let closestTaxi = nearbyTaxis.reduce((i, j) => (i.position.distance(pos) < j.position.distance(pos)) ? i : j);
- if(!closestTaxi.getOccupant(0).isType(ELEMENT_PLAYER)) {
- setVehicleCruiseSpeed(closestTaxi, 0.0);
- setVehicleLocked(closestTaxi, false);
- }
-}
-
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/radio.js b/scripts/server/radio.js
index 38b9f9b0..00f0de01 100644
--- a/scripts/server/radio.js
+++ b/scripts/server/radio.js
@@ -7,6 +7,27 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+class RadioStationData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.name = "";
+ this.url = "";
+ this.genre = "";
+ this.codec = "";
+ this.index = -1;
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["radio_id"];
+ this.name = dbAssoc["radio_name"];
+ this.url = dbAssoc["radio_url"];
+ this.genre = dbAssoc["radio_genre"];
+ this.codec = dbAssoc["radio_codec"];
+ }
+ }
+};
+
+// ===========================================================================
+
function initRadioScript() {
logToConsole(LOG_INFO, "[VRR.Radio]: Initializing radio script ...");
logToConsole(LOG_INFO, "[VRR.Radio]: Radio script initialized successfully!");
diff --git a/scripts/server/staff.js b/scripts/server/staff.js
index ea12b450..6da241e7 100644
--- a/scripts/server/staff.js
+++ b/scripts/server/staff.js
@@ -24,20 +24,20 @@ function initStaffScript() {
*
*/
function kickClientCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
// Prevent kicking admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
- if(!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
+ if (!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
messagePlayerError(client, "You cannot kick this person!");
return false;
}
@@ -45,7 +45,8 @@ function kickClientCommand(command, params, client) {
//getPlayerData(targetClient).customDisconnectReason = reason;
announceAdminAction(`PlayerKicked`, getPlayerName(targetClient));
- targetdisconnectPlayer(client);
+ getPlayerData(targetClient).customDisconnectReason = `Kicked - ${reason}`;
+ disconnectPlayer(targetClient);
}
// ===========================================================================
@@ -60,7 +61,7 @@ function kickClientCommand(command, params, client) {
*
*/
function setStaffTitleCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -69,14 +70,14 @@ function setStaffTitleCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let staffTitle = splitParams.slice(1).join(" ");
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
// Prevent setting titles on staff with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
- if(!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
+ if (!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
messagePlayerError(client, "You cannot set this person's staff title!");
return false;
}
@@ -85,7 +86,6 @@ 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(targetClient, `${getPlayerName(client)} set your staff title to ${staffTitle}`);
- //targetdisconnectPlayer(client);
}
// ===========================================================================
@@ -100,20 +100,20 @@ function setStaffTitleCommand(command, params, client) {
*
*/
function muteClientCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
// Prevent muting admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
- if(!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
+ if (!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
messagePlayerError(client, "You cannot mute this person!");
return false;
}
@@ -135,20 +135,20 @@ function muteClientCommand(command, params, client) {
*
*/
function unMuteClientCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
// Prevent unmuting admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
- if(!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
+ if (!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
messagePlayerError(client, "You cannot unmute this person!");
return false;
}
@@ -170,20 +170,20 @@ function unMuteClientCommand(command, params, client) {
*
*/
function freezeClientCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
// Prevent freeze admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
- if(!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
+ if (!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
messagePlayerError(client, "You cannot freeze this person!");
return false;
}
@@ -206,20 +206,20 @@ function freezeClientCommand(command, params, client) {
*
*/
function unFreezeClientCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
// Prevent unfreezing admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
- if(!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
+ if (!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
messagePlayerError(client, "You cannot freeze this person!");
return false;
}
@@ -242,13 +242,13 @@ function unFreezeClientCommand(command, params, client) {
*
*/
function gotoPlayerCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -283,13 +283,13 @@ function gotoPlayerCommand(command, params, client) {
*
*/
function getPlayerGeoIPInformationCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -313,13 +313,13 @@ function getPlayerGeoIPInformationCommand(command, params, client) {
*
*/
function getPlayerIPInformationCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -339,12 +339,12 @@ function getPlayerIPInformationCommand(command, params, client) {
*
*/
function gotoVehicleCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
- if(typeof getServerData().vehicles[toInteger(params)] == "undefined") {
+ if (typeof getServerData().vehicles[toInteger(params)] == "undefined") {
messagePlayerError(client, "That vehicle ID doesn't exist!");
}
@@ -378,16 +378,16 @@ function gotoVehicleCommand(command, params, client) {
*
*/
function getVehicleCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
- if(typeof getServerData().vehicles[toInteger(params)-1] == "undefined") {
+ if (typeof getServerData().vehicles[toInteger(params) - 1] == "undefined") {
messagePlayerError(client, "That vehicle ID doesn't exist!");
}
- let vehicle = getServerData().vehicles[toInteger(params)-1].vehicle;
+ let vehicle = getServerData().vehicles[toInteger(params) - 1].vehicle;
setElementPosition(vehicle, getPosInFrontOfPos(getPlayerPosition(client), fixAngle(getPlayerHeading(client)), 5.0));
setElementInterior(vehicle, getPlayerInterior(client));
@@ -410,14 +410,14 @@ function getVehicleCommand(command, params, client) {
function warpIntoVehicleCommand(command, params, client) {
let vehicle = getClosestVehicle(getPlayerPosition(client));
- if(areParamsEmpty(params)) {
- if(!getPlayerVehicle(client) && getDistance(getVehiclePosition(vehicle), getPlayerPosition(client)) > getGlobalConfig().vehicleLockDistance) {
+ if (areParamsEmpty(params)) {
+ if (!getPlayerVehicle(client) && getDistance(getVehiclePosition(vehicle), getPlayerPosition(client)) > getGlobalConfig().vehicleLockDistance) {
messagePlayerError(client, getLocaleString(client, "MustBeInOrNearVehicle"));
return false;
}
} else {
let vehicleIndex = getParam(params, " ", 1);
- if(typeof getServerData().vehicles[vehicleIndex] == "undefined") {
+ if (typeof getServerData().vehicles[vehicleIndex] == "undefined") {
messagePlayerError(client, getLocaleString(client, "InvaliVehicle"));
return false;
}
@@ -425,7 +425,7 @@ function warpIntoVehicleCommand(command, params, client) {
vehicle = getServerData().vehicles[vehicleIndex].vehicle;
}
- if(getVehicleData(vehicle)) {
+ if (getVehicleData(vehicle)) {
getPlayerData(client).enteringVehicle = vehicle;
}
@@ -447,14 +447,14 @@ function warpIntoVehicleCommand(command, params, client) {
*
*/
function gotoBusinessCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let businessId = getBusinessFromParams(params)
- if(!getBusinessData(businessId)) {
+ if (!getBusinessData(businessId)) {
messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -487,14 +487,14 @@ function gotoBusinessCommand(command, params, client) {
*
*/
function gotoGameLocationCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let gameLocationId = getGameLocationFromParams(params);
- if(gameLocationId == false) {
+ if (gameLocationId == false) {
messagePlayerError(client, "That game location doesn't exist!");
return false;
}
@@ -528,14 +528,14 @@ function gotoGameLocationCommand(command, params, client) {
*
*/
function gotoHouseCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let houseId = getHouseFromParams(params)
- if(!getHouseData(houseId)) {
+ if (!getHouseData(houseId)) {
messagePlayerError(client, getLocaleString(client, "InvalidHouse"));
return false;
}
@@ -568,21 +568,21 @@ function gotoHouseCommand(command, params, client) {
*
*/
function gotoJobLocationCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let jobId = getJobFromParams(getParam(params, " ", 1)) || getClosestJobLocation(getPlayerPosition(client)).job;
- if(!getJobData(jobId)) {
+ if (!getJobData(jobId)) {
messagePlayerError(client, getLocaleString(client, "InvalidJob"));
return false;
}
let jobLocationId = getParam(params, " ", 2) || 0;
- if(typeof getJobData(jobId).locations[jobLocationId] == "undefined") {
+ if (typeof getJobData(jobId).locations[jobLocationId] == "undefined") {
messagePlayerError(client, `That location ID does not exist!`);
return false;
}
@@ -629,7 +629,7 @@ function gotoNewPlayerSpawnCommand(command, params, client) {
*
*/
function gotoPositionCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -663,8 +663,8 @@ function gotoPositionCommand(command, params, client) {
*/
function teleportForwardCommand(command, params, client) {
let distance = 1.0;
- if(!areParamsEmpty(params)) {
- if(!isNaN(params)) {
+ if (!areParamsEmpty(params)) {
+ if (!isNaN(params)) {
distance = toFloat(params);
}
}
@@ -687,8 +687,8 @@ function teleportForwardCommand(command, params, client) {
*/
function teleportBackwardCommand(command, params, client) {
let distance = 1.0;
- if(!areParamsEmpty(params)) {
- if(!isNaN(params)) {
+ if (!areParamsEmpty(params)) {
+ if (!isNaN(params)) {
distance = toFloat(params);
}
}
@@ -711,8 +711,8 @@ function teleportBackwardCommand(command, params, client) {
*/
function teleportLeftCommand(command, params, client) {
let distance = 1.0;
- if(!areParamsEmpty(params)) {
- if(!isNaN(params)) {
+ if (!areParamsEmpty(params)) {
+ if (!isNaN(params)) {
distance = toFloat(params);
}
}
@@ -735,8 +735,8 @@ function teleportLeftCommand(command, params, client) {
*/
function teleportUpCommand(command, params, client) {
let distance = 1.0;
- if(!areParamsEmpty(params)) {
- if(!isNaN(params)) {
+ if (!areParamsEmpty(params)) {
+ if (!isNaN(params)) {
distance = toFloat(params);
}
}
@@ -759,8 +759,8 @@ function teleportUpCommand(command, params, client) {
*/
function teleportDownCommand(command, params, client) {
let distance = 1.0;
- if(!areParamsEmpty(params)) {
- if(!isNaN(params)) {
+ if (!areParamsEmpty(params)) {
+ if (!isNaN(params)) {
distance = toFloat(params);
}
}
@@ -774,8 +774,8 @@ function teleportDownCommand(command, params, client) {
function teleportRightCommand(command, params, client) {
let distance = 1.0;
- if(!areParamsEmpty(params)) {
- if(!isNaN(params)) {
+ if (!areParamsEmpty(params)) {
+ if (!isNaN(params)) {
distance = toFloat(params);
}
}
@@ -797,18 +797,18 @@ function teleportRightCommand(command, params, client) {
*
*/
function playerInteriorCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
- if(getParamsCount(params, " ") == 1) {
+ if (getParamsCount(params, " ") == 1) {
messagePlayerInfo(client, `${getPlayerName(targetClient)}'s interior is {ALTCOLOUR}${getPlayerInterior(targetClient)}`);
return false;
}
@@ -830,18 +830,18 @@ function playerInteriorCommand(command, params, client) {
*
*/
function playerVirtualWorldCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
- if(getParamsCount(params, " ") == 1) {
+ if (getParamsCount(params, " ") == 1) {
messagePlayerInfo(client, `{ALTCOLOUR}${getPlayerName(targetClient)}'s{MAINCOLOUR} virtual world is {ALTCOLOUR}${getPlayerDimension(targetClient)}`);
return false;
}
@@ -863,13 +863,13 @@ function playerVirtualWorldCommand(command, params, client) {
*
*/
function getPlayerCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -903,20 +903,20 @@ function getPlayerCommand(command, params, client) {
*
*/
function returnPlayerCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
removePlayerFromVehicle(targetClient);
- if(getPlayerData(targetClient).returnToPosition == null) {
+ if (getPlayerData(targetClient).returnToPosition == null) {
messagePlayerError(client, "There is nowhere to return that player to!");
return false;
}
@@ -950,7 +950,7 @@ function returnPlayerCommand(command, params, client) {
*
*/
function addPlayerStaffFlagCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -958,19 +958,19 @@ function addPlayerStaffFlagCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let flagName = getParam(params, " ", 2) || "None";
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
- if(getStaffFlagValue(flagName) == false) {
+ if (getStaffFlagValue(flagName) == false) {
messagePlayerError(client, getLocaleString(client, "InvalidStaffFlag"));
return false;
}
// Prevent setting flags on admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
- if(!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
+ if (!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
messagePlayerError(client, "You cannot give staff flags to this person!");
return false;
}
@@ -992,7 +992,7 @@ function addPlayerStaffFlagCommand(command, params, client) {
*
*/
function removePlayerStaffFlagCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1000,19 +1000,19 @@ function removePlayerStaffFlagCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let flagName = getParam(params, " ", 2) || "None";
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
- if(getStaffFlagValue(flagName) == false) {
+ if (getStaffFlagValue(flagName) == false) {
messagePlayerError(client, "That staff flag doesn't exist!");
return false;
}
// Prevent setting flags on admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
- if(!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
+ if (!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
messagePlayerError(client, "You cannot take staff flags from this person!");
return false;
}
@@ -1034,21 +1034,21 @@ function removePlayerStaffFlagCommand(command, params, client) {
*
*/
function removePlayerStaffFlagsCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
// Prevent setting flags on admins with really high permissions
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
- if(!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("ManageServer")) || doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue("Developer"))) {
+ if (!doesPlayerHaveStaffPermission(client, getStaffFlagValue("ManageServer")) && !doesPlayerHaveStaffPermission(client, getStaffFlagValue("Developer"))) {
messagePlayerError(client, "You cannot clear staff flags for this person!");
return false;
}
@@ -1070,42 +1070,42 @@ function removePlayerStaffFlagsCommand(command, params, client) {
*
*/
function getPlayerStaffFlagsCommand(command, params, client) {
- if(getCommand(command).requireLogin) {
- if(!isPlayerLoggedIn(client)) {
+ if (getCommand(command).requireLogin) {
+ if (!isPlayerLoggedIn(client)) {
messagePlayerError(client, "You must be logged in to use this command!");
return false;
}
}
- if(!doesPlayerHaveStaffPermission(client, getCommandRequiredPermissions(command))) {
+ if (!doesPlayerHaveStaffPermission(client, getCommandRequiredPermissions(command))) {
messagePlayerError(client, "You do not have permission to use this command!");
return false;
}
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
let tempStaffFlags = [];
let serverBitFlagKeys = getServerBitFlagKeys();
- for(let i in serverBitFlagKeys) {
+ for (let i in serverBitFlagKeys) {
let tempFlagValue = getStaffFlagValue(serverBitFlagKeys[i]);
- if(doesPlayerHaveStaffPermission(targetClient, tempFlagValue)) {
+ if (doesPlayerHaveStaffPermission(targetClient, tempFlagValue)) {
tempStaffFlags.push(serverBitFlagKeys[i]);
}
}
let flagList = [];
- for(let i in getServerBitFlagKeys().staffFlagKeys) {
- if(doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue(getServerBitFlagKeys().staffFlagKeys[i]))) {
+ for (let i in getServerBitFlagKeys().staffFlagKeys) {
+ if (doesPlayerHaveStaffPermission(targetClient, getStaffFlagValue(getServerBitFlagKeys().staffFlagKeys[i]))) {
flagList.push(`{softGreen}${getServerBitFlagKeys().staffFlagKeys[i]}`);
} else {
flagList.push(`{softRed}${getServerBitFlagKeys().staffFlagKeys[i]}`);
@@ -1116,7 +1116,7 @@ function getPlayerStaffFlagsCommand(command, params, client) {
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPlayerStaffFlagsList", getPlayerData(targetClient).accountData.name)));
- for(let i in chunkedList) {
+ for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join("{MAINCOLOUR}, "));
}
}
@@ -1133,7 +1133,7 @@ function getPlayerStaffFlagsCommand(command, params, client) {
*
*/
function getStaffFlagsCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1141,7 +1141,7 @@ function getStaffFlagsCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let flagName = getParam(params, " ", 2) || "None";
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1149,7 +1149,7 @@ function getStaffFlagsCommand(command, params, client) {
let chunkedList = splitArrayIntoChunks(getServerBitFlagKeys().staffFlagKeys, 8);
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderStaffFlagsList")));
- for(let i in chunkedList) {
+ for (let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join("{MAINCOLOUR}, "));
}
}
@@ -1166,7 +1166,7 @@ function getStaffFlagsCommand(command, params, client) {
*
*/
function givePlayerMoneyCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1174,7 +1174,7 @@ function givePlayerMoneyCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let amount = toInteger(getParam(params, " ", 2));
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1198,7 +1198,7 @@ function givePlayerMoneyCommand(command, params, client) {
*
*/
function setPlayerAccentCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1206,18 +1206,18 @@ function setPlayerAccentCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let newAccent = getParam(params, " ", 2) || "None";
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
- if(toLowerCase(newAccent) == "None") {
+ if (toLowerCase(newAccent) == "None") {
newAccent = "";
}
setPlayerAccentText(client, newAccent);
- if(newAccent == "") {
+ if (newAccent == "") {
//messagePlayerSuccess(client, `You removed {ALTCOLOUR}${getCharacterFullName(targetClient)}'s {MAINCOLOUR}accent.`);
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} removed {ALTCOLOUR}${getCharacterFullName(targetClient)}'s{MAINCOLOUR} accent.`);
messagePlayerAlert(client, `An admin removed your accent.`);
@@ -1240,14 +1240,14 @@ function setPlayerAccentCommand(command, params, client) {
*
*/
function forceCharacterNameChangeCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1270,7 +1270,7 @@ function forceCharacterNameChangeCommand(command, params, client) {
*
*/
function setCharacterNameCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1284,7 +1284,7 @@ function setCharacterNameCommand(command, params, client) {
let firstName = getParam(params, " ", 2);
let lastName = getParam(params, " ", 3);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1314,7 +1314,7 @@ function setCharacterNameCommand(command, params, client) {
*
*/
function setPlayerSkinCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1328,12 +1328,12 @@ function setPlayerSkinCommand(command, params, client) {
let targetClient = getPlayerFromParams(splitParams[0]);
let skinIndex = getSkinModelIndexFromParams(splitParams.slice(1).join(" "), getGame());
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
- if(!skinIndex) {
+ if (!skinIndex) {
messagePlayerError(client, getLocaleString(client, "InvalidSkin"));
return false;
}
@@ -1353,8 +1353,8 @@ function setPlayerSkinCommand(command, params, client) {
* @return {bool} Whether or not the command was successful
*
*/
- function setPlayerStaffTitleCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+function setPlayerStaffTitleCommand(command, params, client) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1363,7 +1363,7 @@ function setPlayerSkinCommand(command, params, client) {
let targetClient = getPlayerFromParams(splitParams[0]);
let newTitle = splitParams.slice(1).join(" ");
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1385,7 +1385,7 @@ function setPlayerSkinCommand(command, params, client) {
*
*/
function setPlayerHealthCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1399,7 +1399,7 @@ function setPlayerHealthCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let health = getParam(params, " ", 2);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1421,7 +1421,7 @@ function setPlayerHealthCommand(command, params, client) {
*
*/
function setPlayerArmourCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1429,7 +1429,7 @@ function setPlayerArmourCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let armour = getParam(params, " ", 2);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1451,7 +1451,7 @@ function setPlayerArmourCommand(command, params, client) {
*
*/
function setPlayerInfiniteRunCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1459,12 +1459,12 @@ function setPlayerInfiniteRunCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let state = getParam(params, " ", 2) || 0;
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
- if(isNaN(state)) {
+ if (isNaN(state)) {
messagePlayerError(client, `The infinite run state must be a number!`);
return false;
}
@@ -1487,7 +1487,7 @@ function setPlayerInfiniteRunCommand(command, params, client) {
*
*/
function setPlayerWantedLevelCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1495,7 +1495,7 @@ function setPlayerWantedLevelCommand(command, params, client) {
let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let wantedLevel = getParam(params, " ", 2);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1517,14 +1517,14 @@ function setPlayerWantedLevelCommand(command, params, client) {
*
*/
function getVehiclesOwnedByPlayerCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1532,7 +1532,7 @@ function getVehiclesOwnedByPlayerCommand(command, params, client) {
let vehicles = getAllVehiclesOwnedByPlayer(targetClient);
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPlayerVehiclesList", getCharacterFullName(targetClient))));
- for(let i in vehicles) {
+ for (let i in vehicles) {
messagePlayerNormal(client, `🚗 {vehiclePurple}[Vehicle Info] {MAINCOLOUR}ID: {ALTCOLOUR}${vehicles[i].index}, {MAINCOLOUR}DatabaseID: {ALTCOLOUR}${vehicles[i].databaseId}, {MAINCOLOUR}Type: {ALTCOLOUR}${getVehicleName(vehicles[i].vehicle)}[${vehicles[i].model}], {MAINCOLOUR}BuyPrice: {ALTCOLOUR}${vehicles[i].buyPrice}, {MAINCOLOUR}RentPrice: {ALTCOLOUR}${vehicles[i].rentPrice}, {MAINCOLOUR}Locked: {ALTCOLOUR}${getYesNoFromBool(vehicles[i].locked)}, {MAINCOLOUR}Engine: {ALTCOLOUR}${getYesNoFromBool(vehicles[i].engine)}`);
}
}
@@ -1549,14 +1549,14 @@ function getVehiclesOwnedByPlayerCommand(command, params, client) {
*
*/
function getBusinessesOwnedByPlayerCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1564,7 +1564,7 @@ function getBusinessesOwnedByPlayerCommand(command, params, client) {
let businesses = getAllBusinessesOwnedByPlayer(targetClient);
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPlayerBusinessesList", getCharacterFullName(targetClient))));
- for(let i in businesses) {
+ for (let i in businesses) {
let info = [
`Name: ${businesses[i].name}`,
`Locked: ${businesses[i].locked}`,
@@ -1586,14 +1586,14 @@ function getBusinessesOwnedByPlayerCommand(command, params, client) {
*
*/
function getHousesOwnedByPlayerCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1601,7 +1601,7 @@ function getHousesOwnedByPlayerCommand(command, params, client) {
let houses = getAllHousesOwnedByPlayer(targetClient);
messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPlayerHousesList", getCharacterFullName(targetClient))));
- for(let i in houses) {
+ for (let i in houses) {
messagePlayerNormal(client, `🏠 {houseGreen}[House Info] {MAINCOLOUR}Description: {ALTCOLOUR}${houses[i].description}, {MAINCOLOUR}Locked: {ALTCOLOUR}${getYesNoFromBool(intToBool(houses[i].locked))}, {MAINCOLOUR}ID: {ALTCOLOUR}${houses[i].index}/${houses[i].databaseId}`);
}
}
@@ -1618,14 +1618,14 @@ function getHousesOwnedByPlayerCommand(command, params, client) {
*
*/
function forceAccountPasswordResetCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -1643,19 +1643,19 @@ function forceAccountPasswordResetCommand(command, params, client) {
*
*/
function toggleSyncForElementsSpawnedByPlayerCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
let targetClient = getPlayerFromParams(params);
- if(!targetClient) {
+ if (!targetClient) {
messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
- if(!hasBitFlag(getPlayerData(client).accountData.flags.moderation, getModerationFlagValue("DontSyncClientElements"))) {
+ if (!hasBitFlag(getPlayerData(client).accountData.flags.moderation, getModerationFlagValue("DontSyncClientElements"))) {
getPlayerData(client).accountData.flags.moderation = addBitFlag(getPlayerData(client).accountData.flags.moderation, getModerationFlagValue("DontSyncClientElements"));
messageAdmins(`{adminOrange}${getPlayerName(client)}{MAINCOLOUR} turned {softGreen}ON{MAINCOLOUR} client element sync for {ALTCOLOUR}${getPlayerName(targetClient)}`);
} else {
@@ -1667,7 +1667,7 @@ function toggleSyncForElementsSpawnedByPlayerCommand(command, params, client) {
// ===========================================================================
function isPlayerWeaponBanned(client) {
- if(hasBitFlag(getPlayerData(client).accountData.flags.moderation, getModerationFlagValue("WeaponBanned"))) {
+ if (hasBitFlag(getPlayerData(client).accountData.flags.moderation, getModerationFlagValue("WeaponBanned"))) {
return true;
}
@@ -1677,7 +1677,7 @@ function isPlayerWeaponBanned(client) {
// ===========================================================================
function isPlayerJobBanned(client) {
- if(hasBitFlag(getPlayerData(client).accountData.flags.moderation, getModerationFlagValue("JobBanned"))) {
+ if (hasBitFlag(getPlayerData(client).accountData.flags.moderation, getModerationFlagValue("JobBanned"))) {
return true;
}
@@ -1688,14 +1688,14 @@ function isPlayerJobBanned(client) {
function isPlayerPoliceBanned(client) {
let jobId = getJobFromParams("Police");
- if(doesJobHaveWhiteListEnabled(jobId)) {
- if(isPlayerOnJobWhiteList(client, jobId)) {
+ if (doesJobHaveWhiteListEnabled(jobId)) {
+ if (isPlayerOnJobWhiteList(client, jobId)) {
return true;
}
}
- if(doesJobHaveBlackListEnabled(jobId)) {
- if(!isPlayerOnJobBlackList(client, jobId)) {
+ if (doesJobHaveBlackListEnabled(jobId)) {
+ if (!isPlayerOnJobBlackList(client, jobId)) {
return true;
}
}
@@ -1715,7 +1715,7 @@ function isPlayerPoliceBanned(client) {
*
*/
function forceFightStyleCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1738,7 +1738,7 @@ function forceFightStyleCommand(command, params, client) {
// return false;
//}
- if(!fightStyleId) {
+ if (!fightStyleId) {
messagePlayerError(client, `That fight style doesn't exist!`);
messagePlayerError(client, `Fight styles: ${getGameConfig().fightStyles[getGame()].map(fs => fs[0]).join(", ")}`);
return false;
@@ -1762,8 +1762,8 @@ function forceFightStyleCommand(command, params, client) {
* @return {bool} Whether or not the command was successful
*
*/
- function getPlayerCurrentHouseCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+function getPlayerCurrentHouseCommand(command, params, client) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1772,7 +1772,7 @@ function forceFightStyleCommand(command, params, client) {
let houseId = getPlayerHouse(targetClient);
- if(!houseId) {
+ if (!houseId) {
messagePlayerAlert(client, `${getPlayerName(targetClient)} isn't in or at a house!`);
return false;
}
@@ -1793,8 +1793,8 @@ function forceFightStyleCommand(command, params, client) {
* @return {bool} Whether or not the command was successful
*
*/
- function getPlayerCurrentBusinessCommand(command, params, client) {
- if(areParamsEmpty(params)) {
+function getPlayerCurrentBusinessCommand(command, params, client) {
+ if (areParamsEmpty(params)) {
messagePlayerSyntax(client, getCommandSyntaxText(command));
return false;
}
@@ -1803,7 +1803,7 @@ function forceFightStyleCommand(command, params, client) {
let businessId = getPlayerBusiness(targetClient);
- if(!businessId) {
+ if (!businessId) {
messagePlayerAlert(client, `${getPlayerName(targetClient)} isn't in or at a house!`);
return false;
}
diff --git a/scripts/server/startup.js b/scripts/server/startup.js
index c539f568..da2a6c8a 100644
--- a/scripts/server/startup.js
+++ b/scripts/server/startup.js
@@ -10,7 +10,6 @@
function initServerScripts() {
checkForAllRequiredModules();
- initClassScript();
initDatabaseScript();
initConfigScript();
initEmailScript();
@@ -118,6 +117,7 @@ function loadServerDataFromDatabase() {
// Always load these regardless of "test server" status
getServerData().allowedSkins = getAllowedSkins(getGame());
+ getServerData().itemTypes = loadItemTypesFromDatabase();
// Translation Cache
//getServerData().cachedTranslations = new Array(getGlobalConfig().locale.locales.length);
@@ -127,7 +127,6 @@ function loadServerDataFromDatabase() {
// Only load these if the server isn't a testing/dev server
if (!getServerConfig().devServer) {
- getServerData().itemTypes = loadItemTypesFromDatabase();
getServerData().items = loadItemsFromDatabase();
getServerData().businesses = loadBusinessesFromDatabase();
getServerData().houses = loadHousesFromDatabase();
diff --git a/scripts/server/subaccount.js b/scripts/server/subaccount.js
index 65d77c11..094df2c5 100644
--- a/scripts/server/subaccount.js
+++ b/scripts/server/subaccount.js
@@ -7,6 +7,116 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+
+/**
+ * @class Representing a character's (subaccount) data. Loaded and saved in the database
+ */
+ class SubAccountData {
+ constructor(dbAssoc = false) {
+ this.databaseId = 0;
+ this.serverId = 0;
+ this.firstName = "John";
+ this.lastName = "Doe";
+ this.middleName = "Q";
+ this.account = 0;
+ this.skin = 0;
+ this.cash = 0;
+ this.spawnPosition = toVector3(0.0, 0.0, 0.0);
+ this.spawnHeading = 0.0;
+ this.lastLogin = 0;
+ this.clan = 0;
+ this.clanFlags = 0;
+ this.clanRank = 0;
+ this.clanTitle = 0;
+ this.isWorking = false;
+ this.jobUniform = this.skin;
+ this.job = 0;
+ this.jobRank = 0;
+ this.weapons = [];
+ this.inJail = false;
+ this.interior = 0;
+ this.dimension = 0;
+ this.pedScale = toVector3(1.0, 1.0, 1.0);
+ this.walkStyle = 0;
+ this.fightStyle = 0;
+ this.health = 100;
+ this.armour = 100;
+ this.inHouse = 0;
+ this.inBusiness = 0;
+ this.accent = "";
+
+ this.bodyParts = {
+ hair: [0,0],
+ head: [0,0],
+ upper: [0,0],
+ lower: [0,0],
+ };
+
+ this.bodyProps = {
+ hair: [0,0],
+ eyes: [0,0],
+ head: [0,0],
+ leftHand: [0,0],
+ rightHand: [0,0],
+ leftWrist: [0,0],
+ rightWrist: [0,0],
+ hip: [0,0],
+ leftFoot: [0,0],
+ rightFoot: [0,0],
+ };
+
+ if(dbAssoc) {
+ this.databaseId = dbAssoc["sacct_id"];
+ this.serverId = toInteger(dbAssoc["sacct_server"]);
+ this.firstName = dbAssoc["sacct_name_first"];
+ this.lastName = dbAssoc["sacct_name_last"];
+ this.middleName = dbAssoc["sacct_name_middle"] || "";
+ this.account = toInteger(dbAssoc["sacct_acct"]);
+ this.skin = toInteger(dbAssoc["sacct_svr_skin"]);
+ this.cash = toInteger(dbAssoc["sacct_cash"]);
+ this.spawnPosition = toVector3(toFloat(dbAssoc["sacct_pos_x"]), toFloat(dbAssoc["sacct_pos_y"]), toFloat(dbAssoc["sacct_pos_z"]));
+ this.spawnHeading = toFloat(dbAssoc["sacct_rot_z"]);
+ this.lastLogin = toInteger(dbAssoc["sacct_when_lastlogin"]);
+ this.clan = toInteger(dbAssoc["sacct_svr_clan"]);
+ this.clanFlags = toInteger(dbAssoc["sacct_svr_clan_flags"]);
+ this.clanRank = toInteger(dbAssoc["sacct_svr_clan_rank"]);
+ this.clanTitle = toInteger(dbAssoc["sacct_svr_clan_title"]);
+ this.job = toInteger(dbAssoc["sacct_svr_job"]);
+ this.jobRank = toInteger(dbAssoc["sacct_svr_job_rank"]);
+ this.interior = toInteger(dbAssoc["sacct_int"]);
+ this.dimension = toInteger(dbAssoc["sacct_vw"]);
+ this.pedScale = toVector3(toFloat(dbAssoc["sacct_svr_scale_x"]), toFloat(dbAssoc["sacct_svr_scale_y"]), toFloat(dbAssoc["sacct_svr_scale_z"]));
+ this.walkStyle = toInteger(dbAssoc["sacct_svr_walkstyle"]);
+ this.fightStyle = toInteger(dbAssoc["sacct_svr_fightstyle"]);
+ this.health = toInteger(dbAssoc["sacct_health"]);
+ this.armour = toInteger(dbAssoc["sacct_armour"]);
+ this.inHouse = toInteger(dbAssoc["sacct_inhouse"]);
+ this.inBusiness = toInteger(dbAssoc["sacct_inbusiness"]);
+ this.accent = toString(dbAssoc["sacct_accent"]);
+
+ this.bodyParts = {
+ hair: [toInteger(dbAssoc["sacct_svr_hd_part_hair_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_hair_texture"]) || 0],
+ head: [toInteger(dbAssoc["sacct_svr_hd_part_head_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_head_texture"]) || 0],
+ upper: [toInteger(dbAssoc["sacct_svr_hd_part_upper_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_upper_texture"]) || 0],
+ lower: [toInteger(dbAssoc["sacct_svr_hd_part_lower_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_part_lower_texture"]) || 0],
+ };
+
+ this.bodyProps = {
+ hair: [toInteger(dbAssoc["sacct_svr_hd_prop_hair_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_hair_texture"]) || 0],
+ eyes: [toInteger(dbAssoc["sacct_svr_hd_prop_eyes_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_eyes_texture"]) || 0],
+ head: [toInteger(dbAssoc["sacct_svr_hd_prop_head_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_head_texture"]) || 0],
+ leftHand: [toInteger(dbAssoc["sacct_svr_hd_prop_lefthand_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_lefthand_texture"]) || 0],
+ rightHand: [toInteger(dbAssoc["sacct_svr_hd_prop_righthand_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_righthand_texture"]) || 0],
+ leftWrist: [toInteger(dbAssoc["sacct_svr_hd_prop_leftwrist_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_leftwrist_texture"]) || 0],
+ rightWrist: [toInteger(dbAssoc["sacct_svr_hd_prop_rightwrist_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_rightwrist_texture"]) || 0],
+ hip: [toInteger(dbAssoc["sacct_svr_hd_prop_hip_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_hip_texture"]) || 0],
+ leftFoot: [toInteger(dbAssoc["sacct_svr_hd_prop_leftfoot_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_leftfoot_texture"]) || 0],
+ rightFoot: [toInteger(dbAssoc["sacct_svr_hd_prop_rightfoot_model"]) || 0, toInteger(dbAssoc["sacct_svr_hd_prop_rightfoot_texture"]) || 0],
+ };
+ }
+ }
+};
+
function initSubAccountScript() {
logToConsole(LOG_INFO, "[VRR.SubAccount]: Initializing subaccount script ...");
logToConsole(LOG_INFO, "[VRR.SubAccount]: SubAccount script initialized!");
@@ -245,9 +355,9 @@ function showCharacterSelectToClient(client) {
//}, 500);
logToConsole(LOG_DEBUG, `[VRR.SubAccount] ${getPlayerDisplayForConsole(client)} is being shown the character select GUI`);
} else {
- let charactersList = getPlayerData(client).subAccounts.map(sacct, index => `{teal}${index}: {ALTCOLOUR}${sacct.name}`);
+ let charactersList = getPlayerData(client).subAccounts.map((sacct, index) => `{teal}${index + 1}: {ALTCOLOUR}${sacct.firstName} ${sacct.lastName}`);
let chunkedList = splitArrayIntoChunks(charactersList, 5);
- messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderCharacterListSelf")));
+ messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderCharactersListSelf")));
for (let i in chunkedList) {
messagePlayerNormal(client, chunkedList[i].join("{MAINCOLOUR}, "));
}
diff --git a/scripts/server/timers.js b/scripts/server/timers.js
index 484a9998..49d08e07 100644
--- a/scripts/server/timers.js
+++ b/scripts/server/timers.js
@@ -12,7 +12,7 @@ let serverTimers = {};
// ===========================================================================
function saveServerDataToDatabase() {
- if(getServerConfig().pauseSavingToDatabase) {
+ if (getServerConfig().pauseSavingToDatabase) {
return false;
}
@@ -20,67 +20,67 @@ function saveServerDataToDatabase() {
try {
saveAllPlayersToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save players to database: ${error}`);
}
try {
saveAllClansToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save clans to database: ${error}`);
}
try {
saveAllHousesToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save houses to database: ${error}`);
}
try {
saveAllBusinessesToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save businesses to database: ${error}`);
}
try {
saveAllVehiclesToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save vehicles to database: ${error}`);
}
try {
saveAllItemTypesToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save item types to database: ${error}`);
}
try {
saveAllItemsToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save items to database: ${error}`);
}
try {
saveAllJobsToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save jobs to database: ${error}`);
}
try {
saveAllNPCsToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save NPCs to database: ${error}`);
}
try {
saveAllGatesToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save gates to database: ${error}`);
}
try {
saveServerConfigToDatabase();
- } catch(error) {
+ } catch (error) {
logToConsole(LOG_ERROR, `Could not save server config to database: ${error}`);
}
@@ -91,10 +91,10 @@ function saveServerDataToDatabase() {
function initTimers() {
//if(!isDevelopmentServer()) {
- serverTimers.updatePingsTimer = setInterval(updatePings, 5000);
- serverTimers.oneMinuteTimer = setInterval(oneMinuteTimerFunction, 60000);
- serverTimers.fifteenMinuteTimer = setInterval(tenMinuteTimerFunction, 600000);
- serverTimers.thirtyMinuteTimer = setInterval(thirtyMinuteTimerFunction, 1800000);
+ serverTimers.updatePingsTimer = setInterval(updatePings, 5000);
+ serverTimers.oneMinuteTimer = setInterval(oneMinuteTimerFunction, 60000);
+ serverTimers.fifteenMinuteTimer = setInterval(tenMinuteTimerFunction, 600000);
+ serverTimers.thirtyMinuteTimer = setInterval(thirtyMinuteTimerFunction, 1800000);
//}
}
@@ -132,12 +132,12 @@ function thirtyMinuteTimerFunction() {
function checkVehicleRenting() {
let renting = getServerData().rentingVehicleCache;
- for(let i in renting) {
- if(isClientInitialized(renting[i])) {
- if(getPlayerData(renting[i]) != false) {
- if(isPlayerLoggedIn(renting[i] && isPlayerSpawned(renting[i]))) {
- if(getPlayerData(renting[i]).rentingVehicle != false) {
- if(getPlayerCurrentSubAccount(renting[i]).cash < getServerData().vehicles[getPlayerData(renting[i]).rentingVehicle].rentPrice) {
+ for (let i in renting) {
+ if (isClientInitialized(renting[i])) {
+ if (getPlayerData(renting[i]) != false) {
+ if (isPlayerLoggedIn(renting[i] && isPlayerSpawned(renting[i]))) {
+ if (getPlayerData(renting[i]).rentingVehicle != false) {
+ if (getPlayerCurrentSubAccount(renting[i]).cash < getServerData().vehicles[getPlayerData(renting[i]).rentingVehicle].rentPrice) {
messagePlayerAlert(renting[i], `You do not have enough money to continue renting this vehicle!`);
stopRentingVehicle(renting[i]);
} else {
@@ -174,11 +174,11 @@ function checkVehicleRenting() {
function updatePings() {
let clients = getClients();
- for(let i in clients) {
- if(isClientInitialized(clients[i])) {
- if(!clients[i].console) {
+ for (let i in clients) {
+ if (isClientInitialized(clients[i])) {
+ if (!clients[i].console) {
updatePlayerPing(clients[i]);
- if(isPlayerSpawned(clients[i])) {
+ if (isPlayerSpawned(clients[i])) {
updatePlayerCash(clients[i]);
}
}
@@ -190,16 +190,16 @@ function updatePings() {
function checkServerGameTime() {
//if(!getServerConfig().useRealTime) {
- if(getServerConfig().minute >= 59) {
- getServerConfig().minute = 0;
- if(getServerConfig().hour >= 23) {
- getServerConfig().hour = 0;
- } else {
- getServerConfig().hour = getServerConfig().hour + 1;
- }
+ if (getServerConfig().minute >= 59) {
+ getServerConfig().minute = 0;
+ if (getServerConfig().hour >= 23) {
+ getServerConfig().hour = 0;
} else {
- getServerConfig().minute = getServerConfig().minute + 1;
+ getServerConfig().hour = getServerConfig().hour + 1;
}
+ } else {
+ getServerConfig().minute = getServerConfig().minute + 1;
+ }
//} else {
// let dateTime = getCurrentTimeStampWithTimeZone(getServerConfig().realTimeZone);
// getServerConfig().hour = dateTime.getHours();
@@ -213,9 +213,9 @@ function checkServerGameTime() {
function checkPayDays() {
let clients = getClients();
- for(let i in clients) {
- if(isClientInitialized(clients[i])) {
- if(isPlayerLoggedIn(clients[i]) && isPlayerSpawned(clients[i])) {
+ for (let i in clients) {
+ if (isClientInitialized(clients[i])) {
+ if (isPlayerLoggedIn(clients[i]) && isPlayerSpawned(clients[i])) {
getPlayerData(clients[i]).payDayStart = sdl.ticks;
playerPayDay(clients[i]);
@@ -227,8 +227,8 @@ function checkPayDays() {
}
}
- for(let i in getServerData().businesses) {
- if(getBusinessData(i).ownerType != VRR_BIZOWNER_NONE && getBusinessData(i).ownerType != VRR_BIZOWNER_PUBLIC && getBusinessData(i).ownerType != VRR_BIZOWNER_FACTION) {
+ for (let i in getServerData().businesses) {
+ if (getBusinessData(i).ownerType != VRR_BIZOWNER_NONE && getBusinessData(i).ownerType != VRR_BIZOWNER_PUBLIC && getBusinessData(i).ownerType != VRR_BIZOWNER_FACTION) {
getBusinessData(i).till += 1000;
}
}
@@ -237,14 +237,14 @@ function checkPayDays() {
// ===========================================================================
function showRandomTipToAllPlayers() {
- let tipId = getRandom(0, randomTips.length-1);
-
let clients = getClients();
- for(let i in clients) {
- if(isClientInitialized(clients[i])) {
- if(isPlayerLoggedIn(clients[i]) && isPlayerSpawned(clients[i])) {
- if(!doesPlayerHaveRandomTipsDisabled(clients[i])) {
- messagePlayerTimedRandomTip(null, randomTips[tipId]);
+ for (let i in clients) {
+ if (isClientInitialized(clients[i])) {
+ if (isPlayerLoggedIn(clients[i]) && isPlayerSpawned(clients[i])) {
+ if (!doesPlayerHaveRandomTipsDisabled(clients[i])) {
+ let localeId = getPlayerLocaleId(clients[i]);
+ let tipId = getRandom(0, getServerData().localeStrings[localeId]["RandomTips"].length - 1);
+ messagePlayerTip(clients[i], getGroupedLocaleString(clients[i], "RandomTips", tipId));
}
}
}
@@ -255,11 +255,11 @@ function showRandomTipToAllPlayers() {
function checkInactiveVehicleRespawns() {
let vehicles = getElementsByType(ELEMENT_VEHICLE);
- for(let i in vehicles) {
- if(getVehicleData(vehicles[i] != false)) {
- if(isVehicleUnoccupied(vehicles[i])) {
- if(getVehicleData(vehicles[i]).lastActiveTime != false) {
- if(getCurrentUnixTimestamp() - getVehicleData(vehicles[i]).lastActiveTime >= getGlobalConfig().vehicleInactiveRespawnDelay) {
+ for (let i in vehicles) {
+ if (getVehicleData(vehicles[i] != false)) {
+ if (isVehicleUnoccupied(vehicles[i])) {
+ if (getVehicleData(vehicles[i]).lastActiveTime != false) {
+ if (getCurrentUnixTimestamp() - getVehicleData(vehicles[i]).lastActiveTime >= getGlobalConfig().vehicleInactiveRespawnDelay) {
respawnVehicle(vehicles[i]);
getVehicleData(vehicles[i]).lastActiveTime = false;
}
diff --git a/scripts/server/utilities.js b/scripts/server/utilities.js
index a89a7821..275680a7 100644
--- a/scripts/server/utilities.js
+++ b/scripts/server/utilities.js
@@ -12,13 +12,13 @@
// ===========================================================================
function getPositionArea(position) {
- if(typeof position == "Vec3") {
+ if (typeof position == "Vec3") {
position = vec3ToVec2(position);
}
let gameAreas = getGameAreas(getGame());
- for(let i in gameAreas) {
- if(isPositionInArea(position, gameAreas[i][1])) {
+ for (let i in gameAreas) {
+ if (isPositionInArea(position, gameAreas[i][1])) {
return i;
}
}
@@ -30,7 +30,7 @@ function getPositionArea(position) {
function getAreaName(position) {
let areaId = getPositionArea(position);
- if(!areaId) {
+ if (!areaId) {
return false;
}
@@ -50,8 +50,8 @@ function getGameAreas(gameId) {
* @return {ClientData} The player/client's data (class instancee)
*/
function getPlayerData(client) {
- if(client != null) {
- if(isClientInitialized(client)) {
+ if (client != null) {
+ if (isClientInitialized(client)) {
return getServerData().clients[getPlayerId(client)];
}
}
@@ -61,7 +61,7 @@ function getPlayerData(client) {
// ===========================================================================
function initAllClients() {
- getClients().forEach(function(client) {
+ getClients().forEach(function (client) {
initClient(client);
});
}
@@ -72,17 +72,17 @@ function updateServerRules() {
logToConsole(LOG_DEBUG, `[VRR.Utilities]: Updating all server rules ...`);
logToConsole(LOG_DEBUG, `[VRR.Utilities]: Time support: ${isTimeSupported()}`);
- if(isTimeSupported()) {
- if(getServerConfig() != false) {
+ if (isTimeSupported()) {
+ if (getServerConfig() != false) {
let value = makeReadableTime(getServerConfig().hour, getServerConfig().minute);
logToConsole(LOG_DEBUG, `[VRR.Utilities]: Setting server rule "Time" as ${value}`);
server.setRule("Time", value);
}
}
- if(isWeatherSupported()) {
- if(getServerConfig() != false) {
- if(typeof getGameConfig().weatherNames[getGame()] != "undefined") {
+ if (isWeatherSupported()) {
+ if (getServerConfig() != false) {
+ if (typeof getGameConfig().weatherNames[getGame()] != "undefined") {
let value = getGameConfig().weatherNames[getGame()][getServerConfig().weather];
logToConsole(LOG_DEBUG, `[VRR.Utilities]: Setting server rule "Weather" as ${value}`);
server.setRule("Weather", value);
@@ -90,8 +90,8 @@ function updateServerRules() {
}
}
- if(isSnowSupported()) {
- if(getServerConfig() != false) {
+ if (isSnowSupported()) {
+ if (getServerConfig() != false) {
let value = getYesNoFromBool(getServerConfig().fallingSnow);
logToConsole(LOG_DEBUG, `[VRR.Utilities]: Setting server rule "Snowing" as ${value}`);
server.setRule("Snowing", value);
@@ -103,14 +103,14 @@ function updateServerRules() {
// ===========================================================================
function getWeatherFromParams(params) {
- if(isNaN(params)) {
- for(let i in getGameConfig().weatherNames[getGame()]) {
- if(toLowerCase(getGameConfig().weatherNames[getGame()][i]).indexOf(toLowerCase(params)) != -1) {
+ if (isNaN(params)) {
+ for (let i in getGameConfig().weatherNames[getGame()]) {
+ if (toLowerCase(getGameConfig().weatherNames[getGame()][i]).indexOf(toLowerCase(params)) != -1) {
return i;
}
}
} else {
- if(typeof getGameConfig().weatherNames[getGame()][params] != "undefined") {
+ if (typeof getGameConfig().weatherNames[getGame()][params] != "undefined") {
return toInteger(params);
}
}
@@ -121,14 +121,14 @@ function getWeatherFromParams(params) {
// ===========================================================================
function getFightStyleFromParams(params) {
- if(isNaN(params)) {
- for(let i in getGameConfig().fightStyles[getGame()]) {
- if(toLowerCase(getGameConfig().fightStyles[getGame()][i][0]).indexOf(toLowerCase(params)) != -1) {
+ if (isNaN(params)) {
+ for (let i in getGameConfig().fightStyles[getGame()]) {
+ if (toLowerCase(getGameConfig().fightStyles[getGame()][i][0]).indexOf(toLowerCase(params)) != -1) {
return i;
}
}
} else {
- if(typeof getGameConfig().fightStyles[getGame()][params] != "undefined") {
+ if (typeof getGameConfig().fightStyles[getGame()][params] != "undefined") {
return toInteger(params);
}
}
@@ -139,12 +139,12 @@ function getFightStyleFromParams(params) {
// ===========================================================================
function getClosestHospital(position) {
- if(typeof getGameConfig().hospitals[getGame()] == "undefined") {
- return {position: getServerConfig().newCharacter.spawnPosition};
+ if (typeof getGameConfig().hospitals[getGame()] == "undefined") {
+ return { position: getServerConfig().newCharacter.spawnPosition };
} else {
let closest = 0;
- for(let i in getGameConfig().hospitals[getGame()]) {
- if(getDistance(getGameConfig().hospitals[getGame()][i].position, position) < getDistance(getGameConfig().hospitals[getGame()][closest].position, position)) {
+ for (let i in getGameConfig().hospitals[getGame()]) {
+ if (getDistance(getGameConfig().hospitals[getGame()][i].position, position) < getDistance(getGameConfig().hospitals[getGame()][closest].position, position)) {
closest = i;
}
}
@@ -156,12 +156,12 @@ function getClosestHospital(position) {
// ===========================================================================
function getClosestPoliceStation(position) {
- if(typeof getGameConfig().policeStations[getGame()] == "undefined") {
- return {position: getServerConfig().newCharacter.spawnPosition};
+ if (typeof getGameConfig().policeStations[getGame()] == "undefined") {
+ return { position: getServerConfig().newCharacter.spawnPosition };
} else {
let closest = 0;
- for(let i in getGameConfig().policeStations[getGame()]) {
- if(getDistance(getGameConfig().policeStations[getGame()][i].position, position) < getDistance(getGameConfig().policeStations[getGame()][closest].position, position)) {
+ for (let i in getGameConfig().policeStations[getGame()]) {
+ if (getDistance(getGameConfig().policeStations[getGame()][i].position, position) < getDistance(getGameConfig().policeStations[getGame()][closest].position, position)) {
closest = i;
}
}
@@ -173,7 +173,7 @@ function getClosestPoliceStation(position) {
// ===========================================================================
function getPlayerDisplayForConsole(client) {
- if(isNull(client)) {
+ if (isNull(client)) {
return "(Unknown client)";
}
return `${getPlayerName(client)}[${getPlayerId(client)}]`;
@@ -182,7 +182,7 @@ function getPlayerDisplayForConsole(client) {
// ===========================================================================
function getPlayerNameForNameTag(client) {
- if(isPlayerSpawned(client)) {
+ if (isPlayerSpawned(client)) {
return `${getPlayerCurrentSubAccount(client).firstName} ${getPlayerCurrentSubAccount(client).lastName}`;
}
return getPlayerName(client);
@@ -191,7 +191,7 @@ function getPlayerNameForNameTag(client) {
// ===========================================================================
function isPlayerSpawned(client) {
- if(!getPlayerData(client)) {
+ if (!getPlayerData(client)) {
return false;
}
return getPlayerData(client).spawned;
@@ -206,8 +206,8 @@ function getPlayerIsland(client) {
// ===========================================================================
function isAtPayAndSpray(position) {
- for(let i in getGameConfig().payAndSprays[getGame()]) {
- if(getDistance(position, getGameConfig().payAndSprays[getGame()][i]) <= getGlobalConfig().payAndSprayDistance) {
+ for (let i in getGameConfig().payAndSprays[getGame()]) {
+ if (getDistance(position, getGameConfig().payAndSprays[getGame()][i]) <= getGlobalConfig().payAndSprayDistance) {
return true;
}
}
@@ -220,15 +220,15 @@ function isAtPayAndSpray(position) {
function resetClientStuff(client) {
logToConsole(LOG_DEBUG, `[VRR.Utilities] Resetting client data for ${getPlayerDisplayForConsole(client)}`);
- if(!getPlayerData(client)) {
+ if (!getPlayerData(client)) {
return false;
}
- if(isPlayerOnJobRoute(client)) {
+ if (isPlayerOnJobRoute(client)) {
stopJobRoute(client, false, false);
}
- if(getPlayerData(client).rentingVehicle) {
+ if (getPlayerData(client).rentingVehicle) {
stopRentingVehicle(client);
}
@@ -241,9 +241,9 @@ function resetClientStuff(client) {
function getPlayerFromCharacterId(subAccountId) {
let clients = getClients();
- for(let i in clients) {
- for(let j in getPlayerData(clients[i]).subAccounts) {
- if(getPlayerData(clients[i]).subAccounts[j].databaseId == subAccountId) {
+ for (let i in clients) {
+ for (let j in getPlayerData(clients[i]).subAccounts) {
+ if (getPlayerData(clients[i]).subAccounts[j].databaseId == subAccountId) {
return clients[i];
}
}
@@ -256,11 +256,11 @@ function getPlayerFromCharacterId(subAccountId) {
function checkPlayerPedStates() {
let clients = getClients();
- for(let i in clients) {
- if(getPlayerData(clients[i])) {
- if(getPlayerData(clients[i]).pedState) {
- if(isPlayerInAnyVehicle(clients[i])) {
- if(getPlayerData(clients[i]).pedState == VRR_PEDSTATE_EXITINGVEHICLE) {
+ for (let i in clients) {
+ if (getPlayerData(clients[i])) {
+ if (getPlayerData(clients[i]).pedState) {
+ if (isPlayerInAnyVehicle(clients[i])) {
+ if (getPlayerData(clients[i]).pedState == VRR_PEDSTATE_EXITINGVEHICLE) {
getPlayerData(clients[i]).pedState == VRR_PEDSTATE_READY;
}
}
@@ -272,11 +272,11 @@ function checkPlayerPedStates() {
// ===========================================================================
function showConnectCameraToPlayer(client) {
- if(isFadeCameraSupported()) {
+ if (isFadeCameraSupported()) {
fadeCamera(client, true, 1);
}
- if(isCustomCameraSupported()) {
+ if (isCustomCameraSupported()) {
//setPlayerInterior(client, 0);
//setPlayerDimension(client, 0);
setPlayerCameraLookAt(client, getServerConfig().connectCameraPosition, getServerConfig().connectCameraLookAt);
@@ -295,9 +295,9 @@ function showCharacterSelectCameraToPlayer(client) {
function getClosestPlayer(position, exemptPlayer) {
let clients = getClients();
let closest = 0;
- for(let i in clients) {
- if(exemptClient != clients[i]) {
- if(getDistance(getPlayerPosition(clients[i]), position) < getDistance(getPlayerPosition(clients[closest]), position)) {
+ for (let i in clients) {
+ if (exemptClient != clients[i]) {
+ if (getDistance(getPlayerPosition(clients[i]), position) < getDistance(getPlayerPosition(clients[closest]), position)) {
closest = i;
}
}
@@ -315,20 +315,20 @@ function isPlayerMuted(client) {
function getPlayerFromParams(params) {
let clients = getClients();
- if(isNaN(params)) {
- for(let i in clients) {
- if(!clients[i].console) {
- if(toLowerCase(clients[i].name).indexOf(toLowerCase(params)) != -1) {
+ if (isNaN(params)) {
+ for (let i in clients) {
+ if (!clients[i].console) {
+ if (toLowerCase(clients[i].name).indexOf(toLowerCase(params)) != -1) {
return clients[i];
}
- if(toLowerCase(getCharacterFullName(clients[i])).indexOf(toLowerCase(params)) != -1) {
+ if (toLowerCase(getCharacterFullName(clients[i])).indexOf(toLowerCase(params)) != -1) {
return clients[i];
}
}
}
} else {
- if(typeof clients[toInteger(params)] != "undefined") {
+ if (typeof clients[toInteger(params)] != "undefined") {
return clients[toInteger(params)];
}
}
@@ -339,7 +339,7 @@ function getPlayerFromParams(params) {
// ===========================================================================
function updateConnectionLogOnQuit(client, quitReasonId) {
- if(getPlayerData(client) != false) {
+ if (getPlayerData(client) != false) {
quickDatabaseQuery(`UPDATE conn_main SET conn_when_disconnect=NOW(), conn_how_disconnect=${quitReasonId} WHERE conn_id = ${getPlayerData(client).sessionId}`);
}
}
@@ -353,12 +353,12 @@ function updateConnectionLogOnAuth(client, authId) {
// ===========================================================================
function updateConnectionLogOnClientInfoReceive(client, clientVersion, screenWidth, screenHeight) {
- if(getPlayerData(client) != false) {
+ if (getPlayerData(client) != false) {
getPlayerData(client).clientVersion = clientVersion;
}
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let safeClientVersion = escapeDatabaseString(dbConnection, clientVersion);
let safeScreenWidth = escapeDatabaseString(dbConnection, toString(screenWidth));
let safeScreenHeight = escapeDatabaseString(dbConnection, toString(screenHeight));
@@ -377,8 +377,8 @@ function generateRandomPhoneNumber() {
function doesNameContainInvalidCharacters(name) {
let disallowedCharacters = getGlobalConfig().subAccountNameAllowedCharacters;
name = toLowerCase(name);
- for(let i = 0; i < name.length; i++) {
- if(disallowedCharacters.toLowerCase().indexOf(name.charAt(i)) == -1) {
+ for (let i = 0; i < name.length; i++) {
+ if (disallowedCharacters.toLowerCase().indexOf(name.charAt(i)) == -1) {
return true;
}
}
@@ -394,36 +394,12 @@ function getClientFromSyncerId(syncerId) {
// ===========================================================================
-function triggerWebHook(messageString, serverId = getServerId(), type = VRR_DISCORD_WEBHOOK_LOG) {
- if(!getGlobalConfig().discord.webhook.enabled) {
- return false;
- }
-
- let tempURL = getGlobalConfig().discord.webhook.webhookBaseURL;
- tempURL = tempURL.replace("{0}", encodeURI(messageString));
- tempURL = tempURL.replace("{1}", serverId);
- tempURL = tempURL.replace("{2}", type);
- tempURL = tempURL.replace("{3}", getGlobalConfig().discord.webhook.pass);
-
- httpGet(
- tempURL,
- "",
- function(data) {
-
- },
- function(data) {
- }
- );
-}
-
-// ===========================================================================
-
function clearTemporaryVehicles() {
let vehicles = getElementsByType(ELEMENT_VEHICLE);
- for(let i in vehicles) {
- if(!getVehicleData(vehicles[i])) {
+ for (let i in vehicles) {
+ if (!getVehicleData(vehicles[i])) {
let occupants = vehicles[i].getOccupants();
- for(let j in occupants) {
+ for (let j in occupants) {
destroyGameElement(occupants[j]);
}
destroyGameElement(vehicles[i]);
@@ -435,11 +411,11 @@ function clearTemporaryVehicles() {
function clearTemporaryPeds() {
let peds = getElementsByType(ELEMENT_PED);
- for(let i in peds) {
- if(peds[i].owner == -1) {
- if(!peds[i].isType(ELEMENT_PLAYER)) {
- if(peds[i].vehicle == null) {
- if(!getNPCData(peds[i])) {
+ for (let i in peds) {
+ if (peds[i].owner == -1) {
+ if (!peds[i].isType(ELEMENT_PLAYER)) {
+ if (peds[i].vehicle == null) {
+ if (!getNPCData(peds[i])) {
destroyElement(peds[i]);
}
}
@@ -452,6 +428,7 @@ function clearTemporaryPeds() {
function kickAllClients() {
getClients().forEach((client) => {
+ getPlayerData(client).customDisconnectReason = `Kicked - All clients are being disconnected`;
disconnectPlayer(client);
})
}
@@ -459,7 +436,7 @@ function kickAllClients() {
// ===========================================================================
function updateTimeRule() {
- if(isTimeSupported()) {
+ if (isTimeSupported()) {
server.setRule("Time", makeReadableTime(game.time.hour, game.time.minute));
}
}
@@ -473,7 +450,7 @@ function isClientInitialized(client) {
// ===========================================================================
function getPedForNetworkEvent(ped) {
- if(getGame() == VRR_GAME_GTA_IV) {
+ if (getGame() == VRR_GAME_GTA_IV) {
return ped;
} else {
return ped.id;
@@ -485,10 +462,10 @@ function getPedForNetworkEvent(ped) {
// Get how many times a player connected in the last month by name
function getPlayerConnectionsInLastMonthByName(name) {
let dbConnection = connectToDatabase();
- if(dbConnection) {
+ if (dbConnection) {
let safeName = escapeDatabaseString(dbConnection, name);
let result = quickDatabaseQuery(`SELECT COUNT(*) AS count FROM conn_main WHERE conn_when_connect >= NOW() - INTERVAL 1 MONTH AND conn_name = '${safeName}'`);
- if(result) {
+ if (result) {
return result[0].count;
}
}
@@ -500,7 +477,7 @@ function getPlayerConnectionsInLastMonthByName(name) {
function addPrefixNumberFill(number, amount) {
let numberString = toString(number);
- while(numberString.length < amount) {
+ while (numberString.length < amount) {
numberString = toString(`0${numberString}`);
}
return toString(numberString);
diff --git a/scripts/server/vehicle.js b/scripts/server/vehicle.js
index 9c12940a..45e809af 100644
--- a/scripts/server/vehicle.js
+++ b/scripts/server/vehicle.js
@@ -7,6 +7,164 @@
// TYPE: Server (JavaScript)
// ===========================================================================
+// Vehicle Owner Types
+const VRR_VEHOWNER_NONE = 0; // Not owned
+const VRR_VEHOWNER_PLAYER = 1; // Owned by a player (character/subaccount)
+const VRR_VEHOWNER_JOB = 2; // Owned by a job
+const VRR_VEHOWNER_CLAN = 3; // Owned by a clan
+const VRR_VEHOWNER_FACTION = 4; // Owned by a faction (not used at the moment)
+const VRR_VEHOWNER_PUBLIC = 5; // Public vehicle. Anybody can drive it.
+const VRR_VEHOWNER_BIZ = 6; // Owned by a business (also includes dealerships since they're businesses)
+
+// ===========================================================================
+
+// Vehicle Seats
+const VRR_VEHSEAT_DRIVER = 0;
+const VRR_VEHSEAT_FRONTPASSENGER = 1;
+const VRR_VEHSEAT_REARLEFTPASSENGER = 2;
+const VRR_VEHSEAT_REARRIGHTPASSENGER = 3;
+
+// ===========================================================================
+
+/**
+ * @class Representing a vehicle's data. Loaded and saved in the database
+ */
+class VehicleData {
+ constructor(dbAssoc = false, vehicle = false) {
+ // General Info
+ this.databaseId = 0;
+ this.serverId = getServerId();
+ this.model = (vehicle != false) ? getVehicleModelIndexFromModel(vehicle.modelIndex) : 0;
+ this.vehicle = vehicle;
+ this.index = -1;
+ this.needsSaved = false;
+
+ // GTA IV
+ this.ivNetworkId = -1;
+ this.syncPosition = toVector3(0.0, 0.0, 0.0);
+ this.syncHeading = 0.0;
+
+ // Ownership
+ this.ownerType = VRR_VEHOWNER_NONE;
+ this.ownerId = 0;
+ this.buyPrice = 0;
+ this.rentPrice = 0;
+ this.rentedBy = false;
+ this.rentStart = 0;
+
+ // Position and Rotation
+ this.spawnPosition = (vehicle) ? vehicle.position : toVector3(0.0, 0.0, 0.0);
+ this.spawnRotation = (vehicle) ? vehicle.heading : 0.0;
+ this.spawnLocked = false;
+ this.interior = 0;
+ this.dimension = 0;
+
+ // Colour Info
+ this.colour1IsRGBA = 0;
+ this.colour2IsRGBA = 0;
+ this.colour3IsRGBA = 0;
+ this.colour4IsRGBA = 0;
+ this.colour1 = (vehicle) ? vehicle.colour1 : 1;
+ this.colour2 = (vehicle) ? vehicle.colour2 : 1;
+ this.colour3 = (vehicle) ? vehicle.colour3 : 1;
+ this.colour4 = (vehicle) ? vehicle.colour4 : 1;
+ this.livery = 3;
+
+ // Vehicle Attributes
+ this.locked = false;
+ this.engine = false;
+ this.lights = false;
+ this.health = 1000;
+ this.engineDamage = 0;
+ this.visualDamage = 0;
+ this.dirtLevel = 0;
+
+ this.trunkItemCache = [];
+ this.dashItemCache = [];
+
+ this.streamingRadioStation = -1;
+
+ // Other/Misc
+ this.insuranceAccount = 0;
+ this.fuel = 0;
+ this.flags = 0;
+ this.needsSaved = false;
+ this.whoAdded = 0;
+ this.whenAdded = 0;
+ this.licensePlate = "";
+
+ this.lastActiveTime = false;
+
+ if (dbAssoc) {
+ // General Info
+ this.databaseId = toInteger(dbAssoc["veh_id"]);
+ this.serverId = toInteger(dbAssoc["veh_server"]);
+ this.model = toInteger(dbAssoc["veh_model"]);
+
+ // Ownership
+ this.ownerType = toInteger(dbAssoc["veh_owner_type"]);
+ this.ownerId = toInteger(dbAssoc["veh_owner_id"]);
+ this.buyPrice = toInteger(dbAssoc["veh_buy_price"]);
+ this.rentPrice = toInteger(dbAssoc["veh_rent_price"]);
+
+ // Position and Rotation
+ this.spawnPosition = toVector3(dbAssoc["veh_pos_x"], dbAssoc["veh_pos_y"], dbAssoc["veh_pos_z"]);
+ this.spawnRotation = toInteger(dbAssoc["veh_rot_z"]);
+ this.spawnLocked = intToBool(toInteger(dbAssoc["veh_spawn_lock"]));
+ this.interior = toInteger(dbAssoc["veh_int"]);
+ this.dimension = toInteger(dbAssoc["veh_vw"]);
+
+ // Colour Info
+ this.colour1IsRGBA = intToBool(toInteger(dbAssoc["veh_col1_isrgba"]));
+ this.colour2IsRGBA = intToBool(toInteger(dbAssoc["veh_col2_isrgba"]));
+ this.colour3IsRGBA = intToBool(toInteger(dbAssoc["veh_col3_isrgba"]));
+ this.colour4IsRGBA = intToBool(toInteger(dbAssoc["veh_col4_isrgba"]));
+ this.colour1 = toInteger(dbAssoc["veh_col1"]);
+ this.colour2 = toInteger(dbAssoc["veh_col2"]);
+ this.colour3 = toInteger(dbAssoc["veh_col3"]);
+ 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"]));
+ this.lights = intToBool(toInteger(dbAssoc["veh_lights"]));
+ this.health = toInteger(dbAssoc["veh_damage_normal"]);
+ this.engineDamage = toInteger(dbAssoc["veh_damage_engine"]);
+ this.visualDamage = toInteger(dbAssoc["veh_damage_visual"]);
+ this.dirtLevel = toInteger(dbAssoc["veh_dirt_level"]);
+
+ // Other/Misc
+ this.insuranceAccount = toInteger(0);
+ this.fuel = toInteger(0);
+ this.flags = toInteger(0);
+ this.needsSaved = false;
+ this.whoAdded = toInteger(dbAssoc["veh_who_added"]);
+ this.whenAdded = toInteger(dbAssoc["veh_when_added"]);
+ this.licensePlate = toInteger(dbAssoc["veh_license_plate"]);
+ }
+ }
+};
+
+// ===========================================================================
+
function initVehicleScript() {
logToConsole(LOG_INFO, "[VRR.Vehicle]: Initializing vehicle script ...");
logToConsole(LOG_INFO, "[VRR.Vehicle]: Vehicle script initialized successfully!");
@@ -183,7 +341,7 @@ function getVehicleData(vehicle) {
}
}
} else {
- return getServerVehicles().find((v) => v.ivNetworkId == vehicle);
+ return getServerData().vehicles.find((v) => v.ivNetworkId == vehicle);
}
return false;
@@ -346,7 +504,7 @@ function deleteVehicleCommand(command, params, client) {
let dataIndex = getEntityData(vehicle, "vrr.dataSlot");
let vehicleName = getVehicleName(vehicle);
- quickDatabaseQuery(`DELETE FROM veh_main WHERE veh_id = ${getVehicleData(vehicle).databaseId}`);
+ quickDatabaseQuery(`UPDATE veh_main SET veh_deleted = 1 WHERE veh_id = ${getVehicleData(vehicle).databaseId}`);
getServerData().vehicles.splice(dataIndex, 1);
destroyElement(vehicle);
diff --git a/scripts/shared/const.js b/scripts/shared/const.js
index 2abf7090..581fe89d 100644
--- a/scripts/shared/const.js
+++ b/scripts/shared/const.js
@@ -97,6 +97,20 @@ const VRR_VEHBUYSTATE_EXITVEH = 2;
const VRR_VEHBUYSTATE_FARENOUGH = 3;
const VRR_VEHBUYSTATE_WRONGVEH = 4;
+// Islands
+const VRR_ISLAND_NONE = 0; // None
+const VRR_ISLAND_PORTLAND = 0; // Portland Island
+const VRR_ISLAND_STAUNTON = 1; // Staunton Island
+const VRR_ISLAND_SHORESIDEVALE = 2; // Shoreside Vale
+const VRR_ISLAND_VICEWEST = 0; // Western Island of VC
+const VRR_ISLAND_VICEEAST = 1; // Eastern Island of VC
+const VRR_ISLAND_LOSSANTOS = 0; // Los Santos
+const VRR_ISLAND_LASVENTURAS = 1; // Las Venturas
+const VRR_ISLAND_SANFIERRO = 2; // San Fierro
+const VRR_ISLAND_REDCOUNTYNORTH = 4; // Red County North (spans all the way from Palamino/shore on the east east to border of Flint County on the west)
+const VRR_ISLAND_BONECOUNTYNORTH = 5; // Bone County North (usually called Tierra Robada)
+const VRR_ISLAND_BONECOUNTYSOUTH = 6; // Bone County South
+
// 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;
@@ -120,4 +134,4 @@ 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
+const VRR_NPC_ACTION_GUARD_AREA = 7;
diff --git a/scripts/shared/gamedata.js b/scripts/shared/gamedata.js
index 8565a7fb..c987c6b3 100644
--- a/scripts/shared/gamedata.js
+++ b/scripts/shared/gamedata.js
@@ -169,6 +169,16 @@ let supportedFeatures = {
[VRR_GAME_MAFIA_ONE]: false,
[VRR_GAME_MAFIA_TWO]: false,
[VRR_GAME_MAFIA_THREE]: false
+ },
+ interior: {
+ [VRR_GAME_GTA_III]: false,
+ [VRR_GAME_GTA_VC]: true,
+ [VRR_GAME_GTA_SA]: true,
+ [VRR_GAME_GTA_IV]: false,
+ [VRR_GAME_GTA_IV_EFLC]: false,
+ [VRR_GAME_MAFIA_ONE]: false,
+ [VRR_GAME_MAFIA_TWO]: false,
+ [VRR_GAME_MAFIA_THREE]: false
}
};
@@ -4008,6 +4018,20 @@ let gameData = {
[170, "Grenade"],
[182, "RemoteDetonator"],
[1319, "GenericPackageWhite"],
+ [1343, "WoodenBox"],
+ [1339, "CardboardBox"],
+ [1336, "RustyBarrel"],
+ [1348, "TrashDumpster"],
+ [1338, "WoodenPallet"],
+ [1360, "TrafficCone"],
+ [1310, "WashingMachine"],
+ [1347, "TrashBin"],
+ [1396, "MailBox"],
+ [1359, "OrangeRoundRoadBarrier"],
+ [1398, "ParkBench"],
+ [1344, "RedBarrel"],
+ [1349, "StraightRoadBarrier"]
+ [1337, "YellowBarrel"],
],
[VRR_GAME_GTA_VC]: [ // GTA VC
[259, "BrassKnuckles"],
@@ -4769,6 +4793,8 @@ let gameData = {
[VRR_GAME_GTA_III]: [1],
[VRR_GAME_GTA_VC]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[VRR_GAME_GTA_SA]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
+ [VRR_GAME_GTA_IV]: [1, 2, 3],
+ [VRR_GAME_GTA_IV_EFLC]: [1, 2, 3],
},
blipSprites: {
[VRR_GAME_GTA_III]: { // GTA III
@@ -5724,6 +5750,8 @@ let gameData = {
Apartment1: [toVector3(891.87, -308.28, 8.72), 0, false, -1],
JailCell: [toVector3(328.40, -1093.31, 25.98), 0, false, -1],
Church: [toVector3(13.87, -1122.43, 26.12), 0, false, -1],
+ Mansion: [toVector3(1461.00, -173.87, 55.78), 0, false, -1],
+ Garage: [toVector3(-420.69, 289.86, 62.96), 0, false, -1],
},
[VRR_GAME_GTA_VC]: { // GTA VC
Mall: [toVector3(379.62, 1007.00, 19.22), 4, false, -1],