diff --git a/IDEAS.md b/IDEAS.md
index 42b7b7af..555d241a 100644
--- a/IDEAS.md
+++ b/IDEAS.md
@@ -364,4 +364,13 @@ Obviously this would still be using slashes for commands still. The way this wor
* Set model
* Set drop position offset
* Set drop rotation offset
----
\ No newline at end of file
+---
+### Tutorial
+ * Pick up item (grab bottle of beer off ground)
+ * Equip item (switch to bottle of beer item)
+ * Use item (drink bottle of beer item)
+ * Drop item (drop empty bottle on ground)
+ * Take item from vehicle trunk (grab crate from vehicle)
+ * Place item on ground (crate)
+ * Take second beer from crate
+ * Store second beer in trunk
\ No newline at end of file
diff --git a/TODO.md b/TODO.md
index d0094456..d07c17b1 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,21 +1,5 @@
-## Ice cream job
- * VC: -862.39, -578.35, 11.10
-------------------------------------------------------
-* Cut down on engine/lights/lock messages.
-* Get coords for more bus routes.
-* Add more jobs
-------------------------------------------------------
-## Tutorial
- - Pick up item (grab bottle of beer off ground)
- - Equip item (switch to bottle of beer item)
- - Use item (drink bottle of beer item)
- - Drop item (drop empty bottle on ground)
- - Take item from vehicle trunk (grab crate from vehicle)
- - Place item on ground (crate)
- - Take second beer from crate
- - Store second beer in trunk
-
-------------------------------------------------------
-
-------------------------------------------------------
-* Change pizza delivery job to pick a random house door instead of pre-established places on the street.
\ No newline at end of file
+* Finish auto-translate
+* Add /autotranslate to enable/disable automatic chat translations for all languages, or specific ones by short code (RU, ES, etc)
+* Finish working on the new job route system
+* Add ways to acquire drugs. Pot/coke plants, meth labs, etc
+* Finish setting up the persistent NPC system
\ No newline at end of file
diff --git a/config/accents.json b/config/accents.json
new file mode 100644
index 00000000..2b5cb10f
--- /dev/null
+++ b/config/accents.json
@@ -0,0 +1,26 @@
+[
+ "English",
+ "French",
+ "Russian",
+ "Scottish",
+ "Irish",
+ "Spanish",
+ "Southern American",
+ "Italian",
+ "Australian",
+ "Jamaican",
+ "Israeli",
+ "Dutch",
+ "Brazilian",
+ "Portuguese",
+ "German",
+ "Canadian",
+ "Chinese",
+ "Japanese",
+ "Turkish",
+ "Korean",
+ "Estonian",
+ "Sicilian",
+ "Indian",
+ "Rough"
+]
\ No newline at end of file
diff --git a/config/animations.json b/config/animations.json
deleted file mode 100644
index fa53b0d7..00000000
--- a/config/animations.json
+++ /dev/null
@@ -1,134 +0,0 @@
-{
- "gta:iii": [
- ["walk", 0, 0, 1, 0.0, null, null, null, null, 0],
- ["jog", 0, 1, 1, 0.0, null, null, null, null, 0],
- ["look1", 0, 7, 1, 0.0, null, null, null, null, 0],
- ["tired", 0, 9, 1, 0.0, null, null, null, null, 0],
- ["raisegun", 0, 10, 1, 0.0, null, null, null, null, 0],
- ["wave", 0, 12, 1, 0.0, null, null, null, null, 0],
- ["talk", 0, 11, 1, 0.0, null, null, null, null, 0],
- ["stomachhit", 0, 18, 1, 0.0, null, null, null, null, 0],
- ["headhit", 0, 18, 1, 0.0, null, null, null, null, 0],
- ["throw1", 0, 53, 1, 0.0, null, null, null, null, 0],
- ["throw2", 0, 54, 1, 0.0, null, null, null, null, 0],
- ["punch1", 0, 54, 1, 0.0, null, null, null, null, 0],
- ["headbutt", 0, 70, 1, 0.0, null, null, null, null, 0],
- ["kick", 0, 71, 1, 0.0, null, null, null, null, 0],
- ["kneekick", 0, 72, 1, 0.0, null, null, null, null, 0],
- ["punch2", 0, 73, 1, 0.0, null, null, null, null, 0],
- ["flipkick", 0, 74, 1, 0.0, null, null, null, null, 0],
- ["bow", 0, 126, 1, 0.0, null, null, null, null, 0],
- ["opendoor1", 0, 127, 1, 0.0, null, null, null, null, 0],
- ["opendoor2", 0, 128, 1, 0.0, null, null, null, null, 0],
- ["falling", 0, 151, 1, 0.0, null, null, null, null, 0],
- ["dive", 0, 156, 1, 0.0, null, null, null, null, 0],
- ["headscratch", 0, 157, 1, 0.0, null, null, null, null, 0],
- ["look2", 0, 158, 1, 0.0, null, null, null, null, 0],
- ["plant", 0, 162, 1, 0.0, null, null, null, null, 0],
- ["cower", 0, 163, 1, 0.0, null, null, null, null, 0],
- ["aimdown", 0, 160, 1, 0.0, null, null, null, null, 0],
- ["aimcrouch", 0, 165, 1, 0.0, null, null, null, null, 0],
- ["throw3", 0, 166, 1, 0.0, null, null, null, null, 0],
- ["handsup", 0, 167, 1, 0.0, null, null, null, null, 0]
- ],
- "gta:vc": [
- ["walk", 0, 0, 1, 0.0, null, null, null, null, 0],
- ["jog", 0, 1, 1, 0.0, null, null, null, null, 0],
- ["handcuffs", 0, 7, 1, 0.0, null, null, null, null, 0],
- ["tired", 0, 9, 1, 0.0, null, null, null, null, 0],
- ["raisegun", 0, 10, 1, 0.0, null, null, null, null, 0],
- ["wave", 0, 12, 1, 0.0, null, null, null, null, 0],
- ["talk", 0, 11, 1, 0.0, null, null, null, null, 0],
- ["stomachhit", 0, 18, 1, 0.0, null, null, null, null, 0],
- ["headhit", 0, 18, 1, 0.0, null, null, null, null, 0],
- ["headbutt", 0, 49, 1, 0.0, null, null, null, null, 0],
- ["kick", 0, 50, 1, 0.0, null, null, null, null, 0],
- ["kneekick", 0, 51, 1, 0.0, null, null, null, null, 0],
- ["throw2", 0, 54, 1, 0.0, null, null, null, null, 0],
- ["punch1", 0, 52, 1, 0.0, null, null, null, null, 0],
- ["punch2", 0, 53, 1, 0.0, null, null, null, null, 0],
- ["flipkick", 0, 54, 1, 0.0, null, null, null, null, 0],
- ["headscratch", 0, 152, 1, 0.0, null, null, null, null, 0],
- ["aimdown", 0, 155, 1, 0.0, null, null, null, null, 0],
- ["look2", 0, 153, 1, 0.0, null, null, null, null, 0],
- ["handsup", 0, 161, 1, 0.0, null, null, null, null, 0],
- ["cower", 0, 162, 1, 0.0, null, null, null, null, 0],
- ["fucku", 0, 163, 1, 0.0, null, null, null, null, 0],
- ["phone", 0, 166, 1, 0.0, null, null, null, null, 0],
- ["sit", 0, 169, 1, 1.0, null, null, null, null, 0],
- ["atm", 0, 171, 1, 0.0, null, null, null, null, 0],
- ["cpr", 24, 214, 1, 0.0, null, null, null, null, 0],
- ["idle1", 26, 215, 1, 0.0, null, null, null, null, 0],
- ["idle2", 26, 216, 1, 0.0, null, null, null, null, 0],
- ["idle3", 26, 217, 1, 0.0, null, null, null, null, 0],
- ["idle4", 26, 218, 1, 0.0, null, null, null, null, 0],
- ["dance1", 28, 226, 1, 0.0, null, null, null, null, 0],
- ["dance2", 28, 227, 1, 0.0, null, null, null, null, 0],
- ["dance3", 28, 228, 1, 0.0, null, null, null, null, 0],
- ["dance4", 28, 229, 1, 0.0, null, null, null, null, 0],
- ["dance5", 28, 230, 1, 0.0, null, null, null, null, 0],
- ["dance6", 28, 231, 1, 0.0, null, null, null, null, 0],
- ["dance7", 28, 232, 1, 0.0, null, null, null, null, 0],
- ["sitright", 0, 169, 1, 0.0, null, null, null, null, 4],
- ["sitleft", 0, 169, 1, 0.0, null, null, null, null, 3],
- ["sitforward", 0, 169, 1, 0.0, null, null, null, null, 1],
- ["sitback", 0, 169, 1, 0.0, null, null, null, null, 2]
- ],
- "gta:sa":[
- ["walk", 0, 0, 1, 0.0, null, null, null, null, 0],
- ["jog", 0, 1, 1, 0.0, null, null, null, null, 0],
- ["look1", 0, 4, 1, 0.0, null, null, null, null, 0],
- ["holdrifle", 0, 11, 1, 0.0, null, null, null, null, 0],
- ["talk1", 0, 12, 1, 0.0, null, null, null, null, 0],
- ["wave1", 0, 13, 1, 0.0, null, null, null, null, 0],
- ["swim1", 0, 14, 1, 0.0, null, null, null, null, 0],
- ["die1", 0, 15, 1, 0.0, null, null, null, null, 0],
- ["die2", 0, 16, 1, 0.0, null, null, null, null, 0],
- ["diehead", 0, 19, 1, 0.0, null, null, null, null, 0],
- ["diestomach", 0, 20, 1, 0.0, null, null, null, null, 0],
- ["choke", 0, 21, 1, 0.0, null, null, null, null, 0],
- ["remotepress", 0, 48, 1, 0.0, null, null, null, null, 0],
- ["pickup1", 0, 99, 1, 0.0, null, null, null, null, 0],
- ["pickup2", 0, 100, 1, 0.0, null, null, null, null, 0],
- ["backhandright", 0, 103, 1, 0.0, null, null, null, null, 0],
- ["backhandleft", 0, 104, 1, 0.0, null, null, null, null, 0],
- ["knockback", 0, 105, 1, 0.0, null, null, null, null, 0],
- ["idle1", 0, 135, 1, 0.0, null, null, null, null, 0],
- ["knockback", 0, 105, 1, 0.0, null, null, null, null, 0],
- ["cower", 0, 141, 1, 0.0, null, null, null, null, 0],
- ["handsup", 0, 142, 1, 0.0, null, null, null, null, 0],
- ["fucku", 0, 144, 1, 0.0, null, null, null, null, 0],
- ["phoneout", 0, 145, 1, 0.0, null, null, null, null, 0],
- ["phonein", 0, 146, 1, 0.0, null, null, null, null, 0],
- ["phonetalk", 0, 146, 1, 0.0, null, null, null, null, 0],
- ["sit1", 0, 150, 1, 0.0, null, null, null, null, 0],
- ["atm", 0, 151, 1, 0.0, null, null, null, null, 0],
- ["mindtrick", 0, 153, 1, 0.0, null, null, null, null, 0],
- ["faceshocked", 0, 150, 1, 0.0, null, null, null, null, 0],
- ["facesurprised", 0, 150, 1, 0.0, null, null, null, null, 0],
- ["faceconfused", 0, 150, 1, 0.0, null, null, null, null, 0],
- ["faceangry", 0, 159, 1, 0.0, null, null, null, null, 0],
- ["facetalk1", 0, 160, 1, 0.0, null, null, null, null, 0],
- ["look2", 0, 165, 1, 0.0, null, null, null, null, 0],
- ["gestureno", 0, 166, 1, 0.0, null, null, null, null, 0],
- ["gestureyes", 0, 167, 1, 0.0, null, null, null, null, 0],
- ["wave2", 0, 168, 1, 0.0, null, null, null, null, 0],
- ["snort", 0, 169, 1, 0.0, null, null, null, null, 0],
- ["sitright", 0, 150, 1, 0.0, null, null, null, null, 4],
- ["sitleft", 0, 150, 1, 0.0, null, null, null, null, 3],
- ["sitforward", 0, 150, 1, 0.0, null, null, null, null, 1],
- ["sitback", 0, 150, 1, 0.0, null, null, null, null, 2]
- ],
- "invalid1": [
-
- ],
- "gta:iv": [
- ["dance1", "DAN_LOOP_A", "DANCING", 1, 16.0, true, false, true, false, 0]
- ],
- "mafia:one": [
- ["phonepickup", "TelVytoceni"],
- ["phonetalk", "TelStativ"],
- ["phonehangup", "TelZaveseni"],
- ["phonehangup", "TelZaveseni"]
- ]
-}
\ No newline at end of file
diff --git a/config/economy.json b/config/economy.json
index f1d8d5c4..15284ba5 100644
--- a/config/economy.json
+++ b/config/economy.json
@@ -3,6 +3,7 @@
"applyTax": true,
"applyUpkeep": true,
"grossIncomeMultiplier": 1.0,
+ "incomeTaxRate": 0.7,
"upKeepCosts": {
"upKeepPerVehicle": 250,
"upKeepPerHouse": 350,
diff --git a/config/email.json b/config/email.json
index 2108d842..224bdb3d 100644
--- a/config/email.json
+++ b/config/email.json
@@ -13,8 +13,10 @@
"confirmEmail": "Welcome to {SERVERNAME}!\nPlease confirm your email by using the command /verifyemail in-game.\n\nYour verification code is: {VERIFICATIONCODE}",
"emailConfirmed": "Your email has been confirmed on {SERVERNAME}!\nYou may now use this email to reset your password, require two-factor authentication on login, receive offline notifications, and more!",
"twoFactorAuthentication": "Please enter the following code to continue on {SERVERNAME} for {GAMENAME}: {2FACODE}",
- "accountAuthSuccessAlert": "You or someone else has successfully logged in to your account on {SERVERNAME} for {GAMENAME}.\nIP Address: {IPADDRESS}\nLocation: {LOCATION}\nTimestamp: {TIMESTAMP}",
+ "accountAuthSuccessAlert": "You or someone else has successfully logged in to your account on {SERVERNAME} for {GAMENAME}.\n\nIP Address: {IPADDRESS}\nLocation: {LOCATION}\nTimestamp: {TIMESTAMP}\n\nIf you have two-factor authentication enabled (Using /2fa in-game), your account can't be accessed unless a correct 2FA code is entered.",
"accountAuthFailAlert": "You or someone else has failed to login to your account on {SERVERNAME} for {GAMENAME}.\nIP Address: {IPADDRESS}\nLocation: {LOCATION}\nTimestamp: {TIMESTAMP}",
- "offlineMessageAlert": "You have received a private message on {SERVERNAME} for {GAMENAME}. \nYou are receiving this notification because you enabled email message notifications when you're not connected to the server.\nFrom: {FROMNAME}\nTimestamp: {TIMESTAMP}\nMessage: {MESSAGE}"
+ "offlineMessageAlert": "You have received a private message on {SERVERNAME} for {GAMENAME}. \nYou are receiving this notification because you enabled email message notifications when you're not connected to the server.\nFrom: {FROMNAME}\nTimestamp: {TIMESTAMP}\nMessage: {MESSAGE}",
+ "confirmPasswordReset": "You (or someone else) requested to reset your password on {SERVERNAME}!\nPlease confirm this request by entering the code below into the password reset window in-game.\n\nYour verification code is: {VERIFICATIONCODE}\n\n\nIf you did not request a password reset, then there's nothing to worry about since your password can only be reset with the code above.",
+ "passwordChanged": "Your password on {SERVERNAME} has been changed successfully!"
}
}
\ No newline at end of file
diff --git a/config/locale.json b/config/locale.json
index 24138b83..3eccf479 100644
--- a/config/locale.json
+++ b/config/locale.json
@@ -1,3 +1,10 @@
-[
- ["English", "english"]
-]
\ No newline at end of file
+{
+ "apiEmail": "example@example.com",
+ "defaultLanguage": "en",
+ "locales": [
+ ["English", "english", "en"],
+ ["Russian", "russian", "ru"],
+ ["Polish", "polish", "pl"],
+ ["Spanish", "spanish", "es"]
+ ]
+}
\ No newline at end of file
diff --git a/config/roleplay.json b/config/roleplay.json
deleted file mode 100644
index cc6f63bf..00000000
--- a/config/roleplay.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "defaultStreamingRadioVolume": 50,
- "npcFarProximity": 100,
- "npcMediumProximity": 40,
- "npcCloseProximity": 12,
- "meActionDistance": 20,
- "doActionDistance": 15,
- "shoutDistance": 30,
- "talkDistance": 10,
- "whisperDistance": 2,
- "megaphoneDistance": 40,
- "vehicleLockDistance": 5,
- "startWorkingDistance": 5,
- "takeJobDistance": 5,
- "stopWorkingDistance": 10,
- "spawnCarDistance": 5,
- "payAndSprayDistance": 5,
- "exitPropertyDistance": 3.0,
- "enterPropertyDistance": 3.0,
- "businessDimensionStart": 5000,
- "houseDimensionStart": 100,
- "buyVehicleDriveAwayDistance": 25.0,
- "returnToJobVehicleTime": 30,
- "walkieTalkieSpeakerDistance": 10,
- "walkieTalkieTalkDistance": 10,
- "phoneSpeakerDistance": 10,
- "phoneTalkDistance": 10,
- "tazerEffectDuration": 15000,
- "subAccountNameAllowedCharacters": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
- "accents": [
- "English",
- "French",
- "Russian",
- "Scottish",
- "Irish",
- "Spanish",
- "Southern American",
- "Italian",
- "Australian",
- "Jamaican",
- "Israeli",
- "Dutch",
- "Brazilian",
- "Portuguese",
- "German",
- "Canadian",
- "Chinese",
- "Japanese",
- "Turkish",
- "Korean",
- "Estonian",
- "Sicilian",
- "Indian",
- "Rough"
- ]
-}
\ No newline at end of file
diff --git a/files/images/skins/gta3/Skin000.png b/files/images/skins/gta3/Skin000.png
deleted file mode 100644
index 054647c9..00000000
Binary files a/files/images/skins/gta3/Skin000.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin001.png b/files/images/skins/gta3/Skin001.png
deleted file mode 100644
index fb9707f9..00000000
Binary files a/files/images/skins/gta3/Skin001.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin002.png b/files/images/skins/gta3/Skin002.png
deleted file mode 100644
index 8646b9c0..00000000
Binary files a/files/images/skins/gta3/Skin002.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin003.png b/files/images/skins/gta3/Skin003.png
deleted file mode 100644
index 8cc84c27..00000000
Binary files a/files/images/skins/gta3/Skin003.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin004.png b/files/images/skins/gta3/Skin004.png
deleted file mode 100644
index 1f5db208..00000000
Binary files a/files/images/skins/gta3/Skin004.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin005.png b/files/images/skins/gta3/Skin005.png
deleted file mode 100644
index 013d815a..00000000
Binary files a/files/images/skins/gta3/Skin005.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin006.png b/files/images/skins/gta3/Skin006.png
deleted file mode 100644
index 368704ea..00000000
Binary files a/files/images/skins/gta3/Skin006.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin007.png b/files/images/skins/gta3/Skin007.png
deleted file mode 100644
index b983849b..00000000
Binary files a/files/images/skins/gta3/Skin007.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin008.png b/files/images/skins/gta3/Skin008.png
deleted file mode 100644
index f8227b17..00000000
Binary files a/files/images/skins/gta3/Skin008.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin009.png b/files/images/skins/gta3/Skin009.png
deleted file mode 100644
index ee5e8a7f..00000000
Binary files a/files/images/skins/gta3/Skin009.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin010.png b/files/images/skins/gta3/Skin010.png
deleted file mode 100644
index 3d2a456a..00000000
Binary files a/files/images/skins/gta3/Skin010.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin011.png b/files/images/skins/gta3/Skin011.png
deleted file mode 100644
index 09e47b03..00000000
Binary files a/files/images/skins/gta3/Skin011.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin012.png b/files/images/skins/gta3/Skin012.png
deleted file mode 100644
index a2b17951..00000000
Binary files a/files/images/skins/gta3/Skin012.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin013.png b/files/images/skins/gta3/Skin013.png
deleted file mode 100644
index 1dd5a9ba..00000000
Binary files a/files/images/skins/gta3/Skin013.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin014.png b/files/images/skins/gta3/Skin014.png
deleted file mode 100644
index 22983a9b..00000000
Binary files a/files/images/skins/gta3/Skin014.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin015.png b/files/images/skins/gta3/Skin015.png
deleted file mode 100644
index d0cbce28..00000000
Binary files a/files/images/skins/gta3/Skin015.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin016.png b/files/images/skins/gta3/Skin016.png
deleted file mode 100644
index 36a6a448..00000000
Binary files a/files/images/skins/gta3/Skin016.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin017.png b/files/images/skins/gta3/Skin017.png
deleted file mode 100644
index b384c598..00000000
Binary files a/files/images/skins/gta3/Skin017.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin018.png b/files/images/skins/gta3/Skin018.png
deleted file mode 100644
index 7d1d35aa..00000000
Binary files a/files/images/skins/gta3/Skin018.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin019.png b/files/images/skins/gta3/Skin019.png
deleted file mode 100644
index 5484e910..00000000
Binary files a/files/images/skins/gta3/Skin019.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin020.png b/files/images/skins/gta3/Skin020.png
deleted file mode 100644
index ceadc348..00000000
Binary files a/files/images/skins/gta3/Skin020.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin021.png b/files/images/skins/gta3/Skin021.png
deleted file mode 100644
index 113003ae..00000000
Binary files a/files/images/skins/gta3/Skin021.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin022.png b/files/images/skins/gta3/Skin022.png
deleted file mode 100644
index 2d4442dc..00000000
Binary files a/files/images/skins/gta3/Skin022.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin023.png b/files/images/skins/gta3/Skin023.png
deleted file mode 100644
index 0d0cfd8f..00000000
Binary files a/files/images/skins/gta3/Skin023.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin024.png b/files/images/skins/gta3/Skin024.png
deleted file mode 100644
index 228c7838..00000000
Binary files a/files/images/skins/gta3/Skin024.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin025.png b/files/images/skins/gta3/Skin025.png
deleted file mode 100644
index e658a1d6..00000000
Binary files a/files/images/skins/gta3/Skin025.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin030.png b/files/images/skins/gta3/Skin030.png
deleted file mode 100644
index a6fa7469..00000000
Binary files a/files/images/skins/gta3/Skin030.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin031.png b/files/images/skins/gta3/Skin031.png
deleted file mode 100644
index b7162f86..00000000
Binary files a/files/images/skins/gta3/Skin031.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin032.png b/files/images/skins/gta3/Skin032.png
deleted file mode 100644
index 1d427ae0..00000000
Binary files a/files/images/skins/gta3/Skin032.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin033.png b/files/images/skins/gta3/Skin033.png
deleted file mode 100644
index 0ee70d9e..00000000
Binary files a/files/images/skins/gta3/Skin033.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin034.png b/files/images/skins/gta3/Skin034.png
deleted file mode 100644
index 1be3fc2f..00000000
Binary files a/files/images/skins/gta3/Skin034.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin035.png b/files/images/skins/gta3/Skin035.png
deleted file mode 100644
index d1674541..00000000
Binary files a/files/images/skins/gta3/Skin035.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin036.png b/files/images/skins/gta3/Skin036.png
deleted file mode 100644
index 21a05e7d..00000000
Binary files a/files/images/skins/gta3/Skin036.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin037.png b/files/images/skins/gta3/Skin037.png
deleted file mode 100644
index ccf7f5d3..00000000
Binary files a/files/images/skins/gta3/Skin037.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin038.png b/files/images/skins/gta3/Skin038.png
deleted file mode 100644
index 6243e69d..00000000
Binary files a/files/images/skins/gta3/Skin038.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin039.png b/files/images/skins/gta3/Skin039.png
deleted file mode 100644
index 196a08c3..00000000
Binary files a/files/images/skins/gta3/Skin039.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin040.png b/files/images/skins/gta3/Skin040.png
deleted file mode 100644
index d5ed9ffb..00000000
Binary files a/files/images/skins/gta3/Skin040.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin041.png b/files/images/skins/gta3/Skin041.png
deleted file mode 100644
index dda6e0a1..00000000
Binary files a/files/images/skins/gta3/Skin041.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin042.png b/files/images/skins/gta3/Skin042.png
deleted file mode 100644
index 20ebee5d..00000000
Binary files a/files/images/skins/gta3/Skin042.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin043.png b/files/images/skins/gta3/Skin043.png
deleted file mode 100644
index 34d78a85..00000000
Binary files a/files/images/skins/gta3/Skin043.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin044.png b/files/images/skins/gta3/Skin044.png
deleted file mode 100644
index 58c0b1a1..00000000
Binary files a/files/images/skins/gta3/Skin044.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin045.png b/files/images/skins/gta3/Skin045.png
deleted file mode 100644
index 5ef32eb7..00000000
Binary files a/files/images/skins/gta3/Skin045.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin046.png b/files/images/skins/gta3/Skin046.png
deleted file mode 100644
index 30ac43a7..00000000
Binary files a/files/images/skins/gta3/Skin046.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin047.png b/files/images/skins/gta3/Skin047.png
deleted file mode 100644
index 5bf4f32c..00000000
Binary files a/files/images/skins/gta3/Skin047.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin048.png b/files/images/skins/gta3/Skin048.png
deleted file mode 100644
index 212418ce..00000000
Binary files a/files/images/skins/gta3/Skin048.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin049.png b/files/images/skins/gta3/Skin049.png
deleted file mode 100644
index 0f5516d2..00000000
Binary files a/files/images/skins/gta3/Skin049.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin050.png b/files/images/skins/gta3/Skin050.png
deleted file mode 100644
index 2711dbc7..00000000
Binary files a/files/images/skins/gta3/Skin050.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin051.png b/files/images/skins/gta3/Skin051.png
deleted file mode 100644
index e3c8c102..00000000
Binary files a/files/images/skins/gta3/Skin051.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin052.png b/files/images/skins/gta3/Skin052.png
deleted file mode 100644
index 95463025..00000000
Binary files a/files/images/skins/gta3/Skin052.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin053.png b/files/images/skins/gta3/Skin053.png
deleted file mode 100644
index cf759648..00000000
Binary files a/files/images/skins/gta3/Skin053.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin054.png b/files/images/skins/gta3/Skin054.png
deleted file mode 100644
index c4c80fd5..00000000
Binary files a/files/images/skins/gta3/Skin054.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin055.png b/files/images/skins/gta3/Skin055.png
deleted file mode 100644
index 7bc56254..00000000
Binary files a/files/images/skins/gta3/Skin055.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin056.png b/files/images/skins/gta3/Skin056.png
deleted file mode 100644
index 211d465c..00000000
Binary files a/files/images/skins/gta3/Skin056.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin057.png b/files/images/skins/gta3/Skin057.png
deleted file mode 100644
index 9e2900d3..00000000
Binary files a/files/images/skins/gta3/Skin057.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin058.png b/files/images/skins/gta3/Skin058.png
deleted file mode 100644
index 271bf295..00000000
Binary files a/files/images/skins/gta3/Skin058.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin059.png b/files/images/skins/gta3/Skin059.png
deleted file mode 100644
index 5fcbd06e..00000000
Binary files a/files/images/skins/gta3/Skin059.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin060.png b/files/images/skins/gta3/Skin060.png
deleted file mode 100644
index 2514a4c1..00000000
Binary files a/files/images/skins/gta3/Skin060.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin061.png b/files/images/skins/gta3/Skin061.png
deleted file mode 100644
index e4a723af..00000000
Binary files a/files/images/skins/gta3/Skin061.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin062.png b/files/images/skins/gta3/Skin062.png
deleted file mode 100644
index b55d2336..00000000
Binary files a/files/images/skins/gta3/Skin062.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin063.png b/files/images/skins/gta3/Skin063.png
deleted file mode 100644
index f4e946df..00000000
Binary files a/files/images/skins/gta3/Skin063.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin064.png b/files/images/skins/gta3/Skin064.png
deleted file mode 100644
index 396e25eb..00000000
Binary files a/files/images/skins/gta3/Skin064.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin065.png b/files/images/skins/gta3/Skin065.png
deleted file mode 100644
index 76ae94fe..00000000
Binary files a/files/images/skins/gta3/Skin065.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin066.png b/files/images/skins/gta3/Skin066.png
deleted file mode 100644
index c7087802..00000000
Binary files a/files/images/skins/gta3/Skin066.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin067.png b/files/images/skins/gta3/Skin067.png
deleted file mode 100644
index 50621650..00000000
Binary files a/files/images/skins/gta3/Skin067.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin068.png b/files/images/skins/gta3/Skin068.png
deleted file mode 100644
index 6e5afe0b..00000000
Binary files a/files/images/skins/gta3/Skin068.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin069.png b/files/images/skins/gta3/Skin069.png
deleted file mode 100644
index 7a2d79d1..00000000
Binary files a/files/images/skins/gta3/Skin069.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin070.png b/files/images/skins/gta3/Skin070.png
deleted file mode 100644
index b31967e3..00000000
Binary files a/files/images/skins/gta3/Skin070.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin071.png b/files/images/skins/gta3/Skin071.png
deleted file mode 100644
index 6f31ef77..00000000
Binary files a/files/images/skins/gta3/Skin071.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin072.png b/files/images/skins/gta3/Skin072.png
deleted file mode 100644
index 8e626a5a..00000000
Binary files a/files/images/skins/gta3/Skin072.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin073.png b/files/images/skins/gta3/Skin073.png
deleted file mode 100644
index e2654991..00000000
Binary files a/files/images/skins/gta3/Skin073.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin074.png b/files/images/skins/gta3/Skin074.png
deleted file mode 100644
index 261022ab..00000000
Binary files a/files/images/skins/gta3/Skin074.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin075.png b/files/images/skins/gta3/Skin075.png
deleted file mode 100644
index b39eccdc..00000000
Binary files a/files/images/skins/gta3/Skin075.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin076.png b/files/images/skins/gta3/Skin076.png
deleted file mode 100644
index 00840333..00000000
Binary files a/files/images/skins/gta3/Skin076.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin077.png b/files/images/skins/gta3/Skin077.png
deleted file mode 100644
index 7047691f..00000000
Binary files a/files/images/skins/gta3/Skin077.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin078.png b/files/images/skins/gta3/Skin078.png
deleted file mode 100644
index 60e4d7b3..00000000
Binary files a/files/images/skins/gta3/Skin078.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin080.png b/files/images/skins/gta3/Skin080.png
deleted file mode 100644
index 2f9cac82..00000000
Binary files a/files/images/skins/gta3/Skin080.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin081.png b/files/images/skins/gta3/Skin081.png
deleted file mode 100644
index 9b4791e8..00000000
Binary files a/files/images/skins/gta3/Skin081.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin082.png b/files/images/skins/gta3/Skin082.png
deleted file mode 100644
index b25b8290..00000000
Binary files a/files/images/skins/gta3/Skin082.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin083.png b/files/images/skins/gta3/Skin083.png
deleted file mode 100644
index 7301e7f1..00000000
Binary files a/files/images/skins/gta3/Skin083.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin084.png b/files/images/skins/gta3/Skin084.png
deleted file mode 100644
index d4933bad..00000000
Binary files a/files/images/skins/gta3/Skin084.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin085.png b/files/images/skins/gta3/Skin085.png
deleted file mode 100644
index 84e2b06a..00000000
Binary files a/files/images/skins/gta3/Skin085.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin086.png b/files/images/skins/gta3/Skin086.png
deleted file mode 100644
index 694d6a3e..00000000
Binary files a/files/images/skins/gta3/Skin086.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin087.png b/files/images/skins/gta3/Skin087.png
deleted file mode 100644
index c1acc76c..00000000
Binary files a/files/images/skins/gta3/Skin087.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin088.png b/files/images/skins/gta3/Skin088.png
deleted file mode 100644
index 64c8954b..00000000
Binary files a/files/images/skins/gta3/Skin088.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin089.png b/files/images/skins/gta3/Skin089.png
deleted file mode 100644
index 22a36620..00000000
Binary files a/files/images/skins/gta3/Skin089.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin090.png b/files/images/skins/gta3/Skin090.png
deleted file mode 100644
index acf96fdc..00000000
Binary files a/files/images/skins/gta3/Skin090.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin091 (1).png b/files/images/skins/gta3/Skin091 (1).png
deleted file mode 100644
index 9dfc6088..00000000
Binary files a/files/images/skins/gta3/Skin091 (1).png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin091.png b/files/images/skins/gta3/Skin091.png
deleted file mode 100644
index 18205bde..00000000
Binary files a/files/images/skins/gta3/Skin091.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin092.png b/files/images/skins/gta3/Skin092.png
deleted file mode 100644
index 5f7ff067..00000000
Binary files a/files/images/skins/gta3/Skin092.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin093.png b/files/images/skins/gta3/Skin093.png
deleted file mode 100644
index c15a3f5e..00000000
Binary files a/files/images/skins/gta3/Skin093.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin094.png b/files/images/skins/gta3/Skin094.png
deleted file mode 100644
index b697cc4c..00000000
Binary files a/files/images/skins/gta3/Skin094.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin095.png b/files/images/skins/gta3/Skin095.png
deleted file mode 100644
index ccec4296..00000000
Binary files a/files/images/skins/gta3/Skin095.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin096.png b/files/images/skins/gta3/Skin096.png
deleted file mode 100644
index 14f1e7e8..00000000
Binary files a/files/images/skins/gta3/Skin096.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin097.png b/files/images/skins/gta3/Skin097.png
deleted file mode 100644
index 818dfbb9..00000000
Binary files a/files/images/skins/gta3/Skin097.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin098.png b/files/images/skins/gta3/Skin098.png
deleted file mode 100644
index a9f0cee3..00000000
Binary files a/files/images/skins/gta3/Skin098.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin099.png b/files/images/skins/gta3/Skin099.png
deleted file mode 100644
index 3c3167ad..00000000
Binary files a/files/images/skins/gta3/Skin099.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin100.png b/files/images/skins/gta3/Skin100.png
deleted file mode 100644
index 36e79af9..00000000
Binary files a/files/images/skins/gta3/Skin100.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin101.png b/files/images/skins/gta3/Skin101.png
deleted file mode 100644
index dc47a142..00000000
Binary files a/files/images/skins/gta3/Skin101.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin102.png b/files/images/skins/gta3/Skin102.png
deleted file mode 100644
index f4f2460f..00000000
Binary files a/files/images/skins/gta3/Skin102.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin103.png b/files/images/skins/gta3/Skin103.png
deleted file mode 100644
index ee73eda1..00000000
Binary files a/files/images/skins/gta3/Skin103.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin104.png b/files/images/skins/gta3/Skin104.png
deleted file mode 100644
index 64aff992..00000000
Binary files a/files/images/skins/gta3/Skin104.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin105.png b/files/images/skins/gta3/Skin105.png
deleted file mode 100644
index 31eeb0b3..00000000
Binary files a/files/images/skins/gta3/Skin105.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin106.png b/files/images/skins/gta3/Skin106.png
deleted file mode 100644
index 3bf3d541..00000000
Binary files a/files/images/skins/gta3/Skin106.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin107.png b/files/images/skins/gta3/Skin107.png
deleted file mode 100644
index 437fe173..00000000
Binary files a/files/images/skins/gta3/Skin107.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin108.png b/files/images/skins/gta3/Skin108.png
deleted file mode 100644
index 2c729ff1..00000000
Binary files a/files/images/skins/gta3/Skin108.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin109.png b/files/images/skins/gta3/Skin109.png
deleted file mode 100644
index b372db96..00000000
Binary files a/files/images/skins/gta3/Skin109.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin110.png b/files/images/skins/gta3/Skin110.png
deleted file mode 100644
index 22f505e2..00000000
Binary files a/files/images/skins/gta3/Skin110.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin111.png b/files/images/skins/gta3/Skin111.png
deleted file mode 100644
index b5814ace..00000000
Binary files a/files/images/skins/gta3/Skin111.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin112.png b/files/images/skins/gta3/Skin112.png
deleted file mode 100644
index 56faadbf..00000000
Binary files a/files/images/skins/gta3/Skin112.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin113.png b/files/images/skins/gta3/Skin113.png
deleted file mode 100644
index 8f7c6410..00000000
Binary files a/files/images/skins/gta3/Skin113.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin114.png b/files/images/skins/gta3/Skin114.png
deleted file mode 100644
index 6e055a21..00000000
Binary files a/files/images/skins/gta3/Skin114.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin115.png b/files/images/skins/gta3/Skin115.png
deleted file mode 100644
index b3825c59..00000000
Binary files a/files/images/skins/gta3/Skin115.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin116.png b/files/images/skins/gta3/Skin116.png
deleted file mode 100644
index fde854fa..00000000
Binary files a/files/images/skins/gta3/Skin116.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin118.png b/files/images/skins/gta3/Skin118.png
deleted file mode 100644
index 9e88b98f..00000000
Binary files a/files/images/skins/gta3/Skin118.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin119.png b/files/images/skins/gta3/Skin119.png
deleted file mode 100644
index d312bce0..00000000
Binary files a/files/images/skins/gta3/Skin119.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin120.png b/files/images/skins/gta3/Skin120.png
deleted file mode 100644
index 872ceced..00000000
Binary files a/files/images/skins/gta3/Skin120.png and /dev/null differ
diff --git a/files/images/skins/gta3/Skin121.png b/files/images/skins/gta3/Skin121.png
deleted file mode 100644
index 40c5c815..00000000
Binary files a/files/images/skins/gta3/Skin121.png and /dev/null differ
diff --git a/locale/chinese.json b/locale/chinese.json
new file mode 100644
index 00000000..9f689e8d
--- /dev/null
+++ b/locale/chinese.json
@@ -0,0 +1,393 @@
+{
+ "TranslationProvidedBy": "Renzuka Ctone",
+ "LocaleEnglishName": "Chinese",
+ "LocaleNativeName": "Chinese",
+ "LocaleOffer": "This server is available in English. Use {1} to use it.",
+ "LocaleChanged1": "Your language is now set to {1}",
+ "LocaleChanged2": "The server will now display messages in {1}",
+ "LocaleChangedNote": "This does not change messages from other players",
+ "AccentsListHeader": "Accents",
+ "HeaderHelpMainList": "Help Categories",
+ "AccentNotFound": "Accent not found",
+ "AccentSet": "You set your accent to {1}",
+ "AnimationNotFound": "That animation doesn't exist",
+ "AnimationCommandTip": "Use {1} to see a list of valid animations",
+ "AnimationInvalidDistance": "The distance must be between 0 and 3",
+ "AnimationStopCommandTip": "Use {1} to stop your animation",
+ "CantBanClient": "You cannot ban this person",
+ "PlayerAccountBanned": "{1} has been account banned",
+ "ClanNotFound": "Clan not found",
+ "ClanNameTaken": "A clan with that name already exists",
+ "PlayerNotFound": "Player not found",
+ "ClanCantRemoveRanks": "You can't remove clan ranks",
+ "ClanCantAddRanks": "You can't add clan ranks",
+ "ClanRankNotFound": "Clan rank not found",
+ "ClanCantChangeMemberTag": "You can not change clan member's tags",
+ "ClanPlayerNotInSameClan": "That player is not in your clan",
+ "ClanCantChangeRankLevel": "You can not change clan rank's level",
+ "ClanCantChangeRankTag": "You can not change clan rank's tags",
+ "NameNotRegistered": "Your name is not registered! Use {1} to make an account.",
+ "AutomaticLoginIPToggle": "Automatic login by IP is now {1}",
+ "CouldNotRegisterAccount": "There was a problem creating your account. Please contact an admin.",
+ "RandomTipsToggle": "Random tips are now {1}",
+ "ActionTipsToggle": "Action tips are now {1}",
+ "AutoSpawnLastCharToggle": "Automatic spawn as last used character is {1}",
+ "AccountGUISettingToggle": "GUI is now {1}",
+ "On": "On",
+ "Off": "Off",
+ "Yes": "Yes",
+ "No": "No",
+ "True": "True",
+ "False": "False",
+ "Locked": "Locked",
+ "Unlocked": "Unlocked",
+ "PasswordNotGoodEnough": "The new password must meet the requirements!",
+ "PasswordNeedsBase": "Passwords must have at least {1}",
+ "PasswordNeedsCapitals": "{1} capital letters",
+ "PasswordNeedsNumbers": "{1} numbers",
+ "PasswordNeedsSymbols": "{1} symbols",
+ "PasswordsDontMatch": "The new password and confirm new password aren't the same!",
+ "PasswordChanged": "Your password has been changed!",
+ "AutoLoggedInIP": "You have been automatically logged in by IP!",
+ "WelcomeBack": "Welcome back to {1}, {2}! Please {3} to continue.",
+ "WelcomeNewPlayer": "Welcome to {1}, {2}! Please {3} to play.",
+ "InvalidPlayer": "Player not found!",
+ "InvalidBusiness": "Business not found!",
+ "InvalidHouse": "House not found!",
+ "InvalidVehicle": "Vehicle not found!",
+ "InvalidClan": "Clan not found!",
+ "InvalidClanRank": "Clan rank not found!",
+ "InvalidJob": "Job not found!",
+ "InvalidItem": "Item not found!",
+ "InvalidItemType": "Item type not found!",
+ "InvalidRadioStation": "Radio station not found!",
+ "InvalidGate": "Gate not found!",
+ "EntersProperty": "opens the door and enters the {1}",
+ "ExitsProperty": "opens the door and exits the {1}",
+ "EnterExitPropertyDoorLocked": "tries to open the {1} door but fails because it's locked",
+ "PropertyNoInterior": "This {1} does not have an interior, but you can still use commands at the door icon.",
+ "NoBusinessWithItemType": "There is no business with that item available",
+ "HeaderKeyBinds": "Key Binds",
+ "HeaderAccountHelp": "Account Help",
+ "HeaderVehicleHelp": "Vehicle Help",
+ "HeaderVehicleDealershipHelp": "Vehicle Dealership Help",
+ "HeaderJobHelp": "Job Help",
+ "HeaderChatHelp": "Chat Help",
+ "HeaderServerRules": "Server Rules",
+ "HeaderWebsiteInfo": "Website",
+ "HeaderDiscordInfo": "Discord",
+ "HeaderAnimationsList": "Animation List",
+ "HeaderPayAndSprayHelp": "Pay and Spray Help",
+ "HeaderAmmunationHelp": "Ammunation Help",
+ "HeaderVehicleTuneupHelp": "Vehicle Tune Help",
+ "HeaderBindableKeysHelp": "Bindable Keys",
+ "HeaderSkinHelp": "Clothes/Skin Help",
+ "HeaderBusinessHelp": "Business Help",
+ "HeaderClanHelp": "Clan Help",
+ "HeaderPlayerVehiclesList": "Player Vehicles ({1})",
+ "HeaderPlayerBusinessesList": "Player Businesses ({1})",
+ "HeaderClansList": "Clan List",
+ "HeaderAdminsList": "Admin List",
+ "HeaderBadgeInfo": "Badge Information",
+ "HeaderAccentsList": "Accent List",
+ "HeaderPlayerInfo": "Player Information ({1})",
+ "HeaderWealthandTaxHelp": "Wealth and Tax Information",
+ "HeaderCommandInfo": "Command Information ({1})",
+ "HeaderRadioHelp": "Radio Help",
+ "HeaderRadioStationsList": "Radio Stations",
+ "HeaderKeyBindsList": "Key Binds List",
+ "RadioVolumeChanged": "{1} You changed your streaming radio volume to {2}%",
+ "VolumeLevelNotNumber": "The volume level must be a number",
+ "RadioStationLocationInvalid": "You must be in a vehicle, house, or business or have a personal device to change the station!",
+ "ActionBusinessRadioStationChange": "changes the business radio station to {1} ({2})",
+ "ActionHouseRadioStationChange": "changes the house radio station to {1} ({2})",
+ "ActionVehicleRadioStationChange": "changes the vehicle radio station to {1} ({2})",
+ "ActionItemRadioStationChange": "changes the {1}'s station to {2} ({3})",
+ "RandomVehicleCommandsDisabled": "This is a random traffic vehicle and commands can't be used for it.",
+ "HouseDoorLock": "House {1} {2}!",
+ "BusinessDoorLock": "Business {1} {2}!",
+ "ServerGameModeRestarting": "The server game mode is restarting!",
+ "HeaderSelfItemList": "Your Inventory",
+ "HeaderPlayerItemList": "Player Inventory ({1})",
+ "HeaderHouseItemList": "House Inventory",
+ "HeaderBusinessFloorItemList": "Business Inventory (For Sale)",
+ "HeaderBusinessStorageItemList": "Business Inventory (Storage)",
+ "HeaderItemItemList": "{1}'s Inventory",
+ "ItemSlotNotNumber": "The item slot must be a number",
+ "ItemSlotMustBeBetween": "The item slot must be between {1} and {2}!",
+ "UseItemBugged": "The item you're trying to use is bugged. A bug report has been sent to the server developers.",
+ "PickupItemBugged": "The item you're trying to pickup is bugged. A bug report has been sent to the server developers.",
+ "DropItemBugged": "The item you're trying to drop is bugged. A bug report has been sent to the server developers.",
+ "HandsBusy": "Your hands are busy",
+ "CantUseItemInSkinChange": "You can't use an item while customizing your appearance",
+ "CantDropItemInSkinChange": "You can't drop an item while customizing your appearance",
+ "CantPickupItemInSkinChange": "You can't pickup an item while customizing your appearance",
+ "CantSwitchItemInSkinChange": "You can't switch an item while customizing your appearance",
+ "CantGiveItemInSkinChange": "You can't give an item while customizing your appearance",
+ "CantTakeItemInSkinChange": "You can't take an item while customizing your appearance",
+ "ItemUnequippableNoAmmo": "The {1} in slot {2} has no ammo, and can't be equipped!",
+ "NoSpaceSelfInventory": "You don't have any more space in your inventory",
+ "Business": "business",
+ "House": "house",
+ "Clan": "clan",
+ "Vehicle": "vehicle",
+ "Item": "item",
+ "ItemType": "item type",
+ "Gate": "gate",
+ "Door": "door",
+ "ClanRank": "clan rank",
+ "JobRank": "job rank",
+ "RadioStation": "radio station",
+ "Months": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "WeekDays": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "CardinalDirections": [
+ "North",
+ "Northeast",
+ "East",
+ "Southeast",
+ "South",
+ "Southwest",
+ "West",
+ "Northwest"
+ ],
+ "NewPlayerReadyToPlay": [
+ "You have been given some cash. Use {1} to find places to buy items.",
+ "If you need money, jobs are the yellow dots on the radar.",
+ "For a car, visit the car dealership. You can also use a rental vehicle near spawn or take the train",
+ "Be sure to read the {1} and use {2} for info."
+ ],
+ "YourCurrentVehicleDeleted": "The vehicle you were in was deleted.",
+ "Distance": "Distance",
+ "Meters": "Meters",
+ "Feet": "Feet",
+ "Kilometers": "Kilometers",
+ "Miles": "Miles",
+ "MustBeVehicleDriver": "You must be the driver of the vehicle!",
+ "PlayerJoinedServer": "{1} has joined the game from {1}!",
+ "PlayerLeftServer": "{1} has left the game! ({1})",
+ "DisconnectReasons": [
+ "Lost Connection",
+ "Disconnected",
+ "Unsupported Client",
+ "Wrong Game",
+ "Incorrect Password",
+ "Unsupported Executable",
+ "Disconnected",
+ "Banned",
+ "Failed",
+ "Invalid Name",
+ "Crashed"
+ ],
+ "TakeItemFromHouse": "takes a {1} from the house",
+ "TakeItemFromBusinessStorage": "takes a {1} from the business storage",
+ "TakeItemFromBusiness": "takes a {1} from the business",
+ "TakeItemFromItem": "takes a {1} from the {2}",
+ "TakeItemFromVehicleTrunk": "takes a {1} from the trunk",
+ "TakeItemFromVehicleDash": "takes a {1} from the glove compartment",
+ "JobEquipmentInventoryKeyBindTip": "The job equipment is in your inventory. Press {1} to see them.",
+ "JobEquipmentInventoryCommandTip": "The job equipment is in your inventory. Use {1} to see them.",
+ "AccountHelp": [
+ "Do NOT share your password with anybody else. {1} staff will never ask you for your password",
+ "Use {1} to change your password, and {2} if you forgot it",
+ "Some settings you can use: {1}"
+ ],
+ "VehicleHelp": [
+ "Your personal vehicles will save wherever you or somebody else leaves them!",
+ "Visit dealerships to buy new vehicles (Use {1} for more information)",
+ "Some commands: {1}",
+ "Visit a mechanic garage to repair, colour, and tune up your car! {1} for info"
+ ],
+ "VehicleDealershipHelp": [
+ "Visit a vehicle dealer to buy new vehicles. Use {1} to find one.",
+ "At the dealer, enter a car you want to buy, and the price will be shown to you",
+ "If you want to buy the vehicle, use {1} and you will be given keys to test drive it around the parking lot.",
+ "Drive away from the dealership with the new vehicle to confirm the purchase."
+ ],
+ "JobHelp": [
+ "Visit job locations to get a job and earn money. Look for yellow spots on the map",
+ "At a job location, use {1} to get the job. Use {2} to quit your job",
+ "Use {1} to begin working. You can also get a job {2} and {3}",
+ "Most job vehicles are locked. Use {1} near one to enter it.",
+ "When entering a job vehicle, information on how to do the job will be shown to you."
+ ],
+ "ChatHelp": [
+ "There are two main types of chat: out-of-character (OOC) and in-character (IC)",
+ "Mixing these two types is not proper roleplay. See {1} for info.",
+ "Some chat commands: {1}",
+ "Some have shorter names available ({1} to talk, {2} to shout, etc)"
+ ],
+ "ServerRulesHelp": [
+ "Unrealistic actions (powergaming) are not allowed. You aren't superman.",
+ "No terrorist or terrorism roleplay is allowed.",
+ "Always follow instructions given by moderators and admins.",
+ "Do not mix the chats (metagaming). You can't use info in IC that was received OOC",
+ "Keep English in main chats. If you aren't good at English, use {1}"
+ ],
+ "AnimationHelp": [
+ "Animations allow you to enhance roleplay with visual actions",
+ "Use {1} or {2} with a name to use an animation.",
+ "To see a list of animations, use {1}"
+ ],
+ "WeaponHelp": [
+ "Visit an gun store to buy weapons. Use {1} to find one.",
+ "Buying a weapon requires a weapon license.",
+ "Weapon licenses are managed by the police department. Apply there to get one.",
+ "Weapons can also be purchased illegally from some businesses, weapon dealers, and clans."
+ ],
+ "SkinHelp": [
+ "At a clothing store, use {1} to purchase clothes",
+ "When you have a clothing item, equip and use it like any other item to show the skin selection (check {1} to learn how to use items)",
+ "Some skins are restricted to jobs, clans, or for other reasons."
+ ],
+ "KeyBindHelp": [
+ "You can set your own key binds. Use {1} to see your binded keys.",
+ "Use {1} to add a new keybind and {2} to remove one.",
+ "Default keys are: {1} for vehicle engine, {1} for lights, and {3} for lock/unlock",
+ "Press {1} to see your items and {2} to equip an item or {3} to unequip all.",
+ "Press {1} to use the item you're holding, press {2} to drop it, or press {3} to pickup an item from the ground."
+ ],
+ "BusinessHelp": [
+ "Use {1} to purchase items or {2} to see a list of what's for sale at any business",
+ "Businesses are shown with blue names above the icon at their entrance.",
+ "Business owner commands: {1}",
+ "A new car for sale will appear when you drive away from the dealer."
+ ],
+ "ClanHelp": [
+ "Ask an administrator to create a clan (Similar to factions/groups/families)",
+ "Clan owners have full control over their clan once it's created",
+ "Clan commands: {1}",
+ "More clan commands: {1}"
+ ],
+ "RadioStationHelp": [
+ "Use {1} to set the station for your vehicle, house, or business",
+ "Use {2} to see a list of stations",
+ "You can change your radio streaming volume using {1} with 0-100 as the percent"
+ ],
+ "WealthAndTaxHelp": [
+ "Your taxes on payday are {1} percent of your calculated wealth.",
+ "Your calculated wealth is a total sum based on how many vehicles, houses, and businesses you have.",
+ "Each vehicle is {1}, each house is {2}, and each business is {3}",
+ "Use {1} to see your current wealth, and {2} to see how much you'll pay in tax each payday"
+ ],
+ "MustBeInAVehicle": "You need to be in a vehicle!",
+ "MustBeInOrNearVehicle": "You need to be in or near a vehicle!",
+ "MustBeInVehicleFrontSeat": "You need to be in the vehicle front seats!",
+ "MustBeInVehicleDriverSeat": "You need to be the driver!",
+ "DontHaveVehicleKey": "You don't have a key for this vehicle!",
+ "NoGateAccess": "You don't have access to this gate!",
+ "GateBroken": "This gate is broken!",
+ "GateHacked": "The gate does not respond!",
+ "RadioJammed": "You hear only static from the radio.",
+ "VehicleNotForSale": "This vehicle is not for sale!",
+ "VehicleNotForRent": "This vehicle is not for rent!",
+ "BusinessNotForSale": "This business is not for sale!",
+ "BusinessNotForRent": "This business is not for rent!",
+ "HouseNotForSale": "This house is not for sale!",
+ "HouseNotForRent": "This house is not for rent!",
+ "DealershipPurchaseTestDrive": "Drive the vehicle away from the dealership to buy it, or get out to cancel.",
+ "DealershipPurchaseExitedVehicle": "You canceled the vehicle purchase by exiting the vehicle!",
+ "VehiclePurchaseComplete": "This vehicle is now yours! It will save wherever you leave it.",
+ "VehiclePurchaseNotEnoughMoney": "You don't have enough money to buy this vehicle!",
+ "HousePurchaseNotEnoughMoney": "You don't have enough money to buy this house!",
+ "BusinessPurchaseNotEnoughMoney": "You don't have enough money to buy this business!",
+ "Locales": {
+ "English": "English",
+ "Russian": "Russian",
+ "Spanish": "Spanish",
+ "German": "German",
+ "Dutch": "Dutch",
+ "Polish": "Polish"
+ },
+
+ "ADDED-21JAN2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "HeaderPlayerHousesList": "Player Houses ({1})",
+ "HeaderPlayerStaffFlagsList": "Player Staff Flags ({1})",
+ "HeaderStaffFlagsList": "Staff Flags",
+ "NonRPName": "Non-RP name! Choose a new one:",
+ "InvalidStaffFlag": "Staff flag not found!",
+ "InvalidClanFlag": "Clan flag not found!",
+ "InvalidLocale": "Language not found!",
+ "HeaderJobUniformList": "Job Uniforms ({1})",
+ "HeaderJobEquipmentList": "Job Equipment ({1})",
+ "InvalidJobUniform": "Job uniform not found!",
+ "InvalidJobEquipment": "Job equipment not found!",
+ "HeaderVehiclesInRangeList": "Vehicles within {1}",
+ "NoVehiclesWithInRange": "There are no vehicles within {1}",
+ "AmountNotNumber": "The amount must be a number!",
+ "NeedToBeWorking": "You need to be working! Use {1} at a job location or near a job vehicle.",
+ "NeedToBeOnJobRoute": "You need to be doing a job route! Use {1} in a job vehicle",
+ "CurrentJobRouteDeleted": "The job route you were on has been deleted by an admin",
+ "CurrentJobRouteVehicleColoursChanged": "Your job route's vehicle colours were changed by an admin",
+ "NotYourJob": "This is not your job!",
+ "JobPoints": "You can get a job by going the yellow points on the map.",
+ "QuitJobToTakeAnother": "If you want this job, use {1} to quit your current job.",
+ "NotAJobVehicle": "This is not a job vehicle!",
+ "NotYourJobVehicle": "This is not your job's vehicle!",
+ "JobRouteDisabled": "The job route you were on has been disabled by an admin",
+ "HeaderPickupTypes": "Pickup Types",
+ "HeaderBlipTypes": "Map Icon Types",
+ "InvalidGPSLocation": "There are no locations with that name or type",
+ "HeaderBusinessList": "Businesses",
+ "VehicleForSale": "This {1} is buyable for {2}! Use {3} if you want to buy it",
+ "VehicleForRent": "This {1} is rentable for {2}! Use {3} if you want to rent it",
+
+ "ADDED-31JAN2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "LoginFailedInvalidPassword": "Invalid password! {1} attempts remaining",
+ "LoginFailedNoPassword": "You must enter a password! ! {1} attempts remaining",
+ "RegistrationFailedNoPassword": "You must enter a password!",
+ "RegistrationFailedNoPasswordConfirm": "You must confirm the password!",
+ "RegistrationFailedNoEmail": "You must enter an email!",
+ "AccountNameAlreadyRegistered": "Your name is already registered!",
+ "AlreadyLoggedIn": "You are already logged in!",
+ "RegistrationFailedInvalidEmail": "That email is invalid!",
+ "RegistrationFailedPasswordMismatch": "The passwords don't match!",
+ "RegistrationFailedCreateError": "Your account couldn't be created!",
+ "RegistrationSuccess": "Your account has been created!",
+ "RegistrationEmailVerifyReminder": "Don't forget to verify your email! A verification code has been sent to you.",
+ "RegistrationCreateCharReminder": "To play on the server, you will need to make a character.",
+ "NoCharactersGUIMessage": "You have no characters. Would you like to make one?",
+ "NoCharactersGUIWindowTitle": "No characters",
+ "NoCharactersChatMessage": "You have no characters. Use {1} to make one.",
+ "NeedEmailFor2FA": "You need to add your email to your account to use two-factor authentication.",
+ "NeedEmailVerifiedFor2FA": "You need to verify your email to use two-factor authentication.",
+ "SetEmailHelpTip": "Use {1} to set your email.",
+ "VerifyEmailHelpTip": "Use {1} to verify your email.",
+
+ "ADDED-13FEB2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "NearbyRadio": "Nearby radio",
+ "FromRadio": "From radio",
+ "ToRadio": "To radio",
+ "NeedToEnterPropertyCommand": "You need to enter the {1} first! Use {2} to enter and exit",
+ "NeedToEnterPropertyKeyPress": "You need to enter the {1} first! Press {2} to enter and exit",
+ "InventoryFullCantCarry": "You don't have any space to carry this (full inventory)!",
+ "NotEnoughCashNeedAmountMore": "You don't have enough money! You need {1} more!",
+ "AmountMustBeMoreThan": "The amount must be more than {1}!",
+ "WeaponBanned": "You are not allowed to buy or use weapons!",
+ "TimeNotNumber": "The time must be a number",
+ "HeaderDefaultBusinessItemTypes": "Business Item Templates",
+ "FixingStuck": "Fixing your position and virtual world ...",
+ "CantUseCommandYet": "You must wait before you can use this command again!",
+ "NotATester": "You are not a tester!",
+ "AccessDenied": "AccessDenied"
+}
diff --git a/locale/english.json b/locale/english.json
index eedb7815..873af6b4 100644
--- a/locale/english.json
+++ b/locale/english.json
@@ -1,18 +1,19 @@
{
+ "TranslationProvidedBy": "Vortrex",
+ "LocaleEnglishName": "English",
+ "LocaleNativeName": "English",
+ "LocaleOffer": "This server is available in English. Use {1} to use it.",
+ "LocaleChanged1": "Your language is now set to {1}",
+ "LocaleChanged2": "The server will now display messages in {1}",
+ "LocaleChangedNote": "This does not change messages from other players",
"AccentsListHeader": "Accents",
- "HelpListHeader": "Help Categories",
- "HelpSkinHeader": "Skin Help",
- "HelpVehicleHeader": "Vehicle Help",
- "HelpBusinessHeader": "Business Help",
- "HelpHouseHeader": "House Help",
- "HelpRadioHeader": "Radio Help",
- "HelpAnimationHeader": "Animation Help",
+ "HeaderHelpMainList": "Help Categories",
"AccentNotFound": "Accent not found",
- "AccentSet": "You set your accent to {ALTCOLOUR}{1}",
+ "AccentSet": "You set your accent to {1}",
"AnimationNotFound": "That animation doesn't exist",
- "AnimationCommandTip": "Use {ALTCOLOUR}/animlist{MAINCOLOUR} to see a list of valid animations",
+ "AnimationCommandTip": "Use {1} to see a list of valid animations",
"AnimationInvalidDistance": "The distance must be between 0 and 3",
- "AnimationStopCommandTip": "Use {ALTCOLOUR}/stopanim{MAINCOLOUR} to stop your animation",
+ "AnimationStopCommandTip": "Use {1} to stop your animation",
"CantBanClient": "You cannot ban this person",
"PlayerAccountBanned": "{1} has been account banned",
"ClanNotFound": "Clan not found",
@@ -24,5 +25,369 @@
"ClanCantChangeMemberTag": "You can not change clan member's tags",
"ClanPlayerNotInSameClan": "That player is not in your clan",
"ClanCantChangeRankLevel": "You can not change clan rank's level",
- "ClanCantChangeRankTag": "You can not change clan rank's tags"
-}
\ No newline at end of file
+ "ClanCantChangeRankTag": "You can not change clan rank's tags",
+ "NameNotRegistered": "Your name is not registered! Use {1} to make an account.",
+ "AutomaticLoginIPToggle": "Automatic login by IP is now {1}",
+ "CouldNotRegisterAccount": "There was a problem creating your account. Please contact an admin.",
+ "RandomTipsToggle": "Random tips are now {1}",
+ "ActionTipsToggle": "Action tips are now {1}",
+ "AutoSpawnLastCharToggle": "Automatic spawn as last used character is {1}",
+ "AccountGUISettingToggle": "GUI is now {1}",
+ "On": "On",
+ "Off": "Off",
+ "Yes": "Yes",
+ "No": "No",
+ "True": "True",
+ "False": "False",
+ "Locked": "Locked",
+ "Unlocked": "Unlocked",
+ "PasswordNotGoodEnough": "The new password must meet the requirements!",
+ "PasswordNeedsBase": "Passwords must have at least {1}",
+ "PasswordNeedsCapitals": "{1} capital letters",
+ "PasswordNeedsNumbers": "{1} numbers",
+ "PasswordNeedsSymbols": "{1} symbols",
+ "PasswordsDontMatch": "The new password and confirm new password aren't the same!",
+ "PasswordChanged": "Your password has been changed!",
+ "AutoLoggedInIP": "You have been automatically logged in by IP!",
+ "WelcomeBack": "Welcome back to {1}, {2}! Please {3} to continue.",
+ "WelcomeNewPlayer": "Welcome to {1}, {2}! Please {3} to play.",
+ "InvalidPlayer": "Player not found!",
+ "InvalidBusiness": "Business not found!",
+ "InvalidHouse": "House not found!",
+ "InvalidVehicle": "Vehicle not found!",
+ "InvalidClan": "Clan not found!",
+ "InvalidClanRank": "Clan rank not found!",
+ "InvalidJob": "Job not found!",
+ "InvalidItem": "Item not found!",
+ "InvalidItemType": "Item type not found!",
+ "InvalidRadioStation": "Radio station not found!",
+ "InvalidGate": "Gate not found!",
+ "EntersProperty": "opens the door and enters the {1}",
+ "ExitsProperty": "opens the door and exits the {1}",
+ "EnterExitPropertyDoorLocked": "tries to open the {1} door but fails because it's locked",
+ "PropertyNoInterior": "This {1} does not have an interior, but you can still use commands at the door icon.",
+ "NoBusinessWithItemType": "There is no business with that item available",
+ "HeaderKeyBinds": "Key Binds",
+ "HeaderAccountHelp": "Account Help",
+ "HeaderVehicleHelp": "Vehicle Help",
+ "HeaderVehicleDealershipHelp": "Vehicle Dealership Help",
+ "HeaderJobHelp": "Job Help",
+ "HeaderChatHelp": "Chat Help",
+ "HeaderServerRules": "Server Rules",
+ "HeaderWebsiteInfo": "Website",
+ "HeaderDiscordInfo": "Discord",
+ "HeaderAnimationsList": "Animation List",
+ "HeaderPayAndSprayHelp": "Pay and Spray Help",
+ "HeaderAmmunationHelp": "Ammunation Help",
+ "HeaderVehicleTuneupHelp": "Vehicle Tune Help",
+ "HeaderBindableKeysHelp": "Bindable Keys",
+ "HeaderSkinHelp": "Clothes/Skin Help",
+ "HeaderBusinessHelp": "Business Help",
+ "HeaderClanHelp": "Clan Help",
+ "HeaderPlayerVehiclesList": "Player Vehicles ({1})",
+ "HeaderPlayerBusinessesList": "Player Businesses ({1})",
+ "HeaderClansList": "Clan List",
+ "HeaderAdminsList": "Admin List",
+ "HeaderBadgeInfo": "Badge Information",
+ "HeaderAccentsList": "Accent List",
+ "HeaderPlayerInfo": "Player Information ({1})",
+ "HeaderWealthandTaxHelp": "Wealth and Tax Information",
+ "HeaderCommandInfo": "Command Information ({1})",
+ "HeaderRadioHelp": "Radio Help",
+ "HeaderRadioStationsList": "Radio Stations",
+ "HeaderKeyBindsList": "Key Binds List",
+ "RadioVolumeChanged": "{1} You changed your streaming radio volume to {2}%",
+ "VolumeLevelNotNumber": "The volume level must be a number",
+ "RadioStationLocationInvalid": "You must be in a vehicle, house, or business or have a personal device to change the station!",
+ "ActionBusinessRadioStationChange": "changes the business radio station to {1} ({2})",
+ "ActionHouseRadioStationChange": "changes the house radio station to {1} ({2})",
+ "ActionVehicleRadioStationChange": "changes the vehicle radio station to {1} ({2})",
+ "ActionItemRadioStationChange": "changes the {1}'s station to {2} ({3})",
+ "RandomVehicleCommandsDisabled": "This is a random traffic vehicle and commands can't be used for it.",
+ "HouseDoorLock": "House {1} {2}!",
+ "BusinessDoorLock": "Business {1} {2}!",
+ "ServerGameModeRestarting": "The server game mode is restarting!",
+ "HeaderSelfItemList": "Your Inventory",
+ "HeaderPlayerItemList": "Player Inventory ({1})",
+ "HeaderHouseItemList": "House Inventory",
+ "HeaderBusinessFloorItemList": "Business Inventory (For Sale)",
+ "HeaderBusinessStorageItemList": "Business Inventory (Storage)",
+ "HeaderItemItemList": "{1}'s Inventory",
+ "ItemSlotNotNumber": "The item slot must be a number",
+ "ItemSlotMustBeBetween": "The item slot must be between {1} and {2}!",
+ "UseItemBugged": "The item you're trying to use is bugged. A bug report has been sent to the server developers.",
+ "PickupItemBugged": "The item you're trying to pickup is bugged. A bug report has been sent to the server developers.",
+ "DropItemBugged": "The item you're trying to drop is bugged. A bug report has been sent to the server developers.",
+ "HandsBusy": "Your hands are busy",
+ "CantUseItemInSkinChange": "You can't use an item while customizing your appearance",
+ "CantDropItemInSkinChange": "You can't drop an item while customizing your appearance",
+ "CantPickupItemInSkinChange": "You can't pickup an item while customizing your appearance",
+ "CantSwitchItemInSkinChange": "You can't switch an item while customizing your appearance",
+ "CantGiveItemInSkinChange": "You can't give an item while customizing your appearance",
+ "CantTakeItemInSkinChange": "You can't take an item while customizing your appearance",
+ "ItemUnequippableNoAmmo": "The {1} in slot {2} has no ammo, and can't be equipped!",
+ "NoSpaceSelfInventory": "You don't have any more space in your inventory",
+ "Business": "business",
+ "House": "house",
+ "Clan": "clan",
+ "Vehicle": "vehicle",
+ "Item": "item",
+ "ItemType": "item type",
+ "Gate": "gate",
+ "Door": "door",
+ "ClanRank": "clan rank",
+ "JobRank": "job rank",
+ "RadioStation": "radio station",
+ "Months": [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+ ],
+ "WeekDays": [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ ],
+ "CardinalDirections": [
+ "North",
+ "Northeast",
+ "East",
+ "Southeast",
+ "South",
+ "Southwest",
+ "West",
+ "Northwest"
+ ],
+ "NewPlayerReadyToPlay": [
+ "You have been given some cash. Use {1} to find places to buy items.",
+ "If you need money, jobs are the yellow dots on the radar.",
+ "For a car, visit the car dealership. You can also use a rental vehicle near spawn or take the train",
+ "Be sure to read the {1} and use {2} for info."
+ ],
+ "YourCurrentVehicleDeleted": "The vehicle you were in was deleted.",
+ "Distance": "Distance",
+ "Meters": "Meters",
+ "Feet": "Feet",
+ "Kilometers": "Kilometers",
+ "Miles": "Miles",
+ "MustBeVehicleDriver": "You must be the driver of the vehicle!",
+ "PlayerJoinedServer": "{1} has joined the game from {1}!",
+ "PlayerLeftServer": "{1} has left the game! ({1})",
+ "DisconnectReasons": [
+ "Lost Connection",
+ "Disconnected",
+ "Unsupported Client",
+ "Wrong Game",
+ "Incorrect Password",
+ "Unsupported Executable",
+ "Disconnected",
+ "Banned",
+ "Failed",
+ "Invalid Name",
+ "Crashed"
+ ],
+ "TakeItemFromHouse": "takes a {1} from the house",
+ "TakeItemFromBusinessStorage": "takes a {1} from the business storage",
+ "TakeItemFromBusiness": "takes a {1} from the business",
+ "TakeItemFromItem": "takes a {1} from the {2}",
+ "TakeItemFromVehicleTrunk": "takes a {1} from the trunk",
+ "TakeItemFromVehicleDash": "takes a {1} from the glove compartment",
+ "JobEquipmentInventoryKeyBindTip": "The job equipment is in your inventory. Press {1} to see them.",
+ "JobEquipmentInventoryCommandTip": "The job equipment is in your inventory. Use {1} to see them.",
+ "AccountHelp": [
+ "Do NOT share your password with anybody else. {1} staff will never ask you for your password",
+ "Use {1} to change your password, and {2} if you forgot it",
+ "Some settings you can use: {1}"
+ ],
+ "VehicleHelp": [
+ "Your personal vehicles will save wherever you or somebody else leaves them!",
+ "Visit dealerships to buy new vehicles (Use {1} for more information)",
+ "Some commands: {1}",
+ "Visit a mechanic garage to repair, colour, and tune up your car! {1} for info"
+ ],
+ "VehicleDealershipHelp": [
+ "Visit a vehicle dealer to buy new vehicles. Use {1} to find one.",
+ "At the dealer, enter a car you want to buy, and the price will be shown to you",
+ "If you want to buy the vehicle, use {1} and you will be given keys to test drive it around the parking lot.",
+ "Drive away from the dealership with the new vehicle to confirm the purchase."
+ ],
+ "JobHelp": [
+ "Visit job locations to get a job and earn money. Look for yellow spots on the map",
+ "At a job location, use {1} to get the job. Use {2} to quit your job",
+ "Use {1} to begin working. You can also get a job {2} and {3}",
+ "Most job vehicles are locked. Use {1} near one to enter it.",
+ "When entering a job vehicle, information on how to do the job will be shown to you."
+ ],
+ "ChatHelp": [
+ "There are two main types of chat: out-of-character (OOC) and in-character (IC)",
+ "Mixing these two types is not proper roleplay. See {1} for info.",
+ "Some chat commands: {1}",
+ "Some have shorter names available ({1} to talk, {2} to shout, etc)"
+ ],
+ "ServerRulesHelp": [
+ "Unrealistic actions (powergaming) are not allowed. You aren't superman.",
+ "No terrorist or terrorism roleplay is allowed.",
+ "Always follow instructions given by moderators and admins.",
+ "Do not mix the chats (metagaming). You can't use info in IC that was received OOC",
+ "Keep English in main chats. If you aren't good at English, use {1}"
+ ],
+ "AnimationHelp": [
+ "Animations allow you to enhance roleplay with visual actions",
+ "Use {1} or {2} with a name to use an animation.",
+ "To see a list of animations, use {1}"
+ ],
+ "WeaponHelp": [
+ "Visit an gun store to buy weapons. Use {1} to find one.",
+ "Buying a weapon requires a weapon license.",
+ "Weapon licenses are managed by the police department. Apply there to get one.",
+ "Weapons can also be purchased illegally from some businesses, weapon dealers, and clans."
+ ],
+ "SkinHelp": [
+ "At a clothing store, use {1} to purchase clothes",
+ "When you have a clothing item, equip and use it like any other item to show the skin selection (check {1} to learn how to use items)",
+ "Some skins are restricted to jobs, clans, or for other reasons."
+ ],
+ "KeyBindHelp": [
+ "You can set your own key binds. Use {1} to see your binded keys.",
+ "Use {1} to add a new keybind and {2} to remove one.",
+ "Default keys are: {1} for vehicle engine, {1} for lights, and {3} for lock/unlock",
+ "Press {1} to see your items and {2} to equip an item or {3} to unequip all.",
+ "Press {1} to use the item you're holding, press {2} to drop it, or press {3} to pickup an item from the ground."
+ ],
+ "BusinessHelp": [
+ "Use {1} to purchase items or {2} to see a list of what's for sale at any business",
+ "Businesses are shown with blue names above the icon at their entrance.",
+ "Business owner commands: {1}",
+ "A new car for sale will appear when you drive away from the dealer."
+ ],
+ "ClanHelp": [
+ "Ask an administrator to create a clan (Similar to factions/groups/families)",
+ "Clan owners have full control over their clan once it's created",
+ "Clan commands: {1}",
+ "More clan commands: {1}"
+ ],
+ "RadioStationHelp": [
+ "Use {1} to set the station for your vehicle, house, or business",
+ "Use {2} to see a list of stations",
+ "You can change your radio streaming volume using {1} with 0-100 as the percent"
+ ],
+ "WealthAndTaxHelp": [
+ "Your taxes on payday are {1} percent of your calculated wealth.",
+ "Your calculated wealth is a total sum based on how many vehicles, houses, and businesses you have.",
+ "Each vehicle is {1}, each house is {2}, and each business is {3}",
+ "Use {1} to see your current wealth, and {2} to see how much you'll pay in tax each payday"
+ ],
+ "MustBeInAVehicle": "You need to be in a vehicle!",
+ "MustBeInOrNearVehicle": "You need to be in or near a vehicle!",
+ "MustBeInVehicleFrontSeat": "You need to be in the vehicle front seats!",
+ "MustBeInVehicleDriverSeat": "You need to be the driver!",
+ "DontHaveVehicleKey": "You don't have a key for this vehicle!",
+ "NoGateAccess": "You don't have access to this gate!",
+ "GateBroken": "This gate is broken!",
+ "GateHacked": "The gate does not respond!",
+ "RadioJammed": "You hear only static from the radio.",
+ "VehicleNotForSale": "This vehicle is not for sale!",
+ "VehicleNotForRent": "This vehicle is not for rent!",
+ "BusinessNotForSale": "This business is not for sale!",
+ "BusinessNotForRent": "This business is not for rent!",
+ "HouseNotForSale": "This house is not for sale!",
+ "HouseNotForRent": "This house is not for rent!",
+ "DealershipPurchaseTestDrive": "Drive the vehicle away from the dealership to buy it, or get out to cancel.",
+ "DealershipPurchaseExitedVehicle": "You canceled the vehicle purchase by exiting the vehicle!",
+ "VehiclePurchaseComplete": "This vehicle is now yours! It will save wherever you leave it.",
+ "VehiclePurchaseNotEnoughMoney": "You don't have enough money to buy this vehicle!",
+ "HousePurchaseNotEnoughMoney": "You don't have enough money to buy this house!",
+ "BusinessPurchaseNotEnoughMoney": "You don't have enough money to buy this business!",
+ "Locales": {
+ "English": "English",
+ "Russian": "Russian",
+ "Spanish": "Spanish",
+ "German": "German",
+ "Dutch": "Dutch",
+ "Polish": "Polish"
+ },
+
+ "ADDED-21JAN2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "HeaderPlayerHousesList": "Player Houses ({1})",
+ "HeaderPlayerStaffFlagsList": "Player Staff Flags ({1})",
+ "HeaderStaffFlagsList": "Staff Flags",
+ "NonRPName": "Non-RP name! Choose a new one:",
+ "InvalidStaffFlag": "Staff flag not found!",
+ "InvalidClanFlag": "Clan flag not found!",
+ "InvalidLocale": "Language not found!",
+ "HeaderJobUniformList": "Job Uniforms ({1})",
+ "HeaderJobEquipmentList": "Job Equipment ({1})",
+ "InvalidJobUniform": "Job uniform not found!",
+ "InvalidJobEquipment": "Job equipment not found!",
+ "HeaderVehiclesInRangeList": "Vehicles within {1}",
+ "NoVehiclesWithInRange": "There are no vehicles within {1}",
+ "AmountNotNumber": "The amount must be a number!",
+ "NeedToBeWorking": "You need to be working! Use {1} at a job location or near a job vehicle.",
+ "NeedToBeOnJobRoute": "You need to be doing a job route! Use {1} in a job vehicle",
+ "CurrentJobRouteDeleted": "The job route you were on has been deleted by an admin",
+ "CurrentJobRouteVehicleColoursChanged": "Your job route's vehicle colours were changed by an admin",
+ "NotYourJob": "This is not your job!",
+ "JobPoints": "You can get a job by going the yellow points on the map.",
+ "QuitJobToTakeAnother": "If you want this job, use {1} to quit your current job.",
+ "NotAJobVehicle": "This is not a job vehicle!",
+ "NotYourJobVehicle": "This is not your job's vehicle!",
+ "JobRouteDisabled": "The job route you were on has been disabled by an admin",
+ "HeaderPickupTypes": "Pickup Types",
+ "HeaderBlipTypes": "Map Icon Types",
+ "InvalidGPSLocation": "There are no locations with that name or type",
+ "HeaderBusinessList": "Businesses",
+ "VehicleForSale": "This {1} is buyable for {2}! Use {3} if you want to buy it",
+ "VehicleForRent": "This {1} is rentable for {2}! Use {3} if you want to rent it",
+
+ "ADDED-31JAN2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "LoginFailedInvalidPassword": "Invalid password! {1} attempts remaining",
+ "LoginFailedNoPassword": "You must enter a password! ! {1} attempts remaining",
+ "RegistrationFailedNoPassword": "You must enter a password!",
+ "RegistrationFailedNoPasswordConfirm": "You must confirm the password!",
+ "RegistrationFailedNoEmail": "You must enter an email!",
+ "AccountNameAlreadyRegistered": "Your name is already registered!",
+ "AlreadyLoggedIn": "You are already logged in!",
+ "RegistrationFailedInvalidEmail": "That email is invalid!",
+ "RegistrationFailedPasswordMismatch": "The passwords don't match!",
+ "RegistrationFailedCreateError": "Your account couldn't be created!",
+ "RegistrationSuccess": "Your account has been created!",
+ "RegistrationEmailVerifyReminder": "Don't forget to verify your email! A verification code has been sent to you.",
+ "RegistrationCreateCharReminder": "To play on the server, you will need to make a character.",
+ "NoCharactersGUIMessage": "You have no characters. Would you like to make one?",
+ "NoCharactersGUIWindowTitle": "No characters",
+ "NoCharactersChatMessage": "You have no characters. Use {1} to make one.",
+ "NeedEmailFor2FA": "You need to add your email to your account to use two-factor authentication.",
+ "NeedEmailVerifiedFor2FA": "You need to verify your email to use two-factor authentication.",
+ "SetEmailHelpTip": "Use {1} to set your email.",
+ "VerifyEmailHelpTip": "Use {1} to verify your email.",
+
+ "ADDED-13FEB2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "NearbyRadio": "Nearby radio",
+ "FromRadio": "From radio",
+ "ToRadio": "To radio",
+ "NeedToEnterPropertyCommand": "You need to enter the {1} first! Use {2} to enter and exit",
+ "NeedToEnterPropertyKeyPress": "You need to enter the {1} first! Press {2} to enter and exit",
+ "InventoryFullCantCarry": "You don't have any space to carry this (full inventory)!",
+ "NotEnoughCashNeedAmountMore": "You don't have enough money! You need {1} more!",
+ "AmountMustBeMoreThan": "The amount must be more than {1}!",
+ "WeaponBanned": "You are not allowed to buy or use weapons!",
+ "TimeNotNumber": "The time must be a number",
+ "HeaderDefaultBusinessItemTypes": "Business Item Templates",
+ "FixingStuck": "Fixing your position and virtual world ...",
+ "CantUseCommandYet": "You must wait before you can use this command again!",
+ "NotATester": "You are not a tester!",
+ "AccessDenied": "AccessDenied"
+}
diff --git a/locale/polish.json b/locale/polish.json
new file mode 100644
index 00000000..70f96050
--- /dev/null
+++ b/locale/polish.json
@@ -0,0 +1,393 @@
+{
+ "TranslationProvidedBy": "Suprise444",
+ "LocaleEnglishName": "Polish",
+ "LocaleNativeName": "Polski",
+ "LocaleOffer": "Ten serwer jest dostępny w języku Polskim. Użyj {1} aby go użyć.",
+ "LocaleChanged1": "Twój język jest ustawiony na {1}",
+ "LocaleChanged2": "Serwer będzie teraz pokazywał wiadomości w języku {1}",
+ "LocaleChangedNote": "To nie zmienia wiadomości od innych graczy",
+ "AccentsListHeader": "Akcenty",
+ "HeaderHelpMainList": "Pomoc - Kategorie",
+ "AccentNotFound": "Akcent nie znaleziony",
+ "AccentSet": "Ustawiłeś swój akcent na {1}",
+ "AnimationNotFound": "Ta animcja nie istnieje",
+ "AnimationCommandTip": "Użyj {1} aby zobaczyć listę działających animacji",
+ "AnimationInvalidDistance": "Dystans musi być między 0 i 3",
+ "AnimationStopCommandTip": "Użyj {1} aby zatrzymać swoją animacje",
+ "CantBanClient": "Nie możesz zbanować tej osoby",
+ "PlayerAccountBanned": "{1} został zbanowany",
+ "ClanNotFound": "Nie znaleziono klanu",
+ "ClanNameTaken": "Klan z taką nazwą już istnieje",
+ "PlayerNotFound": "Nie znaleziono gracza",
+ "ClanCantRemoveRanks": "Nie możesz usuwać rang klanu",
+ "ClanCantAddRanks": "Nie możesz dodawać rang klanu",
+ "ClanRankNotFound": "Nie znaleziono rangi klanu",
+ "ClanCantChangeMemberTag": "Nie możesz zmienić tagu członka klanu",
+ "ClanPlayerNotInSameClan": "Ten gracz nie jest w twoim klanie",
+ "ClanCantChangeRankLevel": "Nie możesz zmienić poziomu rangi klanu",
+ "ClanCantChangeRankTag": "Nie możesz zmienić tagu rangi klanu",
+ "NameNotRegistered": "Twoja nazwa nie jest zarejestrowana! Użyj {1} aby stworzyć konto.",
+ "AutomaticLoginIPToggle": "Automatyczny login przez IP jest teraz {1}",
+ "CouldNotRegisterAccount": "Napotkano problem podczas tworzenia twojego konta. Proszę skontaktuj się z administratorem.",
+ "RandomTipsToggle": "Losowe wskazówki są teraz {1}",
+ "ActionTipsToggle": "Wskazówki akcji są teraz {1}",
+ "AutoSpawnLastCharToggle": "Automatyczny spawn jako ostatnia postać jest teraz {1}",
+ "AccountGUISettingToggle": "GUI jest teraz {1}",
+ "On": "Włączony",
+ "Off": "Wyłączony",
+ "Yes": "Tak",
+ "No": "Nie",
+ "True": "Prawda",
+ "False": "Fałsz",
+ "Locked": "Zamknięty",
+ "Unlocked": "Otwarty",
+ "PasswordNotGoodEnough": "Nowe hasło musi spełniać wymagania!",
+ "PasswordNeedsBase": "Hasło musi mieć przynajmniej {1}",
+ "PasswordNeedsCapitals": "{1} dużych liter",
+ "PasswordNeedsNumbers": "{1} numerów",
+ "PasswordNeedsSymbols": "{1} symboli",
+ "PasswordsDontMatch": "Hasła nie są takie same!",
+ "PasswordChanged": "Twoje hasło zostało zmienione!",
+ "AutoLoggedInIP": "Zostałeś automatycznie zalogowany przez IP!",
+ "WelcomeBack": "Witaj ponownie w {1}, {2}! Użyj {3} aby kontynuować.",
+ "WelcomeNewPlayer": "Witaj w {1}, {2}! Użyj {3} aby zagrać.",
+ "InvalidPlayer": "Praca nie znaleziona!",
+ "InvalidBusiness": "Biznes nie znaleziony!",
+ "InvalidHouse": "Mieszkanie nie znalezione!",
+ "InvalidVehicle": "Pojazd nie znaleziony!",
+ "InvalidClan": "Klan nie znaleziony!",
+ "InvalidClanRank": "Ranga klanu nie znaleziona!",
+ "InvalidJob": "Gracz nie znaleziony!",
+ "InvalidItem": "Przedmiot nie znaleziony!",
+ "InvalidItemType": "Rodzaj przedmiot nie znaleziony!",
+ "InvalidRadioStation": "Stacja radiowa nie znaleziona!",
+ "InvalidGate": "Brama nie znaleziona!",
+ "EntersProperty": "otwiera drzwi i wchodzi do {1}",
+ "ExitsProperty": "otwiera drzwi i wychodzi z {1}",
+ "EnterExitPropertyDoorLocked": "próbuje otworzyć {1} drzwi, ale nie udaje się, ponieważ są zamknięte",
+ "PropertyNoInterior": "Ten {1} nie ma wnętrza, ale dalej możesz używaj komend przy ikonie drzwi.",
+ "NoBusinessWithItemType": "Nie ma biznesu, który posiada ten przedmiot",
+ "HeaderKeyBinds": "Przypisania klawiszy",
+ "HeaderAccountHelp": "Pomoc - Konto",
+ "HeaderVehicleHelp": "Pomoc - Pojazd",
+ "HeaderVehicleDealershipHelp": "Pomoc - Dealer Samochodów",
+ "HeaderJobHelp": "Pomoc - Praca",
+ "HeaderChatHelp": "Pomoc - Czat",
+ "HeaderServerRules": "Zasady serwera",
+ "HeaderWebsiteInfo": "Strona",
+ "HeaderDiscordInfo": "Discord",
+ "HeaderAnimationsList": "Lista Animacji",
+ "HeaderPayAndSprayHelp": "Pomoc - Pay and Spray",
+ "HeaderAmmunationHelp": "Pomoc - Ammunation",
+ "HeaderVehicleTuneupHelp": "Pomoc - Ulepszanie Aut",
+ "HeaderBindableKeysHelp": "Przypisywalne klawisze",
+ "HeaderSkinHelp": "Pomoc - Ubrania/Skóra",
+ "HeaderBusinessHelp": "Pomoc - Biznes",
+ "HeaderClanHelp": "Pomoc - Klan",
+ "HeaderPlayerVehiclesList": "Pojazdy Gracza ({1})",
+ "HeaderPlayerBusinessesList": "Biznesy Gracza ({1})",
+ "HeaderClansList": "Lista Klanów",
+ "HeaderAdminsList": "Lista Administracji",
+ "HeaderBadgeInfo": "Informacje o Odznace",
+ "HeaderAccentsList": "Lista Akcentów",
+ "HeaderPlayerInfo": "Informacje o Graczu ({1})",
+ "HeaderWealthandTaxHelp": "Informacje o Bogactwach i Podatkach",
+ "HeaderCommandInfo": "Informacje o Komendzie ({1})",
+ "HeaderRadioHelp": "Pomoc - Radio",
+ "HeaderRadioStationsList": "Stacje Radiowe",
+ "HeaderKeyBindsList": "Lista przypisań klawiszy",
+ "RadioVolumeChanged": "{1} Zmieniłeś głośność swojego radia na {2}%",
+ "VolumeLevelNotNumber": "Poziom głośności musi być liczbą",
+ "RadioStationLocationInvalid": "Musisz być w aucie, domu, biznesie lub mieć osobite urządzenie by zmienić stacje radiową!",
+ "ActionBusinessRadioStationChange": "zmienia biznesową stacje radiową na {1} ({2})",
+ "ActionHouseRadioStationChange": "zmienia domową stacje radiową na {1} ({2})",
+ "ActionVehicleRadioStationChange": "zmienia samochodową stacje radiową na {1} ({2})",
+ "ActionItemRadioStationChange": "zmienia stacje {1} na {2} ({3})",
+ "RandomVehicleCommandsDisabled": "To losowy pojazd uliczny i komendy nie mogą być na nim użyte.",
+ "HouseDoorLock": "Mieszkanie {1} {2}!",
+ "BusinessDoorLock": "Biznes {1} {2}!",
+ "ServerGameModeRestarting": "Tryb gry serwera się restartuje!",
+ "HeaderSelfItemList": "Twój ekwipunek",
+ "HeaderPlayerItemList": "Ekwipunek gracza ({1})",
+ "HeaderHouseItemList": "Ekwipunek mieszkania",
+ "HeaderBusinessFloorItemList": "Ekwipunek Bizneus (Na sprzedaż)",
+ "HeaderBusinessStorageItemList": "Ekwipunek Bizenus (Magazyn)",
+ "HeaderItemItemList": "Ekwipunek {1}",
+ "ItemSlotNotNumber": "Slot przedmiotu musi być liczbą",
+ "ItemSlotMustBeBetween": "Slot itemu musi być liczbą między {1} i {2}!",
+ "UseItemBugged": "Przedmiot, który próbujesz użyć jest popsuty. Zgłoszenie zostało wysłane do deweloperów serwera.",
+ "PickupItemBugged": "Przedmiot, który próbujesz podnieść jest popsuty. Zgłoszenie zostało wysłane do deweloperów serwera.",
+ "DropItemBugged": "Przedmiot, który próbujesz upuścić jest popsuty. Zgłoszenie zostało wysłane do deweloperów serwera.",
+ "HandsBusy": "Twoje ręce są zajęte",
+ "CantUseItemInSkinChange": "Nie możesz użyć przedmiotu podczas zmieniania swojego wizerunku",
+ "CantDropItemInSkinChange": "Nie możesz upuścić przedmiotu podczas zmieniania swojego wizerunku",
+ "CantPickupItemInSkinChange": "Nie możesz podnieść przedmiotu podczas zmieniania swojego wizerunku",
+ "CantSwitchItemInSkinChange": "Nie możesz zmienić przedmiotu podczas zmieniania swojego wizerunku",
+ "CantGiveItemInSkinChange": "Nie możesz dać przedmiotu podczas zmieniania swojego wizerunku",
+ "CantTakeItemInSkinChange": "Nie możesz wziąć przedmiotu podczas zmieniania swojego wizerunku",
+ "ItemUnequippableNoAmmo": "{1} w slocie {2} nie ma amunicji i nie może zostać użyty!",
+ "NoSpaceSelfInventory": "Nie masz już miesca w ekwipunku",
+ "Business": "biznes",
+ "House": "mieszkanie",
+ "Clan": "klan",
+ "Vehicle": "pojazd",
+ "Item": "przedmiot",
+ "ItemType": "rodzaj przedmiotu",
+ "Gate": "brama",
+ "Door": "drzwi",
+ "ClanRank": "ranga klanu",
+ "JobRank": "praca rangi",
+ "RadioStation": "stacja radiowa",
+ "Months": [
+ "Styczeń",
+ "Luty",
+ "Marzec",
+ "Kwiecień",
+ "Maj",
+ "Czerwiec",
+ "Lipiec",
+ "Sierpień",
+ "Wrzesień",
+ "Październik",
+ "Listopad",
+ "Grudzień"
+ ],
+ "WeekDays": [
+ "Niedziela",
+ "Poniedziałek",
+ "Wtorek",
+ "Środa",
+ "Czwartek",
+ "Piątek",
+ "Sobota"
+ ],
+ "CardinalDirections": [
+ "Północ",
+ "Północny wschód",
+ "Wschód",
+ "Południowy zachód",
+ "Południe",
+ "Południowy wschód",
+ "Zachód",
+ "Północny zachód"
+ ],
+ "NewPlayerReadyToPlay": [
+ "Dostałeś trochę pieniędzy. Użyj {1} aby znaleść miejsca do kupowania przedmiotów.",
+ "Jeżeli potrzebujesz pieniędzy, żółte kropki na mapie to miejsca pracy.",
+ "Aby zdobyć auto musisz odwiedzić dealera samochodów. Możesz też wypożyczyć samochód przy spawnie lub użyć pociągu",
+ "Pamiętaj aby przeczytać {1} i użyć {2} aby zdobyć więcej informacji."
+ ],
+ "YourCurrentVehicleDeleted": "Samochód w którym przebywałeś został usunięty.",
+ "Distance": "Odległość",
+ "Meters": "Metry",
+ "Feet": "Stopy",
+ "Kilometers": "Kilometry",
+ "Miles": "Mile",
+ "MustBeVehicleDriver": "Musisz być kierowcą tego pojazdu!",
+ "PlayerJoinedServer": "{1} dołączył do gry z {1}!",
+ "PlayerLeftServer": "{1} wyszedł z gry! ({1})",
+ "DisconnectReasons": [
+ "Utracenie Połączenia",
+ "Odłączenie",
+ "Niewspierana Wersja",
+ "Nieprawidłowa Gra",
+ "Błędne Hasło",
+ "Niewspierany Plik Wykonalny",
+ "Odłączenie",
+ "Zbanowany",
+ "Nie udane",
+ "Nieprawidłowa Nazwa",
+ "Crashed"
+ ],
+ "TakeItemFromHouse": "bierze {1} z mieszkania",
+ "TakeItemFromBusinessStorage": "bierze {1} z magazynu biznesu",
+ "TakeItemFromBusiness": "bierze {1} z biznesu",
+ "TakeItemFromItem": "bierze {1} z {2}",
+ "TakeItemFromVehicleTrunk": "bierze {1} z bagażnika",
+ "TakeItemFromVehicleDash": "bierze {1} ze schowka",
+ "JobEquipmentInventoryKeyBindTip": "Wyposażenie służbowe jest w twoim ekwipunku. Naciśnij {1} aby je zobaczyć.",
+ "JobEquipmentInventoryCommandTip": "Wyposażenie służbowe jest w twoim ekwipunku. Użyj {1} aby je zobaczyć.",
+ "AccountHelp": [
+ "NIE PODAWAJ nikomu swojego hasła. {1} nigdy nie zapyta cię o twoje hasło",
+ "Użyj {1} aby zmienić swoje hasło i {2} jeżeli je zapomniałeś",
+ "Kilka ustawień które możesz użyć: {1}"
+ ],
+ "VehicleHelp": [
+ "Twoje osobiste auta zapisują się za każdym razem jak ktoś wyjdzie z gry!",
+ "Odwiedź dealera samochodów, aby zakupić pojazd (Użyj {1} po więcej informacji)",
+ "Kilka komend: {1}",
+ "Odwiedź warsztat mechanika aby naprawić, pokolorować i/lub ulepszyć swój pojazd! {1} po więcej informacji"
+ ],
+ "VehicleDealershipHelp": [
+ "Odwiedź dealera samochodów, aby zakupić nowy pojazd. Użyj {1} aby jednego zlokalizować.",
+ "Przy dealerze samochodów, wejdź do auta, które chcesz kupić i ukaże ci się jego cena.",
+ "Jeśli chcesz kupić pojazd, użyj {1} i dostanie kluczyki by przetestować je na parkingu.",
+ "Odjedź od dealera samochodów, aby potwierdzić zakup pojazdu."
+ ],
+ "JobHelp": [
+ "Odwiedzaj miejsca pracy aby zarabiać pieniądze. Szkuaj zółtych punktów na mapie",
+ "Przy miejscu pracy, użyj {1} aby zdobyć prace. Użyj {2} by opuścić swoją pracę",
+ "Użyj {1} aby zacząć pracę. Możesz też dostać pracę {2} i {3}",
+ "Większość pojazdów służbowych jest zamknięta. Użyj {1} obok niego aby do niego wsiąść.",
+ "Przy wsiadaniu do pojazdu służbowego, dostaniesz informacje jak wykonać podjętą pracę."
+ ],
+ "ChatHelp": [
+ "Są 2 główne rodzaje chatów: Poza postacią (OOC) i w postaci (IC)",
+ "Mieszanie tych 2 rodzajów jest nieprawidłowym roleplay'em. Zobacz {1} po więcej informacji.",
+ "Kilka komend na chacie: {1}",
+ "Niektóre mają dostępne krótsze nazwy ({1} by rozmawiać, {2} by krzyczeć, itp.)"
+ ],
+ "ServerRulesHelp": [
+ "Nierealistyczne akcje (powergaming) są niedozwolone. Nie jesteś superman'em.",
+ "Roleplay na tle terrorystycznym jest niedozowolony.",
+ "Zawszę słuchaj się administracji.",
+ "Nie mieszaj czatów (metagaming). Nie możesz używać informacji w postaci, jeżeli uzyskałeś je poza nią.",
+ "Używaj języka angielskiego na głównych chatach. Jeżeli nie jestes dobry z angielskiego, użyj {1}"
+ ],
+ "AnimationHelp": [
+ "Animacje pozwalają ci bardziej wczuć się w swoją role.",
+ "Używaj {1} lub {2} z nazwą by użyć animacji.",
+ "By zobaczyć liste animacji, użyj {1}"
+ ],
+ "WeaponHelp": [
+ "Odwiedź sklep z bronią, aby kupić nową broń. Użyj {1} by znaleźć taki sklep.",
+ "Musisz posiadać licenje na broń, aby takową kupić.",
+ "Licencje broni są wydawanie przez policję. Zaaplikuj się tam, aby taką zdobyć.",
+ "Bronie mogą być też kupowane nielegalnie od niektórych bizensów, dealerów broni i klanów."
+ ],
+ "SkinHelp": [
+ "W sklepie z ubraniami, użyj {1} aby kupić ubrania.",
+ "Kiedy masz ubrania, wyposaż się w nie i użyj je jak każdy inny przedmiot by ukazać modyfikacje postaci (sprawdź {1} aby zobaczyć jak używać itemy)",
+ "Niektóre skiny są dostępne tylko dla niektórych osób, klanów lub z innych powodów."
+ ],
+ "KeyBindHelp": [
+ "Możesz zmienić przypisania klawiszy. Użyj {1} aby zobaczyć twoje przypisane klawisze.",
+ "Użyj {1} aby dodać nowe przypisanie i {2} aby je usunąć.",
+ "Domyślnymi przyciskami są: {1} aby uruchomić pojazd, {1} aby użyć świateł, and {3} aby otworzyć/zamknąć pojazd",
+ "Naciśnij {1} aby zobaczyć swoje itemy i {2} aby wyposażyć się w jakiś przedmiot lub {3} aby go schować.",
+ "Naciśnij {1} aby użyć przedmiot, który trzymasz, naciśnij {2} aby go upuścić lub naciśnij {3} aby podnieść jakiś przedmiot z ziemi."
+ ],
+ "BusinessHelp": [
+ "Użyj {1} aby kupować przedmioty lub {2} aby zobaczyć listę co jest na sprzedaż w jakimkolwiek bizensie.",
+ "Biznesy mają niebieskie nazwy nad ikoną przy ich wejściu.",
+ "Komendy właściciela biznesu: {1}",
+ "Nowe auto na sprzedaż pojawi się po odjechaniu od dealera samochodów."
+ ],
+ "ClanHelp": [
+ "Zapytaj administratora o stworzenie klanu (Podobne do fakcji/grup/rodzin)",
+ "Właściciele klanu mają pełną kontrole over nad ich klanem od momentu gdy jest stworzony",
+ "Komendy klanu: {1}",
+ "Więcej komend klanu: {1}"
+ ],
+ "RadioStationHelp": [
+ "Użyj {1} by ustawić stację twojego auta, mieszkania lub biznesu",
+ "Użyj {2} by zobaczyć listę stacji",
+ "Możesz zmienić głośność swojego radia używając {1} i liczbą od 0 do 100 jako procenty"
+ ],
+ "WealthAndTaxHelp": [
+ "Twoje podatki przy wypłacie są {1} procentami twojego przeliczonego bogactwa.",
+ "Twoja przeliczone bogactwo jest obliczone wliczając twoje pojazdy, mieszkania i biznesy, które posiadasz.",
+ "Każdy pojazd jest {1}, każde mieszkanie jest {2} i każdy biznes jest {3}",
+ "Użyj {1} aby zobaczyć swoje bogactow i {2} zobaczyć ile będziesz musiał zapłacić przy następnej wypłacie"
+ ],
+ "MustBeInAVehicle": "Musisz być w pojeździe!",
+ "MustBeInOrNearVehicle": "Musisz być w lub obok pojazdu!",
+ "MustBeInVehicleFrontSeat": "Musisz być w przednim siedzeniu pojazdu!",
+ "MustBeInVehicleDriverSeat": "Musisz być kierowcą pojazdu!",
+ "DontHaveVehicleKey": "Nie masz klucza do tego pojazdu!",
+ "NoGateAccess": "Nie masz dostępu do tej bramy!",
+ "GateBroken": "Ta brama jest popsuta!",
+ "GateHacked": "Ta brama nie odpowiada!",
+ "RadioJammed": "Słysysz tylko szumy z radia.",
+ "VehicleNotForSale": "To auto nie jest na sprzedaż!",
+ "VehicleNotForRent": "Tego pojazdu nie można wypożyczyć!",
+ "BusinessNotForSale": "Ten biznes nie jest na sprzedaż!",
+ "BusinessNotForRent": "Tego biznesu nie można wypożyczyć!",
+ "HouseNotForSale": "This house is not for sale!",
+ "HouseNotForRent": "Tego biznesu nie można wypożyczyć!",
+ "DealershipPurchaseTestDrive": "Odjedź pojazdem od dealera samochodów aby go kupić, lub wysiądź aby anulować zakup.",
+ "DealershipPurchaseExitedVehicle": "Anulowałeś kupno pojazdu, ponieważ wysiadłeś z pojazdu!",
+ "VehiclePurchaseComplete": "Ten pojazd jest teraz twój, zapiszę się nieważne gdzie jest.",
+ "VehiclePurchaseNotEnoughMoney": "Nie masz wystarczająco dużo funduszy aby kupić to auto!",
+ "HousePurchaseNotEnoughMoney": "Nie masz wystarczająco dużo funduszy aby kupić to mieszkanie!",
+ "BusinessPurchaseNotEnoughMoney": "Nie masz wystarczająco dużo funduszy aby kupić ten biznes!",
+ "Locales": {
+ "English": "Angielski",
+ "Russian": "Rosyjski",
+ "Spanish": "Hiszpański",
+ "German": "Niemiecki",
+ "Dutch": "Holenderski",
+ "Polish": "Polski"
+ },
+
+ "ADDED-21JAN2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "HeaderPlayerHousesList": "Mieszkania Gracza ({1})",
+ "HeaderPlayerStaffFlagsList": "Flagi Administracji ({1})",
+ "HeaderStaffFlagsList": "Flagi Administracji",
+ "NonRPName": "Nieprawidłowa nazwa roleplay! Wybierz nową:",
+ "InvalidStaffFlag": "Flaga administracji nie znaleziona!",
+ "InvalidClanFlag": "Flaga klanu nie znaleziona!",
+ "InvalidLocale": "Język nie znaleziony!",
+ "HeaderJobUniformList": "Mundury robocze ({1})",
+ "HeaderJobEquipmentList": "Wyposażenie robocze ({1})",
+ "InvalidJobUniform": "Mundur roboczy nie znaleziony!",
+ "InvalidJobEquipment": "Wyposażenie robocze nie znalezione!",
+ "HeaderVehiclesInRangeList": "Pojazdy w {1}",
+ "NoVehiclesWithInRange": "Nie ma pojazdów w {1}",
+ "AmountNotNumber": "Ilość musi być liczbą!",
+ "NeedToBeWorking": "Musisz być w pracy! Użyj {1} w punkcie pracy lub obok pojazdu służbowego.",
+ "NeedToBeOnJobRoute": "Musisz być w trasie! Użyj {1} w pojeździe służbowym",
+ "CurrentJobRouteDeleted": "Trasa służbowa, którą jechałeś została usunięta przez Administratora",
+ "CurrentJobRouteVehicleColoursChanged": "Kolory pojazdów na twojej trasie zostały zmienione przez Administratora.",
+ "NotYourJob": "To nie twoja praca!",
+ "JobPoints": "Możesz zdobyć pracę udając się do żółtych punktów na mapie.",
+ "QuitJobToTakeAnother": "Jeżeli chcesz tą prace, użyj {1} aby opuścić swoją dotychczasową pracę.",
+ "NotAJobVehicle": "To nie jest pojazd służbowy!",
+ "NotYourJobVehicle": "To nie jest twój pojazd służbowy!",
+ "JobRouteDisabled": "Trasa służbowa, którą jechałeś została usunięta przed Administratora",
+ "HeaderPickupTypes": "Rodzaję Pickup'ów",
+ "HeaderBlipTypes": "Rodzaje Ikon Mapy",
+ "InvalidGPSLocation": "Nie ma lokalizacji z taką nazwą lub rodzajem",
+ "HeaderBusinessList": "Biznesy",
+ "VehicleForSale": "Ten {1} jest do kupienia za {2}! Użyj {3} jeżeli chcesz go kupić",
+ "VehicleForRent": "Ten {1} jest do wynajęcia za {2}! Użyj {3} jeżeli chcesz go wynająć",
+
+ "ADDED-31JAN2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "LoginFailedInvalidPassword": "Invalid password! {1} attempts remaining",
+ "LoginFailedNoPassword": "You must enter a password! ! {1} attempts remaining",
+ "RegistrationFailedNoPassword": "You must enter a password!",
+ "RegistrationFailedNoPasswordConfirm": "You must confirm the password!",
+ "RegistrationFailedNoEmail": "You must enter an email!",
+ "AccountNameAlreadyRegistered": "Your name is already registered!",
+ "AlreadyLoggedIn": "You are already logged in!",
+ "RegistrationFailedInvalidEmail": "That email is invalid!",
+ "RegistrationFailedPasswordMismatch": "The passwords don't match!",
+ "RegistrationFailedCreateError": "Your account couldn't be created!",
+ "RegistrationSuccess": "Your account has been created!",
+ "RegistrationEmailVerifyReminder": "Don't forget to verify your email! A verification code has been sent to you.",
+ "RegistrationCreateCharReminder": "To play on the server, you will need to make a character.",
+ "NoCharactersGUIMessage": "You have no characters. Would you like to make one?",
+ "NoCharactersGUIWindowTitle": "No characters",
+ "NoCharactersChatMessage": "You have no characters. Use {1} to make one.",
+ "NeedEmailFor2FA": "You need to add your email to your account to use two-factor authentication.",
+ "NeedEmailVerifiedFor2FA": "You need to verify your email to use two-factor authentication.",
+ "SetEmailHelpTip": "Use {1} to set your email.",
+ "VerifyEmailHelpTip": "Use {1} to verify your email.",
+
+ "ADDED-13FEB2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "NearbyRadio": "Nearby radio",
+ "FromRadio": "From radio",
+ "ToRadio": "To radio",
+ "NeedToEnterPropertyCommand": "You need to enter the {1} first! Use {2} to enter and exit",
+ "NeedToEnterPropertyKeyPress": "You need to enter the {1} first! Press {2} to enter and exit",
+ "InventoryFullCantCarry": "You don't have any space to carry this (full inventory)!",
+ "NotEnoughCashNeedAmountMore": "You don't have enough money! You need {1} more!",
+ "AmountMustBeMoreThan": "The amount must be more than {1}!",
+ "WeaponBanned": "You are not allowed to buy or use weapons!",
+ "TimeNotNumber": "The time must be a number",
+ "HeaderDefaultBusinessItemTypes": "Business Item Templates",
+ "FixingStuck": "Fixing your position and virtual world ...",
+ "CantUseCommandYet": "You must wait before you can use this command again!",
+ "NotATester": "You are not a tester!",
+ "AccessDenied": "AccessDenied"
+}
diff --git a/locale/russian.json b/locale/russian.json
new file mode 100644
index 00000000..7580425c
--- /dev/null
+++ b/locale/russian.json
@@ -0,0 +1,392 @@
+{
+ "TranslationProvidedBy": "VNDTTS",
+ "LocaleEnglishName": "Russian",
+ "LocaleNativeName": "Русский",
+ "LocaleOffer": "Этот сервер доступен на русском. Используйте {1} чтобы его использовать.",
+ "LocaleChanged1": "Ваш язык был установлен на {1}",
+ "LocaleChanged2": "Этот сервер теперь будет показывать сообщения в {1}",
+ "LocaleChangedNote": "Это не влияет на сообщения других игроков",
+ "AccentsListHeader": "Акценты",
+ "HeaderHelpMainList": "Помощь Категории",
+ "AccentNotFound": "Не удалось найти акцент",
+ "AccentSet": "Вы установили свой акцент на {1}",
+ "AnimationNotFound": "Такой анимации не существует",
+ "AnimationCommandTip": "Используйте {1} чтобы просмотреть список доступных анимаций",
+ "AnimationInvalidDistance": "Дистанция должна быть между 0 и 3",
+ "AnimationStopCommandTip": "Используйте {1} чтобы остановить анимацию",
+ "CantBanClient": "Вы не можете забанить этого игрока",
+ "PlayerAccountBanned": "Аккаунт {1} был заблокирован ",
+ "ClanNotFound": "Не удалось найти клан",
+ "ClanNameTaken": "Клан с таким именем уже существует",
+ "PlayerNotFound": "Не удалось найти игрока",
+ "ClanCantRemoveRanks": "Вы не можете убрать ранги клана",
+ "ClanCantAddRanks": "Вы не можете добавить новые ранги клана",
+ "ClanRankNotFound": "Не удалось найти ранг клана",
+ "ClanCantChangeMemberTag": "Вы не можете изменить теги членов клана",
+ "ClanPlayerNotInSameClan": "Игрок не в вашем клане",
+ "ClanCantChangeRankLevel": "Вы не можете изменить уровень ранга клана",
+ "ClanCantChangeRankTag": "Вы не можете изменить теги ранга клана",
+ "NameNotRegistered": "Ваше имя не зарегестрировано! Используйте {1} чтобы создать аккаунт.",
+ "AutomaticLoginIPToggle": "Автоматический вход по IP теперь {1}",
+ "CouldNotRegisterAccount": "Возникла проблема при создании аккаунта. Пожалуйста свяжитесь с администратором.",
+ "RandomTipsToggle": "Случайные подсказки теперь {1}",
+ "ActionTipsToggle": "Местные подсказки теперь {1}",
+ "AutoSpawnLastCharToggle": "Автоматическое возрождение как последний выбраный персонаж теперь {1}",
+ "AccountGUISettingToggle": "GUI теперь {1}",
+ "On": "Включен",
+ "Off": "Выключен",
+ "Yes": "Да",
+ "No": "Нет",
+ "True": "Верно",
+ "False": "Неверно",
+ "Locked": "Закрыто",
+ "Unlocked": "Открыто",
+ "PasswordNotGoodEnough": "Новый пароль должен соответсвовать требованиям !",
+ "PasswordNeedsBase": "Пароль должен местить не меншьше {1}",
+ "PasswordNeedsCapitals": "{1} Заглавные буквы",
+ "PasswordNeedsNumbers": "{1} цифры",
+ "PasswordNeedsSymbols": "{1} символы",
+ "PasswordsDontMatch": "Новый пароль и его подтверджение не совпадают!",
+ "PasswordChanged": "Ваш пароль был изменен!",
+ "AutoLoggedInIP": "Вы автоматически войшли по IP!",
+ "WelcomeBack": "Добро пожаловать {1}, {2}! Используйте {3} чтобы продолжить.",
+ "WelcomeNewPlayer": "Добро пожаловать в {1}, {2}! Используйте {3} чтобы начать играть.",
+ "InvalidPlayer": "Не удалось найти игрока!",
+ "InvalidBusiness": "Не удалось найти бизнес!",
+ "InvalidHouse": "Не удалось найти дом!",
+ "InvalidVehicle": "Не удалось найти транспорт!",
+ "InvalidClan": "Не удалось найти клан!",
+ "InvalidClanRank": "Не удалось найти ранг клана!",
+ "InvalidJob": "Не удалось найти работу!",
+ "InvalidItem": "Не удалось найти предмет!",
+ "InvalidItemType": "Не удалось найти предмет!",
+ "InvalidRadioStation": "Не удалось найти радиостанцию!",
+ "InvalidGate": "Не удалось найти ворота!",
+ "EntersProperty": "открывает дверь и входит в {1}",
+ "ExitsProperty": "открывает дверь и покидает {1}",
+ "EnterExitPropertyDoorLocked": "пытаеться открыть двери {1} но у него не выходить потому-что двери закрыты",
+ "PropertyNoInterior": "У {1} нет доступного интерьера, но вы все еще можете использовать комманды стоя на значке возле входа.",
+ "NoBusinessWithItemType": "Нет бизнесов в которых этот предмет доступен",
+ "HeaderKeyBinds": "Привязки",
+ "HeaderAccountHelp": "Помощь Аккаунт",
+ "HeaderVehicleHelp": "Помощь Транспорт",
+ "HeaderVehicleDealershipHelp": "Помощь Автосалон",
+ "HeaderJobHelp": "Помощь Работа",
+ "HeaderChatHelp": "Помощь Чат",
+ "HeaderServerRules": "Правила Сервера",
+ "HeaderWebsiteInfo": "Сайт",
+ "HeaderDiscordInfo": "Discord",
+ "HeaderAnimationsList": "Список Анимаций",
+ "HeaderPayAndSprayHelp": "Помощь Pay 'n' Spray",
+ "HeaderAmmunationHelp": "Помощь Аммунация",
+ "HeaderVehicleTuneupHelp": "Помощь Тюнинг Автомобиля",
+ "HeaderBindableKeysHelp": "Кнопки которые можно привязать",
+ "HeaderSkinHelp": "Помощь Одежда/Облик",
+ "HeaderBusinessHelp": "Помощь Бизнес",
+ "HeaderClanHelp": "Помощь Клан",
+ "HeaderPlayerVehiclesList": "Транспорт Игрока ({1})",
+ "HeaderPlayerBusinessesList": "Бизнесы Игрока ({1})",
+ "HeaderClansList": "Список кланов",
+ "HeaderAdminsList": "Список администраторов",
+ "HeaderBadgeInfo": "Информация значка",
+ "HeaderAccentsList": "Список акцентов",
+ "HeaderPlayerInfo": "Информация об игроке ({1})",
+ "HeaderWealthandTaxHelp": "Информация о достатке и налогах",
+ "HeaderCommandInfo": "Информация о команде ({1})",
+ "HeaderRadioHelp": "Помощь Радио",
+ "HeaderRadioStationsList": "Радиостанции",
+ "HeaderKeyBindsList": "Список привязок",
+ "RadioVolumeChanged": "{1} Вы сменили громкость звука на {2}%",
+ "VolumeLevelNotNumber": "Уровень звука должен быть в цифрах",
+ "RadioStationLocationInvalid": "Вы должны находится в транспорте, доме, или бизнесе или иметь устройство чтобы сменить радиостанцию!",
+ "ActionBusinessRadioStationChange": "меняет радиостанцию бизнеса на {1} ({2})",
+ "ActionHouseRadioStationChange": "меняет радиостанцию дома на {1} ({2})",
+ "ActionVehicleRadioStationChange": "меняет радиостанцию транспорта на {1} ({2})",
+ "ActionItemRadioStationChange": "переключает станцию {1} на станцию {2} ({3})",
+ "RandomVehicleCommandsDisabled": "Это случайная машина трафика, команды на нее не работают.",
+ "HouseDoorLock": "Дом {1} {2}!",
+ "BusinessDoorLock": "Бизнес {1} {2}!",
+ "ServerGameModeRestarting": "Режим игры сервера перезапускается!",
+ "HeaderSelfItemList": "Ваш инвентарь",
+ "HeaderPlayerItemList": "Инвентарь игрока ({1})",
+ "HeaderHouseItemList": "Инвентарь дома",
+ "HeaderBusinessFloorItemList": "Инвентарь бизнеса (Продажа)",
+ "HeaderBusinessStorageItemList": "Инвертарь бизнеса (Хранилище)",
+ "HeaderItemItemList": "Инвентарь {1}",
+ "ItemSlotNotNumber": "Слот предмета должен быть цифрой",
+ "ItemSlotMustBeBetween": "Слот этого предмета должен находиться между {1} и {2}!",
+ "UseItemBugged": "Предмет который вы пытаетесь использовать забагован. Баг репорт был послан разработчикам сервера.",
+ "PickupItemBugged": "Предмет который вы пытаетесь поднять забагован. Баг репорт был послан разработчикам сервера.",
+ "DropItemBugged": "Предмет который вы пытаетесь выкинуть забагован. Баг репорт был послан разработчикам сервера.",
+ "HandsBusy": "Ваши руки заняты",
+ "CantUseItemInSkinChange": "Вы не можете использовать предметы когда вы меняете свой облик",
+ "CantDropItemInSkinChange": "Вы не можете кидать предметы когда вы меняете свой облик",
+ "CantPickupItemInSkinChange": "Вы не можете подбирать предметы когда вы меняете свой облик",
+ "CantSwitchItemInSkinChange": "Вы не можете переключать предметы когда вы меняете свой облик",
+ "CantGiveItemInSkinChange": "Вы не можете давать предметы когда вы меняете свой облик",
+ "CantTakeItemInSkinChange": "Вы не можете брать предметы когда вы меняете свой облик",
+ "ItemUnequippableNoAmmo": "{1} на слоте {2} не имеет патронов и не может быть экипирован!",
+ "NoSpaceSelfInventory": "У вас не осталось места в инвентаре",
+ "Business": "бизнес",
+ "House": "дом",
+ "Clan": "клан",
+ "Vehicle": "транспорт",
+ "Item": "предмет",
+ "ItemType": "тип предмета",
+ "Gate": "ворота",
+ "Door": "двери",
+ "ClanRank": "Ранг клана",
+ "JobRank": "Ранг работы",
+ "RadioStation": "радиостанция",
+ "Months": [
+ "Январь",
+ "Февраль",
+ "Март",
+ "Апрель",
+ "Май",
+ "Июнь",
+ "Июль",
+ "Август",
+ "Сентябрь",
+ "Октябрь",
+ "Ноябрь",
+ "Декабрь"
+ ],
+ "WeekDays": [
+ "Воскресенье",
+ "Понедельник",
+ "Вторник",
+ "Среда",
+ "Четверг",
+ "Пятница",
+ "Субота"
+ ],
+ "CardinalDirections": [
+ "Север",
+ "Северо-восток",
+ "Восток",
+ "Юго-восток",
+ "Юг",
+ "Юго-запад",
+ "Запад",
+ "Северо-запад"
+ ],
+ "NewPlayerReadyToPlay": [
+ "Вам было надано немного денег. Используйте {1} чтобы найти места в которых можно купить предметы.",
+ "Если вам нужны деньги, желтые точки это места работы на карте.",
+ "Если вам нужен транспорт, посетите автосалон. Вы также можете использовать орендовочный транспорт возле начальной зоны или сесть на поезд",
+ "Не забудьте ознакомиться с {1} и использовать {2} для информации."
+ ],
+ "YourCurrentVehicleDeleted": "Транспорт в котором вы находились было удалено.",
+ "Distance": "Дистанция",
+ "Meters": "Метров",
+ "Feet": "Футов",
+ "Kilometers": "Километры",
+ "Miles": "Мили",
+ "MustBeVehicleDriver": "Вы можете быть только водителем!",
+ "PlayerJoinedServer": "{1} присоеденился к игре из {1}!",
+ "PlayerLeftServer": "{1} покинул игру! ({1})",
+ "DisconnectReasons": [
+ "Потеряно соединение",
+ "Отключен",
+ "Неподерживаемый клинт",
+ "Неправильная игра",
+ "Неправильный пароль",
+ "Неподдерживаемый Exe",
+ "Disconnected",
+ "Забанен",
+ "Не удалось",
+ "Не правильное имя",
+ "Вылетел"
+ ],
+ "TakeItemFromHouse": "Берет {1} из дома",
+ "TakeItemFromBusinessStorage": "Берет {1} из хранилища",
+ "TakeItemFromBusiness": "Берет {1} из бизнеса",
+ "TakeItemFromItem": "Достает {1} из {2}",
+ "TakeItemFromVehicleTrunk": "Достает {1} из багажника",
+ "TakeItemFromVehicleDash": "Достает {1} из бардачка",
+ "JobEquipmentInventoryKeyBindTip": "Рабочее снаряжение у вас в инвентаре. Нажмите {1} чтобы его просмотреть.",
+ "JobEquipmentInventoryCommandTip": "Рабочее снаряжение у вас в инвентаре. Используйте {1} чтобы его просмотреть.",
+ "AccountHelp": [
+ "Не предоставляйте свой пароль никому. {1} персонал никогда не будет спрашивать у вас пароль ",
+ "Используйте {1} чтобы изменить ваш пароль, и {2} если вы его забыли",
+ "Некоторые опции: {1}"
+ ],
+ "VehicleHelp": [
+ "Ваш личный транспорт будет сохранен в любом месте где вы, или кто-либо другой его оставит!",
+ "Посетите автосалон чтобы приобрести новый транспорт (Используйте {1} чтобы увидеть больше информации)",
+ "Некоторые комманды: {1}",
+ "Посетите гараж механика чтобы починить, изменить цвет, и затюнинговать ваш автомобиль! {1} для информации"
+ ],
+ "VehicleDealershipHelp": [
+ "Посетите автосалон чтобы приобрести новый транспорт. Используйте {1} чтобы найти его.",
+ "Ввойдите в транспорт который вы хотите приобрести, и цена на него будет вам показана",
+ "Если хотите приобрести транспорт, используйте {1} и вам дадут ключи чтобы провести тест-драйв на парковке.",
+ "Покиньте автосалон на вашем новом транспорте чтобы подвердить покупку."
+ ],
+ "JobHelp": [
+ "Посетите места работы, получите работу и зарабатывайте деньги. Ищите желтые точки на карте",
+ "На месте работы, используйте {1} чтобы получить работу. Используйте {2} чтобы оставить работу",
+ "Используйте {1} чтобы начать работать. Вы также можете получить работу {2} и {3}",
+ "Большинство рабочего транспорта изначально закрыто. Используйте {1} находясь возле него чтобы войти.",
+ "Во время входа в рабочий транспорт, информация о том, как работать будет вам предоставлена."
+ ],
+ "ChatHelp": [
+ "Существуют два основных типов чата: внутри персонажа и вне его",
+ "Смешивать их не считается полноценной ролевой игрой. Просмотрите {1} для информации.",
+ "Некоторые комманды чата: {1}",
+ "Некоторые имеют укороченые версии ({1} чтобы говорить, {2} чтобы выкрикивать, и так далее)"
+ ],
+ "ServerRulesHelp": [
+ "Нереалистичные действия запрещены. Вы не супермен.",
+ "Ролевая игра за террориста и терроризм запрещены.",
+ "Всегда следуйте соблюдайте инструкии даные модератором или администратором.",
+ "Вам не позволяется использовать информацию полученую вне персонажа, персонажем ",
+ "Пожалуйста придерживаетесь английского в главном чате, если вы плохо знаете английский, используйте {1}"
+ ],
+ "AnimationHelp": [
+ "Анимации позволяют вам улучшить составляющую ролевой игры с помощью визуальных действий",
+ "Используте {1} или {2} с названием тобы применить анимацию.",
+ "Чтобы просмотреть список доступных анимаций, используйте {1}"
+ ],
+ "WeaponHelp": [
+ "Посетите магазин оружия что-бы приобрести оружие. Используйте {1} чтобы найти.",
+ "Оружие невозможно купить без лицензии.",
+ "Лицензиями на оружие занимается отделение полиции. Обратитесь туда чтобы заполучить лицензию.",
+ "Оружие также может быть приобретено нелегально от некоторых бизнесов, торговцев оружием, и кланов."
+ ],
+ "SkinHelp": [
+ "В магазине одежды используйте {1} чтобы купить одежду",
+ "Когда у вас есть предмет одежды, экипируйте его и используйте его как любой другой предмет чтобы просмотреть меню выбора облика персонажа (Просмотрите {1} чтобы научиться использовать предметы)",
+ "Некоторые облики ограничены только для некоторых работ, кланов, или по каким-то другим причинам."
+ ],
+ "KeyBindHelp": [
+ "Вы можете сами создавать ваши привязки на кнопки. Используйте {1} чтобы просмотреть ваши привязки.",
+ "Используйте {1} чтобы добавить новую приязку или {2} чтобы убрать ее.",
+ "Стандартные привязки: {1} для мотора, {1} для фар, и {3} для открытия/закрытия",
+ "Используйте {1} чтобы просмотреть ваши предметы {2} чтобы экипировать предмет или {3} чтобы убрать.",
+ "Используйте {1} чтобы использвать предмет который вы держите в руках, используйте {2} чтобы его выбростить, или используйте {3} чтобы подобрать предмет."
+ ],
+ "BusinessHelp": [
+ "Используйте {1} чтобы покупать предметы или {2} чтобы просмотреть список того, что продаеться в любом бизнесе",
+ "Бизнесы имеют их названия синим цветом над иконкой возле входа.",
+ "Комманды владельца бизнеса: {1}",
+ "Новый автомобиль появится после того как вы уедете из автосалона."
+ ],
+ "ClanHelp": [
+ "Попросите администратора чтобы основать клан",
+ "Владельцы клана имеют полный контроль над ихним кланом после его основания",
+ "Комманды клана: {1}",
+ "Больше комманд клана: {1}"
+ ],
+ "RadioStationHelp": [
+ "Используйте {1} чтобы выбрать радиостанцию для вашего траспорта, дома, или бизнеса",
+ "Используйте {2} чтобы просмотреть список радиостанций",
+ "Вы можете изменить громкость радио используя {1} с 0-100 в качестве процентов"
+ ],
+ "WealthAndTaxHelp": [
+ "Вы платите {1} процентов от вашего расчетного уровня достатка.",
+ "Ваш расчетный уровень достатка зависит от того, сколько вам принадлежит транспорта, домов и бизнесов.",
+ "Каждый транспорт это {1}, каждый дом это {2}, И каждый бизнес это {3}",
+ "Используйте {1} чтобы просмотреть ваш текущий достаток, и {2} чтобы просмотреть сколько вы платите налогов с каждой зарплаты"
+ ],
+ "MustBeInAVehicle": "Вы должны быть внутри транспорта!",
+ "MustBeInOrNearVehicle": "Вы должны быть возле транспорта!",
+ "MustBeInVehicleFrontSeat": "Вы можете сидеть только спереди!",
+ "MustBeInVehicleDriverSeat": "Вы можете быть только водителем!",
+ "DontHaveVehicleKey": "У вас нет ключей к этому транспорту!",
+ "NoGateAccess": "У вас нет доступа к воротам!",
+ "GateBroken": "Эти ворота сломаны!",
+ "GateHacked": "Ворота не отвечают!",
+ "RadioJammed": "Из радио доносится лишь шум.",
+ "VehicleNotForSale": "Этот транспорт не продается!",
+ "VehicleNotForRent": "Этот транспорт не сдается в оренду! ",
+ "BusinessNotForSale": "Этот бизнес не продается!",
+ "BusinessNotForRent": "Этот бизнес не сдается в оренду!",
+ "HouseNotForSale": "Этот дом не продаеться!",
+ "HouseNotForRent": "Этот дом не сдаеться в оренду!",
+ "DealershipPurchaseTestDrive": "Уедьте из автосалона чтобы подтвердить покупку транспорта, или выйдете из него чтобы отменить.",
+ "DealershipPurchaseExitedVehicle": "Вы отменили покупку транспорта покинув его!",
+ "VehiclePurchaseComplete": "Этот транспорт теперь принадлежит вам! Он останется там где вы его оставили.",
+ "VehiclePurchaseNotEnoughMoney": "у вас недостаточно денег для покупки этого транспорта!",
+ "HousePurchaseNotEnoughMoney": "У вас недостаточно денег для покупки этого дома!",
+ "BusinessPurchaseNotEnoughMoney": "У вас недостаточно денег для покупки этого бизнеса!",
+ "Locales": {
+ "English": "Английский",
+ "Russian": "Русский",
+ "Spanish": "Испанский",
+ "German": "Немецкий",
+ "Dutch": "Нидерландский"
+ },
+
+ "ADDED-21JAN2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "HeaderPlayerHousesList": "Player Houses ({1})",
+ "HeaderPlayerStaffFlagsList": "Player Staff Flags ({1})",
+ "HeaderStaffFlagsList": "Staff Flags",
+ "NonRPName": "Non-RP name! Choose a new one:",
+ "InvalidStaffFlag": "Staff flag not found!",
+ "InvalidClanFlag": "Clan flag not found!",
+ "InvalidLocale": "Language not found!",
+ "HeaderJobUniformList": "Job Uniforms ({1})",
+ "HeaderJobEquipmentList": "Job Equipment ({1})",
+ "InvalidJobUniform": "Job uniform not found!",
+ "InvalidJobEquipment": "Job equipment not found!",
+ "HeaderVehiclesInRangeList": "Vehicles within {1}",
+ "NoVehiclesWithInRange": "There are no vehicles within {1}",
+ "AmountNotNumber": "The amount must be a number!",
+ "NeedToBeWorking": "You need to be working! Use {1} at a job location or near a job vehicle.",
+ "NeedToBeOnJobRoute": "You need to be doing a job route! Use {1} in a job vehicle",
+ "CurrentJobRouteDeleted": "The job route you were on has been deleted by an admin",
+ "CurrentJobRouteVehicleColoursChanged": "Your job route's vehicle colours were changed by an admin",
+ "NotYourJob": "This is not your job!",
+ "JobPoints": "You can get a job by going the yellow points on the map.",
+ "QuitJobToTakeAnother": "If you want this job, use {1} to quit your current job.",
+ "NotAJobVehicle": "This is not a job vehicle!",
+ "NotYourJobVehicle": "This is not your job's vehicle!",
+ "JobRouteDisabled": "The job route you were on has been disabled by an admin",
+ "HeaderPickupTypes": "Pickup Types",
+ "HeaderBlipTypes": "Map Icon Types",
+ "InvalidGPSLocation": "There are no locations with that name or type",
+ "HeaderBusinessList": "Businesses",
+ "VehicleForSale": "This {1} is buyable for {2}! Use {3} if you want to buy it",
+ "VehicleForRent": "This {1} is rentable for {2}! Use {3} if you want to rent it",
+
+ "ADDED-31JAN2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "LoginFailedInvalidPassword": "Invalid password! {1} attempts remaining",
+ "LoginFailedNoPassword": "You must enter a password! ! {1} attempts remaining",
+ "RegistrationFailedNoPassword": "You must enter a password!",
+ "RegistrationFailedNoPasswordConfirm": "You must confirm the password!",
+ "RegistrationFailedNoEmail": "You must enter an email!",
+ "AccountNameAlreadyRegistered": "Your name is already registered!",
+ "AlreadyLoggedIn": "You are already logged in!",
+ "RegistrationFailedInvalidEmail": "That email is invalid!",
+ "RegistrationFailedPasswordMismatch": "The passwords don't match!",
+ "RegistrationFailedCreateError": "Your account couldn't be created!",
+ "RegistrationSuccess": "Your account has been created!",
+ "RegistrationEmailVerifyReminder": "Don't forget to verify your email! A verification code has been sent to you.",
+ "RegistrationCreateCharReminder": "To play on the server, you will need to make a character.",
+ "NoCharactersGUIMessage": "You have no characters. Would you like to make one?",
+ "NoCharactersGUIWindowTitle": "No characters",
+ "NoCharactersChatMessage": "You have no characters. Use {1} to make one.",
+ "NeedEmailFor2FA": "You need to add your email to your account to use two-factor authentication.",
+ "NeedEmailVerifiedFor2FA": "You need to verify your email to use two-factor authentication.",
+ "SetEmailHelpTip": "Use {1} to set your email.",
+ "VerifyEmailHelpTip": "Use {1} to verify your email.",
+
+ "ADDED-13FEB2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "NearbyRadio": "Nearby radio",
+ "FromRadio": "From radio",
+ "ToRadio": "To radio",
+ "NeedToEnterPropertyCommand": "You need to enter the {1} first! Use {2} to enter and exit",
+ "NeedToEnterPropertyKeyPress": "You need to enter the {1} first! Press {2} to enter and exit",
+ "InventoryFullCantCarry": "You don't have any space to carry this (full inventory)!",
+ "NotEnoughCashNeedAmountMore": "You don't have enough money! You need {1} more!",
+ "AmountMustBeMoreThan": "The amount must be more than {1}!",
+ "WeaponBanned": "You are not allowed to buy or use weapons!",
+ "TimeNotNumber": "The time must be a number",
+ "HeaderDefaultBusinessItemTypes": "Business Item Templates",
+ "FixingStuck": "Fixing your position and virtual world ...",
+ "CantUseCommandYet": "You must wait before you can use this command again!",
+ "NotATester": "You are not a tester!",
+ "AccessDenied": "AccessDenied"
+}
diff --git a/locale/spanish.json b/locale/spanish.json
new file mode 100644
index 00000000..520ef55f
--- /dev/null
+++ b/locale/spanish.json
@@ -0,0 +1,397 @@
+{
+ "TranslationProvidedBy": "PerikiyoXD",
+ "LocaleEnglishName": "Español",
+ "LocaleNativeName": "Inglés",
+ "LocaleOffer": "Este servidor se encuentra disponible en Español. Utilice {1} para usarlo",
+ "LocaleChanged1": "El idioma se ha configurado a {1}",
+ "LocaleChanged2": "El servidor mostrará los mensajes en {1}",
+ "LocaleChangedNote": "Esto no cambia los mensajes de otros jugadores",
+ "AccentsListHeader": "Acentos",
+ "HelpListHeader": "Categorías de ayuda",
+ "HelpSkinHeader": "Ayuda de personajes",
+ "HelpVehicleHeader": "Ayuda de vehículos",
+ "HelpBusinessHeader": "Ayuda de negocios",
+ "HelpHouseHeader": "Ayuda de casas",
+ "HelpRadioHeader": "Ayuda de radio",
+ "HelpAnimationHeader": "Ayuda de animaciones",
+ "AccentNotFound": "Acento no encontrado",
+ "AccentSet": "Acento establecido como {1}",
+ "AnimationNotFound": "Esa animación no existe",
+ "AnimationCommandTip": "Usa {1} para ver la lista de animaciones",
+ "AnimationInvalidDistance": "La distancia debe ser un numero entre el 0 y el 3",
+ "AnimationStopCommandTip": "Usa {1} para detener la animación actual",
+ "CantBanClient": "No se puede vetar a esta persona",
+ "PlayerAccountBanned": "La cuenta de {1} ha sido vetada",
+ "ClanNotFound": "Clan no encontrado",
+ "ClanNameTaken": "Ya existe un clan con ese nombre",
+ "PlayerNotFound": "Jugador no encontrado",
+ "ClanCantRemoveRanks": "No puedes eliminar rangos del clan",
+ "ClanCantAddRanks": "No puedes añadir rangos del clan",
+ "ClanRankNotFound": "No se encontró el rango del clan indicado",
+ "ClanCantChangeMemberTag": "No puedes cambiar las etiquetas del miembro del clan",
+ "ClanPlayerNotInSameClan": "El jugador indicado no está en tu clan",
+ "ClanCantChangeRankLevel": "No puedes cambiar el nivel del rango del clan",
+ "ClanCantChangeRankTag": "No puedes cambiar la etiqueta del rango del clan",
+ "NameNotRegistered": "¡Tu nombre no está registrado! Usa {1} para crear una cuenta",
+ "AutomaticLoginIPToggle": "Se ha {1} el inicio de sesión automático por IP",
+ "CouldNotRegisterAccount": "Hubo un problema al crear su cuenta. Por favor, póngase en contacto con un administrador",
+ "RandomTipsToggle": "Se han {1} los Consejos aleatorios",
+ "ActionTipsToggle": "Se han {1} los Consejos de acción",
+ "AutoSpawnLastCharToggle": "Se ha {1} reaparecer con el ultimo personaje usado",
+ "AccountGUISettingToggle": "Se ha {1} la Interfaz de Usuario",
+ "On": "Encendido",
+ "Off": "Apagado",
+ "Yes": "Si",
+ "No": "No",
+ "True": "True",
+ "False": "False",
+ "Locked": "Locked",
+ "Unlocked": "Unlocked",
+ "PasswordNotGoodEnough": "La nueva contraseña debe cumplir los requisitos",
+ "PasswordNeedsBase": "Las contraseñas deben tener al menos {1}",
+ "PasswordNeedsCapitals": "{1} letras mayúsculas",
+ "PasswordNeedsNumbers": "{1} números",
+ "PasswordNeedsSymbols": "{1} símbolos",
+ "PasswordsDontMatch": "La nueva contraseña y la confirmación de la nueva contraseña no son iguales.",
+ "PasswordChanged": "Su contraseña ha sido cambiada",
+ "AutoLoggedInIP": "Ha iniciado la sesion automáticamente por su IP",
+ "WelcomeBack": "¡Bienvenidos de nuevo a {1}, {2}! Por favor, {3} para continuar",
+ "WelcomeNewPlayer": "¡Bienvenido a {1}, {2}! Por favor, {3} para jugar",
+ "InvalidPlayer": "Jugador no encontrado",
+ "InvalidBusiness": "Negocio no encontrada",
+ "InvalidHouse": "Casa no encontrada",
+ "InvalidVehicle": "Vehículo no encontrado",
+ "InvalidClan": "Clan no encontrado",
+ "InvalidClanRank": "Rango del clan no encontrado",
+ "InvalidJob": "Trabajo no encontrado",
+ "InvalidItem": "Objeto no encontrado",
+ "InvalidItemType": "Tipo de objeto no encontrado",
+ "InvalidRadioStation": "Estación de radio no encontrada",
+ "InvalidGate": "Puerta no encontrada",
+ "EntersProperty": "abre la puerta y entra en el {1}",
+ "ExitsProperty": "abre la puerta y sale del {1}",
+ "EnterExitPropertyDoorLocked": "intenta abrir la puerta {1} pero no lo consigue porque está cerrada",
+ "PropertyNoInterior": "Este {1} no tiene un interior, pero todavía puede utilizar los comandos en el icono de la puerta",
+ "NoBusinessWithItemType": "No hay ningun negocio con ese objeto disponible",
+ "HeaderKeyBinds": "Atajos de teclado",
+ "HeaderAccountHelp": "Account Help",
+ "HeaderVehicleHelp": "Vehicle Help",
+ "HeaderVehicleDealerships": "Ayuda del Concesionario de Vehiculos",
+ "HeaderJobHelp": "Ayuda del Trabajo",
+ "HeaderChatHelp": "Ayuda del Chat",
+ "HeaderServerRules": "Reglas del Servidor",
+ "HeaderWebsiteInfo": "Sitio Web",
+ "HeaderDiscordInfo": "Discord",
+ "HeaderAnimationsList": "Lista de animaciones",
+ "HeaderPayAndSprayHelp": "Ayuda de 'Pay and Spray'",
+ "HeaderAmmunationHelp": "Ayuda de 'Ammunation'",
+ "HeaderVehicleTuneupHelp": "Ayuda de Puesta a punto del vehículo",
+ "HeaderBindableKeysHelp": "Atajos de teclado",
+ "HeaderSkinHelp": "Ayuda de Ropa/Personaje",
+ "HeaderBusinessHelp": "Ayuda del negocio",
+ "HeaderClanHelp": "Ayuda del clan",
+ "HeaderPlayerVehiclesList": "Vehiculos del jugador ({1})",
+ "HeaderPlayerBusinessesList": "Negocios del jugador ({1})",
+ "HeaderClansList": "Lista de clanes",
+ "HeaderAdminsList": "Lista de administradores",
+ "HeaderBadgeInfo": "Información de la placa",
+ "HeaderAccentsList": "Lista de acentos",
+ "HeaderPlayerInfo": "Información del jugador ({1})",
+ "HeaderWealthandTaxHelp": "Información sobre el patrimonio y los impuestos",
+ "HeaderCommandInfo": "Información de comando ({1})",
+ "HeaderRadioHelp": "Ayuda para la radio",
+ "HeaderRadioStationsList": "Emisoras de radio",
+ "HeaderKeyBindsList": "Lista de atajos de teclado",
+ "RadioVolumeChanged": "{1} Has cambiado el volumen de tu radio en directo a {2}%",
+ "VolumeLevelNotNumber": "El volumen debe ser un número",
+ "RadioStationLocationInvalid": "Debe estar en un vehículo, casa o negocio o tener un dispositivo personal para cambiar la emisora",
+ "ActionBusinessRadioStationChange": "cambia la emisora de la radio del negocio a {1} ({2})",
+ "ActionHouseRadioStationChange": "cambia la emisora de la radio de la casa a {1} ({2})",
+ "ActionVehicleRadioStationChange": "cambia la emisora de la radio del vehículo a {1} ({2})",
+ "ActionItemRadioStationChange": "cambia la estación de {1} a {2} ({3})",
+ "RandomVehicleCommandsDisabled": "Este es un vehículo de tráfico aleatorio y los comandos no se pueden utilizar en él",
+ "HouseDoorLock": "Casa {1} {2}!",
+ "BusinessDoorLock": "Negocio {1} {2}!",
+ "ServerGameModeRestarting": "El modo de juego del servidor se reinicia",
+ "HeaderSelfItemList": "Su inventario",
+ "HeaderPlayerItemList": "Inventario del jugador ({1})",
+ "HeaderHouseItemList": "Inventario de la casa",
+ "HeaderBusinessFloorItemList": "Inventario del negocio (En venta)",
+ "HeaderBusinessStorageItemList": "Inventario del negocio (Almacén)",
+ "HeaderItemItemList": "Inventario de {1}",
+ "ItemSlotNotNumber": "La ranura del objeto debe ser un número",
+ "ItemSlotMustBeBetween": "La ranura del objeto debe ser un número entre {1} y {2}!",
+ "UseItemBugged": "El objeto que intentas utilizar tiene un error. Se ha enviado un informe de error a los desarrolladores del servidor",
+ "PickupItemBugged": "El objeto que intentas recoger tiene un error. Se ha enviado un informe de error a los desarrolladores del servidor",
+ "DropItemBugged": "El objeto que intentas soltar tiene un error. Se ha enviado un informe de error a los desarrolladores del servidor",
+ "HandsBusy": "Tus manos están ocupadas",
+ "CantUseItemInSkinChange": "No puedes usar un objeto mientras personalizas tu apariencia",
+ "CantDropItemInSkinChange": "No puedes soltar un objeto mientras personalizas tu apariencia",
+ "CantPickupItemInSkinChange": "No puedes recoger un objeto mientras personalizas tu apariencia",
+ "CantSwitchItemInSkinChange": "No puedes cambiar de objeto mientras se personaliza la apariencia",
+ "CantGiveItemInSkinChange": "No puedes dar un objeto mientras personalizas tu apariencia",
+ "CantTakeItemInSkinChange": "No puedes coger un objeto mientras personalizas tu apariencia",
+ "ItemUnequippableNoAmmo": "{1} (ranura {2}) no tiene munición y no puede equiparse",
+ "NoSpaceSelfInventory": "No tienes más espacio en tu inventario",
+ "Business": "negocio",
+ "House": "casa",
+ "Clan": "clan",
+ "Vehicle": "vehiculo",
+ "Item": "objeto",
+ "ItemType": "tipo de objeto",
+ "Gate": "portón",
+ "Door": "puerta",
+ "ClanRank": "rango del clan",
+ "JobRank": "rango del trabajo",
+ "RadioStation": "estación de radio",
+ "Months": [
+ "Enero",
+ "Febrero",
+ "Marzo",
+ "Abril",
+ "Mayo",
+ "Junio",
+ "Julio",
+ "Agosto",
+ "Septiembre",
+ "Octubre",
+ "Noviembre",
+ "Diciembre"
+ ],
+ "WeekDays": [
+ "Domingo",
+ "Lunes",
+ "Martes",
+ "Miércoles",
+ "Jueves",
+ "Viernes",
+ "Sábado"
+ ],
+ "CardinalDirections": [
+ "Norte",
+ "Noreste",
+ "Este",
+ "Sureste",
+ "Sur",
+ "Suroeste",
+ "Oeste",
+ "Noroeste"
+ ],
+ "NewPlayerReadyToPlay": [
+ "Te han dado algo de dinero. Usa {1} para encontrar lugares donde comprar artículos",
+ "Si necesitas dinero, los trabajos son los puntos amarillos del radar",
+ "Para conseguir un coche, visita el concesionario de coches. También puedes utilizar un vehículo de alquiler cerca del punto de aparición o tomar el tren",
+ "Asegúrese de leer el {1} y utilizar el {2} para obtener información"
+ ],
+ "YourCurrentVehicleDeleted": "El vehículo en el que estabas fue eliminado",
+ "Distance": "Distancia",
+ "Meters": "Metros",
+ "Feet": "Pies",
+ "Kilometers": "Kilómetros",
+ "Miles": "Millas",
+ "MustBeVehicleDriver": "¡Debes ser el conductor del vehículo!",
+ "PlayerJoinedServer": "¡{1} se unió al juego desde {1}!",
+ "PlayerLeftServer": "¡{1} ha abandonado el juego! ({1})",
+ "DisconnectReasons": [
+ "Conexión perdida",
+ "Desconectado",
+ "Cliente no admitido",
+ "Juego incorrecto",
+ "Contraseña incorrecta",
+ "Ejecutable no admitidos",
+ "Desconectado",
+ "Vetado",
+ "Fallido",
+ "Nombre inválido",
+ "Fallo del programa"
+ ],
+ "TakeItemFromHouse": "saca {1} de la casa",
+ "TakeItemFromBusinessStorage": "saca {1} del almacén del negocio",
+ "TakeItemFromBusiness": "saca {1} del negocio",
+ "TakeItemFromItem": "saca {1} del {2}",
+ "TakeItemFromVehicleTrunk": "saca {1} del maletero",
+ "TakeItemFromVehicleDash": "saca {1} de la guantera",
+ "JobEquipmentInventoryKeyBindTip": "El equipo de trabajo está en su inventario. Pulse {1} para verlas",
+ "JobEquipmentInventoryCommandTip": "El equipo de trabajo está en su inventario. Utilice {1} para verlos",
+ "AccountHelp": [
+ "NO comparta su contraseña con nadie más. El personal de {1} nunca le pedirá su contraseña",
+ "Utilice {1} para cambiar su contraseña, y {2} si la ha olvidado",
+ "Algunos comandos: {1}"
+ ],
+ "VehicleHelp": [
+ "Sus vehículos personales se guardarán donde usted u otra persona los deje",
+ "Visite un concesionario para comprar vehículos nuevos. {1} para más información)",
+ "Algunos comandos: {1}",
+ "Visita un taller mecánico para reparar, colorear y poner a punto tu coche. {1} para más información"
+ ],
+ "VehicleDealershipHelp": [
+ "Visite un concesionario para comprar vehículos nuevos. {1} para encontrar uno",
+ "En el concesionario, introduce el coche que quieres comprar, y se te mostrará el precio",
+ "Si quieres comprar el vehículo, utiliza {1} y te darán las llaves para que lo pruebes en el aparcamiento",
+ "Salga del concesionario con el vehículo nuevo para confirmar la compra"
+ ],
+ "JobHelp": [
+ "Visita los lugares de trabajo para conseguir un empleo y ganar dinero. Busca puntos amarillos en el mapa",
+ "En un lugar de trabajo, usa {1} para conseguir el trabajo. Utiliza {2} para dejar el trabajo",
+ "Usa {1} para empezar a trabajar. También puedes conseguir un trabajo {2} y {3}",
+ "La mayoría de los vehículos de trabajo están cerrados. Usa {1} cerca de uno para entrar en él",
+ "Al entrar en un vehículo de trabajo, se le mostrará información sobre cómo hacer el trabajo"
+ ],
+ "ChatHelp": [
+ "Hay dos tipos principales de chat: fuera del personaje (OOC) y dentro del personaje (IC)",
+ "Mezclar estos dos tipos no resulta en un juego de rol apropiado. Vea {1} para más información",
+ "Algunos comandos del chat: {1}",
+ "Algunos tienen nombres más cortos disponibles ({1} para hablar, {2} para gritar, etc)"
+ ],
+ "ServerRulesHelp": [
+ "Las acciones irreales (powergaming) no están permitidas. No eres Superman",
+ "No se permite ningún juego de rol terrorista o de terrorismo",
+ "Siga siempre las instrucciones de los moderadores y administradores",
+ "No mezcles los chats (metagaming). No puedes usar información en IC que fue recibida OOC",
+ "Mantén el inglés en los chats principales. Si no se te da bien el inglés, utiliza {1}"
+ ],
+ "AnimationHelp": [
+ "Las animaciones permiten mejorar el juego de rol con acciones visuales",
+ "Utilice {1} o {2} con un nombre para utilizar una animación",
+ "Para ver una lista de animaciones, utilice {1}"
+ ],
+ "WeaponHelp": [
+ "Visita una armería para comprar armas. Usa {1} para encontrar una",
+ "La compra de un arma requiere una licencia de armas",
+ "Las licencias de armas son gestionadas por el departamento de policía. Solicítela allí para obtenerla",
+ "Las armas también pueden comprarse ilegalmente en algunos negocios, vendedores de armas y clanes"
+ ],
+ "SkinHelp": [
+ "En una tienda de ropa, usa {1} para comprar ropa",
+ "Cuando tengas un objeto de ropa, equípalo y úsalo como cualquier otro objeto para mostrar la selección de personajes (revisa {1} para aprender a usar objetos)",
+ "Algunas pieles están restringidas a trabajos, clanes o por otras razones"
+ ],
+ "KeyBindHelp": [
+ "Puedes establecer tus propias combinaciones de teclas. Utilice {1} para ver sus teclas vinculadas",
+ "Utilice {1} para añadir una nueva combinación de teclas y {2} para eliminar una",
+ "Las teclas por defecto son: {1} para el motor del vehículo, {1} para las luces y {3} para el bloqueo/desbloqueo",
+ "Pulsa {1} para ver tus objetos y {2} para equipar un objeto o {3} para desequipar todos",
+ "Pulsa {1} para usar el objeto que tienes en la mano, pulsa {2} para dejarlo caer o pulsa {3} para recoger un objeto del suelo"
+ ],
+ "BusinessHelp": [
+ "Utilice {1} para comprar artículos o {2} para ver una lista de lo que está a la venta en cualquier negocio",
+ "Las empresas aparecen con nombres azules sobre el icono de su entrada",
+ "Comandos del dueño del negocio: {1}",
+ "Un coche nuevo en venta aparecerá cuando salgas del concesionario"
+ ],
+ "ClanHelp": [
+ "Pedir a un administrador que cree un clan (similar a las facciones/grupos/familias)",
+ "Los propietarios de clanes tienen pleno control sobre su clan una vez creado",
+ "Comandos de clan: {1}",
+ "Más comandos del clan: {1}"
+ ],
+ "RadioStationHelp": [
+ "Utilice {1} para fijar la estación de su vehículo, casa o negocio",
+ "Utilice {2} para ver una lista de estaciones",
+ "Puedes cambiar el volumen de tu radio usando {1} con 0-100 como porcentaje"
+ ],
+ "WealthAndTaxHelp": [
+ "Sus impuestos en el día de pago son el {1} por ciento de su riqueza calculada",
+ "Su riqueza calculada es una suma total basada en cuántos vehículos, casas y negocios tiene",
+ "Cada vehículo es {1}, cada casa es {2}, y cada negocio es {3}",
+ "Utilice {1} para ver su patrimonio actual, y {2} para ver cuánto pagará de impuestos cada día de pago"
+ ],
+ "MustBeInAVehicle": "Necesitas estar en un vehículo",
+ "MustBeInOrNearVehicle": "Tienes que estar dentro o cerca de un vehículo",
+ "MustBeInVehicleFrontSeat": "Tienes que estar en los asientos delanteros del vehículo",
+ "MustBeInVehicleDriverSeat": "Tienes que ser el conductor",
+ "DontHaveVehicleKey": "No tiene una llave para este vehículo",
+ "NoGateAccess": "No tienes acceso a esta puerta",
+ "GateBroken": "Esta puerta está rota",
+ "GateHacked": "La puerta no funciona",
+ "RadioJammed": "Sólo se oye la estática de la radio",
+ "VehicleNotForSale": "Este vehículo no está en venta",
+ "VehicleNotForRent": "Este vehículo no se alquila",
+ "BusinessNotForSale": "Este negocio no está en venta",
+ "BusinessNotForRent": "Este negocio no se alquila",
+ "HouseNotForSale": "Esta casa no está en venta",
+ "HouseNotForRent": "Esta casa no está en alquiler",
+ "DealershipPurchaseTestDrive": "Conduzca fuera del concesionario para comprar el vehículo, o salga del vehículo para cancelar",
+ "DealershipPurchaseExitedVehicle": "Has cancelado la compra del vehículo al salir de él",
+ "VehiclePurchaseComplete": "¡Este vehículo es ahora tuyo! Se guardará donde quiera que lo dejes",
+ "VehiclePurchaseNotEnoughMoney": "No tienes suficiente dinero para comprar este vehículo",
+ "HousePurchaseNotEnoughMoney": "No tienes suficiente dinero para comprar esta casa",
+ "BusinessPurchaseNotEnoughMoney": "No tienes suficiente dinero para comprar este negocio",
+ "Locales": {
+ "English": "Inglés",
+ "Russian": "Ruso",
+ "Spanish": "Español",
+ "German": "Alemán",
+ "Dutch": "Holandés",
+ "Polish": "Polaco"
+ },
+ "HeaderPlayerHousesList": "Casas del jugador ({1})",
+ "HeaderPlayerStaffFlagsList": "Banderas administrativas del jugador ({1})",
+ "HeaderStaffFlagsList": "Banderas administrativas",
+ "NonRPName": "¡Nombre no RP! Elige uno nuevo:",
+ "InvalidStaffFlag": "Bandera administrativa no encontrada",
+ "InvalidClanFlag": "Bandera del clan no encontrada",
+ "InvalidLocale": "Language not found!",
+ "HeaderJobUniformList": "Job Uniforms ({1})",
+ "HeaderJobEquipmentList": "Job Equipment ({1})",
+ "InvalidJobUniform": "Job uniform not found!",
+ "InvalidJobEquipment": "Job equipment not found!",
+ "HeaderVehiclesInRangeList": "Vehicles within {1}",
+ "NoVehiclesWithInRange": "There are no vehicles within {1}",
+ "AmountNotNumber": "The amount must be a number!",
+ "NeedToBeWorking": "You need to be working! Use {1} at a job location or near a job vehicle.",
+ "NeedToBeOnJobRoute": "You need to be doing a job route! Use {1} in a job vehicle",
+ "CurrentJobRouteDeleted": "The job route you were on has been deleted by an admin",
+ "CurrentJobRouteVehicleColoursChanged": "Your job route's vehicle colours were changed by an admin",
+ "NotYourJob": "This is not your job!",
+ "JobPoints": "You can get a job by going the yellow points on the map.",
+ "QuitJobToTakeAnother": "If you want this job, use {1} to quit your current job.",
+ "NotAJobVehicle": "This is not a job vehicle!",
+ "NotYourJobVehicle": "This is not your job's vehicle!",
+ "JobRouteDisabled": "The job route you were on has been disabled by an admin",
+ "HeaderPickupTypes": "Pickup Types",
+ "HeaderBlipTypes": "Map Icon Types",
+ "InvalidGPSLocation": "There are no locations with that name or type",
+ "HeaderBusinessList": "Businesses",
+ "VehicleForSale": "This {1} is buyable for {2}! Use {3} if you want to buy it",
+ "VehicleForRent": "This {1} is rentable for {2}! Use {3} if you want to rent it",
+
+ "ADDED-31JAN2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "LoginFailedInvalidPassword": "Invalid password! {1} attempts remaining",
+ "LoginFailedNoPassword": "You must enter a password! ! {1} attempts remaining",
+ "RegistrationFailedNoPassword": "You must enter a password!",
+ "RegistrationFailedNoPasswordConfirm": "You must confirm the password!",
+ "RegistrationFailedNoEmail": "You must enter an email!",
+ "AccountNameAlreadyRegistered": "Your name is already registered!",
+ "AlreadyLoggedIn": "You are already logged in!",
+ "RegistrationFailedInvalidEmail": "That email is invalid!",
+ "RegistrationFailedPasswordMismatch": "The passwords don't match!",
+ "RegistrationFailedCreateError": "Your account couldn't be created!",
+ "RegistrationSuccess": "Your account has been created!",
+ "RegistrationEmailVerifyReminder": "Don't forget to verify your email! A verification code has been sent to you.",
+ "RegistrationCreateCharReminder": "To play on the server, you will need to make a character.",
+ "NoCharactersGUIMessage": "You have no characters. Would you like to make one?",
+ "NoCharactersGUIWindowTitle": "No characters",
+ "NoCharactersChatMessage": "You have no characters. Use {1} to make one.",
+ "NeedEmailFor2FA": "You need to add your email to your account to use two-factor authentication.",
+ "NeedEmailVerifiedFor2FA": "You need to verify your email to use two-factor authentication.",
+ "SetEmailHelpTip": "Use {1} to set your email.",
+ "VerifyEmailHelpTip": "Use {1} to verify your email.",
+
+ "ADDED-13FEB2022": "DO NOT TRANSLATE. This string is just a comment to separate newly added translations.",
+ "NearbyRadio": "Nearby radio",
+ "FromRadio": "From radio",
+ "ToRadio": "To radio",
+ "NeedToEnterPropertyCommand": "You need to enter the {1} first! Use {2} to enter and exit",
+ "NeedToEnterPropertyKeyPress": "You need to enter the {1} first! Press {2} to enter and exit",
+ "InventoryFullCantCarry": "You don't have any space to carry this (full inventory)!",
+ "NotEnoughCashNeedAmountMore": "You don't have enough money! You need {1} more!",
+ "AmountMustBeMoreThan": "The amount must be more than {1}!",
+ "WeaponBanned": "You are not allowed to buy or use weapons!",
+ "TimeNotNumber": "The time must be a number",
+ "HeaderDefaultBusinessItemTypes": "Business Item Templates",
+ "FixingStuck": "Fixing your position and virtual world ...",
+ "CantUseCommandYet": "You must wait before you can use this command again!",
+ "NotATester": "You are not a tester!",
+ "AccessDenied": "AccessDenied"
+}
diff --git a/meta.xml b/meta.xml
index 75e6a368..a4c5301a 100644
--- a/meta.xml
+++ b/meta.xml
@@ -9,11 +9,11 @@
-
+
-
+
@@ -25,7 +25,6 @@
-
@@ -44,12 +43,11 @@
-
+
-
@@ -57,6 +55,7 @@
+
@@ -69,6 +68,7 @@
+
@@ -78,6 +78,7 @@
+
@@ -86,7 +87,7 @@
-
+
@@ -131,10 +132,6 @@
-
-
-
-
@@ -198,4 +195,8 @@
+
+
+
+
diff --git a/scripts/client/animation.js b/scripts/client/animation.js
index 843b3f32..2d5760e5 100644
--- a/scripts/client/animation.js
+++ b/scripts/client/animation.js
@@ -8,8 +8,9 @@
// ===========================================================================
function makePedPlayAnimation(pedId, animGroup, animId, animType, animSpeed, loop, loopNoControl, freezeLastFrame, returnToOriginalPosition, freezePlayer) {
+ logToConsole(LOG_DEBUG, `[VRR.Animation] Playing animation ${animGroup}/${animId} for ped ${pedId}`);
if(getGame() < VRR_GAME_GTA_IV) {
- if(animType == VRR_ANIMTYPE_ADD) {
+ if(animType == VRR_ANIMTYPE_NORMAL || animType == VRR_ANIMTYPE_SURRENDER) {
if(getGame() == VRR_GAME_GTA_VC || getGame() == VRR_GAME_GTA_SA) {
getElementFromId(pedId).clearAnimations();
} else {
@@ -17,7 +18,7 @@ function makePedPlayAnimation(pedId, animGroup, animId, animType, animSpeed, loo
}
getElementFromId(pedId).addAnimation(animGroup, animId);
- if(getElementFromId(pedId) == localPlayer && !freezePlayer) {
+ if(getElementFromId(pedId) == localPlayer && freezePlayer == true) {
inAnimation = true;
setLocalPlayerControlState(false, false);
localPlayer.collisionsEnabled = false;
@@ -25,9 +26,6 @@ function makePedPlayAnimation(pedId, animGroup, animId, animType, animSpeed, loo
} else if(animType == VRR_ANIMTYPE_BLEND) {
getElementFromId(pedId).position = getElementFromId(pedId).position;
getElementFromId(pedId).blendAnimation(animGroup, animId, animSpeed);
- } else if(animType == VRR_ANIMTYPE_MOVEADD) {
- getElementFromId(pedId).position = getElementFromId(pedId).position;
- getElementFromId(pedId).blendAnimation(animGroup, animId, animSpeed);
}
} else {
natives.requestAnims(animGroup);
@@ -40,9 +38,37 @@ function makePedPlayAnimation(pedId, animGroup, animId, animType, animSpeed, loo
function forcePedAnimation(pedId, animGroup, animId, animType, animSpeed, loop, loopNoControl, freezeLastFrame, returnToOriginalPosition) {
if(getGame() < VRR_GAME_GTA_IV) {
forcedAnimation = [animGroup, animId];
- setLocalPlayerControlState(false, false);
getElementFromId(pedId).position = getElementFromId(pedId).position;
getElementFromId(pedId).addAnimation(animGroup, animId);
+
+ if(getElementFromId(pedId) == localPlayer) {
+ inAnimation = true;
+ setLocalPlayerControlState(false, false);
+ localPlayer.collisionsEnabled = false;
+ }
+ }
+}
+
+// ===========================================================================
+
+function makePedStopAnimation(pedId) {
+ if(getElementFromId(pedId) == null) {
+ return false;
+ }
+
+ if(getGame() != VRR_GAME_GTA_IV) {
+ if(getGame() == VRR_GAME_GTA_VC || getGame() == VRR_GAME_GTA_SA) {
+ getElementFromId(pedId).clearAnimations();
+ } else {
+ getElementFromId(pedId).clearObjective();
+ }
+ }
+
+ if(getElementFromId(pedId) == localPlayer) {
+ if(getGame() != VRR_GAME_GTA_IV) {
+ localPlayer.collisionsEnabled = true;
+ }
+ setLocalPlayerControlState(true, false);
}
}
diff --git a/scripts/client/content.js b/scripts/client/content.js
new file mode 100644
index 00000000..d09d8074
--- /dev/null
+++ b/scripts/client/content.js
@@ -0,0 +1,65 @@
+// ===========================================================================
+// Vortrex's Roleplay Resource
+// https://github.com/VortrexFTW/gtac_roleplay
+// ===========================================================================
+// FILE: content.js
+// DESC: Provides connection to extra content resources
+// TYPE: Client (JavaScript)
+// ===========================================================================
+
+function getCustomImage(imageName) {
+ let contentResource = findResourceByName(getGameData().extraContentResource[getGame()]);
+ if(contentResource != null) {
+ if(contentResource.isStarted) {
+ let image = contentResource.exports.getCustomImage(imageName);
+ if(image != null) {
+ return image;
+ }
+ }
+ }
+ return false;
+}
+
+// ===========================================================================
+
+function getCustomFont(fontName) {
+ let contentResource = findResourceByName(getGameData().extraContentResource[getGame()]);
+ if(contentResource != null) {
+ if(contentResource.isStarted) {
+ let font = contentResource.exports.getCustomFont(fontName);
+ if(font != null) {
+ return font;
+ }
+ }
+ }
+ return false;
+}
+
+// ===========================================================================
+
+function getCustomAudio(audioName) {
+ let contentResource = findResourceByName(getGameData().extraContentResource[getGame()]);
+ if(contentResource != null) {
+ if(contentResource.isStarted) {
+ let audioFile = contentResource.exports.getCustomAudio(audioName);
+ if(audioFile != null) {
+ return audioFile;
+ }
+ }
+ }
+ return false;
+}
+
+// ===========================================================================
+
+function playCustomAudio(audioName, volume = 0.5, loop = false) {
+ let contentResource = findResourceByName(getGameData().extraContentResource[getGame()]);
+ if(contentResource != null) {
+ if(contentResource.isStarted) {
+ contentResource.exports.playCustomAudio(audioName, volume, loop);
+ }
+ }
+ return false;
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/event.js b/scripts/client/event.js
index d62e331e..03ae0839 100644
--- a/scripts/client/event.js
+++ b/scripts/client/event.js
@@ -102,6 +102,8 @@ function onProcess(event, deltaTime) {
function onKeyUp(event, keyCode, scanCode, keyModifiers) {
processSkinSelectKeyPress(keyCode);
//processKeyDuringAnimation();
+ processGUIKeyPress(keyCode);
+ processToggleGUIKeyPress(keyCode);
}
// ===========================================================================
@@ -143,7 +145,7 @@ function onElementStreamIn(event, element) {
function onLocalPlayerExitedVehicle(event, vehicle, seat) {
logToConsole(LOG_DEBUG, `[VRR.Event] Local player exited vehicle`);
if(areServerElementsSupported()) {
- triggerNetworkEvent("vrr.onPlayerExitVehicle", getVehicleForNetworkEvent(vehicle), seat);
+ sendNetworkEventToServer("vrr.onPlayerExitVehicle", getVehicleForNetworkEvent(vehicle), seat);
}
if(inVehicleSeat) {
@@ -158,7 +160,7 @@ function onLocalPlayerEnteredVehicle(event, vehicle, seat) {
logToConsole(LOG_DEBUG, `[VRR.Event] Local player entered vehicle`);
if(areServerElementsSupported()) {
- triggerNetworkEvent("vrr.onPlayerEnterVehicle", getVehicleForNetworkEvent(vehicle), seat);
+ sendNetworkEventToServer("vrr.onPlayerEnterVehicle", getVehicleForNetworkEvent(vehicle), seat);
if(inVehicleSeat == 0) {
if(inVehicle.owner != -1) {
@@ -183,7 +185,7 @@ function onPedInflictDamage(event, damagedEntity, damagerEntity, weaponId, healt
if(damagedEntity == localPlayer) {
//if(!weaponDamageEnabled[damagerEntity.name]) {
event.preventDefault();
- triggerNetworkEvent("vrr.weaponDamage", damagerEntity.name, weaponId, pedPiece, healthLoss);
+ sendNetworkEventToServer("vrr.weaponDamage", damagerEntity.name, weaponId, pedPiece, healthLoss);
//}
}
}
@@ -194,7 +196,7 @@ function onPedInflictDamage(event, damagedEntity, damagerEntity, weaponId, healt
function onLocalPlayerEnterSphere(event, sphere) {
logToConsole(LOG_DEBUG, `[VRR.Event] Local player entered sphere`);
- if(sphere == jobRouteStopSphere) {
+ if(sphere == jobRouteLocationSphere) {
enteredJobRouteSphere();
}
}
diff --git a/scripts/client/gui.js b/scripts/client/gui.js
index 4cdc7bc7..6b62002b 100644
--- a/scripts/client/gui.js
+++ b/scripts/client/gui.js
@@ -9,9 +9,10 @@
var app = {};
-let robotoFont = "Roboto";
+let mainFont = "Roboto"; // "Arial"
-let mainLogoPath = (typeof gta == "undefined") ? "files/images/mafiac-logo.png" : "files/images/gtac-logo.png";
+//let mainLogoPath = (typeof gta == "undefined") ? "files/images/mafiac-logo.png" : "files/images/gtac-logo.png";
+let mainLogoPath = "files/images/server-logo.png";
let primaryColour = [200, 200, 200];
let secondaryColour = [16, 16, 16];
@@ -28,6 +29,12 @@ let textInputAlpha = 180;
let guiReady = false;
+let guiSubmitKey = false;
+let guiLeftKey = false;
+let guiRightKey = false;
+let guiUpKey = false;
+let guiDownKey = false;
+
// ===========================================================================
let placesOfOrigin = [
@@ -70,21 +77,21 @@ function initGUI() {
initInfoDialogGUI();
initErrorDialogGUI();
initYesNoDialogGUI();
- initResetPasswordGUI();
- initChangePasswordGUI();
initTwoFactorAuthenticationGUI();
initListGUI();
+ initResetPasswordGUI();
+ initChangePasswordGUI();
closeAllWindows();
guiReady = true;
logToConsole(LOG_DEBUG, `[VRR.GUI] All GUI created successfully!`);
- triggerNetworkEvent("vrr.guiReady", true);
+ sendNetworkEventToServer("vrr.guiReady", true);
};
// ===========================================================================
-let closeAllWindows = function() {
+function closeAllWindows() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Closing all GUI windows`);
infoDialog.window.shown = false;
yesNoDialog.window.shown = false;
@@ -98,47 +105,64 @@ let closeAllWindows = function() {
resetPassword.window.shown = false;
passwordChange.window.shown = false;
mexui.setInput(false);
+ mexui.focusedControl = false;
+
+ guiSubmitKey = false;
+ guiLeftKey = false;
+ guiRightKey = false;
+ guiUpKey = false;
+ guiDownKey = false;
}
// ===========================================================================
-let isAnyGUIActive = function() {
+function isAnyGUIActive() {
if(!guiReady) {
- if(infoDialog.window.shown) {
- return true;
- }
+ return false;
+ }
- if(yesNoDialog.window.shown) {
- return true;
- }
+ if(infoDialog.window.shown == true) {
+ return true;
+ }
- if(errorDialog.window.shown) {
- return true;
- }
+ if(yesNoDialog.window.shown == true) {
+ return true;
+ }
- if(register.window.shown) {
- return true;
- }
+ if(errorDialog.window.shown == true) {
+ return true;
+ }
- if(login.window.shown) {
- return true;
- }
+ if(register.window.shown == true) {
+ return true;
+ }
- if(newCharacter.window.shown) {
- return true;
- }
+ if(login.window.shown == true) {
+ return true;
+ }
- if(characterSelect.window.shown) {
- return true;
- }
+ if(newCharacter.window.shown == true) {
+ return true;
+ }
- if(twoFactorAuth.window.shown) {
- return true;
- }
+ if(characterSelect.window.shown == true) {
+ return true;
+ }
- if(listDialog.window.shown) {
- return true;
- }
+ if(twoFactorAuth.window.shown == true) {
+ return true;
+ }
+
+ if(listDialog.window.shown == true) {
+ return true;
+ }
+
+ if(resetPassword.window.shown == true) {
+ return true;
+ }
+
+ if(passwordChange.window.shown == true) {
+ return true;
}
return false;
@@ -146,49 +170,49 @@ let isAnyGUIActive = function() {
// ===========================================================================
-addNetworkHandler("vrr.showCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
+addNetworkEventHandler("vrr.showCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show character selection window`);
showCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, skinId);
});
// ===========================================================================
-addNetworkHandler("vrr.switchCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
+addNetworkEventHandler("vrr.switchCharacterSelect", function(firstName, lastName, cash, clan, lastPlayed, skinId) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to update character selection window with new info`);
switchCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, skinId);
});
// ===========================================================================
-addNetworkHandler("vrr.showError", function(errorMessage, errorTitle) {
+addNetworkEventHandler("vrr.showError", function(errorMessage, errorTitle) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show error window`);
showError(errorMessage, errorTitle);
});
// ===========================================================================
-addNetworkHandler("vrr.showPrompt", function(promptMessage, promptTitle) {
+addNetworkEventHandler("vrr.showPrompt", function(promptMessage, promptTitle) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show prompt window`);
showYesNoPromptGUI(promptMessage, promptTitle);
});
// ===========================================================================
-addNetworkHandler("vrr.showInfo", function(infoMessage) {
+addNetworkEventHandler("vrr.showInfo", function(infoMessage) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received request from server to show info dialog`);
showInfo(infoMessage);
});
// ===========================================================================
-addNetworkHandler("vrr.loginSuccess", function() {
+addNetworkEventHandler("vrr.loginSuccess", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of successful login from server`);
loginSuccess();
});
// ===========================================================================
-addNetworkHandler("vrr.characterSelectSuccess", function() {
+addNetworkEventHandler("vrr.characterSelectSuccess", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of successful character selection from server`);
characterSelectSuccess();
setChatWindowEnabled(true);
@@ -196,35 +220,49 @@ addNetworkHandler("vrr.characterSelectSuccess", function() {
// ===========================================================================
-addNetworkHandler("vrr.loginFailed", function(remainingAttempts) {
+addNetworkEventHandler("vrr.loginFailed", function(remainingAttempts) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of failed login from server`);
loginFailed(remainingAttempts);
});
// ===========================================================================
-addNetworkHandler("vrr.registrationSuccess", function() {
+addNetworkEventHandler("vrr.registrationSuccess", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of successful registration from server`);
registrationSuccess();
});
// ===========================================================================
-addNetworkHandler("vrr.registrationFailed", function(errorMessage) {
+addNetworkEventHandler("vrr.registrationFailed", function(errorMessage) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of failed registration from server`);
registrationFailed(errorMessage);
});
// ===========================================================================
-addNetworkHandler("vrr.newCharacterFailed", function(errorMessage) {
+addNetworkEventHandler("vrr.newCharacterFailed", function(errorMessage) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal of failed registration from server`);
newCharacterFailed(errorMessage);
});
// ===========================================================================
-addNetworkHandler("vrr.guiColour", function(red1, green1, blue1, red2, green2, blue2, red3, green3, blue3) {
+addNetworkEventHandler("vrr.changePassword", function() {
+ logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal to change password from server`);
+ showChangePasswordGUI();
+});
+
+// ===========================================================================
+
+addNetworkEventHandler("vrr.showResetPasswordCodeInput", function() {
+ logToConsole(LOG_DEBUG, `[VRR.GUI] Received signal to input reset password code from server`);
+ resetPasswordCodeInputGUI();
+});
+
+// ===========================================================================
+
+addNetworkEventHandler("vrr.guiColour", function(red1, green1, blue1, red2, green2, blue2, red3, green3, blue3) {
logToConsole(LOG_DEBUG, `[VRR.GUI] Received new GUI colours from server: ${red1}, ${green1}, ${blue1} / ${red2}, ${green2}, ${blue2} / ${red3}, ${green3}, ${blue3}`);
primaryColour = [red1, green1, blue1];
secondaryColour = [red2, green2, blue2];
@@ -236,10 +274,10 @@ addNetworkHandler("vrr.guiColour", function(red1, green1, blue1, red2, green2, b
// ===========================================================================
-addNetworkHandler("vrr.guiInit", function() {
+addNetworkEventHandler("vrr.guiInit", function() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Initializing MexUI app`);
//initGUI();
- triggerNetworkEvent("vrr.guiReady", true);
+ sendNetworkEventToServer("vrr.guiReady", true);
});
// ===========================================================================
@@ -247,6 +285,37 @@ addNetworkHandler("vrr.guiInit", function() {
function hideAllGUI() {
closeAllWindows();
setChatWindowEnabled(true);
+ guiSubmitKey = false;
}
-// ===========================================================================
\ No newline at end of file
+// ===========================================================================
+
+function processGUIKeyPress(keyCode) {
+ if(!isAnyGUIActive()) {
+ return false;
+ }
+
+ if(keyCode == SDLK_RETURN || keyCode == SDLK_RETURN2) {
+ if(guiSubmitKey != false) {
+ guiSubmitKey();
+ }
+ } else if(keyCode == SDLK_LEFT) {
+ if(guiLeftKey != false) {
+ guiLeftKey();
+ }
+ } else if(keyCode == SDLK_RIGHT) {
+ if(guiRightKey != false) {
+ guiRightKey();
+ }
+ }
+}
+
+// ===========================================================================
+
+function processToggleGUIKeyPress(keyCode) {
+ if(keyCode == disableGUIKey) {
+ sendNetworkEventToServer("vrr.toggleGUI");
+ }
+}
+
+// ===========================================================================
diff --git a/scripts/client/gui/2fa.js b/scripts/client/gui/2fa.js
index 16c092c2..8bdebc81 100644
--- a/scripts/client/gui/2fa.js
+++ b/scripts/client/gui/2fa.js
@@ -47,12 +47,12 @@ function initTwoFactorAuthenticationGUI() {
},
});
- twoFactorAuth.codeLabel = twoFactorAuth.window.text(20, 135, 260, 20, 'Please enter the code from your authenticator app!', {
+ twoFactorAuth.codeLabel = twoFactorAuth.window.text(20, 135, 260, 20, 'Please enter the code sent to your email!', {
main: {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(200, 200, 200, 255),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
@@ -65,7 +65,7 @@ function initTwoFactorAuthenticationGUI() {
borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], textInputAlpha),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -73,7 +73,7 @@ function initTwoFactorAuthenticationGUI() {
placeholder: {
textColour: toColour(200, 200, 200, 150),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], 255),
@@ -86,7 +86,7 @@ function initTwoFactorAuthenticationGUI() {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(0, 0, 0, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -105,6 +105,8 @@ function showTwoFactorAuthGUI() {
setChatWindowEnabled(false);
mexui.setInput(true);
twoFactorAuth.window.shown = true;
+ mexui.focusedControl = twoFactorAuth.codeInput;
+ guiSubmitKey = checkTwoFactorAuth;
}
// ===========================================================================
@@ -127,7 +129,7 @@ function twoFactorAuthSuccess() {
function checkTwoFactorAuth() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Checking two-factor authentication with server ...`);
- triggerNetworkEvent("vrr.checkTwoFactorAuth", twoFactorAuth.codeInput.lines[0]);
+ sendNetworkEventToServer("vrr.2fa", twoFactorAuth.codeInput.lines[0]);
}
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/gui/changepass.js b/scripts/client/gui/changepass.js
index a16a5dfe..b95a4b22 100644
--- a/scripts/client/gui/changepass.js
+++ b/scripts/client/gui/changepass.js
@@ -13,7 +13,6 @@ let passwordChange = {
messageLabel: null,
passwordInput: null,
confirmPasswordInput: null,
- verificationCodeInput: null,
submitButton: null,
};
@@ -40,30 +39,30 @@ function initChangePasswordGUI() {
passwordChange.window.titleBarIconSize = toVector2(0,0);
passwordChange.window.titleBarHeight = 0;
- passwordChange.window.image(115, 10, 65, 65, mainLogoPath, {
+ passwordChange.window.image(85, -10, 140, 140, mainLogoPath, {
focused: {
borderColour: toColour(0, 0, 0, 0),
},
});
- passwordChange.messageLabel = passwordChange.window.text(20, 75, 260, 20, 'Check your email for a verification code!', {
+ passwordChange.messageLabel = passwordChange.window.text(20, 75, 260, 20, 'Enter a new password', {
main: {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(200, 200, 200, 255),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
},
});
- passwordChange.passwordInput = passwordChange.window.textInput(20, 100, 260, 25, '', {
+ passwordChange.passwordInput = passwordChange.window.textInput(20, 130, 260, 25, '', {
main: {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -72,18 +71,18 @@ function initChangePasswordGUI() {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 200),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
}
});
passwordChange.passwordInput.masked = true;
passwordChange.passwordInput.placeholder = "Password";
- passwordChange.confirmPasswordInput = passwordChange.window.textInput(20, 130, 260, 25, '', {
+ passwordChange.confirmPasswordInput = passwordChange.window.textInput(20, 160, 260, 25, '', {
main: {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -92,37 +91,18 @@ function initChangePasswordGUI() {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 200),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
}
});
passwordChange.confirmPasswordInput.masked = true;
passwordChange.confirmPasswordInput.placeholder = "Confirm password";
- passwordChange.verificationCodeInput = passwordChange.window.textInput(20, 160, 260, 25, '', {
- main: {
- backgroundColour: toColour(0, 0, 0, 120),
- textColour: toColour(200, 200, 200, 255),
- textSize: 10.0,
- textFont: robotoFont,
- },
- caret: {
- lineColour: toColour(255, 255, 255, 255),
- },
- placeholder: {
- backgroundColour: toColour(0, 0, 0, 120),
- textColour: toColour(200, 200, 200, 200),
- textSize: 10.0,
- textFont: robotoFont,
- }
- });
- passwordChange.verificationCodeInput.placeholder = "Verification Code (From Email)";
-
passwordChange.submitButton = passwordChange.window.button(20, 195, 260, 30, 'CHANGE PASSWORD', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(255, 255, 255, 255),
textSize: 12.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -147,7 +127,7 @@ function passwordChangeFailed(errorMessage) {
function checkChangePassword() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Checking password change with server ...`);
- triggerNetworkEvent("vrr.checkChangePassword", passwordChange.passwordInput.lines[0], passwordChange.confirmPasswordInput.lines[0], passwordChange.verificationCodeInput.lines[0]);
+ sendNetworkEventToServer("vrr.checkChangePassword", passwordChange.passwordInput.lines[0], passwordChange.confirmPasswordInput.lines[0]);
}
// ===========================================================================
@@ -158,12 +138,15 @@ function showChangePasswordGUI() {
setChatWindowEnabled(false);
mexui.setInput(true);
passwordChange.window.shown = true;
+ mexui.focusedControl = passwordChange.passwordInput;
+ guiSubmitKey = checkChangePassword;
}
// ===========================================================================
function passwordChangeSuccess() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Server reports password change was successful`);
+ guiSubmitKey = false;
closeAllWindows();
}
diff --git a/scripts/client/gui/charselect.js b/scripts/client/gui/charselect.js
index f7b7ea1d..fb9b25fb 100644
--- a/scripts/client/gui/charselect.js
+++ b/scripts/client/gui/charselect.js
@@ -28,24 +28,26 @@ function initCharacterSelectGUI() {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
},
- title: {
- textSize: 11.0,
- textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
- backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
- },
- icon: {
- textSize: 0.0,
- textColour: toColour(0, 0, 0, 0),
- backgroundColour: toColour(0, 0, 0, 0),
- }
+ title: {
+ textSize: 12.0,
+ textColour: toColour(0, 0, 0, 0),
+ backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
+ },
+ icon: {
+ textSize: 12.0,
+ textColour: toColour(0, 0, 0, 0),
+ backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], windowTitleAlpha),
+ }
});
+ characterSelect.window.titleBarIconSize = toVector2(0,0);
+ characterSelect.window.titleBarHeight = 0;
characterSelect.nameText = characterSelect.window.text(5, 40, 200, 25, 'Lastname, Firstname', {
main: {
textSize: 14.0,
textAlign: 0.0,
textColour: toColour(255, 255, 255, 220),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
@@ -57,7 +59,7 @@ function initCharacterSelectGUI() {
textSize: 9.0,
textAlign: 0.0,
textColour: toColour(255, 255, 255, 220),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
@@ -69,7 +71,7 @@ function initCharacterSelectGUI() {
textSize: 9.0,
textAlign: 0.0,
textColour: toColour(255, 255, 255, 220),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
@@ -81,19 +83,19 @@ function initCharacterSelectGUI() {
textSize: 9.0,
textAlign: 0.0,
textColour: toColour(255, 255, 255, 220),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
}
});
- characterSelect.selectCharacterButton = characterSelect.window.button(85, 130, 260, 25, 'SELECT', {
+ characterSelect.selectCharacterButton = characterSelect.window.button(85, 130, 260, 25, 'PLAY', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
- textSize: 12.0,
- textFont: robotoFont,
+ textSize: 10.0,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -105,8 +107,8 @@ function initCharacterSelectGUI() {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
- textSize: 12.0,
- textFont: robotoFont,
+ textSize: 10.0,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -114,12 +116,12 @@ function initCharacterSelectGUI() {
}
}, showNewCharacter);
- characterSelect.previousCharacterButton = characterSelect.window.button(5, 130, 75, 25, '< PREV', {
+ characterSelect.previousCharacterButton = characterSelect.window.button(5, 130, 75, 25, 'PREV', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -127,12 +129,12 @@ function initCharacterSelectGUI() {
}
}, selectPreviousCharacter);
- characterSelect.nextCharacterButton = characterSelect.window.button(350, 130, 75, 25, 'NEXT >', {
+ characterSelect.nextCharacterButton = characterSelect.window.button(350, 130, 75, 25, 'NEXT', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -168,33 +170,28 @@ function showCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, ski
function showNewCharacter() {
closeAllWindows();
logToConsole(LOG_DEBUG, `[VRR.GUI] Showing new character dialog window`);
- setChatWindowEnabled(false);
- mexui.setInput(true);
- setHUDEnabled(false);
- newCharacter.window.shown = true;
-
- showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
+ showNewCharacterGUI();
}
// ===========================================================================
function selectNextCharacter() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Requesting next character info from server for character select window`);
- triggerNetworkEvent("vrr.nextCharacter");
+ sendNetworkEventToServer("vrr.nextCharacter");
}
// ===========================================================================
function selectPreviousCharacter() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Requesting previous character info from server for character select window`);
- triggerNetworkEvent("vrr.previousCharacter");
+ sendNetworkEventToServer("vrr.previousCharacter");
}
// ===========================================================================
function selectThisCharacter() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Tell server the current shown character was selected in character select window`);
- triggerNetworkEvent("vrr.selectCharacter");
+ sendNetworkEventToServer("vrr.selectCharacter");
}
// ===========================================================================
@@ -207,8 +204,16 @@ function switchCharacterSelectGUI(firstName, lastName, cash, clan, lastPlayed, s
characterSelect.cashText.text = `Money: $${cash}`;
characterSelect.clanText.text = `Clan: ${clan}`;
characterSelect.lastPlayedText.text = `Last Played: ${lastPlayed}`;
- characterSelect.skinImage = characterSelect.window.image(310, 32, 100, 90, "files/images/skins/none.png");
+
+ if(characterSelect.skinImage != null) {
+ characterSelect.skinImage.remove();
+ }
+ characterSelect.skinImage = (getGame() == VRR_GAME_GTA_III) ? characterSelect.window.image(310, 32, 100, 90, `files/images/skins/gta3/${getSkinImage(skinId)}.png`) : characterSelect.window.image(310, 32, 100, 90, "files/images/skins/none.png");
+
characterSelect.window.shown = true;
+ guiSubmitKey = selectThisCharacter;
+ guiLeftKey = selectPreviousCharacter;
+ guiRightKey = selectNextCharacter;
}
// ===========================================================================
@@ -218,4 +223,16 @@ function characterSelectSuccess() {
closeAllWindows();
}
+// ===========================================================================
+
+function getSkinImage(skinId, gameId = getGame()) {
+ if(skinId < 10) {
+ return `Skin_00${skinId}.png`;
+ } else if(skinId > 10 && skinId < 100) {
+ return `Skin_0${skinId}.png`;
+ } else if(skinId > 100) {
+ return `Skin_${skinId}.png`;
+ }
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/gui/clanmgr.js b/scripts/client/gui/clanmgr.js
index 7355ba95..54d33359 100644
--- a/scripts/client/gui/clanmgr.js
+++ b/scripts/client/gui/clanmgr.js
@@ -5,4 +5,14 @@
// FILE: clanmgr.js
// DESC: Provides clan manager GUI
// TYPE: Client (JavaScript)
-// ===========================================================================
\ No newline at end of file
+// ===========================================================================
+
+let clanManager = {
+ window: null,
+ generalTab: null,
+ ranksTab: null,
+ membersTab: null,
+ vehiclesTab: null,
+ businessesTab: null,
+ housesTab: null,
+};
\ No newline at end of file
diff --git a/scripts/client/gui/error.js b/scripts/client/gui/error.js
index d26f90d0..25315568 100644
--- a/scripts/client/gui/error.js
+++ b/scripts/client/gui/error.js
@@ -39,19 +39,19 @@ function initErrorDialogGUI() {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(255, 255, 255, 255),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
},
});
- errorDialog.okayButton = errorDialog.window.button(20, 95, 360, 30, 'OK', {
+ errorDialog.okayButton = errorDialog.window.button(5, 105, 390, 30, 'OK', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
diff --git a/scripts/client/gui/html/login.js b/scripts/client/gui/html/login.js
new file mode 100644
index 00000000..8b5ae2f8
--- /dev/null
+++ b/scripts/client/gui/html/login.js
@@ -0,0 +1,18 @@
+
+
+ Connected RP: Login
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/client/gui/info.js b/scripts/client/gui/info.js
index 1a958849..7ecff81b 100644
--- a/scripts/client/gui/info.js
+++ b/scripts/client/gui/info.js
@@ -38,19 +38,19 @@ function initInfoDialogGUI() {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(255, 255, 255, 220),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
},
});
- infoDialog.okayButton = infoDialog.window.button(20, 95, 360, 30, 'OK', {
+ infoDialog.okayButton = infoDialog.window.button(5, 105, 390, 30, 'OK', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
diff --git a/scripts/client/gui/list.js b/scripts/client/gui/list.js
index e45fd39c..00d94be9 100644
--- a/scripts/client/gui/list.js
+++ b/scripts/client/gui/list.js
@@ -41,7 +41,7 @@ function initListGUI() {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(255, 255, 255, 220),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
@@ -73,4 +73,35 @@ function initListGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Created list dialog GUI`);
}
+// ===========================================================================
+
+function showListGUI() {
+ closeAllWindows();
+ logToConsole(LOG_DEBUG, `[VRR.GUI] Showing login window`);
+ setChatWindowEnabled(false);
+ mexui.setInput(true);
+ listDialog.window.shown = true;
+ guiSubmitKey = checkListDialogSelection;
+ guiUpKey = selectPreviousListItem;
+ guiDownKey = selectNextListItem;
+}
+
+// ===========================================================================
+
+function checkListDialogSelection() {
+
+}
+
+// ===========================================================================
+
+function selectPreviousListItem() {
+
+}
+
+// ===========================================================================
+
+function selectNextListItem() {
+
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/gui/login.js b/scripts/client/gui/login.js
index 9b72ee14..60f4b15f 100644
--- a/scripts/client/gui/login.js
+++ b/scripts/client/gui/login.js
@@ -22,7 +22,7 @@ let login = {
function initLoginGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating login GUI ...`);
- login.window = mexui.window(game.width/2-150, game.height/2-129, 300, 258, 'LOGIN', {
+ login.window = mexui.window(game.width/2-150, game.height/2-130, 300, 260, 'LOGIN', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -42,7 +42,7 @@ function initLoginGUI() {
login.window.titleBarIconSize = toVector2(0,0);
login.window.titleBarHeight = 0;
- login.logoImage = login.window.image(100, 20, 100, 100, mainLogoPath, {
+ login.logoImage = login.window.image(5, 20, 290, 80, mainLogoPath, {
focused: {
borderColour: toColour(0, 0, 0, 0),
},
@@ -53,7 +53,7 @@ function initLoginGUI() {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(200, 200, 200, 255),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
@@ -66,7 +66,7 @@ function initLoginGUI() {
borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], textInputAlpha),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -74,7 +74,7 @@ function initLoginGUI() {
placeholder: {
textColour: toColour(200, 200, 200, 150),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], 255),
@@ -88,7 +88,7 @@ function initLoginGUI() {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(0, 0, 0, 255),
textSize: 12.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -96,13 +96,12 @@ function initLoginGUI() {
},
}, checkLogin);
- /*
- login.forgotPasswordButton = login.window.button(200, 240, 60, 15, 'FORGOT PASSWORD', {
+ login.forgotPasswordButton = login.window.button(200, 240, 80, 15, 'RESET PASS', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(0, 0, 0, 255),
textSize: 8.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -110,18 +109,17 @@ function initLoginGUI() {
},
}, switchToPasswordResetGUI);
- login.resetPasswordLabel = login.window.text(20, 140, 60, 15, 'Need to reset your password? Click here >', {
+ login.resetPasswordLabel = login.window.text(125, 240, 60, 15, 'Forgot your password?', {
main: {
textSize: 8.0,
textAlign: 1.0,
- textColour: toColour(200, 200, 200, 255),
- textFont: robotoFont,
+ textColour: toColour(180, 180, 180, 255),
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
},
});
- */
logToConsole(LOG_DEBUG, `[VRR.GUI] Created login GUI`);
}
@@ -134,15 +132,16 @@ function showLoginGUI() {
setChatWindowEnabled(false);
mexui.setInput(true);
login.window.shown = true;
-
- showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
+ mexui.focusedControl = login.passwordInput;
+ guiSubmitKey = checkLogin;
+ //showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
}
// ===========================================================================
function checkLogin() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Checking login with server ...`);
- triggerNetworkEvent("vrr.checkLogin", login.passwordInput.lines[0]);
+ sendNetworkEventToServer("vrr.checkLogin", login.passwordInput.lines[0]);
}
// ===========================================================================
@@ -158,7 +157,15 @@ function loginFailed(errorMessage) {
function loginSuccess() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Server reports login was successful`);
+ guiSubmitKey = false;
closeAllWindows();
}
-// ===========================================================================
\ No newline at end of file
+// ===========================================================================
+
+function switchToPasswordResetGUI() {
+ closeAllWindows();
+ logToConsole(LOG_DEBUG, `[VRR.GUI] Showing password reset dialog window`);
+ showResetPasswordGUI();
+ return false;
+}
\ No newline at end of file
diff --git a/scripts/client/gui/newchar.js b/scripts/client/gui/newchar.js
index 07f0c7c9..8de5c579 100644
--- a/scripts/client/gui/newchar.js
+++ b/scripts/client/gui/newchar.js
@@ -21,7 +21,7 @@ let newCharacter = {
function initNewCharacterGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating new character GUI ...`);
- newCharacter.window = mexui.window(game.width/2-130, game.height/2-100, 300, 200, 'Character Name', {
+ newCharacter.window = mexui.window(game.width/2-130, game.height/2-100, 300, 200, 'New Character', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -40,7 +40,7 @@ function initNewCharacterGUI() {
newCharacter.window.titleBarIconSize = toVector2(0,0);
newCharacter.window.titleBarHeight = 0;
- newCharacter.mainLogoImage = newCharacter.window.image(115, 10, 65, 65, mainLogoPath, {
+ newCharacter.mainLogoImage = newCharacter.window.image(5, 20, 290, 80, mainLogoPath, {
focused: {
borderColour: toColour(0, 0, 0, 0),
},
@@ -51,7 +51,7 @@ function initNewCharacterGUI() {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(200, 200, 200, 255),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
@@ -63,7 +63,7 @@ function initNewCharacterGUI() {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -72,7 +72,7 @@ function initNewCharacterGUI() {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 200),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
}
});
newCharacter.firstNameInput.placeholder = "First Name";
@@ -82,7 +82,7 @@ function initNewCharacterGUI() {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -91,7 +91,7 @@ function initNewCharacterGUI() {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(150, 150, 150, 200),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
}
});
newCharacter.lastNameInput.placeholder = "Last Name";
@@ -100,8 +100,8 @@ function initNewCharacterGUI() {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(255, 255, 255, 255),
- textSize: 12.0,
- textFont: robotoFont,
+ textSize: 10.0,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -143,7 +143,7 @@ function checkNewCharacter() {
return false;
}
- triggerNetworkEvent("vrr.checkNewCharacter",
+ sendNetworkEventToServer("vrr.checkNewCharacter",
newCharacter.firstNameInput.lines[0],
newCharacter.lastNameInput.lines[0],
);
@@ -157,6 +157,8 @@ function showNewCharacterGUI() {
setChatWindowEnabled(false);
mexui.setInput(true);
newCharacter.window.shown = true;
+ mexui.focusedInput = newCharacter.firstNameInput;
+ guiSubmitButton = checkNewCharacter;
}
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/gui/register.js b/scripts/client/gui/register.js
index 62900123..1d1e0378 100644
--- a/scripts/client/gui/register.js
+++ b/scripts/client/gui/register.js
@@ -21,7 +21,7 @@ let register = {
function initRegisterGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating register GUI ...`);
- register.window = mexui.window(game.width/2-130, game.height/2-125, 300, 250, 'Register', {
+ register.window = mexui.window(game.width/2-150, game.height/2-150, 300, 300, 'Register', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -40,30 +40,30 @@ function initRegisterGUI() {
register.window.titleBarIconSize = toVector2(0,0);
register.window.titleBarHeight = 0;
- register.window.image(115, 10, 65, 65, mainLogoPath, {
+ register.window.image(5, 20, 290, 80, mainLogoPath, {
focused: {
borderColour: toColour(0, 0, 0, 0),
},
});
- register.messageLabel = register.window.text(20, 75, 260, 20, 'Create an account', {
+ register.messageLabel = register.window.text(20, 125, 260, 20, 'Create an account', {
main: {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(200, 200, 200, 255),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
},
});
- register.passwordInput = register.window.textInput(20, 100, 260, 25, '', {
+ register.passwordInput = register.window.textInput(20, 150, 260, 25, '', {
main: {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -72,18 +72,18 @@ function initRegisterGUI() {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 200),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
}
});
register.passwordInput.masked = true;
register.passwordInput.placeholder = "Password";
- register.confirmPasswordInput = register.window.textInput(20, 130, 260, 25, '', {
+ register.confirmPasswordInput = register.window.textInput(20, 180, 260, 25, '', {
main: {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -92,18 +92,18 @@ function initRegisterGUI() {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 200),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
}
});
register.confirmPasswordInput.masked = true;
register.confirmPasswordInput.placeholder = "Confirm password";
- register.emailInput = register.window.textInput(20, 160, 260, 25, '', {
+ register.emailInput = register.window.textInput(20, 210, 260, 25, '', {
main: {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -112,17 +112,17 @@ function initRegisterGUI() {
backgroundColour: toColour(0, 0, 0, 120),
textColour: toColour(200, 200, 200, 200),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
}
});
register.emailInput.placeholder = "Email";
- register.registerButton = register.window.button(20, 195, 260, 30, 'CREATE ACCOUNT', {
+ register.registerButton = register.window.button(20, 245, 260, 30, 'CREATE ACCOUNT', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(255, 255, 255, 255),
textSize: 12.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -147,7 +147,7 @@ function registrationFailed(errorMessage) {
function checkRegistration() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Checking registration with server ...`);
- triggerNetworkEvent("vrr.checkRegistration", register.passwordInput.lines[0], register.confirmPasswordInput.lines[0], register.emailInput.lines[0]);
+ sendNetworkEventToServer("vrr.checkRegistration", register.passwordInput.lines[0], register.confirmPasswordInput.lines[0], register.emailInput.lines[0]);
}
// ===========================================================================
@@ -158,14 +158,16 @@ function showRegistrationGUI() {
setChatWindowEnabled(false);
mexui.setInput(true);
register.window.shown = true;
-
- showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
+ mexui.focusedControl = register.passwordInput;
+ guiSubmitKey = checkRegistration;
+ //showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
}
// ===========================================================================
function registrationSuccess() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Server reports registration was successful`);
+ guiSubmitKey = false;
closeAllWindows();
}
diff --git a/scripts/client/gui/resetpass.js b/scripts/client/gui/resetpass.js
index 16767578..433e0046 100644
--- a/scripts/client/gui/resetpass.js
+++ b/scripts/client/gui/resetpass.js
@@ -22,7 +22,7 @@ let resetPassword = {
function initResetPasswordGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Creating password reset GUI ...`);
- resetPassword.window = mexui.window(game.width/2-150, game.height/2-129, 300, 258, 'RESET PASSWORD', {
+ resetPassword.window = mexui.window(game.width/2-150, game.height/2-130, 300, 260, 'RESET PASSWORD', {
main: {
backgroundColour: toColour(secondaryColour[0], secondaryColour[1], secondaryColour[2], windowAlpha),
transitionTime: 500,
@@ -42,7 +42,7 @@ function initResetPasswordGUI() {
resetPassword.window.titleBarIconSize = toVector2(0,0);
resetPassword.window.titleBarHeight = 0;
- resetPassword.logoImage = resetPassword.window.image(100, 20, 100, 100, mainLogoPath, {
+ resetPassword.logoImage = resetPassword.window.image(5, 20, 290, 80, mainLogoPath, {
focused: {
borderColour: toColour(0, 0, 0, 0),
},
@@ -53,7 +53,7 @@ function initResetPasswordGUI() {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(200, 200, 200, 255),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
@@ -66,7 +66,7 @@ function initResetPasswordGUI() {
borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], textInputAlpha),
textColour: toColour(200, 200, 200, 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
caret: {
lineColour: toColour(255, 255, 255, 255),
@@ -74,7 +74,7 @@ function initResetPasswordGUI() {
placeholder: {
textColour: toColour(200, 200, 200, 150),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], 255),
@@ -87,7 +87,7 @@ function initResetPasswordGUI() {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
textSize: 12.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -95,12 +95,12 @@ function initResetPasswordGUI() {
},
}, checkResetPassword);
- resetPassword.backToLoginButton = resetPassword.window.button(200, 240, 60, 15, 'CANCEL', {
+ resetPassword.backToLoginButton = resetPassword.window.button(200, 240, 80, 15, 'LOGIN', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
textSize: 8.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -108,12 +108,12 @@ function initResetPasswordGUI() {
},
}, switchToLoginGUI);
- resetPassword.backToLoginLabel = resetPassword.window.text(20, 140, 60, 15, 'Remembered your password? Click here >', {
+ resetPassword.backToLoginLabel = resetPassword.window.text(125, 240, 60, 15, 'Remember your password?', {
main: {
textSize: 8.0,
textAlign: 1.0,
textColour: toColour(200, 200, 200, 255),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
@@ -131,15 +131,16 @@ function showResetPasswordGUI() {
setChatWindowEnabled(false);
mexui.setInput(true);
resetPassword.window.shown = true;
-
- showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
+ mexui.focusedControl = resetPassword.emailInput;
+ guiSubmitButton = checkResetPassword;
+ //showSmallGameMessage(`If you don't have a mouse cursor, press ${toUpperCase(getKeyNameFromId(disableGUIKey))} to disable GUI`, COLOUR_WHITE, 7500);
}
// ===========================================================================
function checkResetPassword() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Checking password reset with server ...`);
- triggerNetworkEvent("vrr.checkResetPassword", resetPassword.emailInput.lines[0]);
+ sendNetworkEventToServer("vrr.checkResetPassword", resetPassword.emailInput.lines[0]);
}
// ===========================================================================
@@ -153,14 +154,22 @@ function resetPasswordFailed(errorMessage) {
// ===========================================================================
-function resetPasswordSuccess() {
+function resetPasswordCodeInputGUI() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Server reports password reset was successful`);
+
+ resetPassword.messageLabel.text = "Check your email for a verification code";
+ resetPassword.messageLabel.styles.main.textColour = toColour(180, 32, 32, 255);
+ resetPassword.emailInput.text = "";
+ resetPassword.emailInput.placeholder = "Verification Code";
+
+ guiSubmitButton = checkResetPassword;
closeAllWindows();
}
// ===========================================================================
function switchToLoginGUI() {
+ guiSubmitKey = false;
closeAllWindows();
showLoginGUI();
}
diff --git a/scripts/client/gui/yesno.js b/scripts/client/gui/yesno.js
index 4d7b2c10..a7ee4f32 100644
--- a/scripts/client/gui/yesno.js
+++ b/scripts/client/gui/yesno.js
@@ -41,19 +41,19 @@ function initYesNoDialogGUI() {
textSize: 10.0,
textAlign: 0.5,
textColour: toColour(255, 255, 255, 255),
- textFont: robotoFont,
+ textFont: mainFont,
},
focused: {
borderColour: toColour(0, 0, 0, 0),
},
});
- yesNoDialog.yesButton = yesNoDialog.window.button(20, 95, 175, 30, 'YES', {
+ yesNoDialog.yesButton = yesNoDialog.window.button(5, 100, 197, 25, 'YES', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -61,12 +61,12 @@ function initYesNoDialogGUI() {
},
}, yesNoDialogAnswerYes);
- yesNoDialog.noButton = yesNoDialog.window.button(205, 95, 175, 30, 'NO', {
+ yesNoDialog.noButton = yesNoDialog.window.button(202, 105, 197, 25, 'NO', {
main: {
backgroundColour: toColour(primaryColour[0], primaryColour[1], primaryColour[2], buttonAlpha),
textColour: toColour(primaryTextColour[0], primaryTextColour[1], primaryTextColour[2], 255),
textSize: 10.0,
- textFont: robotoFont,
+ textFont: mainFont,
textAlign: 0.5,
},
focused: {
@@ -90,7 +90,7 @@ function showYesNoPromptGUI(promptMessage, promptTitle) {
function yesNoDialogAnswerNo() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Responding with answer NO to server prompt`);
- triggerNetworkEvent("vrr.promptAnswerNo");
+ sendNetworkEventToServer("vrr.promptAnswerNo");
closeAllWindows();
}
@@ -98,7 +98,7 @@ function yesNoDialogAnswerNo() {
function yesNoDialogAnswerYes() {
logToConsole(LOG_DEBUG, `[VRR.GUI] Responding with answer YES to server prompt`);
- triggerNetworkEvent("vrr.promptAnswerYes");
+ sendNetworkEventToServer("vrr.promptAnswerYes");
closeAllWindows();
}
diff --git a/scripts/client/index.js b/scripts/client/index.js
new file mode 100644
index 00000000..4dd994ea
--- /dev/null
+++ b/scripts/client/index.js
@@ -0,0 +1,34 @@
+// For RAGEMP only
+
+// Shared Scripts
+require("../scripts/shared/const.js");
+require("../scripts/shared/utilities.js");
+require("../scripts/shared/gamedata.js");
+
+// Multiplayer Mod (Wrapped Natives)
+require("scripts/client/native/ragemp.js");
+
+// Client Scripts
+require("scripts/client/gui.js");
+require("scripts/client/main.js");
+require("scripts/client/nametag.js");
+require("scripts/client/sync.js");
+require("scripts/client/scoreboard.js");
+require("scripts/client/keybind.js");
+require("scripts/client/chatbox.js");
+require("scripts/client/label.js");
+require("scripts/client/skin-select.js");
+require("scripts/client/server.js");
+require("scripts/client/job.js");
+require("scripts/client/event.js");
+require("scripts/client/item.js");
+require("scripts/client/utilities.js");
+require("scripts/client/messaging.js");
+require("scripts/client/logo.js");
+require("scripts/client/afk.js");
+require("scripts/client/mousecam.js");
+require("scripts/client/radio.js");
+require("scripts/client/animation.js");
+
+// Startup
+require("scripts/client/startup.js");
\ No newline at end of file
diff --git a/scripts/client/job.js b/scripts/client/job.js
index efd5e7b9..c993aa16 100644
--- a/scripts/client/job.js
+++ b/scripts/client/job.js
@@ -9,8 +9,8 @@
let localPlayerJobType = 0;
let localPlayerWorking = false;
-let jobRouteStopBlip = null;
-let jobRouteStopSphere = null;
+let jobRouteLocationBlip = null;
+let jobRouteLocationSphere = null;
// ===========================================================================
@@ -35,21 +35,21 @@ function setLocalPlayerWorkingState(tempWorking) {
// ===========================================================================
-function showJobRouteStop(position, colour) {
- logToConsole(LOG_DEBUG, `[VRR.Job] Showing route stop`);
+function showJobRouteLocation(position, colour) {
+ logToConsole(LOG_DEBUG, `[VRR.Job] Showing job route location`);
if(getMultiplayerMod() == VRR_MPMOD_GTAC) {
if(game.game == VRR_GAME_GTA_SA) {
- jobRouteStopSphere = game.createPickup(1318, position, 1);
+ jobRouteLocationSphere = game.createPickup(1318, position, 1);
} else {
- jobRouteStopSphere = game.createSphere(position, 3);
- jobRouteStopSphere.colour = colour;
+ jobRouteLocationSphere = game.createSphere(position, 3);
+ jobRouteLocationSphere.colour = colour;
}
- if(jobRouteStopBlip != null) {
- destroyElement(jobRouteStopBlip);
+ if(jobRouteLocationBlip != null) {
+ destroyElement(jobRouteLocationBlip);
}
- blinkJobRouteStopBlip(10, position, colour);
+ blinkJobRouteLocationBlip(10, position, colour);
}
}
@@ -57,30 +57,39 @@ function showJobRouteStop(position, colour) {
function enteredJobRouteSphere() {
logToConsole(LOG_DEBUG, `[VRR.Job] Entered job route sphere`);
- tellServerPlayerArrivedAtJobRouteStop();
- destroyElement(jobRouteStopSphere);
- destroyElement(jobRouteStopBlip);
- jobRouteStopSphere = null;
- jobRouteStopBlip = null;
+ tellServerPlayerArrivedAtJobRouteLocation();
+ destroyElement(jobRouteLocationSphere);
+ destroyElement(jobRouteLocationBlip);
+ jobRouteLocationSphere = null;
+ jobRouteLocationBlip = null;
}
// ===========================================================================
-function blinkJobRouteStopBlip(times, position, colour) {
+function blinkJobRouteLocationBlip(times, position, colour) {
for(let i = 1 ; i <= times ; i++) {
setTimeout(function() {
- if(jobRouteStopBlip != null) {
- destroyElement(jobRouteStopBlip);
- jobRouteStopBlip = null;
+ if(jobRouteLocationBlip != null) {
+ destroyElement(jobRouteLocationBlip);
+ jobRouteLocationBlip = null;
} else {
- jobRouteStopBlip = game.createBlip(position, 0, 2, colour);
+ jobRouteLocationBlip = game.createBlip(position, 0, 2, colour);
}
}, 500*i);
}
setTimeout(function() {
- jobRouteStopBlip = game.createBlip(position, 0, 2, colour);
+ jobRouteLocationBlip = game.createBlip(position, 0, 2, colour);
}, 500*times+1);
}
+// ===========================================================================
+
+function hideJobRouteLocation() {
+ destroyElement(jobRouteLocationSphere);
+ destroyElement(jobRouteLocationBlip);
+ jobRouteLocationSphere = null;
+ jobRouteLocationBlip = null;
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/jsconfig.json b/scripts/client/jsconfig.json
index 9c32b246..a5e369f2 100644
--- a/scripts/client/jsconfig.json
+++ b/scripts/client/jsconfig.json
@@ -1,11 +1,14 @@
{
"compilerOptions": {
"module": "commonjs",
- "target": "ES6",
+ "target": "es6",
"moduleResolution": "classic"
},
"include": [
- "./*.js",
- "../shared/*.js"
+ "*.js",
+ "gui/*.js",
+ "native/*.js",
+ "../shared/*.js",
+ "../third-party/mexui/*"
]
}
\ No newline at end of file
diff --git a/scripts/client/keybind.js b/scripts/client/keybind.js
index edbb18b7..4c8c2d9c 100644
--- a/scripts/client/keybind.js
+++ b/scripts/client/keybind.js
@@ -26,16 +26,20 @@ function bindAccountKey(key, keyState) {
logToConsole(LOG_DEBUG, `[VRR.KeyBind]: Binded key ${toUpperCase(getKeyNameFromId(key))} (${key})`);
keyBinds.push(toInteger(key));
bindKey(toInteger(key), keyState, function(event) {
+ if(isAnyGUIActive()) {
+ return false;
+ }
+
if(hasKeyBindDelayElapsed()) {
if(canLocalPlayerUseKeyBinds()) {
logToConsole(LOG_DEBUG, `[VRR.KeyBind]: Using keybind for key ${toUpperCase(getKeyNameFromId(key))} (${key})`);
lastKeyBindUse = sdl.ticks;
tellServerPlayerUsedKeyBind(key);
} else {
- logToConsole(LOG_ERROR, `[VRR.KeyBind]: Failed to use keybind for key ${toUpperCase(getKeyNameFromId(key))} (${key}) - Not allowed to use keybinds!`);
+ logToConsole(LOG_DEBUG, `[VRR.KeyBind]: Failed to use keybind for key ${toUpperCase(getKeyNameFromId(key))} (${key}) - Not allowed to use keybinds!`);
}
} else {
- logToConsole(LOG_ERROR, `[VRR.KeyBind]: Failed to use keybind for key ${toUpperCase(getKeyNameFromId(key))} (${key}) - Not enough time has passed since last keybind use!`);
+ logToConsole(LOG_DEBUG, `[VRR.KeyBind]: Failed to use keybind for key ${toUpperCase(getKeyNameFromId(key))} (${key}) - Not enough time has passed since last keybind use!`);
}
});
}
@@ -62,7 +66,19 @@ function hasKeyBindDelayElapsed() {
// ===========================================================================
function canLocalPlayerUseKeyBinds() {
- return true; //(!usingSkinSelector && isSpawned && !itemActionDelayEnabled);
+ if(isAnyGUIActive()) {
+ return false;
+ }
+
+ if(!isSpawned) {
+ return false;
+ }
+
+ if(itemActionDelayEnabled) {
+ return false;
+ }
+
+ return true;
}
// ===========================================================================
diff --git a/scripts/client/label.js b/scripts/client/label.js
index 2bbaa16a..70e2df8e 100644
--- a/scripts/client/label.js
+++ b/scripts/client/label.js
@@ -127,7 +127,7 @@ function renderPropertyEntranceLabel(name, position, locked, isBusiness, price,
break;
case VRR_PROPLABEL_INFO_BUYBIZ:
- infoText = `Use /bizbuy to buy this business`;
+ infoText = `Use /buy to purchase items`;
break;
//case VRR_PROPLABEL_INFO_RENTBIZ:
@@ -253,37 +253,39 @@ function processLabelRendering() {
for(let i in pickups) {
if(pickups[i].getData("vrr.label.type") != null) {
if(getDistance(localPlayer.position, pickups[i].position) <= renderLabelDistance) {
- let price = "0";
- let rentPrice = "0";
- let labelInfoType = VRR_PROPLABEL_INFO_NONE;
- if(pickups[i].getData("vrr.label.price") != null) {
- price = makeLargeNumberReadable(pickups[i].getData("vrr.label.price"));
- }
+ if(!pickups[i].isOnScreen) {
+ let price = "0";
+ let rentPrice = "0";
+ let labelInfoType = VRR_PROPLABEL_INFO_NONE;
+ if(pickups[i].getData("vrr.label.price") != null) {
+ price = makeLargeNumberReadable(pickups[i].getData("vrr.label.price"));
+ }
- if(pickups[i].getData("vrr.label.rentprice") != null) {
- rentPrice = makeLargeNumberReadable(pickups[i].getData("vrr.label.rentprice"));
- }
+ if(pickups[i].getData("vrr.label.rentprice") != null) {
+ rentPrice = makeLargeNumberReadable(pickups[i].getData("vrr.label.rentprice"));
+ }
- if(pickups[i].getData("vrr.label.help") != null) {
- labelInfoType = pickups[i].getData("vrr.label.help");
- }
+ if(pickups[i].getData("vrr.label.help") != null) {
+ labelInfoType = pickups[i].getData("vrr.label.help");
+ }
- switch(pickups[i].getData("vrr.label.type")) {
- case VRR_LABEL_BUSINESS:
- renderPropertyEntranceLabel(pickups[i].getData("vrr.label.name"), pickups[i].position, pickups[i].getData("vrr.label.locked"), true, price, rentPrice, labelInfoType);
- break;
+ switch(pickups[i].getData("vrr.label.type")) {
+ case VRR_LABEL_BUSINESS:
+ renderPropertyEntranceLabel(pickups[i].getData("vrr.label.name"), pickups[i].position, pickups[i].getData("vrr.label.locked"), true, price, rentPrice, labelInfoType);
+ break;
- case VRR_LABEL_HOUSE:
- renderPropertyEntranceLabel(pickups[i].getData("vrr.label.name"), pickups[i].position, pickups[i].getData("vrr.label.locked"), false, price, rentPrice, labelInfoType);
- break;
+ case VRR_LABEL_HOUSE:
+ renderPropertyEntranceLabel("House", pickups[i].position, pickups[i].getData("vrr.label.locked"), false, price, rentPrice, labelInfoType);
+ break;
- case VRR_LABEL_JOB:
- renderJobLabel(pickups[i].getData("vrr.label.name"), pickups[i].position, pickups[i].getData("vrr.label.jobType"));
- break;
+ case VRR_LABEL_JOB:
+ renderJobLabel(pickups[i].getData("vrr.label.name"), pickups[i].position, pickups[i].getData("vrr.label.jobType"));
+ break;
- case VRR_LABEL_EXIT:
- renderPropertyExitLabel(pickups[i].position);
- break;
+ case VRR_LABEL_EXIT:
+ renderPropertyExitLabel(pickups[i].position);
+ break;
+ }
}
}
}
diff --git a/scripts/client/main.js b/scripts/client/main.js
index d673be80..7292f970 100644
--- a/scripts/client/main.js
+++ b/scripts/client/main.js
@@ -64,6 +64,8 @@ let vehiclePurchaseState = VRR_VEHBUYSTATE_NONE;
let vehiclePurchasing = null;
let vehiclePurchasePosition = null;
+let forceWantedLevel = 0;
+
// Pre-cache all allowed skins
let allowedSkins = getAllowedSkins(getGame());
diff --git a/scripts/client/nametag.js b/scripts/client/nametag.js
index 15c212c6..7009f884 100644
--- a/scripts/client/nametag.js
+++ b/scripts/client/nametag.js
@@ -165,6 +165,13 @@ function updateNametags(element) {
let distance = playerPos.distance(elementPos);
if(distance <= nametagDistance) {
+ if(typeof game.processLineOfSight != "undefined") {
+ let losCheck = game.processLineOfSight(playerPos, elementPos, true, false, false, true, true, false, true, true);
+ if(losCheck != null) {
+ return false;
+ }
+ }
+
if(element.type == ELEMENT_PLAYER) {
let name = element.name;
let colour = COLOUR_WHITE;
diff --git a/scripts/client/native/connected.js b/scripts/client/native/connected.js
index e69de29b..69335fb2 100644
--- a/scripts/client/native/connected.js
+++ b/scripts/client/native/connected.js
@@ -0,0 +1,144 @@
+// ===========================================================================
+// Vortrex's Roleplay Resource
+// https://github.com/VortrexFTW/gtac_roleplay
+// ===========================================================================
+// FILE: connected.js
+// DESC: Provides wrapped natives for GTA Connected and Mafia Connected mods
+// TYPE: Server (JavaScript)
+// ===========================================================================
+
+function sendNetworkEventToPlayer(networkEvent, client, ...args) {
+ triggerNetworkEvent.apply(null, networkEvent, client, args);
+}
+
+// ===========================================================================
+
+function getPlayerPosition() {
+ return localPlayer.position;
+}
+
+// ===========================================================================
+
+function setPlayerPosition(position) {
+ localPlayer.position = position;
+}
+
+// ===========================================================================
+
+function getElementPosition(element) {
+ return element.position;
+}
+
+// ===========================================================================
+
+function setElementPosition(element, position) {
+ if(!element.isSyncer) {
+ return false;
+ }
+
+ element.position = position;
+}
+
+// ===========================================================================
+
+function deleteGameElement(element, position) {
+ if(!element.isOwner) {
+ return false;
+ }
+
+ destroyGameElement(element);
+}
+
+// ===========================================================================
+
+function createGameVehicle(modelIndex, position, heading) {
+ return game.createVehicle(getGameData().vehicles[getGame()][modelIndex][0], position, heading);
+}
+
+// ===========================================================================
+
+function addNetworkEventHandler(eventName, handlerFunction) {
+ addNetworkHandler(eventName, handlerFunction);
+}
+
+// ===========================================================================
+
+function sendNetworkEventToServer(eventName, ...args) {
+ let argsArray = [eventName];
+ argsArray = argsArray.concat(args);
+ triggerNetworkEvent.apply(null, argsArray);
+}
+
+// ===========================================================================
+
+function getElementId(element) {
+ return element.id;
+}
+
+// ===========================================================================
+
+function getClientFromIndex(index) {
+ let clients = getClients();
+ for(let i in clients) {
+ if(clients[i].index == index) {
+ return clients[i];
+ }
+ }
+}
+
+// ===========================================================================
+
+function getVehiclesInRange(position, distance) {
+ return getElementsByType(ELEMENT_VEHICLE).filter(x => x.player && x.position.distance(position) <= distance);
+}
+
+// ===========================================================================
+
+function getClientsInRange(position, distance) {
+ return getPlayersInRange(position, distance);
+}
+
+// ===========================================================================
+
+function getCiviliansInRange(position, distance) {
+ return getElementsByType(ELEMENT_PED).filter(x => !x.isType(ELEMENT_PLAYER) && getElementPosition(x).position.distance(position) <= distance);
+}
+
+// ===========================================================================
+
+function getPlayersInRange(position, distance) {
+ return getClients().filter(x => getPlayerPosition(x).distance(position) <= distance);
+}
+
+// ===========================================================================
+
+function getElementsByTypeInRange(elementType, position, distance) {
+ return getElementsByType(elementType).filter(x => getElementPosition(x).position.distance(position) <= distance);
+}
+
+// ===========================================================================
+
+function getClosestCivilian(position) {
+ return getElementsByType(ELEMENT_PED).reduce((i, j) => ((i.position.distance(position) <= j.position.distance(position)) ? i : j));
+}
+
+// ===========================================================================
+
+function is2dPositionOnScreen(pos2d) {
+ return pos2d.x >= 0 && pos2d.y >= 0 && pos2d.x <= game.width && pos2d.y <= game.height;
+}
+
+// ===========================================================================
+
+function getVehiclesInRange(position, range) {
+ let vehicles = getElementsByType(ELEMENT_VEHICLE);
+ let inRangeVehicles = [];
+ for(let i in vehicles) {
+ if(getDistance(position, vehicles[i].position) <= range) {
+ inRangeVehicles.push(vehicles[i]);
+ }
+ }
+ return inRangeVehicles;
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/radio.js b/scripts/client/radio.js
index 33ab85ad..2608e834 100644
--- a/scripts/client/radio.js
+++ b/scripts/client/radio.js
@@ -22,7 +22,9 @@ function playStreamingRadio(url, loop, volume, element = false) {
// ===========================================================================
function stopStreamingRadio() {
- streamingRadio.stop();
+ if(streamingRadio != null) {
+ streamingRadio.stop();
+ }
streamingRadio = null;
}
@@ -38,12 +40,7 @@ function setStreamingRadioVolume(volume) {
// ===========================================================================
function playAudioFile(audioName, loop, volume) {
- let resource = findResourceByName("connectedrp-extra");
- if(resource == null) {
- return false;
- }
-
- resource.exports.playCustomAudio(audioName, volume/100);
+ playCustomAudio(audioName, volume/100, loop);
}
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/server.js b/scripts/client/server.js
index 2ac8df8b..b5bb5da8 100644
--- a/scripts/client/server.js
+++ b/scripts/client/server.js
@@ -18,101 +18,108 @@ function initServerScript() {
function addAllNetworkHandlers() {
logToConsole(LOG_DEBUG, "[VRR.Server]: Adding network handlers ...");
- addNetworkHandler("vrr.smallGameMessage", showSmallGameMessage);
- addNetworkHandler("vrr.working", setLocalPlayerWorkingState);
- addNetworkHandler("vrr.jobType", setLocalPlayerJobType);
- addNetworkHandler("vrr.passenger", enterVehicleAsPassenger);
+ addNetworkEventHandler("vrr.smallGameMessage", showSmallGameMessage);
+ addNetworkEventHandler("vrr.working", setLocalPlayerWorkingState);
+ addNetworkEventHandler("vrr.jobType", setLocalPlayerJobType);
+ addNetworkEventHandler("vrr.passenger", enterVehicleAsPassenger);
- addNetworkHandler("vrr.freeze", setLocalPlayerFrozenState);
- addNetworkHandler("vrr.control", setLocalPlayerControlState);
- addNetworkHandler("vrr.fadeCamera", fadeLocalCamera);
- addNetworkHandler("vrr.removeFromVehicle", removeLocalPlayerFromVehicle);
- addNetworkHandler("vrr.clearPeds", clearLocalPlayerOwnedPeds);
- addNetworkHandler("vrr.restoreCamera", restoreLocalCamera);
- addNetworkHandler("vrr.cameraLookAt", setLocalCameraLookAt);
- addNetworkHandler("vrr.logo", setServerLogoRenderState);
- addNetworkHandler("vrr.ambience", setCityAmbienceState);
- addNetworkHandler("vrr.runCode", runClientCode);
- addNetworkHandler("vrr.clearWeapons", clearLocalPlayerWeapons);
- addNetworkHandler("vrr.giveWeapon", giveLocalPlayerWeapon);
- addNetworkHandler("vrr.position", setLocalPlayerPosition);
- addNetworkHandler("vrr.heading", setLocalPlayerHeading);
- addNetworkHandler("vrr.interior", setLocalPlayerInterior);
- addNetworkHandler("vrr.minuteDuration", setMinuteDuration);
- addNetworkHandler("vrr.showJobRouteStop", showJobRouteStop);
- addNetworkHandler("vrr.snow", setSnowState);
- addNetworkHandler("vrr.health", setLocalPlayerHealth);
- addNetworkHandler("vrr.enterPropertyKey", setEnterPropertyKey);
- addNetworkHandler("vrr.skinSelect", toggleSkinSelect);
- addNetworkHandler("vrr.hotbar", updatePlayerHotBar);
- addNetworkHandler("vrr.pedSpeech", playPedSpeech);
- addNetworkHandler("vrr.clearPedState", clearLocalPedState);
- addNetworkHandler("vrr.drunkEffect", setLocalPlayerDrunkEffect);
- addNetworkHandler("vrr.showItemActionDelay", showItemActionDelay);
- addNetworkHandler("vrr.set2DRendering", setPlayer2DRendering);
- addNetworkHandler("vrr.mouseCursor", toggleMouseCursor);
- addNetworkHandler("vrr.mouseCamera", toggleMouseCamera);
- addNetworkHandler("vrr.mouseCameraForce", setMouseCameraState);
- addNetworkHandler("vrr.weaponDamageEnabled", setPlayerWeaponDamageEnabled);
- addNetworkHandler("vrr.weaponDamageEvent", setPlayerWeaponDamageEvent);
- addNetworkHandler("vrr.spawned", onServerSpawnedPlayer);
- addNetworkHandler("vrr.money", setLocalPlayerCash);
- addNetworkHandler("vrr.armour", setLocalPlayerArmour);
+ addNetworkEventHandler("vrr.freeze", setLocalPlayerFrozenState);
+ addNetworkEventHandler("vrr.control", setLocalPlayerControlState);
+ addNetworkEventHandler("vrr.fadeCamera", fadeLocalCamera);
+ addNetworkEventHandler("vrr.removeFromVehicle", removeLocalPlayerFromVehicle);
+ addNetworkEventHandler("vrr.clearPeds", clearLocalPlayerOwnedPeds);
+ addNetworkEventHandler("vrr.restoreCamera", restoreLocalCamera);
+ addNetworkEventHandler("vrr.cameraLookAt", setLocalCameraLookAt);
+ addNetworkEventHandler("vrr.logo", setServerLogoRenderState);
+ addNetworkEventHandler("vrr.ambience", setCityAmbienceState);
+ addNetworkEventHandler("vrr.runCode", runClientCode);
+ addNetworkEventHandler("vrr.clearWeapons", clearLocalPlayerWeapons);
+ addNetworkEventHandler("vrr.giveWeapon", giveLocalPlayerWeapon);
+ addNetworkEventHandler("vrr.position", setLocalPlayerPosition);
+ addNetworkEventHandler("vrr.heading", setLocalPlayerHeading);
+ addNetworkEventHandler("vrr.interior", setLocalPlayerInterior);
+ addNetworkEventHandler("vrr.minuteDuration", setMinuteDuration);
+ addNetworkEventHandler("vrr.showJobRouteLocation", showJobRouteLocation);
+ addNetworkEventHandler("vrr.hideJobRouteLocation", hideJobRouteLocation);
+ addNetworkEventHandler("vrr.snow", setSnowState);
+ addNetworkEventHandler("vrr.health", setLocalPlayerHealth);
+ addNetworkEventHandler("vrr.enterPropertyKey", setEnterPropertyKey);
+ addNetworkEventHandler("vrr.skinSelect", toggleSkinSelect);
+ addNetworkEventHandler("vrr.hotbar", updatePlayerHotBar);
+ addNetworkEventHandler("vrr.pedSpeech", playPedSpeech);
+ addNetworkEventHandler("vrr.clearPedState", clearLocalPedState);
+ addNetworkEventHandler("vrr.drunkEffect", setLocalPlayerDrunkEffect);
+ addNetworkEventHandler("vrr.showItemActionDelay", showItemActionDelay);
+ addNetworkEventHandler("vrr.set2DRendering", setPlayer2DRendering);
+ addNetworkEventHandler("vrr.mouseCursor", toggleMouseCursor);
+ addNetworkEventHandler("vrr.mouseCamera", toggleMouseCamera);
+ addNetworkEventHandler("vrr.mouseCameraForce", setMouseCameraState);
+ addNetworkEventHandler("vrr.weaponDamageEnabled", setPlayerWeaponDamageEnabled);
+ addNetworkEventHandler("vrr.weaponDamageEvent", setPlayerWeaponDamageEvent);
+ addNetworkEventHandler("vrr.spawned", onServerSpawnedPlayer);
+ addNetworkEventHandler("vrr.money", setLocalPlayerCash);
+ addNetworkEventHandler("vrr.armour", setLocalPlayerArmour);
+ addNetworkEventHandler("vrr.wantedLevel", forceLocalPlayerWantedLevel);
- addNetworkHandler("vrr.delKeyBind", unBindAccountKey);
- addNetworkHandler("vrr.addKeyBind", bindAccountKey);
- addNetworkHandler("vrr.clearKeyBinds", clearKeyBinds);
+ addNetworkEventHandler("vrr.delKeyBind", unBindAccountKey);
+ addNetworkEventHandler("vrr.addKeyBind", bindAccountKey);
+ addNetworkEventHandler("vrr.clearKeyBinds", clearKeyBinds);
- addNetworkHandler("vrr.nametag", updatePlayerNameTag);
- addNetworkHandler("vrr.ping", updatePlayerPing);
+ addNetworkEventHandler("vrr.nametag", updatePlayerNameTag);
+ addNetworkEventHandler("vrr.ping", updatePlayerPing);
- addNetworkHandler("vrr.m", receiveChatBoxMessageFromServer);
- addNetworkHandler("vrr.chatScrollLines", setChatScrollLines);
+ addNetworkEventHandler("vrr.m", receiveChatBoxMessageFromServer);
+ addNetworkEventHandler("vrr.chatScrollLines", setChatScrollLines);
- addNetworkHandler("vrr.radioStream", playStreamingRadio);
- addNetworkHandler("vrr.audioFileStream", playAudioFile);
- addNetworkHandler("vrr.stopRadioStream", stopStreamingRadio);
- addNetworkHandler("vrr.radioVolume", setStreamingRadioVolume);
+ addNetworkEventHandler("vrr.radioStream", playStreamingRadio);
+ addNetworkEventHandler("vrr.audioFileStream", playAudioFile);
+ addNetworkEventHandler("vrr.stopRadioStream", stopStreamingRadio);
+ addNetworkEventHandler("vrr.radioVolume", setStreamingRadioVolume);
- addNetworkHandler("vrr.veh.lights", setVehicleLights);
- addNetworkHandler("vrr.veh.engine", setVehicleEngine);
- addNetworkHandler("vrr.veh.repair", repairVehicle);
+ addNetworkEventHandler("vrr.veh.lights", setVehicleLights);
+ addNetworkEventHandler("vrr.veh.engine", setVehicleEngine);
+ addNetworkEventHandler("vrr.veh.repair", repairVehicle);
- addNetworkHandler("vrr.pedAnim", makePedPlayAnimation);
- addNetworkHandler("vrr.pedStopAnim", makePedStopAnimation);
- addNetworkHandler("vrr.hideAllGUI", hideAllGUI);
- addNetworkHandler("vrr.gameScript", setGameScriptState);
- addNetworkHandler("vrr.clientInfo", serverRequestedClientInfo);
- addNetworkHandler("vrr.interiorLights", updateInteriorLightsState);
+ addNetworkEventHandler("vrr.pedAnim", makePedPlayAnimation);
+ addNetworkEventHandler("vrr.pedStopAnim", makePedStopAnimation);
+ addNetworkEventHandler("vrr.localPlayerSkin", setLocalPlayerSkin);
+ addNetworkEventHandler("vrr.forcePedAnim", forcePedAnimation);
+ addNetworkEventHandler("vrr.hideAllGUI", hideAllGUI);
+ addNetworkEventHandler("vrr.gameScript", setGameScriptState);
+ addNetworkEventHandler("vrr.clientInfo", serverRequestedClientInfo);
+ addNetworkEventHandler("vrr.interiorLights", updateInteriorLightsState);
- addNetworkHandler("vrr.syncElement", forceSyncElementProperties);
- addNetworkHandler("vrr.elementPosition", setElementPosition);
- addNetworkHandler("vrr.elementCollisions", setElementCollisionsEnabled);
+ addNetworkEventHandler("vrr.syncElement", forceSyncElementProperties);
+ addNetworkEventHandler("vrr.elementPosition", setElementPosition);
+ addNetworkEventHandler("vrr.elementCollisions", setElementCollisionsEnabled);
- addNetworkHandler("vrr.vehBuyState", setVehiclePurchaseState);
+ addNetworkEventHandler("vrr.vehBuyState", setVehiclePurchaseState);
- addNetworkHandler("vrr.showRegistration", showRegistrationGUI);
- addNetworkHandler("vrr.showNewCharacter", showNewCharacterGUI);
- addNetworkHandler("vrr.showLogin", showLoginGUI);
+ addNetworkEventHandler("vrr.showRegistration", showRegistrationGUI);
+ addNetworkEventHandler("vrr.showNewCharacter", showNewCharacterGUI);
+ addNetworkEventHandler("vrr.showLogin", showLoginGUI);
+
+ addNetworkEventHandler("vrr.logLevel", setLogLevel);
+ addNetworkEventHandler("vrr.infiniteRun", setLocalPlayerInfiniteRun);
}
// ===========================================================================
function sendResourceReadySignalToServer() {
- triggerNetworkEvent("vrr.clientReady");
+ sendNetworkEventToServer("vrr.clientReady");
}
// ===========================================================================
function sendResourceStartedSignalToServer() {
- triggerNetworkEvent("vrr.clientStarted");
+ sendNetworkEventToServer("vrr.clientStarted");
}
// ===========================================================================
function sendResourceStoppedSignalToServer() {
if(isConnected) {
- triggerNetworkEvent("vrr.clientStopped");
+ sendNetworkEventToServer("vrr.clientStopped");
}
}
@@ -122,10 +129,12 @@ function setPlayer2DRendering(hudState, labelState, smallGameMessageState, score
logToConsole(LOG_DEBUG, `[VRR.Main] Updating render states (HUD: ${hudState}, Labels: ${labelState}, Bottom Text: ${smallGameMessageState}, Scoreboard: ${scoreboardState}, HotBar: ${hotBarState}, Item Action Delay: ${itemActionDelayState})`);
renderHUD = hudState;
- if(typeof setHUDEnabled != "undefined") {
- if(getGame() == VRR_GAME_GTA_IV) {
- natives.displayHud(false);
- } else {
+ if(getGame() == VRR_GAME_GTA_IV) {
+ natives.displayCash(hudState);
+ natives.displayAmmo(hudState);
+ natives.displayHud(hudState);
+ } else {
+ if(typeof setHUDEnabled != "undefined") {
setHUDEnabled(hudState);
}
}
@@ -151,19 +160,19 @@ function onServerSpawnedPlayer(state) {
// ===========================================================================
function tellServerPlayerUsedKeyBind(key) {
- triggerNetworkEvent("vrr.useKeyBind", key);
+ sendNetworkEventToServer("vrr.useKeyBind", key);
}
// ===========================================================================
-function tellServerPlayerArrivedAtJobRouteStop() {
- triggerNetworkEvent("vrr.arrivedAtJobRouteStop");
+function tellServerPlayerArrivedAtJobRouteLocation() {
+ sendNetworkEventToServer("vrr.arrivedAtJobRouteLocation");
}
// ===========================================================================
function tellServerItemActionDelayComplete() {
- triggerNetworkEvent("vrr.itemActionDelayComplete");
+ sendNetworkEventToServer("vrr.itemActionDelayComplete");
}
// ===========================================================================
@@ -173,13 +182,13 @@ function sendServerClientInfo() {
if(typeof CLIENT_VERSION_MAJOR != "undefined") {
clientVersion = `${CLIENT_VERSION_MAJOR}.${CLIENT_VERSION_MINOR}.${CLIENT_VERSION_PATCH}.${CLIENT_VERSION_BUILD}`;
}
- triggerNetworkEvent("vrr.clientInfo", clientVersion, game.width, game.height);
+ sendNetworkEventToServer("vrr.clientInfo", clientVersion, game.width, game.height);
}
// ===========================================================================
function sendServerNewAFKStatus(state) {
- triggerNetworkEvent("vrr.afk", state);
+ sendNetworkEventToServer("vrr.afk", state);
}
// ===========================================================================
@@ -235,6 +244,10 @@ function setElementPosition(elementId, position) {
return false;
}
+ if(!getElementFromId(elementId).isSyncer) {
+ return false;
+ }
+
getElementFromId(elementId).position = position;
}
@@ -250,25 +263,6 @@ function setElementCollisionsEnabled(elementId, state) {
// ===========================================================================
-function makePedStopAnimation(pedId) {
- if(getElementFromId(pedId) == null) {
- return false;
- }
-
- if(getGame() == VRR_GAME_GTA_VC || getGame() == VRR_GAME_GTA_SA) {
- getElementFromId(pedId).clearAnimations();
- } else {
- getElementFromId(pedId).clearObjective();
- }
-
- if(getElementFromId(pedId) == localPlayer) {
- localPlayer.collisionsEnabled = true;
- setLocalPlayerControlState(true, false);
- }
-}
-
-// ===========================================================================
-
function setLocalPlayerPedPartsAndProps(parts, props) {
for(let i in parts) {
localPlayer.changeBodyPart(parts[0], parts[1], parts[2]);
@@ -284,4 +278,37 @@ function setLocalPlayerArmour(armour) {
}
}
+// ===========================================================================
+
+function forceLocalPlayerWantedLevel(wantedLevel) {
+ forceWantedLevel = toInteger(wantedLevel);
+}
+
+// ===========================================================================
+
+function setLogLevel(level) {
+ logLevel = level;
+}
+
+// ===========================================================================
+
+function setLocalPlayerInfiniteRun(state) {
+ if(localPlayer != null) {
+ if(getGame() == VRR_GAME_GTA_III || getGame() == VRR_GAME_GTA_VC) {
+ game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), boolToInt(state));
+ }
+ }
+}
+
+// ===========================================================================
+
+function setLocalPlayerSkin(skinId) {
+ if(getGame() == VRR_GAME_GTA_IV) {
+ //natives.changePlayerModel(natives.getPlayerId(), skinId);
+ localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ } else {
+ localPlayer.skin = skinId;
+ }
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/client/skin-select.js b/scripts/client/skin-select.js
index 42bf3b8a..2f3149e7 100644
--- a/scripts/client/skin-select.js
+++ b/scripts/client/skin-select.js
@@ -53,7 +53,12 @@ function processSkinSelectKeyPress(keyCode) {
}
logToConsole(LOG_DEBUG, `Switching to skin ${allowedSkins[skinSelectorIndex][1]} (Index: ${skinSelectorIndex}, Skin: ${allowedSkins[skinSelectorIndex][0]})`);
skinSelectMessageTextTop = allowedSkins[skinSelectorIndex][1];
- localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ if(getGame() == VRR_GAME_GTA_IV) {
+ //natives.changePlayerModel(natives.getPlayerId(), allowedSkins[skinSelectorIndex][0]);
+ localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ } else {
+ localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ }
} else if(keyCode == SDLK_PAGEDOWN) {
if(skinSelectorIndex <= 0) {
skinSelectorIndex = allowedSkins.length-1;
@@ -62,13 +67,18 @@ function processSkinSelectKeyPress(keyCode) {
}
logToConsole(LOG_DEBUG, `Switching to skin ${allowedSkins[skinSelectorIndex][1]} (Index: ${skinSelectorIndex}, Skin: ${allowedSkins[skinSelectorIndex][0]})`);
skinSelectMessageTextTop = allowedSkins[skinSelectorIndex][1];
- localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ if(getGame() == VRR_GAME_GTA_IV) {
+ //natives.changePlayerModel(natives.getPlayerId(), allowedSkins[skinSelectorIndex][0]);
+ localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ } else {
+ localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ }
} else if(keyCode == SDLK_RETURN) {
- triggerNetworkEvent("vrr.skinSelected", skinSelectorIndex);
+ sendNetworkEventToServer("vrr.skinSelected", skinSelectorIndex);
toggleSkinSelect(false);
return true;
} else if(keyCode == SDLK_BACKSPACE) {
- triggerNetworkEvent("vrr.skinSelected", -1);
+ sendNetworkEventToServer("vrr.skinSelected", -1);
toggleSkinSelect(false);
return true;
}
@@ -109,22 +119,18 @@ function toggleSkinSelect(state) {
game.setCameraLookAt(frontCameraPosition, localPlayer.position, true);
}
- localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ if(getGame() == VRR_GAME_GTA_IV) {
+ //natives.changePlayerModel(natives.getPlayerId(), allowedSkins[skinSelectorIndex][0]);
+ localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ } else {
+ localPlayer.skin = allowedSkins[skinSelectorIndex][0];
+ }
+
skinSelectMessageTextTop = allowedSkins[skinSelectorIndex][1];
- gui.showCursor(true, false);
- //localPlayer.invincible = true;
- //localPlayer.setProofs(true, true, true, true, true);
- localPlayer.collisionsEnabled = false;
-
+ setLocalPlayerControlState(false, false);
} else {
usingSkinSelector = false;
- //game.restoreCamera(true);
- gui.showCursor(false, true);
- if(localPlayer) {
- //localPlayer.invincible = false;
- //localPlayer.setProofs(false, false, false, false, false);
- localPlayer.collisionsEnabled = true;
- }
+ setLocalPlayerControlState(false, false);
}
}
diff --git a/scripts/client/sync.js b/scripts/client/sync.js
index 11a06bec..3da59074 100644
--- a/scripts/client/sync.js
+++ b/scripts/client/sync.js
@@ -10,13 +10,13 @@
function processSync(event, deltaTime) {
if(localPlayer != null) {
if(!areServerElementsSupported()) {
- triggerNetworkEvent("vrr.player.position", localPlayer.position);
- triggerNetworkEvent("vrr.player.heading", localPlayer.heading);
+ sendNetworkEventToServer("vrr.player.position", localPlayer.position);
+ sendNetworkEventToServer("vrr.player.heading", localPlayer.heading);
}
//if(game.game == VRR_GAME_GTA_SA) {
// let lookAtPos = getLocalPlayerLookAtPosition();
- // triggerNetworkEvent("vrr.player.lookat", lookAtPos);
+ // sendNetworkEventToServer("vrr.player.lookat", lookAtPos);
// setEntityData(localPlayer, "vrr.headLook", lookAtPos);
// let peds = getPeds();
// for(let i in peds) {
@@ -31,7 +31,7 @@ function processSync(event, deltaTime) {
logToConsole(LOG_DEBUG, `Local player died`);
localPlayer.clearWeapons();
calledDeathEvent = true;
- triggerNetworkEvent("vrr.playerDeath");
+ sendNetworkEventToServer("vrr.playerDeath");
}
}
@@ -84,33 +84,43 @@ function syncVehicleProperties(vehicle) {
}
}
- //if(doesEntityDataExist(vehicle, "vrr.panelStatus")) {
- // let panelsStatus = getEntityData(vehicle, "vrr.panelStatus");
- // for(let i in panelsStatus) {
- // vehicle.setPanelStatus(i, panelsStatus[i]);
- // }
- //}
+ if(doesEntityDataExist(vehicle, "vrr.invincible")) {
+ let invincible = getEntityData(vehicle, "vrr.invincible");
+ element.setProofs(invincible, invincible, invincible, invincible, invincible);
+ }
- //if(doesEntityDataExist(vehicle, "vrr.wheelStatus")) {
- // let wheelsStatus = getEntityData(vehicle, "vrr.wheelStatus");
- // for(let i in wheelsStatus) {
- // vehicle.setWheelStatus(i, wheelsStatus[i]);
- // }
- //}
+ if(doesEntityDataExist(vehicle, "vrr.panelStatus")) {
+ let panelsStatus = getEntityData(vehicle, "vrr.panelStatus");
+ for(let i in panelsStatus) {
+ vehicle.setPanelStatus(i, panelsStatus[i]);
+ }
+ }
- //if(doesEntityDataExist(vehicle, "vrr.lightStatus")) {
- // let lightStatus = getEntityData(vehicle, "vrr.lightStatus");
- // for(let i in lightStatus) {
- // vehicle.setLightStatus(i, lightStatus[i]);
- // }
- //}
+ if(doesEntityDataExist(vehicle, "vrr.wheelStatus")) {
+ let wheelsStatus = getEntityData(vehicle, "vrr.wheelStatus");
+ for(let i in wheelsStatus) {
+ vehicle.setWheelStatus(i, wheelsStatus[i]);
+ }
+ }
- //if(doesEntityDataExist(vehicle, "vrr.suspensionHeight")) {
- // let suspensionHeight = getEntityData(vehicle, "vrr.suspensionHeight");
- // vehicle.setSuspensionHeight(suspensionHeight);
- //}
+ if(doesEntityDataExist(vehicle, "vrr.lightStatus")) {
+ let lightStatus = getEntityData(vehicle, "vrr.lightStatus");
+ for(let i in lightStatus) {
+ vehicle.setLightStatus(i, lightStatus[i]);
+ }
+ }
+
+ if(doesEntityDataExist(vehicle, "vrr.suspensionHeight")) {
+ let suspensionHeight = getEntityData(vehicle, "vrr.suspensionHeight");
+ vehicle.setSuspensionHeight(suspensionHeight);
+ }
if(getGame() == VRR_GAME_GTA_SA) {
+ let allUpgrades = getGameData().vehicleUpgrades[getGame()];
+ for(let i in allUpgrades) {
+ vehicle.removeUpgrade(i);
+ }
+
if(doesEntityDataExist(vehicle, "vrr.upgrades")) {
let upgrades = getEntityData(vehicle, "vrr.upgrades");
for(let i in upgrades) {
@@ -131,18 +141,6 @@ function syncVehicleProperties(vehicle) {
}
}
}
-
- if(getGame() == VRR_GAME_GTA_III) {
- if(vehicle.isOwner && vehicle.modelIndex == 116) {
- vehicle.colour1 = 0;
- vehicle.colour2 = 1;
- }
- } else if(getGame() == VRR_GAME_GTA_VC) {
- if(vehicle.isOwner && vehicle.modelIndex == 156) {
- vehicle.colour1 = 0;
- vehicle.colour2 = 1;
- }
- }
}
// ===========================================================================
diff --git a/scripts/client/utilities.js b/scripts/client/utilities.js
index ceeae35a..ed0abb08 100644
--- a/scripts/client/utilities.js
+++ b/scripts/client/utilities.js
@@ -184,11 +184,14 @@ function setLocalPlayerFrozenState(state) {
function setLocalPlayerControlState(controlState, cursorState = false) {
logToConsole(LOG_DEBUG, `[VRR.Utilities] Setting control state to ${controlState} (Cursor: ${cursorState})`);
controlsEnabled = controlState;
- //localPlayer.invincible = true;
- //if(getGame() != VRR_GAME_GTA_IV) {
- // localPlayer.collisionsEnabled = controlState;
- // localPlayer.invincible = false;
- //}
+ if(getGame() == VRR_GAME_GTA_III || getGame() == VRR_GAME_GTA_VC) {
+ game.SET_PLAYER_CONTROL(localClient.index, boolToInt(controlState));
+ }
+
+ if(getGame() != VRR_GAME_GTA_IV) {
+ localPlayer.collisionsEnabled = controlState;
+ localPlayer.invincible = true;
+ }
}
// ===========================================================================
@@ -261,10 +264,10 @@ function runClientCode(code, returnTo) {
try {
returnValue = eval("(" + code + ")");
} catch(error) {
- triggerNetworkEvent("vrr.runCodeFail", returnTo, code);
+ sendNetworkEventToServer("vrr.runCodeFail", returnTo, code);
return false;
}
- triggerNetworkEvent("vrr.runCodeSuccess", returnTo, code, returnValue);
+ sendNetworkEventToServer("vrr.runCodeSuccess", returnTo, code, returnValue);
}
// ===========================================================================
@@ -282,26 +285,21 @@ function enterVehicleAsPassenger() {
function giveLocalPlayerWeapon(weaponId, ammo, active) {
logToConsole(LOG_DEBUG, `[VRR.Utilities] Giving weapon ${weaponId} with ${ammo} ammo`);
- localPlayer.giveWeapon(weaponId, ammo, active);
- forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(weaponId));
- forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(weaponId));
forceWeapon = weaponId;
-}
-
-// ===========================================================================
-
-function giveLocalPlayerWeapon(weaponId, ammo, active) {
- logToConsole(LOG_DEBUG, `[VRR.Utilities] Giving weapon ${weaponId} with ${ammo} ammo`);
if(getGame() == VRR_GAME_MAFIA_ONE) {
localPlayer.giveWeapon(weaponId, 0, ammo);
forceWeaponAmmo = 0;
forceWeaponClipAmmo = ammo;
} else {
localPlayer.giveWeapon(weaponId, ammo, active);
- forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(weaponId));
- forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(weaponId));
+ if(getGame() < VRR_GAME_GTA_IV) {
+ forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(weaponId));
+ forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(weaponId));
+ } else {
+ forceWeaponAmmo = ammo;
+ forceWeaponClipAmmo = ammo;
+ }
}
- forceWeapon = weaponId;
}
// ===========================================================================
@@ -542,17 +540,19 @@ function processWantedLevelReset() {
}
if(typeof localPlayer.wantedLevel != "undefined") {
- localPlayer.wantedLevel = 0;
+ localPlayer.wantedLevel = forceWantedLevel;
}
}
// ===========================================================================
function processLocalPlayerVehicleControlState() {
- let position = getLocalPlayerPosition();
-
if(areServerElementsSupported()) {
if(inVehicle && localPlayer.vehicle != null) {
+ if(getEntityData(localPlayer.vehicle, "vrr.engine") == false) {
+ localPlayer.vehicle.engine = false;
+ }
+
if(!localPlayer.vehicle.engine) {
if(typeof localPlayer.vehicle.velocity != "undefined") {
localPlayer.vehicle.velocity = toVector3(0.0, 0.0, 0.0);
@@ -600,8 +600,8 @@ function processLocalPlayerSphereEntryExitHandling() {
function processJobRouteSphere() {
if(game.game == VRR_GAME_GTA_SA) {
let position = getLocalPlayerPosition();
- if(jobRouteStopSphere != null) {
- if(getDistance(position, jobRouteStopSphere.position) <= 2.0) {
+ if(jobRouteLocationSphere != null) {
+ if(getDistance(position, jobRouteLocationSphere.position) <= 2.0) {
enteredJobRouteSphere();
}
}
@@ -615,11 +615,15 @@ function forceLocalPlayerEquippedWeaponItem() {
if(forceWeapon != 0) {
if(localPlayer.weapon != forceWeapon) {
localPlayer.weapon = forceWeapon;
- localPlayer.setWeaponClipAmmunition(getWeaponSlot(forceWeapon), forceWeaponClipAmmo);
- localPlayer.setWeaponAmmunition(getWeaponSlot(forceWeapon), forceWeaponAmmo);
+ if(getGame() <= VRR_GAME_GTA_IV) {
+ localPlayer.setWeaponClipAmmunition(getWeaponSlot(forceWeapon), forceWeaponClipAmmo);
+ localPlayer.setWeaponAmmunition(getWeaponSlot(forceWeapon), forceWeaponAmmo);
+ }
} else {
- forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(forceWeapon));
- forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(forceWeapon));
+ if(getGame() <= VRR_GAME_GTA_IV) {
+ forceWeaponClipAmmo = localPlayer.getWeaponClipAmmunition(getWeaponSlot(forceWeapon));
+ forceWeaponAmmo = localPlayer.getWeaponAmmunition(getWeaponSlot(forceWeapon));
+ }
}
} else {
if(localPlayer.weapon > 0) {
@@ -731,7 +735,7 @@ function processNearbyPickups() {
//if(pickups[i].interior == localPlayer.interior && pickups[i].dimension == localPlayer.dimension) {
if(currentPickup != pickups[i]) {
currentPickup = pickups[i];
- triggerNetworkEvent("vrr.pickup", pickups[i].id);
+ sendNetworkEventToServer("vrr.pickup", pickups[i].id);
}
//}
}
@@ -746,14 +750,19 @@ function setUpInitialGame() {
game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
game.setGameStat(STAT_PROGRESSMADE, 9999);
game.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
+ game.SET_CAR_DENSITY_MULTIPLIER(3.0);
+ game.SET_PED_DENSITY_MULTIPLIER(3.0);
game.onMission = true;
+ SetStandardControlsEnabled(true);
return true;
}
if(getGame() == VRR_GAME_GTA_VC) {
game.SET_PLAYER_NEVER_GETS_TIRED(game.GET_PLAYER_ID(), 0);
- game.setGameStat(STAT_PROGRESSMADE, 0);
- game.setGameStat(STAT_TOTALPROGRESSINGAME, 0);
+ game.setGameStat(STAT_PROGRESSMADE, 9999);
+ game.setGameStat(STAT_TOTALPROGRESSINGAME, 9999);
+ game.SET_CAR_DENSITY_MULTIPLIER(3.0);
+ game.SET_PED_DENSITY_MULTIPLIER(3.0);
game.REQUEST_ANIMATION("bikev");
game.REQUEST_ANIMATION("bikeh");
@@ -779,6 +788,7 @@ function setUpInitialGame() {
game.LOAD_ALL_MODELS_NOW();
game.onMission = true;
+ SetStandardControlsEnabled(true);
return true;
}
@@ -787,14 +797,14 @@ function setUpInitialGame() {
game.setGameStat(STAT_WEAPONTYPE_PISTOL_SILENCED_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_DESERT_EAGLE_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_SHOTGUN_SKILL, 400);
- game.setGameStat(STAT_WEAPONTYPE_SAWNOFF_SHOTGUN_SKILL, 1);
+ game.setGameStat(STAT_WEAPONTYPE_SAWNOFF_SHOTGUN_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_SPAS12_SHOTGUN_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_MICRO_UZI_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_MP5_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_AK47_SKILL, 400);
game.setGameStat(STAT_WEAPONTYPE_M4_SKILL, 400);
game.setGameStat(STAT_DRIVING_SKILL, 9999);
- game.setGameStat(STAT_FAT, 0);
+ game.setGameStat(STAT_FAT, 9999);
game.setGameStat(STAT_ENERGY, 9999);
game.setGameStat(STAT_CYCLE_SKILL, 9999);
game.setGameStat(STAT_BIKE_SKILL, 9999);
@@ -804,9 +814,9 @@ function setUpInitialGame() {
game.setGameStat(STAT_RESPECT_TOTAL, 0);
game.setGameStat(STAT_SEX_APPEAL, 0);
game.setGameStat(STAT_STAMINA, 9999);
- game.setGameStat(STAT_TOTAL_PROGRESS, 100);
+ game.setGameStat(STAT_TOTAL_PROGRESS, 9999);
game.setGameStat(STAT_UNDERWATER_STAMINA, 9999);
- game.setGameStat(STAT_BODY_MUSCLE, 0);
+ game.setGameStat(STAT_BODY_MUSCLE, 9999);
game.setDefaultInteriors(false);
game.onMission = true;
@@ -814,7 +824,7 @@ function setUpInitialGame() {
}
if(getGame() == VRR_GAME_GTA_IV) {
- natives.allowEmergencyServices(true);
+ natives.allowEmergencyServices(false);
natives.setCreateRandomCops(true);
natives.setMaxWantedLevel(0);
natives.setWantedMultiplier(0.0);
@@ -826,13 +836,13 @@ function setUpInitialGame() {
natives.setPlayersDropMoneyInNetworkGame(false);
natives.setSyncWeatherAndGameTime(false);
natives.usePlayerColourInsteadOfTeamColour(true);
- natives.setDisplayPlayerNameAndIcon(false);
+ natives.setDisplayPlayerNameAndIcon(natives.getPlayerId(), false);
natives.removeTemporaryRadarBlipsForPickups();
natives.setPickupsFixCars(false);
- natives.displayCash(true);
- natives.displayAmmo(true);
- natives.displayHud(true);
- natives.displayAreaName(true);
+ natives.displayCash(false);
+ natives.displayAmmo(false);
+ natives.displayHud(false);
+ natives.displayAreaName(false);
natives.setPoliceRadarBlips(false);
natives.requestAnims("DANCING");
@@ -861,18 +871,18 @@ function processGameSpecifics() {
function processVehiclePurchasing() {
if(vehiclePurchaseState == VRR_VEHBUYSTATE_TESTDRIVE) {
if(inVehicle == false) {
- vehiclePurchaseState = VRR_VEHBUYSTATE_EXITEDVEH;
- triggerNetworkEvent("vrr.vehBuyState", VRR_VEHBUYSTATE_EXITEDVEH);
+ vehiclePurchaseState = VRR_VEHBUYSTATE_EXITVEH;
+ sendNetworkEventToServer("vrr.vehBuyState", VRR_VEHBUYSTATE_EXITVEH);
return false;
} else {
- if(vehiclePurchasing.id == inVehicle) {
+ if(vehiclePurchasing == inVehicle) {
if(getDistance(inVehicle.position, vehiclePurchasePosition) >= 25) {
vehiclePurchaseState = VRR_VEHBUYSTATE_FARENOUGH;
- triggerNetworkEvent("vrr.vehBuyState", VRR_VEHBUYSTATE_FARENOUGH);
+ sendNetworkEventToServer("vrr.vehBuyState", VRR_VEHBUYSTATE_FARENOUGH);
}
} else {
vehiclePurchaseState = VRR_VEHBUYSTATE_WRONGVEH;
- triggerNetworkEvent("vrr.vehBuyState", VRR_VEHBUYSTATE_WRONGVEH);
+ sendNetworkEventToServer("vrr.vehBuyState", VRR_VEHBUYSTATE_WRONGVEH);
}
}
}
@@ -880,10 +890,16 @@ function processVehiclePurchasing() {
// ===========================================================================
-function setVehiclePurchaseState(state, vehicle, position) {
+function setVehiclePurchaseState(state, vehicleId, position) {
vehiclePurchaseState = state;
+
+ if(vehicleId != null) {
+ vehiclePurchasing = getElementFromId(vehicleId);
+ } else {
+ vehiclePurchasing = null;
+ }
+
vehiclePurchasePosition = position;
- vehiclePurchasing = vehicle;
}
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/accent.js b/scripts/server/accent.js
index c1f683e8..6b76c45e 100644
--- a/scripts/server/accent.js
+++ b/scripts/server/accent.js
@@ -59,9 +59,9 @@ function setAccentCommand(command, params, client) {
// ===========================================================================
function listAccentsCommand(command, params, client) {
- let stationList = getGlobalConfig().accents;
+ let accentList = getGlobalConfig().accents;
- let chunkedList = splitArrayIntoChunks(stationList, 8);
+ let chunkedList = splitArrayIntoChunks(accentList, 8);
messagePlayerInfo(client, `{clanOrange}== {jobYellow}Accents {clanOrange}==================================`);
@@ -70,4 +70,69 @@ function listAccentsCommand(command, params, client) {
}
}
+// ===========================================================================
+
+function getAccentFromParams(params) {
+ if(isNaN(params)) {
+ for(let i in getGlobalConfig().accents) {
+ if(toLowerCase(getGlobalConfig().accents[i]).indexOf(toLowerCase(params)) != -1) {
+ return i;
+ }
+ }
+ } else {
+ if(typeof getGlobalConfig().accents[params] != "undefined") {
+ return toInteger(params);
+ }
+ }
+
+ return false;
+}
+
+// ===========================================================================
+
+function reloadAccentConfigurationCommand(command, params, client) {
+ getGlobalConfig().accents = loadAccentConfig();
+ messageAdmins(`${client.name} {MAINCOLOUR}has reloaded the accent list`);
+}
+
+// ===========================================================================
+
+function addAccentCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let newAccentName = params;
+
+ if(getAccentFromParams(newAccentName) != false) {
+ messagePlayerError(client, `That accent already exists!`)
+ return false;
+ }
+
+ getGlobalConfig().accents.push(newAccentName);
+ saveAccentConfig();
+ messageAdmins(`${client.name} {MAINCOLOUR}added a new accent: ${newAccentName}`);
+}
+
+// ===========================================================================
+
+function removeAccentCommand(command, params, client) {
+ if(areParamsEmpty(params)) {
+ messagePlayerSyntax(client, getCommandSyntaxText(command));
+ return false;
+ }
+
+ let newAccentName = params;
+
+ if(!getAccentFromParams(newAccentName)) {
+ messagePlayerError(client, `That accent doesn't exist!`)
+ return false;
+ }
+
+ getGlobalConfig().accents.push(newAccentName);
+ saveAccentConfig();
+ messageAdmins(`${client.name} {MAINCOLOUR}added a new accent: ${newAccentName}`);
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/account.js b/scripts/server/account.js
index c12f2b7d..ff9764c5 100644
--- a/scripts/server/account.js
+++ b/scripts/server/account.js
@@ -16,7 +16,7 @@ function initAccountScript() {
function loginCommand(command, params, client) {
if(!isPlayerRegistered(client)) {
- messagePlayerError(client, "Your name is not registered! Use /register to make an account.");
+ messagePlayerError(client, getLocaleString(client, "NameNotRegistered"));
return false;
}
@@ -36,10 +36,10 @@ function toggleAutoLoginByIPCommand(command, params, client) {
if(hasBitFlag(getPlayerData(client).accountData.settings, flagValue)) {
getPlayerData(client).accountData.settings = removeBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerSuccess(client, `Automatic login by IP is now {softRed}OFF {white}`);
+ messagePlayerSuccess(client, getLocaleString(client, "AutomaticLoginIPToggle", `{softRed}${toUpperCase(getLocaleString(client, "Off"))}`));
} else {
getPlayerData(client).accountData.settings = addBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerSuccess(client, `Automatic login by IP is now {softGreen}ON {white}(${client.ip})`);
+ messagePlayerSuccess(client, getLocaleString(client, "AutomaticLoginIPToggle", `{softGreen}${toUpperCase(getLocaleString(client, "On"))}`));
}
return true;
}
@@ -51,10 +51,10 @@ function toggleNoRandomTipsCommand(command, params, client) {
if(hasBitFlag(getPlayerData(client).accountData.settings, flagValue)) {
getPlayerData(client).accountData.settings = removeBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerSuccess(client, `Random tips are now {softRed}OFF`);
+ messagePlayerSuccess(client, getLocaleString(client, "RandomTipsToggle", `{softRed}${toUpperCase(getLocaleString(client, "Off"))}`));
} else {
getPlayerData(client).accountData.settings = addBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerSuccess(client, `Random tips are now {softGreen}ON`);
+ messagePlayerSuccess(client, getLocaleString(client, "RandomTipsToggle", `{softGreen}${toUpperCase(getLocaleString(client, "On"))}`));
}
return true;
}
@@ -66,10 +66,10 @@ function toggleNoActionTipsCommand(command, params, client) {
if(hasBitFlag(getPlayerData(client).accountData.settings, flagValue)) {
getPlayerData(client).accountData.settings = removeBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerSuccess(client, `Action tips are now {softRed}OFF`);
+ messagePlayerSuccess(client, getLocaleString(client, "ActionTipsToggle", `{softRed}${toUpperCase(getLocaleString(client, "Off"))}`));
} else {
getPlayerData(client).accountData.settings = addBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerSuccess(client, `Action tips are now {softGreen}ON`);
+ messagePlayerSuccess(client, getLocaleString(client, "ActionTipsToggle", `{softGreen}${toUpperCase(getLocaleString(client, "On"))}`));
}
return true;
}
@@ -81,10 +81,10 @@ function toggleAutoSelectLastCharacterCommand(command, params, client) {
if(hasBitFlag(getPlayerData(client).accountData.settings, flagValue)) {
getPlayerData(client).accountData.settings = removeBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerSuccess(client, `Automatic spawn as last used character is now {softRed}OFF`);
+ messagePlayerSuccess(client, getLocaleString(client, "AutoSpawnLastCharToggle", `{softRed}${toUpperCase(getLocaleString(client, "Off"))}`));
} else {
getPlayerData(client).accountData.settings = addBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerSuccess(client, `Automatic spawn as last used character is now {softGreen}ON`);
+ messagePlayerSuccess(client, getLocaleString(client, "AutoSpawnLastCharToggle", `{softGreen}${toUpperCase(getLocaleString(client, "On"))}`));
}
return true;
}
@@ -96,17 +96,17 @@ function toggleAccountGUICommand(command, params, client) {
if(!doesPlayerHaveGUIEnabled(client)) {
getPlayerData(client).accountData.settings = removeBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerNormal(client, `⚙️ GUI is now {softGreen}ON. {white}(if server has it enabled)`);
+ messagePlayerNormal(client, getLocaleString(client, "GUIAccountSettingToggle", `{softRed}${toUpperCase(getLocaleString(client, "Off"))}`));
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} has toggled GUI for their account ON.`);
} else {
getPlayerData(client).accountData.settings = addBitFlag(getPlayerData(client).accountData.settings, flagValue);
- messagePlayerNormal(client, `⚙️ GUI is now {softRed}OFF. {white}(Any GUI stuff will be use via commands and message in the chatbox)`);
- logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} has toggled GUI for their account OFF.`);
+ messagePlayerNormal(client, getLocaleString(client, "GUIAccountSettingToggle", `{softGreen}${toUpperCase(getLocaleString(client, "On"))}`));
+ logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} has toggled GUI for their account ON.`);
}
if(!isPlayerLoggedIn(client)) {
if(getPlayerData().accountData.databaseId != 0) {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
showPlayerLoginGUI(client);
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the login GUI`);
} else {
@@ -115,7 +115,7 @@ function toggleAccountGUICommand(command, params, client) {
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the login message (GUI disabled)`);
}
} else {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
showPlayerRegistrationGUI(client);
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the register GUI`);
} else {
@@ -170,34 +170,30 @@ function toggleAccountServerLogoCommand(command, params, client) {
// ===========================================================================
-// UNFINISHED!
-// TO-DO: Make GUI, add command to generate code to add to auth app and command to input code returned by auth app
function toggleAccountTwoFactorAuthCommand(command, params, client) {
let flagValue = getAccountSettingsFlagValue("TwoStepAuth");
if(getEmailConfig().enabled) {
- if(getPlayerData(client).accountData.emailAddress != "") {
- messagePlayerError(client, `You need to add your email to your account to use two-factor authentication.`);
- messagePlayerTip(client, `{MAINCOLOUR}Use {ALTCOLOUR}/setemail {MAINCOLOUR}to add your email.`);
+ if(getPlayerData(client).accountData.emailAddress == "") {
+ messagePlayerError(client, getLocaleString(client, "NeedEmailFor2FA"));
+ messagePlayerTip(client, getLocaleString(client, "SetEmailHelpTip", `{ALTCOLOUR}/setemail{MAINCOLOUR}`));
return false;
}
- if(isAccountEmailVerified(getPlayerData(client).accountData)) {
- messagePlayerError(client, `You need to verify your email to your account to use two-factor authentication.`);
- messagePlayerTip(client, `{MAINCOLOUR}Use {ALTCOLOUR}/verifyemail {MAINCOLOUR}to verify your email.`);
+ if(!isAccountEmailVerified(getPlayerData(client).accountData)) {
+ messagePlayerError(client, getLocaleString(client, "NeedEmailVerifiedFor2FA"));
+ messagePlayerTip(client, getLocaleString(client, "VerifyEmailHelpTip", `{ALTCOLOUR}/verifyemail{MAINCOLOUR}`));
return false;
}
}
if(!doesPlayerHaveTwoFactorAuthEnabled(client)) {
- getPlayerData(client).accountData.settings = removeBitFlag(getPlayerData(client).accountData.settings, flagValue);
+ getPlayerData(client).accountData.settings = addBitFlag(getPlayerData(client).accountData.settings, flagValue);
messagePlayerSuccess(client, `{MAINCOLOUR}You have turned ${getBoolRedGreenInlineColour(false)}ON {MAINCOLOUR} two factor authentication!{ALTCOLOUR}${addtoAuthenticatorCode}`);
- messagePlayerAlert(client, `You will be required to enter a code sent to your email every time you log on.`);
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} has toggled two-factor authentication ON for their account`);
} else {
- getPlayerData(client).accountData.settings = addBitFlag(getPlayerData(client).accountData.settings, flagValue);
+ getPlayerData(client).accountData.settings = removeBitFlag(getPlayerData(client).accountData.settings, flagValue);
messagePlayerSuccess(client, `You have turned ${getBoolRedGreenInlineColour(false)}OFF {MAINCOLOUR}two-factor authentication for login.`);
- messagePlayerAlert(client, `You won't be required to enter a code sent to your email every time you log on anymore.`);
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} has toggled two-factor authentication OFF for their account`);
}
return true;
@@ -230,11 +226,10 @@ function changeAccountPasswordCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
- let oldPassword = splitParams[0];
- let newPassword = splitParams[1];
+ let oldPassword = getParam(params, " ", 1);
+ let newPassword = getParam(params, " ", 2);
- if(isAccountPasswordCorrect(getPlayerData(client).accountData, hashAccountPassword(getPlayerName(client), oldPassword))) {
+ if(isAccountPasswordCorrect(getPlayerData(client).accountData, hashAccountPassword(getPlayerData(client).accountData.name, oldPassword))) {
messagePlayerError(client, `The old password is invalid!`);
return false;
}
@@ -282,8 +277,7 @@ function setAccountEmailCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
- let emailAddress = splitParams[0];
+ let emailAddress = getParam(params, " ", 1);
if(!isValidEmailAddress(emailAddress)) {
messagePlayerError(client, `The email '${emailAddress} is not valid!`);
@@ -320,8 +314,7 @@ function verifyAccountEmailCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
- let verificationCode = splitParams[0];
+ let verificationCode = getParam(params, " ", 1);
if(isAccountEmailVerified(getPlayerData(client).accountData)) {
messagePlayerError(client, `You already verified your email!`);
@@ -353,8 +346,7 @@ function resetAccountPasswordCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
- let verificationCode = splitParams[0] || "";
+ let verificationCode = getParam(params, " ", 1) || "";
if(!isAccountEmailVerified(getPlayerData(client).accountData)) {
messagePlayerError(client, `Your email is not verified. Your password will not be reset!`);
@@ -386,8 +378,7 @@ function setAccountDiscordCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
- let discordName = splitParams[0];
+ let discordName = getParam(params, " ", 1);
if(!isValidEmailAddress(emailAddress)) {
messagePlayerError(client, `The discord '${discordName} is not valid!`);
@@ -459,7 +450,6 @@ function loadAccountFromName(accountName, fullLoad = false) {
let dbAssoc = fetchQueryAssoc(dbQuery);
let tempAccountData = new AccountData(dbAssoc);
if(fullLoad) {
- tempAccountData.keyBinds = loadAccountKeybindsFromDatabase(tempAccountData.databaseId);
tempAccountData.messages = loadAccountMessagesFromDatabase(tempAccountData.databaseId);
tempAccountData.notes = loadAccountStaffNotesFromDatabase(tempAccountData.databaseId);
tempAccountData.contacts = loadAccountContactsFromDatabase(tempAccountData.databaseId);
@@ -486,7 +476,6 @@ function loadAccountFromId(accountId, fullLoad = false) {
let tempAccountData = new AccountData(dbAssoc);
freeDatabaseQuery(dbQuery);
if(fullLoad) {
- tempAccountData.keyBinds = loadAccountKeybindsFromDatabase(tempAccountData.databaseId);
tempAccountData.messages = loadAccountMessagesFromDatabase(tempAccountData.databaseId);
tempAccountData.notes = loadAccountStaffNotesFromDatabase(tempAccountData.databaseId);
tempAccountData.contacts = loadAccountContactsFromDatabase(tempAccountData.databaseId);
@@ -577,13 +566,31 @@ function loginSuccess(client) {
client.administrator = true;
}
+ if(doesServerHaveTesterOnlyEnabled()) {
+ if(!hasBitFlag(getPlayerData(client).accountData.flags.moderation, getModerationFlagValue("IsTester"))) {
+ setTimeout(function() {
+ client.disconnect();
+ }, 3500);
+
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
+ logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the error GUI (not a tester).`);
+ showPlayerErrorGUI(client, getLocaleString(client, "NotATester"), getLocaleString(client, "AccessDenied"));
+ return false;
+ } else {
+ logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the "not a tester" error message (GUI disabled).`);
+ messagePlayerError(client, getLocaleString(client, "NotATester"));
+ return false;
+ }
+ }
+ }
+
if(getPlayerData(client).subAccounts.length == 0) {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
- showPlayerPromptGUI(client, `You have no characters. Would you like to make one?`, "No characters");
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
+ showPlayerPromptGUI(client, getLocaleString(client, "NoCharactersGUIMessage"), getLocaleString(client, "NoCharactersGUIWindowTitle"));
getPlayerData(client).promptType = VRR_PROMPT_CREATEFIRSTCHAR;
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the no characters prompt GUI`);
} else {
- messagePlayerAlert(client, `You have no characters. Use /newchar to make one.`);
+ messagePlayerAlert(client, getLocaleString(client, "NoCharactersChatMessage", `{ALTCOLOUR}/newchar{MAINCOLOUR}`));
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the no characters message (GUI disabled)`);
}
} else {
@@ -621,6 +628,7 @@ function saveAccountToDatabase(accountData) {
["acct_code_verifyemail", accountData.emailVerificationCode],
["acct_streaming_radio_volume", accountData.streamingRadioVolume],
["acct_ip", accountData.ipAddress],
+ ["acct_locale", accountData.locale],
];
let data2 = [
@@ -749,10 +757,10 @@ function createAccount(name, password, email = "") {
if(getDatabaseInsertId(dbConnection) > 0) {
let tempAccountData = loadAccountFromId(getDatabaseInsertId(dbConnection), false);
createDefaultAccountServerData(tempAccountData.databaseId);
- tempAccountData.keyBinds = loadAccountKeybindsFromDatabase(tempAccountData.databaseId);
tempAccountData.messages = loadAccountMessagesFromDatabase(tempAccountData.databaseId);
tempAccountData.notes = loadAccountStaffNotesFromDatabase(tempAccountData.databaseId);
tempAccountData.contacts = loadAccountContactsFromDatabase(tempAccountData.databaseId);
+ tempAccountData.flags.admin = 0;
return tempAccountData;
}
}
@@ -770,7 +778,7 @@ function checkLogin(client, password) {
if(isPlayerLoggedIn(client)) {
logToConsole(LOG_WARN, `[VRR.Account] ${getPlayerDisplayForConsole(client)} attempted to login but is already logged in`);
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
showPlayerLoginSuccessGUI(client);
} else {
messagePlayerError(client, "You are already logged in!");
@@ -781,7 +789,7 @@ function checkLogin(client, password) {
if(!isPlayerRegistered(client)) {
logToConsole(LOG_WARN, `[VRR.Account] ${getPlayerDisplayForConsole(client)} attempted to login but is not registered`);
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
showPlayerRegistrationGUI(client);
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the register GUI`);
} else {
@@ -793,7 +801,7 @@ function checkLogin(client, password) {
if(areParamsEmpty(password)) {
logToConsole(LOG_WARN, `[VRR.Account] ${getPlayerDisplayForConsole(client)} attempted to login but failed (empty password). ${getPlayerData(client).loginAttemptsRemaining} login attempts remaining`);
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
showPlayerLoginFailedGUI(client, `Invalid password! ${getPlayerData(client).loginAttemptsRemaining} tries remaining.`);
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the login GUI with ${getPlayerData(client).loginAttemptsRemaining} login attempts remaining alert.`);
} else {
@@ -809,7 +817,7 @@ function checkLogin(client, password) {
if(!isAccountPasswordCorrect(getPlayerData(client).accountData, hashAccountPassword(getPlayerName(client), password))) {
logToConsole(LOG_WARN, `[VRR.Account] ${getPlayerDisplayForConsole(client)} attempted to login but failed (wrong password). ${getPlayerData(client).loginAttemptsRemaining} login attempts remaining`);
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
showPlayerLoginFailedGUI(client, `Invalid password! ${getPlayerData(client).loginAttemptsRemaining} tries remaining.`);
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the login GUI with ${getPlayerData(client).loginAttemptsRemaining} login attempts remaining alert.`);
} else {
@@ -823,7 +831,13 @@ function checkLogin(client, password) {
return false;
}
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ //if(doesPlayerHaveTwoFactorAuthEnabled(client)) {
+ // getPlayerData(client).twoFactorAuthCode = toUpperCase(generateRandomString(6));
+ // showPlayerTwoFactorAuthenticationGUI(client);
+ // return true;
+ //}
+
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
showPlayerLoginSuccessGUI(client);
}
@@ -840,76 +854,84 @@ function checkRegistration(client, password, confirmPassword = "", emailAddress
logToConsole(LOG_DEBUG, `[VRR.Account]: Checking registration for ${getPlayerName(client)}`);
if(isPlayerRegistered(client)) {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
showPlayerLoginGUI(client);
} else {
- messagePlayerError(client, "Your name is already registered!");
+ messagePlayerError(client, getLocaleString(client, "AlreadyRegistered"));
+ logToConsole(LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to create an account (already registered)`);
}
return false;
}
if(isPlayerLoggedIn(client)) {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
showPlayerLoginSuccessGUI(client);
} else {
- messagePlayerError(client, "You are already logged in!");
+ messagePlayerError(client, getLocaleString(client, "AlreadyLoggedIn"));
+ logToConsole(LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to create an account (already logged in)`);
}
return false;
}
if(areParamsEmpty(password)) {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
- showPlayerRegistrationFailedGUI(client, "Password cannot be blank!");
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
+ showPlayerRegistrationFailedGUI(client, getLocaleString(client, "RegistrationFailedNoPassword"));
+ logToConsole(LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to create an account (password is blank)`);
} else {
messagePlayerError(client, "The password cannot be blank!");
+ logToConsole(LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to create an account (password is blank)`);
}
return false;
}
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
if(areParamsEmpty(confirmPassword)) {
- showPlayerRegistrationFailedGUI(client, "Password confirm cannot be blank!");
+ showPlayerRegistrationFailedGUI(client, getLocaleString(client, "RegistrationFailedNoPasswordConfirm"));
+ logToConsole(LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to create an account (password confirm is blank)`);
return false;
}
}
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
if(areParamsEmpty(emailAddress)) {
- showPlayerRegistrationFailedGUI(client, "Email address cannot be blank!");
+ showPlayerRegistrationFailedGUI(client, getLocaleString(client, "RegistrationFailedNoEmail"));
+ logToConsole(LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to create an account (email address is blank)`);
return false;
}
}
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
if(password != confirmPassword) {
- showPlayerRegistrationFailedGUI(client, "The passwords must match!");
+ showPlayerRegistrationFailedGUI(client, getLocaleString(client, "RegistrationFailedPasswordMismatch"));
+ logToConsole(LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to create an account (password and confirm don't match)`);
return false;
}
}
if(!doesPasswordMeetRequirements(password)) {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
// Work on this later. Function should return true by default anyway for now.
- showPlayerRegistrationFailedGUI(client, "Password doesn't meet requirements!");
+ showPlayerRegistrationFailedGUI(client, getLocaleString(client, "RegistrationFailedNoPasswordWeak"));
+ logToConsole(LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to create an account (password doesn't meet requirements)`);
} else {
messagePlayerError(client, "Password doesn't meet requirements!");
}
return false
}
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
if(!isValidEmailAddress(emailAddress)) {
- showPlayerRegistrationFailedGUI(client, "You must put a valid email!");
+ showPlayerRegistrationFailedGUI(client, getLocaleString(client, "RegistrationFailedInvalidEmail"));
return false
}
}
let accountData = createAccount(getPlayerName(client), password, emailAddress);
if(!accountData) {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
- showPlayerRegistrationFailedGUI(client, "Your account could not be created!");
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
+ showPlayerRegistrationFailedGUI(client, getLocaleString(client, "RegistrationFailedCreateError"));
} else {
- messagePlayerAlert(client, "Your account could not be created!");
+ messagePlayerAlert(client, getLocaleString(client, "RegistrationFailedCreateError"));
}
messagePlayerAlert(client, `${getServerName()} staff have been notified of the problem and will fix it shortly.`);
@@ -919,29 +941,123 @@ function checkRegistration(client, password, confirmPassword = "", emailAddress
getPlayerData(client).accountData = accountData;
getPlayerData(client).loggedIn = true;
- messagePlayerSuccess(client, "Your account has been created!");
+ messagePlayerSuccess(client, getLocaleString(client, "RegistrationSuccess"));
if(checkForSMTPModule() && getEmailConfig().enabled) {
- messagePlayerAlert(client, "Don't forget to verify your email! A verification code has been sent to you");
+ messagePlayerAlert(client, getLocaleString(client, "RegistrationEmailVerifyReminder"));
+ let emailVerificationCode = generateEmailVerificationCode();
+ setAccountEmailVerificationCode(getPlayerData(client).accountData, emailVerificationCode);
+ sendEmailVerificationEmail(client, emailVerificationCode);
+ logToConsole(LOG_WARN, `${getPlayerDisplayForConsole(client)} was sent a registration email verification code`);
}
- messagePlayerAlert(client, "To play on the server, you will need to make a character.");
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
- showPlayerRegistrationSuccessGUI(client);
- showPlayerPromptGUI(client, "You have no characters. Would you like to make one?", "No Characters");
- getPlayerData(client).promptType = VRR_PROMPT_CREATEFIRSTCHAR;
+ if(doesServerHaveTesterOnlyEnabled() && !isPlayerATester(client)) {
+ setTimeout(function() {
+ client.disconnect();
+ }, 5000);
- if(checkForSMTPModule() && getEmailConfig().enabled) {
- let emailVerificationCode = generateEmailVerificationCode();
- setAccountEmailVerificationCode(getPlayerData(client).accountData, emailVerificationCode);
- sendEmailVerificationEmail(client, emailVerificationCode);
- }
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
+ logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the error GUI (not a tester).`);
+ showPlayerErrorGUI(client, getLocaleString(client, "NotATester"), getLocaleString(client, "AccessDenied"));
+ return false;
+ } else {
+ logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the "not a tester" error message (GUI disabled).`);
+ messagePlayerError(client, getLocaleString(client, "NotATester"));
+ return false;
+ }
} else {
- messagePlayerAlert(client, `You have no characters. Use /newchar to make one.`);
+ messagePlayerAlert(client, getLocaleString(client, "RegistrationCreateCharReminder"));
+
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
+ showPlayerRegistrationSuccessGUI(client);
+ showPlayerPromptGUI(client, getLocaleString(client, "NoCharactersMessage"), getLocaleString(client, "NoCharactersWindowTitle"), getLocaleString(client, "Yes"), getLocaleString(client, "No"));
+ getPlayerData(client).promptType = VRR_PROMPT_CREATEFIRSTCHAR;
+ } else {
+ messagePlayerAlert(client, getLocaleString(client, "NoCharactersChatMessage"), `{ALTCOLOUR}/newchar{MAINCOLOUR}`);
+ }
}
};
// ===========================================================================
+function checkAccountResetPasswordRequest(client, inputText) {
+ if(getPlayerData(client).passwordResetState == VRR_RESETPASS_STATE_NONE) {
+ if(toLowerCase(getPlayerData(client).accountData.emailAddress) != toLowerCase(inputText)) {
+ logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (email not correct)`);
+ return false;
+ }
+
+ let passwordResetCode = toUpperCase(generateEmailVerificationCode());
+ getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_CODEINPUT;
+ getPlayerData(client).passwordResetCode = passwordResetCode;
+ sendPasswordResetEmail(client, passwordResetCode);
+ showPlayerResetPasswordCodeInputGUI(client);
+ logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} reset their password. Awaiting verification code input ...`);
+ } else if(getPlayerData(client).passwordResetState == VRR_RESETPASS_STATE_CODEINPUT) {
+ if(getPlayerData(client).passwordResetCode == toUpperCase(inputText)) {
+ getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_SETPASS;
+ showPlayerChangePasswordGUI(client);
+ logToConsole(LOG_DEBUG, `${getPlayerDisplayForConsole(client)} entered the correct reset password verification code. Awaiting new password input ...`);
+ } else {
+ getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_NONE;
+ client.disconnect();
+ logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to reset their password (verification code not correct)`);
+ }
+ }
+
+ return false;
+}
+
+// ===========================================================================
+
+function checkAccountChangePassword(client, newPassword, confirmNewPassword) {
+ if(!isPlayerLoggedIn(client)) {
+ if(getPlayerData(client).passwordResetState != VRR_RESETPASS_STATE_SETPASS) {
+ //getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_NONE;
+ //client.disconnect();
+ logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to change their password (not logged in or not using reset password)`);
+ return false;
+ }
+ }
+
+ //if(isAccountPasswordCorrect(getPlayerData(client).accountData, hashAccountPassword(getPlayerName(client), oldPassword))) {
+ // messagePlayerError(client, `The old password is incorrect!`);
+ // return false;
+ //}
+
+ if(!doesPasswordMeetRequirements(newPassword)) {
+ let passwordRequirementsString = `${needsCapitals}, ${needsNumbers}, ${needsSymbols}`;
+ let needsCapitals = getLocaleString(client, "PasswordNeedsCapitals", "1");
+ let needsNumbers = getLocaleString(client, "PasswordNeedsNumbers", "1");
+ let needsSymbols = getLocaleString(client, "PasswordNeedsSymbols", "1");
+
+ messagePlayerError(client, getLocaleString(client, "AccountPasswordNeedsImproved"));
+ messagePlayerInfo(client, getLocaleString(client, "PasswordNeedsBase", passwordRequirementsString));
+ logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to change their password (password doesn't mean requirements)`);
+ return false;
+ }
+
+ if(newPassword != confirmNewPassword) {
+ messagePlayerError(client, getLocaleString(client, "PasswordsDontMatch"));
+ logToConsole(LOG_DEBUG|LOG_WARN, `${getPlayerDisplayForConsole(client)} failed to change their password (password and confirm don't match)`);
+ return false;
+ }
+
+ getPlayerData(client).accountData.password = hashAccountPassword(getPlayerData(client).accountData.name, newPassword);
+ getPlayerData(client).accountData.needsSaved = true;
+ getPlayerData(client).passwordResetCode = "";
+
+ saveAccountToDatabase(getPlayerData(client).accountData);
+
+ if(getPlayerData(client).passwordResetState == VRR_RESETPASS_STATE_SETPASS) {
+ getPlayerData(client).passwordResetState = VRR_RESETPASS_STATE_NONE;
+ }
+
+ messagePlayerSuccess(client, getLocaleString(client, "PasswordChanged"));
+ showPlayerLoginGUI(client);
+}
+
+// ===========================================================================
+
function isValidEmailAddress(emailAddress) {
return true;
}
@@ -985,9 +1101,6 @@ function savePlayerToDatabase(client) {
getPlayerCurrentSubAccount(client).interior = getPlayerInterior(client);
getPlayerCurrentSubAccount(client).dimension = getPlayerDimension(client);
}
-
- getPlayerCurrentSubAccount(client).inHouse = (isPlayerInAnyHouse(client)) ? getPlayerHouse(client) : 0;
- getPlayerCurrentSubAccount(client).inBusiness = (isPlayerInAnyBusiness(client)) ? getPlayerBusiness(client) : 0;
}
saveSubAccountToDatabase(getPlayerCurrentSubAccount(client));
@@ -1003,6 +1116,12 @@ function initClient(client) {
return false;
}
+ if(client.getData("vrr.isInitialized") != null || client.getData("vrr.isInitialized") == true) {
+ return false;
+ }
+
+ client.setData("vrr.isInitialized", true, false);
+
sendPlayerGUIColours(client);
sendPlayerGUIInit(client);
updatePlayerSnowState(client);
@@ -1019,36 +1138,37 @@ function initClient(client) {
getServerData().clients[client.index] = new ClientData(client, tempAccountData, tempSubAccounts);
- let sessionId = saveConnectionToDatabase(client);
- getServerData().clients[client.index].session = sessionId;
- getServerData().clients[client.index].connectTime = Math.ceil(sdl.ticks);
+ getServerData().clients[client.index].sessionId = saveConnectionToDatabase(client);
+ getServerData().clients[client.index].connectTime = getCurrentUnixTimestamp();
+ requestClientInfo(client);
if(tempAccountData != false) {
if(isAccountAutoIPLoginEnabled(tempAccountData) && getPlayerData(client).accountData.ipAddress == client.ip) {
- messagePlayerAlert(client, "You have been automatically logged in via IP!");
+ messagePlayerAlert(client, getLocaleString(client, "AutoLoggedInIP"));
loginSuccess(client);
} else {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the login GUI.`);
showPlayerLoginGUI(client);
- addPlayerKeyBind(client, getKeyIdFromParams("insert"), "gui", "");
} else {
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the login message (GUI disabled).`);
- messagePlayerNormal(client, `Welcome back to ${getServerName()}, ${getPlayerName(client)}! Please /login to continue.`, getColourByName("softGreen"));
+ messagePlayerNormal(client, getLocaleString(client, "WelcomeBack", getServerName(), getPlayerName(client), "/login"),getColourByName("softGreen"));
}
playRadioStreamForPlayer(client, getServerIntroMusicURL(), true, getPlayerStreamingRadioVolume(client));
}
} else {
- if(getServerConfig().useGUI && doesPlayerHaveGUIEnabled(client)) {
+ if(doesServerHaveGUIEnabled() && doesPlayerHaveGUIEnabled(client)) {
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the register GUI.`);
showPlayerRegistrationGUI(client);
- addPlayerKeyBind(client, getKeyIdFromParams("insert"), "gui", "");
} else {
logToConsole(LOG_DEBUG, `[VRR.Account] ${getPlayerDisplayForConsole(client)} is being shown the register message (GUI disabled).`);
- messagePlayerNormal(client, `Welcome to ${getServerName()}, ${getPlayerName(client)}! Please /register to continue.`, getColourByName("softGreen"));
+ messagePlayerNormal(client, getLocaleString(client, "WelcomeNewPlayer", getServerName(), getPlayerName(client), "/register"), getColourByName("softGreen"));
}
playRadioStreamForPlayer(client, getServerIntroMusicURL(), true, getPlayerStreamingRadioVolume(client));
}
+
+ getServerData().clients[client.index].keyBinds = loadAccountKeybindsFromDatabase(getServerData().clients[client.index].accountData.databaseId);
+ sendAccountKeyBindsToClient(client);
}
}, 2500);
}
@@ -1061,11 +1181,9 @@ function saveConnectionToDatabase(client) {
let safeName = escapeDatabaseString(dbConnection, getPlayerName(client));
let dbQueryString = `INSERT INTO conn_main (conn_when_connect, conn_server, conn_script_version, conn_game_version, conn_client_version, conn_name, conn_ip) VALUES (NOW(), ${getServerConfig().databaseId}, '${scriptVersion}', '${client.gameVersion}', '0.0.0', '${safeName}', '${client.ip}')`;
queryDatabase(dbConnection, dbQueryString);
- let connectionId = getDatabaseInsertId(dbConnection);
- setEntityData(client, "vrr.connection", connectionId, false);
- getPlayerData(client).connectionId = connectionId;
- requestClientInfo(client);
+ return getDatabaseInsertId(dbConnection);
}
+ return 0;
}
// ===========================================================================
@@ -1096,19 +1214,21 @@ function loadAccountKeybindsFromDatabase(accountDatabaseID) {
tempAccountKeybinds.push(tempKeyBindData);
}
- if(dbConnection) {
- dbQuery = queryDatabase(dbConnection, `SELECT * FROM acct_hotkey WHERE acct_hotkey_enabled = 1 AND acct_hotkey_acct = ${accountDatabaseID} AND acct_hotkey_server = ${getServerId()}`);
- if(dbQuery) {
- if(dbQuery.numRows > 0) {
- while(dbAssoc = fetchQueryAssoc(dbQuery)) {
- let tempAccountKeyBindData = new KeyBindData(dbAssoc);
- tempAccountKeybinds.push(tempAccountKeyBindData);
- logToConsole(LOG_DEBUG, `[VRR.Account]: Account keybind '${tempAccountKeyBindData.databaseId}' (Key ${tempAccountKeyBindData.key} '${toUpperCase(getKeyNameFromId(tempAccountKeyBindData.key))}') loaded from database successfully!`);
+ if(accountDatabaseID != 0 && typeof accountDatabaseId != "undefined") {
+ if(dbConnection) {
+ dbQuery = queryDatabase(dbConnection, `SELECT * FROM acct_hotkey WHERE acct_hotkey_enabled = 1 AND acct_hotkey_acct = ${accountDatabaseID} AND acct_hotkey_server = ${getServerId()}`);
+ if(dbQuery) {
+ if(dbQuery.numRows > 0) {
+ while(dbAssoc = fetchQueryAssoc(dbQuery)) {
+ let tempAccountKeyBindData = new KeyBindData(dbAssoc);
+ tempAccountKeybinds.push(tempAccountKeyBindData);
+ logToConsole(LOG_DEBUG, `[VRR.Account]: Account keybind '${tempAccountKeyBindData.databaseId}' (Key ${tempAccountKeyBindData.key} '${toUpperCase(getKeyNameFromId(tempAccountKeyBindData.key))}') loaded from database successfully!`);
+ }
}
+ freeDatabaseQuery(dbQuery);
}
- freeDatabaseQuery(dbQuery);
+ disconnectFromDatabase(dbConnection);
}
- disconnectFromDatabase(dbConnection);
}
logToConsole(LOG_DEBUG, `[VRR.Account]: ${tempAccountKeybinds.length} account keybinds for account ${accountDatabaseID} loaded from database successfully!`);
@@ -1252,6 +1372,12 @@ function isAccountTwoFactorAuthenticationVerified(accountData) {
// ===========================================================================
+function doesPlayerHaveTwoFactorAuthEnabled(client) {
+ return hasBitFlag(getPlayerData(client).accountData.flags.settings, getAccountSettingsFlagValue("TwoFactorAuth"));
+}
+
+// ===========================================================================
+
function setAccountEmail(accountData, emailAddress) {
accountData.emailAddress = emailAddress;
}
@@ -1280,6 +1406,16 @@ function sendEmailVerificationEmail(client, emailVerificationCode) {
// ===========================================================================
+function sendPasswordResetEmail(client, verificationCode) {
+ let emailBodyText = getEmailConfig().bodyContent.confirmPasswordReset;
+ emailBodyText = emailBodyText.replace("{VERIFICATIONCODE}", verificationCode);
+ emailBodyText = emailBodyText.replace("{SERVERNAME}", getServerName());
+
+ sendEmail(getPlayerData(client).accountData.emailAddress, getPlayerData(client).accountData.name, `Reset your password on ${getServerName()}`, emailBodyText);
+}
+
+// ===========================================================================
+
function verifyAccountEmail(accountData, verificationCode) {
let emailVerificationCode = generateRandomString(10);
@@ -1321,7 +1457,7 @@ function sendAccountLoginSuccessNotification(emailAddress, name, ip, game = getS
let emailBodyText = getEmailConfig().bodyContent.accountAuthSuccessAlert;
emailBodyText = emailBodyText.replace("{GAMENAME}", getGameName(game));
emailBodyText = emailBodyText.replace("{IPADDRESS}", ip);
- emailBodyText = emailBodyText.replace("{LOCATION}", `${cityName}, ${countryName}, ${countryName}`);
+ emailBodyText = emailBodyText.replace("{LOCATION}", `${cityName}, ${subDivisionName}, ${countryName}`);
emailBodyText = emailBodyText.replace("{SERVERNAME}", getServerName());
emailBodyText = emailBodyText.replace("{TIMESTAMP}", date.toLocaleString('en-US'));
@@ -1341,4 +1477,24 @@ function doesPlayerHaveRandomTipsDisabled(client) {
return isAccountSettingFlagEnabled(getPlayerData(client).accountData, getAccountSettingsFlagValue("NoRandomTips"));
}
+// ===========================================================================
+
+function checkPlayerTwoFactorAuthentication(client, authCode) {
+ if(getPlayerData(client).twoFactorAuthCode != "") {
+ if(toUpperCase(getPlayerData(client).twoFactorAuthCode) == toUpperCase(authCode)) {
+ loginSuccess(client);
+ return true;
+ }
+ }
+
+ client.disconnect();
+ return false;
+}
+
+// ===========================================================================
+
+function isPlayerATester(client) {
+
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/animation.js b/scripts/server/animation.js
index 21ebce09..ff253583 100644
--- a/scripts/server/animation.js
+++ b/scripts/server/animation.js
@@ -20,41 +20,50 @@ function playPlayerAnimationCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
- let animationSlot = getAnimationFromParams(splitParams[0]);
- let animationPositionOffset = getAnimationFromParams(splitParams[1]) || 1;
+let animationSlot = getAnimationFromParams(getParam(params, " ", 1));
+ let animationPositionOffset = 1;
if(!animationSlot) {
- messagePlayerError(client, getLocaleString("AnimationNotFound"));
- messagePlayerInfo(client, getLocaleString("AnimationHelpTip"));
+ messagePlayerError(client, getLocaleString(client, "AnimationNotFound"));
+ messagePlayerInfo(client, getLocaleString(client, "AnimationHelpTip"), `{ALTCOLOUR}/animlist{MAINCOLOUR}`);
return false;
}
if(toInteger(animationPositionOffset) < 0 || toInteger(animationPositionOffset) > 3) {
- messagePlayerError(client, getLocaleString("AnimationInvalidDistance"));
+ messagePlayerError(client, getLocaleString(client, "AnimationInvalidDistance"));
return false;
}
- getPlayerData(client).currentAnimation = animationSlot;
- getPlayerData(client).currentAnimationPositionOffset = animationSlot;
- getPlayerData(client).currentAnimationPositionReturnTo = getPlayerPosition(client);
- getPlayerData(client).animationStart = getCurrentUnixTimestamp();
- //setEntityData(getPlayerData(client).ped, "vrr.animation", animationSlot, true);
- messagePlayerTip(client, ``);
- makePedPlayAnimation(getPlayerData(client).ped, animationSlot, animationPositionOffset);
-
- if(getAnimationData(animationSlot)[9] != VRR_ANIMMOVE_NONE) {
- if(getGame() < VRR_GAME_GTA_SA) {
- setPlayerMouseCameraState(client, true);
- }
+ if(getAnimationData(animationSlot)[3] == VRR_ANIMTYPE_SURRENDER) {
+ getPlayerData(client).pedState = VRR_PEDSTATE_HANDSUP;
}
+
+ if(isPlayerHandCuffed(client) || isPlayerTazed(client) || isPlayerInForcedAnimation(client)) {
+ messagePlayerError(client, `You aren't able to do that`);
+ return false;
+ }
+
+ messagePlayerTip(client, getLocaleString(client, "AnimationStopCommandTip", "{ALTCOLOUR}/stopanim{MAINCOLOUR}"));
+ makePlayerPlayAnimation(client, animationSlot, animationPositionOffset);
}
// ===========================================================================
function stopPlayerAnimationCommand(command, params, client) {
+ if(isPlayerHandCuffed(client) || isPlayerTazed(client) || isPlayerInForcedAnimation(client)) {
+ messagePlayerError(client, `You aren't able to do that`);
+ return false;
+ }
+
setPlayerPosition(client, getPlayerData(client).currentAnimationPositionReturnTo);
makePedStopAnimation(getPlayerData(client).ped);
+
+ getPlayerData(client).currentAnimation = -1;
+ getPlayerData(client).currentAnimationPositionOffset = false;
+ getPlayerData(client).currentAnimationPositionReturnTo = false;
+ getPlayerData(client).animationStart = 0;
+ getPlayerData(client).animationForced = false;
+
setPlayerMouseCameraState(client, false);
}
@@ -65,17 +74,89 @@ function showAnimationListCommand(command, params, client) {
let chunkedList = splitArrayIntoChunks(animList, 10);
- messagePlayerInfo(client, `{clanOrange}== {jobYellow}Animation List {clanOrange}===========================`);
+ messagePlayerInfo(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderAnimationsList")));
for(let i in chunkedList) {
- messagePlayerInfo(client, chunkedList[i].join(", "));
+ messagePlayerNormal(client, chunkedList[i].join(", "));
}
}
// ===========================================================================
+/**
+ * @param {number} animationSlot - The slot index of the animation
+ * @return {Array} The animation's data (array)
+ */
function getAnimationData(animationSlot, gameId = getServerGame()) {
return getGameData().animations[gameId][animationSlot];
}
+// ===========================================================================
+
+function isPlayerInForcedAnimation(client) {
+ return getPlayerData(client).animationForced;
+}
+
+// ===========================================================================
+
+function makePlayerPlayAnimation(client, animationSlot, offsetPosition = 1) {
+ getPlayerData(client).currentAnimation = animationSlot;
+ getPlayerData(client).currentAnimationPositionOffset = offsetPosition;
+ getPlayerData(client).currentAnimationPositionReturnTo = getPlayerPosition(client);
+ getPlayerData(client).animationStart = getCurrentUnixTimestamp();
+ getPlayerData(client).animationForced = false;
+
+ makePedPlayAnimation(getPlayerData(client).ped, animationSlot, offsetPosition);
+
+ //if(getAnimationData(animationSlot)[9] != VRR_ANIMMOVE_NONE) {
+ // if(getGame() < VRR_GAME_GTA_SA) {
+ // setPlayerMouseCameraState(client, true);
+ // }
+ //}
+}
+
+// ===========================================================================
+
+function forcePlayerPlayAnimation(client, animationSlot, offsetPosition = 1) {
+ getPlayerData(client).currentAnimation = animationSlot;
+ getPlayerData(client).currentAnimationPositionOffset = offsetPosition;
+ getPlayerData(client).currentAnimationPositionReturnTo = getPlayerPosition(client);
+ getPlayerData(client).animationStart = getCurrentUnixTimestamp();
+ getPlayerData(client).animationForced = true;
+
+ setPlayerControlState(client, false);
+ forcePedAnimation(getPlayerData(client).ped, animationSlot, offsetPosition);
+}
+
+// ===========================================================================
+
+function makePlayerStopAnimation(client) {
+ //setPlayerPosition(client, getPlayerData(client).currentAnimationPositionReturnTo);
+ makePedStopAnimation(getPlayerData(client).ped);
+
+ getPlayerData(client).currentAnimation = -1;
+ getPlayerData(client).currentAnimationPositionOffset = false;
+ getPlayerData(client).currentAnimationPositionReturnTo = false;
+ getPlayerData(client).animationStart = 0;
+ getPlayerData(client).animationForced = false;
+}
+
+// ===========================================================================
+
+function getAnimationFromParams(params) {
+ if(isNaN(params)) {
+ for(let i in getGameData().animations[getServerGame()]) {
+ if(toLowerCase(getGameData().animations[getServerGame()][i][0]).indexOf(toLowerCase(params)) != -1) {
+ return i;
+ }
+ }
+ } else {
+ if(typeof getGameData().animations[getServerGame()][params] != "undefined") {
+ return toInteger(params);
+ }
+ }
+
+ return false;
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/anticheat.js b/scripts/server/anticheat.js
index bebfe6bf..e82b5079 100644
--- a/scripts/server/anticheat.js
+++ b/scripts/server/anticheat.js
@@ -248,4 +248,44 @@ function isPlayerExemptFromAntiCheat(client) {
return false;
}
+// ===========================================================================
+
+function canPlayerUsePoliceJob(client) {
+ if(getPlayerData(client).accountData.flags.moderation & getServerBitFlags().moderationFlags.policeBanned) {
+ return false;
+ }
+
+ return true;
+}
+
+// ===========================================================================
+
+function canClientUseFireJob(client) {
+ if(getPlayerData(client).accountData.flags.moderation & getServerBitFlags().moderationFlags.fireBanned) {
+ return false;
+ }
+
+ return true;
+}
+
+// ===========================================================================
+
+function canClientUseAmmunations(client) {
+ if(getPlayerData(client).accountData.flags.moderation & getServerBitFlags().moderationFlags.AmmuBanned) {
+ return false;
+ }
+
+ return true;
+}
+
+// ===========================================================================
+
+function canClientUseGuns(client) {
+ if(getPlayerData(client).accountData.flags.moderation & getServerBitFlags().moderationFlags.GunBanned) {
+ return false;
+ }
+
+ return true;
+}
+
// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/ban.js b/scripts/server/ban.js
index f3ed83ff..cfd6154b 100644
--- a/scripts/server/ban.js
+++ b/scripts/server/ban.js
@@ -23,7 +23,7 @@ function accountBanCommand(command, params, client) {
}
let splitParams = params.split(" ");
- let targetClient = getPlayerFromParams(splitParams[0]);
+ let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let reason = splitParams.slice(1).join(" ");
if(!targetClient) {
@@ -39,7 +39,7 @@ function accountBanCommand(command, params, client) {
logToConsole(LOG_WARN, `[VRR.Ban]: ${getPlayerDisplayForConsole(targetClient)} (${getPlayerData(targetClient).accountData.name}) account was banned by ${getPlayerDisplayForConsole(client)}. Reason: ${reason}`);
- messageAdminAction(`${getPlayerDisplayForConsole(targetClient)} (${getPlayerData(targetClient).accountData.name}) has been account banned.`);
+ messageAdminAction(`{ALTCOLOUR}${getPlayerData(targetClient).currentSubAccountData.name} {MAINCOLOUR}has been account banned.`);
banAccount(getPlayerData(targetClient).accountData.databaseId, getPlayerData(client).accountData.databaseId, reason);
disconnectPlayer(client);
}
@@ -53,7 +53,7 @@ function subAccountBanCommand(command, params, client, fromDiscord) {
}
let splitParams = params.split(" ");
- let targetClient = getPlayerFromParams(splitParams[0]);
+ let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let reason = splitParams.slice(1).join(" ");
if(!targetClient) {
@@ -69,7 +69,7 @@ function subAccountBanCommand(command, params, client, fromDiscord) {
logToConsole(LOG_WARN, `[VRR.Ban]: ${getPlayerDisplayForConsole(targetClient)} (${getPlayerData(targetClient).accountData.name})'s subaccount was banned by ${getPlayerDisplayForConsole(client)}. Reason: ${reason}`);
- messageAdminAction(`${getPlayerData(targetClient).currentSubAccountData.name} has been character banned.`);
+ messageAdminAction(`{ALTCOLOUR}${getPlayerData(targetClient).currentSubAccountData.name} {MAINCOLOUR}has been character banned.`);
banSubAccount(getPlayerData(targetClient).currentSubAccountData.databaseId, getPlayerData(client).accountData.databaseId, reason);
disconnectPlayer(client);
@@ -84,7 +84,7 @@ function ipBanCommand(command, params, client, fromDiscord) {
}
let splitParams = params.split(" ");
- let targetClient = getPlayerFromParams(splitParams[0]);
+ let targetClient = getPlayerFromParams(getParam(params, " ", 1));
let reason = splitParams.slice(1).join(" ");
if(!targetClient) {
@@ -98,7 +98,7 @@ function ipBanCommand(command, params, client, fromDiscord) {
return false;
}
- messageAdminAction(`${targetgetPlayerName(client)} has been IP banned.`);
+ messageAdminAction(`{ALTCOLOUR}${getPlayerData(targetClient).currentSubAccountData.name} {MAINCOLOUR}has been IP banned.`);
banIPAddress(targetClient.ip, getPlayerData(client).accountData.databaseId, reason);
server.banIP(targetClient.ip);
@@ -114,8 +114,8 @@ function subNetBanCommand(command, params, client, fromDiscord) {
}
let splitParams = params.split(" ");
- let targetClient = getPlayerFromParams(splitParams[0]);
- let octetAmount = Number(splitParams[1]);
+ let targetClient = getPlayerFromParams(getParam(params, " ", 1));
+ let octetAmount = Number(getParam(params, " ", 2));
let reason = splitParams.slice(2).join(" ");
if(!targetClient) {
@@ -129,7 +129,7 @@ function subNetBanCommand(command, params, client, fromDiscord) {
return false;
}
- messageAdminAction(`${targetgetPlayerName(client)} has been banned from the server (subnet ban).`);
+ messageAdminAction(`{ALTCOLOUR}${getPlayerData(targetClient).currentSubAccountData.name} {MAINCOLOUR}has been subnet banned`);
banSubNet(targetClient.ip, getSubNet(targetClient.ip, octetAmount), getPlayerData(client).accountData.databaseId, reason);
server.banIP(targetClient.ip);
diff --git a/scripts/server/bitflag.js b/scripts/server/bitflag.js
index a29b49cb..b095c2e8 100644
--- a/scripts/server/bitflag.js
+++ b/scripts/server/bitflag.js
@@ -62,6 +62,8 @@ let serverBitFlagKeys = {
"TwoFactorAuthVerified",
"NonRoleplayCharacterName",
"CanHearEverything",
+ "DontSyncClientElements",
+ "IsTester"
],
factionFlagKeys: [
"None",
@@ -408,7 +410,7 @@ function getModerationFlagValue(flagName) {
// ===========================================================================
-function getServerSettingFlagValue(flagName) {
+function getServerSettingsFlagValue(flagName) {
if(flagName == "All") {
return -1;
}
@@ -434,11 +436,12 @@ function givePlayerStaffFlag(client, flagName) {
// ===========================================================================
function takePlayerStaffFlag(client, flagName) {
- if(!getStaffFlagValue(flagName)) {
+ let flagValue = getStaffFlagValue(flagName);
+ if(!flagValue) {
return false;
}
- getPlayerData(client).accountData.flags.admin = getPlayerData(client).accountData.flags.admin & ~getStaffFlagValue(flagName);
+ getPlayerData(client).accountData.flags.admin = removeBitFlag(getPlayerData(client).accountData.flags.admin, flagValue);
return true;
}
diff --git a/scripts/server/business.js b/scripts/server/business.js
index 5c23034b..e68a0722 100644
--- a/scripts/server/business.js
+++ b/scripts/server/business.js
@@ -11,19 +11,13 @@ function initBusinessScript() {
logToConsole(LOG_INFO, "[VRR.Business]: Initializing business script ...");
getServerData().businesses = loadBusinessesFromDatabase();
- cacheAllBusinessItems();
- if(getServerConfig().createBusinessPickups) {
- }
-
- if(getServerConfig().createBusinessBlips) {
-
- }
createAllBusinessPickups();
createAllBusinessBlips();
setAllBusinessIndexes();
+ cacheAllBusinessItems();
logToConsole(LOG_INFO, "[VRR.Business]: Business script initialized successfully!");
return true;
@@ -143,7 +137,7 @@ function loadBusinessGameScriptsFromDatabase(businessId) {
// ===========================================================================
function createBusinessCommand(command, params, client) {
- let tempBusinessData = createBusiness(params, getPlayerPosition(client), toVector3(0.0, 0.0, 0.0), getGameConfig().pickupModels[getServerGame()].business, getGameConfig().blipSprites[getServerGame()].business, getPlayerInterior(client), getPlayerDimension(client));
+ let tempBusinessData = createBusiness(params, getPlayerPosition(client), toVector3(0.0, 0.0, 0.0), getGameConfig().pickupModels[getServerGame()].Business, getGameConfig().blipSprites[getServerGame()].Business, getPlayerInterior(client), getPlayerDimension(client));
tempBusinessData.needsSaved = true;
let businessId = getServerData().businesses.push(tempBusinessData);
setAllBusinessIndexes();
@@ -166,15 +160,15 @@ function createBusinessLocationCommand(command, params, client) {
return false;
}
- let locationType = toString(splitParams[0]);
- let businessId = (isPlayerInAnyBusiness(splitParams[1])) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
+ let locationType = toString(getParam(params, " ", 1));
+ let businessId = (isPlayerInAnyBusiness(getParam(params, " ", 2))) ? getPlayerBusiness(client) : getClosestBusinessEntrance(getPlayerPosition(client));
if(!areParamsEmpty(params)) {
businessId = getBusinessFromParams(params);
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -217,7 +211,7 @@ function deleteBusinessCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -228,7 +222,7 @@ function deleteBusinessCommand(command, params, client) {
// ===========================================================================
function deleteBusinessLocationCommand(command, params, client) {
- //let businessId = toInteger(splitParams[1]);
+ //let businessId = toInteger(getParam(params, " ", 2));
//deleteBusinessLocation(businessId);
//messagePlayerSuccess(client, `Business '${tempBusinessData.name} deleted!`);
}
@@ -241,7 +235,7 @@ function setBusinessNameCommand(command, params, client) {
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -269,12 +263,12 @@ function setBusinessOwnerCommand(command, params, client) {
let businessId = getPlayerBusiness(client);
if(!newBusinessOwner) {
- messagePlayerError(client, "Player not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -287,7 +281,7 @@ function setBusinessOwnerCommand(command, params, client) {
getBusinessData(businessId).ownerId = getPlayerCurrentSubAccount(newBusinessOwner).databaseId;
getBusinessData(businessId).needsSaved = true;
- messagePlayerSuccess(`{MAINCOLOUR}You gave business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}to {ALTCOLOUR}${newBusinessOwner.name}`);
+ messagePlayerSuccess(client, `{MAINCOLOUR}You gave business {businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR} to {ALTCOLOUR}${getCharacterFullName(newBusinessOwner)}`);
}
// ===========================================================================
@@ -302,12 +296,12 @@ function setBusinessJobCommand(command, params, client) {
let businessId = getPlayerBusiness(client);
if(!getJobData(jobId)) {
- messagePlayerError(client, "Job not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidJob"));
return false;
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -320,7 +314,7 @@ function setBusinessJobCommand(command, params, client) {
getBusinessData(businessId).ownerId = getJobData(jobId).databaseId;
getBusinessData(businessId).needsSaved = true;
- messagePlayerSuccess(`{MAINCOLOUR}You set the owner of business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}to the {jobYellow}${getJobData(jobId).name}`);
+ messagePlayerSuccess(client, `{MAINCOLOUR}You set the owner of business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}to the {jobYellow}${getJobData(jobId).name}`);
}
// ===========================================================================
@@ -329,14 +323,14 @@ function setBusinessClanCommand(command, params, client) {
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(getLocaleString(client, "InvalidBusiness"));
return false;
}
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
@@ -349,7 +343,7 @@ function setBusinessClanCommand(command, params, client) {
getBusinessData(businessId).ownerId = getClanData(clanId).databaseId;
getBusinessData(businessId).needsSaved = true;
- messagePlayerSuccess(`{MAINCOLOUR}You gave business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}to the {clanOrange}${getClanData(clanId).name} {MAINCOLOUR}clan!`);
+ messagePlayerSuccess(client, `{MAINCOLOUR}You gave business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}to the {clanOrange}${getClanData(clanId).name} {MAINCOLOUR}clan!`);
}
// ===========================================================================
@@ -358,7 +352,7 @@ function setBusinessRankCommand(command, params, client) {
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -373,14 +367,14 @@ function setBusinessRankCommand(command, params, client) {
let clanId = getClanIdFromDatabaseId(getBusinessData(businessId).ownerId);
rankId = getClanRankFromParams(clanId, params);
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
getBusinessData(businessId).rank = getClanRankData(clanId, rankId).databaseId;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set their {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}rank to {ALTCOLOUR}${getClanRankData(clanId, rankId).name} {MAINCOLOUR}of the {clanOrange}${getClanData(clanId).name} {MAINCOLOUR}clan!`);
+ messagePlayerSuccess(client, `{MAINCOLOUR}You set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}rank to {ALTCOLOUR}${getClanRankData(clanId, rankId).name} {MAINCOLOUR}of the {clanOrange}${getClanData(clanId).name} {MAINCOLOUR}clan!`);
} else if(getBusinessData(businessId).ownerType == VRR_VEHOWNER_JOB) {
getBusinessData(businessId).rank = rankId;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}rank to {ALTCOLOUR}${rankId} {MAINCOLOUR}of the {jobYellow}${getJobData(getJobIdFromDatabaseId(getBusinessData(businessId).ownerId)).name} {MAINCOLOUR}job!`);
+ messagePlayerSuccess(client, `{MAINCOLOUR}You set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}rank to {ALTCOLOUR}${rankId} {MAINCOLOUR}of the {jobYellow}${getJobData(getJobIdFromDatabaseId(getBusinessData(businessId).ownerId)).name} {MAINCOLOUR}job!`);
}
getBusinessData(businessId).needsSaved = true;
@@ -406,21 +400,21 @@ function setBusinessRankCommand(command, params, client) {
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError("Business not found!");
+ messagePlayerError(getLocaleString(client, "InvalidBusiness"));
return false;
}
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
let clanRankId = getClanRankFromParams(clanId, params);
if(!getClanRankData(clanId, clanRankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
@@ -437,7 +431,7 @@ function setBusinessRankCommand(command, params, client) {
getBusinessData(businessId).clanRank = getClanRankData(clanId, clanRankId).level;
getBusinessData(businessId).needsSaved = true;
- messagePlayerSuccess(`{MAINCOLOUR}You set business {businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR}'s clan rank to {clanOrange}${getClanRankData(clanId, clanRankId).name} {MAINCOLOUR}(level ${getClanRankData(clanId, clanRankId).level}) and above!`);
+ messagePlayerSuccess(client, `{MAINCOLOUR}You set business {businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR}'s clan rank to {clanOrange}${getClanRankData(clanId, clanRankId).name} {MAINCOLOUR}(level ${getClanRankData(clanId, clanRankId).level}) and above!`);
}
// ===========================================================================
@@ -457,12 +451,12 @@ function setBusinessJobCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
if(!getJobData(jobId)) {
- messagePlayerError(client, "Job not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidJob"));
return false;
}
@@ -470,7 +464,7 @@ function setBusinessJobCommand(command, params, client) {
getBusinessData(businessId).ownerId = getJobData(jobId).databaseId;
getBusinessData(businessId).needsSaved = true;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}owner to the {jobYellow}${getJobData(jobId).name} {MAINCOLOUR}job`);
+ messagePlayerSuccess(client, `{MAINCOLOUR}You set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}owner to the {jobYellow}${getJobData(jobId).name} {MAINCOLOUR}job`);
}
// ===========================================================================
@@ -483,7 +477,7 @@ function setBusinessPublicCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -491,7 +485,28 @@ function setBusinessPublicCommand(command, params, client) {
getBusinessData(businessId).ownerId = 0;
getBusinessData(businessId).needsSaved = true;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}owner set to {ALTCOLOUR}public`);
+ messagePlayerSuccess(client, `{MAINCOLOUR}You set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}owner set to {ALTCOLOUR}public`);
+}
+
+// ===========================================================================
+
+function removeBusinessOwnerCommand(command, params, client) {
+ let businessId = getPlayerBusiness(client);
+
+ if(!areParamsEmpty(params)) {
+ businessId = getBusinessFromParams(params);
+ }
+
+ if(!getBusinessData(businessId)) {
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
+ return false;
+ }
+
+ getBusinessData(businessId).ownerType = VRR_BIZOWNER_NONE;
+ getBusinessData(businessId).ownerId = -1;
+
+ getBusinessData(businessId).needsSaved = true;
+ messagePlayerSuccess(client, `{MAINCOLOUR}You removed business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}owner`);
}
// ===========================================================================
@@ -504,7 +519,7 @@ function lockUnlockBusinessCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -517,7 +532,7 @@ function lockUnlockBusinessCommand(command, params, client) {
setEntityData(getBusinessData(businessId).entrancePickup, "vrr.label.locked", getBusinessData(businessId).locked, true);
getBusinessData(businessId).needsSaved = true;
- messagePlayerSuccess(client, `${getLockedUnlockedEmojiFromBool((getBusinessData(businessId).locked))} Business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}${getLockedUnlockedTextFromBool((getBusinessData(businessId).locked))}!`);
+ messagePlayerSuccess(client, `${getLockedUnlockedEmojiFromBool((getBusinessData(businessId).locked))} Business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}${getLockedUnlockedFromBool((getBusinessData(businessId).locked))}!`);
}
// ===========================================================================
@@ -535,7 +550,7 @@ function lockUnlockBusinessCommand(command, params, client) {
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -554,12 +569,11 @@ function lockUnlockBusinessCommand(command, params, client) {
// ===========================================================================
function setBusinessEntranceFeeCommand(command, params, client) {
- let splitParams = params.split(" ");
- let entranceFee = toInteger(splitParams[0]) || 0;
+ let entranceFee = toInteger(getParam(params, " ", 1)) || 0;
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -570,7 +584,7 @@ function setBusinessEntranceFeeCommand(command, params, client) {
getBusinessData(businessId).entranceFee = entranceFee;
getBusinessData(businessId).needsSaved = true;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}entrance fee to [#AAAAAAA]$${entranceFee}`);
+ messagePlayerSuccess(client, `{MAINCOLOUR}You set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}entrance fee to [#AAAAAAA]$${entranceFee}`);
}
// ===========================================================================
@@ -583,7 +597,7 @@ function getBusinessInfoCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -624,7 +638,7 @@ function getBusinessFloorItemsCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -641,7 +655,7 @@ function getBusinessStorageItemsCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -651,19 +665,24 @@ function getBusinessStorageItemsCommand(command, params, client) {
// ===========================================================================
function setBusinessPickupCommand(command, params, client) {
- let splitParams = params.split(" ");
- let typeParam = splitParams[0] || "business";
+ let typeParam = getParam(params, " ", 1) || "business";
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
if(isNaN(typeParam)) {
if(isNull(getGameConfig().pickupModels[getServerGame()][typeParam])) {
- messagePlayerError(client, "Invalid business type! Use a business type name or a pickup model ID");
- messagePlayerInfo(client, `Pickup Types: {ALTCOLOUR}${Object.keys(getGameConfig().pickupModels[getServerGame()]).join(", ")}`)
+ messagePlayerError(client, "Invalid pickup type! Use a pickup type name or a model ID");
+ let pickupTypes = Object.keys(getGameConfig().pickupModels[getServerGame()]);
+ let chunkedList = splitArrayIntoChunks(pickupTypes, 10);
+
+ messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderPickupTypes")));
+ for(let i in chunkedList) {
+ messagePlayerInfo(client, chunkedList[i].join(", "));
+ }
return false;
}
@@ -676,18 +695,17 @@ function setBusinessPickupCommand(command, params, client) {
getBusinessData(businessId).needsSaved = true;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}pickup display to {ALTCOLOUR}${toLowerCase(typeParam)}'!`);
+ messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}pickup display to {ALTCOLOUR}${typeParam}!`);
}
// ===========================================================================
function setBusinessInteriorTypeCommand(command, params, client) {
- let splitParams = params.split(" ");
- let typeParam = splitParams[0] || "business";
+ let typeParam = getParam(params, " ", 1) || "business";
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -698,26 +716,26 @@ function setBusinessInteriorTypeCommand(command, params, client) {
getBusinessData(businessId).exitInterior = -1;
getBusinessData(businessId).hasInterior = false;
getBusinessData(businessId).exitPickupModel = -1;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}removed business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}interior`);
+ messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}removed business {businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR} interior`);
return false;
}
- if(isNull(getGameConfig().interiorTemplates[getServerGame()][typeParam])) {
+ if(isNull(getGameConfig().interiors[getServerGame()][typeParam])) {
messagePlayerError(client, "Invalid interior type! Use an interior type name");
- let interiorTypesList = Object.keys(getGameConfig().interiorTemplates[getServerGame()]);
+ let interiorTypesList = Object.keys(getGameConfig().interiors[getServerGame()]);
let chunkedList = splitArrayIntoChunks(interiorTypesList, 10);
- messagePlayerInfo(client, `{clanOrange}== {jobYellow}Interior Types {clanOrange}=======================`);
+ messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderInteriorTypes")));
for(let i in chunkedList) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
return false;
}
- getBusinessData(businessId).exitPosition = getGameConfig().interiorTemplates[getServerGame()][typeParam][0];
- getBusinessData(businessId).exitInterior = getGameConfig().interiorTemplates[getServerGame()][typeParam][1];
+ getBusinessData(businessId).exitPosition = getGameConfig().interiors[getServerGame()][typeParam][0];
+ getBusinessData(businessId).exitInterior = getGameConfig().interiors[getServerGame()][typeParam][1];
getBusinessData(businessId).exitDimension = getBusinessData(businessId).databaseId+getGlobalConfig().businessDimensionStart;
- getBusinessData(businessId).exitPickupModel = getGameConfig().pickupModels[getServerGame()].exit;
+ getBusinessData(businessId).exitPickupModel = getGameConfig().pickupModels[getServerGame()].Exit;
getBusinessData(businessId).hasInterior = true;
}
@@ -730,26 +748,31 @@ function setBusinessInteriorTypeCommand(command, params, client) {
getBusinessData(businessId).needsSaved = true;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}interior type to {ALTCOLOUR}${toLowerCase(typeParam)}`);
+ messageAdmins(`{ALTCOLOUR}${getPlayerName(client)}{MAINCOLOUR} set business {businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR} interior type to {ALTCOLOUR}${typeParam}`);
}
// ===========================================================================
function setBusinessBlipCommand(command, params, client) {
- let splitParams = params.split(" ");
-
- let typeParam = splitParams[0] || "business";
+ let typeParam = getParam(params, " ", 1) || "business";
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
if(isNaN(typeParam)) {
if(isNull(getGameConfig().blipSprites[getServerGame()][typeParam])) {
messagePlayerError(client, "Invalid business type! Use a business type name or a blip image ID");
- messagePlayerInfo(client, `Blip Types: {ALTCOLOUR}${Object.keys(getGameConfig().blipSprites[getServerGame()]).join(", ")}`)
+
+ let blipTypes = Object.keys(getGameConfig().blipSprites[getServerGame()]);
+ let chunkedList = splitArrayIntoChunks(blipTypes, 10);
+
+ messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderBlipTypes")));
+ for(let i in chunkedList) {
+ messagePlayerInfo(client, chunkedList[i].join(", "));
+ }
return false;
}
@@ -761,28 +784,34 @@ function setBusinessBlipCommand(command, params, client) {
resetBusinessBlips(businessId);
getBusinessData(businessId).needsSaved = true;
- messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}blip display to {ALTCOLOUR}${toLowerCase(typeParam)}`);
+ messageAdmins(`{ALTCOLOUR}${getPlayerName(client)} {MAINCOLOUR}set business {businessBlue}${getBusinessData(businessId).name}{MAINCOLOUR} blip display to {ALTCOLOUR}${typeParam}`);
}
// ===========================================================================
function giveDefaultItemsToBusinessCommand(command, params, client) {
- let splitParams = params.split(" ");
-
- let typeParam = splitParams[0] || "business";
+ let typeParam = getParam(params, " ", 1) || "business";
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
if(!isNaN(typeParam)) {
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
+ return false;
}
if(isNull(getGameConfig().defaultBusinessItems[getServerGame()][typeParam])) {
messagePlayerError(client, "Invalid business items type! Use a business items type name");
- messagePlayerInfo(client, `Blip Types: {ALTCOLOUR}${Object.keys(getGameConfig().defaultBusinessItems[getServerGame()]).join(", ")}`)
+ let businessItemTypes = Object.keys(getGameConfig().defaultBusinessItems[getServerGame()]);
+ let chunkedList = splitArrayIntoChunks(businessItemTypes, 10);
+
+ messagePlayerNormal(client, makeChatBoxSectionHeader(getLocaleString(client, "HeaderDefaultBusinessItemTypes")));
+ for(let i in chunkedList) {
+ messagePlayerInfo(client, chunkedList[i].join(", "));
+ }
return false;
}
@@ -806,7 +835,7 @@ function setBusinessEntranceLabelToDealershipCommand(command, params, client) {
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -818,17 +847,16 @@ function setBusinessEntranceLabelToDealershipCommand(command, params, client) {
// ===========================================================================
function deleteBusinessFloorItemsCommand(command, params, client) {
- let splitParams = params.split(" ");
-
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
- for(let i in getBusinessData(businessId).floorItemCache) {
- deleteItem(getBusinessData(businessId).floorItemCache);
+ let tempCache = getBusinessData(businessId).floorItemCache;
+ for(let i in tempCache) {
+ deleteItem(tempCache[i]);
}
cacheBusinessItems(businessId);
@@ -839,17 +867,16 @@ function deleteBusinessFloorItemsCommand(command, params, client) {
// ===========================================================================
function deleteBusinessStorageItemsCommand(command, params, client) {
- let splitParams = params.split(" ");
-
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
- for(let i in getBusinessData(businessId).storageItemCache) {
- deleteItem(getBusinessData(businessId).storageItemCache);
+ let tempCache = getBusinessData(businessId).storageItemCache;
+ for(let i in tempCache) {
+ deleteItem(tempCache[i]);
}
cacheBusinessItems(businessId);
@@ -865,13 +892,11 @@ function withdrawFromBusinessCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
-
- let amount = toInteger(splitParams[0]) || 0;
+ let amount = toInteger(getParam(params, " ", 1)) || 0;
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -901,13 +926,11 @@ function setBusinessBuyPriceCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
-
- let amount = toInteger(splitParams[0]) || 0;
+ let amount = toInteger(getParam(params, " ", 1)) || 0;
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -936,13 +959,11 @@ function depositIntoBusinessCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
-
- let amount = toInteger(splitParams[0]) || 0;
+ let amount = toInteger(getParam(params, " ", 1)) || 0;
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -995,7 +1016,7 @@ function orderItemForBusinessCommand(command, params, client) {
logToConsole(LOG_DEBUG, `[VRR.Business] ${getPlayerDisplayForConsole(client)} is ordering ${amount} ${splitParams.slice(0,-2).join(" ")} (${value})`);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -1041,7 +1062,7 @@ function viewBusinessTillAmountCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -1059,17 +1080,17 @@ function buyBusinessCommand(command, params, client) {
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
if(getBusinessData(businessId).buyPrice <= 0) {
- messagePlayerError(client, `Business {businessBlue}${getBusinessData(businessId).name} {MAINCOLOUR}is not for sale!`);
+ messagePlayerError(client, getLocaleString(client, "BusinessNotForSale"));
return false;
}
if(getPlayerCurrentSubAccount(client).cash < getBusinessData(businessId).buyPrice) {
- messagePlayerError(client, `You don't have enough money to buy business {businessBlue}${getBusinessData(businessId).name}!`);
+ messagePlayerError(client, getLocaleString(client, "BusinessPurchaseNotEnoughMoney"));
return false;
}
@@ -1093,7 +1114,7 @@ function moveBusinessEntranceCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -1124,7 +1145,7 @@ function moveBusinessExitCommand(command, params, client) {
}
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -1223,7 +1244,12 @@ function saveAllBusinessesToDatabase() {
// ===========================================================================
function saveBusinessToDatabase(businessId) {
- let tempBusinessData = getServerData().businesses[businessId]
+ let tempBusinessData = getServerData().businesses[businessId];
+
+ if(!tempBusinessData.needsSaved) {
+ return false;
+ }
+
logToConsole(LOG_DEBUG, `[VRR.Business]: Saving business '${tempBusinessData.name}' to database ...`);
let dbConnection = connectToDatabase();
if(dbConnection) {
@@ -1315,17 +1341,17 @@ function createBusinessEntrancePickup(businessId) {
}
if(getBusinessData(businessId).entrancePickupModel != -1) {
- let pickupModelId = getGameConfig().pickupModels[getServerGame()].business;
+ let pickupModelId = getGameConfig().pickupModels[getServerGame()].Business;
if(getServerData().businesses[businessId].entrancePickupModel != 0) {
pickupModelId = getBusinessData(businessId).entrancePickupModel;
}
+ logToConsole(LOG_VERBOSE, `[VRR.Job]: Creating entrance pickup for business ${getBusinessData(businessId).name} (model ${pickupModelId})`);
+
getBusinessData(businessId).entrancePickup = createGamePickup(pickupModelId, getBusinessData(businessId).entrancePosition, getGameConfig().pickupTypes[getServerGame()].business);
setElementOnAllDimensions(getBusinessData(businessId).entrancePickup, false);
setElementDimension(getBusinessData(businessId).entrancePickup, getBusinessData(businessId).entranceDimension);
- setElementStreamInDistance(getBusinessData(businessId).entrancePickup, getGlobalConfig().businessPickupStreamInDistance);
- setElementStreamOutDistance(getBusinessData(businessId).entrancePickup, getGlobalConfig().businessPickupStreamOutDistance);
updateBusinessPickupLabelData(businessId);
addToWorld(getBusinessData(businessId).entrancePickup);
}
@@ -1339,17 +1365,17 @@ function createBusinessEntranceBlip(businessId) {
}
if(getBusinessData(businessId).entranceBlipModel != -1) {
- let blipModelId = getGameConfig().blipSprites[getServerGame()].business;
+ let blipModelId = getGameConfig().blipSprites[getServerGame()].Business;
if(getServerData().businesses[businessId].entranceBlipModel != 0) {
blipModelId = getBusinessData(businessId).entranceBlipModel;
}
+ logToConsole(LOG_VERBOSE, `[VRR.Job]: Creating entrance blip for business ${getBusinessData(businessId).name} (model ${blipModelId})`);
+
getBusinessData(businessId).entranceBlip = createGameBlip(getBusinessData(businessId).entrancePosition, blipModelId, 1, getColourByName("businessBlue"));
setElementOnAllDimensions(getBusinessData(businessId).entranceBlip, false);
setElementDimension(getBusinessData(businessId).entranceBlip, getBusinessData(businessId).entranceDimension);
- setElementStreamInDistance(getBusinessData(businessId).entranceBlip, getGlobalConfig().businessBlipStreamInDistance);
- setElementStreamOutDistance(getBusinessData(businessId).entranceBlip, getGlobalConfig().businessBlipStreamOutDistance);
addToWorld(getBusinessData(businessId).entranceBlip);
}
}
@@ -1363,17 +1389,17 @@ function createBusinessExitPickup(businessId) {
if(getBusinessData(businessId).hasInterior) {
if(getBusinessData(businessId).exitPickupModel != -1) {
- let pickupModelId = getGameConfig().pickupModels[getServerGame()].exit;
+ let pickupModelId = getGameConfig().pickupModels[getServerGame()].Exit;
if(getServerData().businesses[businessId].exitPickupModel != 0) {
pickupModelId = getBusinessData(businessId).exitPickupModel;
}
+ logToConsole(LOG_VERBOSE, `[VRR.Job]: Creating exit pickup for business ${getBusinessData(businessId).name} (model ${pickupModelId})`);
+
getBusinessData(businessId).exitPickup = createGamePickup(pickupModelId, getBusinessData(businessId).exitPosition, getGameConfig().pickupTypes[getServerGame()].business);
setElementDimension(getBusinessData(businessId).exitPickup, getBusinessData(businessId).exitDimension);
setElementOnAllDimensions(getBusinessData(businessId).exitPickup, false);
- setElementStreamInDistance(getBusinessData(businessId).exitPickup, getGlobalConfig().businessPickupStreamInDistance);
- setElementStreamOutDistance(getBusinessData(businessId).exitPickup, getGlobalConfig().businessPickupStreamOutDistance);
updateBusinessPickupLabelData(businessId);
addToWorld(getBusinessData(businessId).exitPickup);
}
@@ -1389,17 +1415,20 @@ function createBusinessExitBlip(businessId) {
if(getBusinessData(businessId).hasInterior) {
if(getBusinessData(businessId).exitBlipModel != -1) {
- let blipModelId = getGameConfig().blipSprites[getServerGame()].business;
+ let blipModelId = getGameConfig().blipSprites[getServerGame()].Business;
if(getServerData().businesses[businessId].exitBlipModel != 0) {
blipModelId = getBusinessData(businessId).exitBlipModel;
}
+ logToConsole(LOG_VERBOSE, `[VRR.Job]: Creating exit blip for business ${getBusinessData(businessId).name} (model ${blipModelId})`);
+
getBusinessData(businessId).exitBlip = createGameBlip(getBusinessData(businessId).exitPosition, blipModelId, 1, getColourByName("businessBlue"));
setElementDimension(getBusinessData(businessId).exitBlip, getBusinessData(businessId).entranceDimension);
setElementOnAllDimensions(getBusinessData(businessId).exitBlip, false);
- setElementStreamInDistance(getBusinessData(businessId).exitBlip, getGlobalConfig().businessBlipStreamInDistance);
- setElementStreamOutDistance(getBusinessData(businessId).exitBlip, getGlobalConfig().businessBlipStreamOutDistance);
+ //getBusinessData(businessId).exitBlip.interior = getBusinessData(businessId).exitInterior;
+ //setEntityData(getBusinessData(businessId).exitBlip, "vrr.owner.type", VRR_BLIP_BUSINESS_EXIT, false);
+ //setEntityData(getBusinessData(businessId).exitBlip, "vrr.owner.id", businessId, false);
addToWorld(getBusinessData(businessId).exitBlip);
}
}
@@ -1421,8 +1450,8 @@ function deleteBusiness(businessId, deletedBy = 0) {
disconnectFromDatabase(dbConnection);
}
- deleteAllBusinessBlips(businessId);
- deleteAllBusinessPickups(businessId);
+ deleteBusinessBlips(businessId);
+ deleteBusinessPickups(businessId);
removePlayersFromBusiness(businessId);
@@ -1457,8 +1486,8 @@ function exitBusiness(client) {
let businessId = getPlayerBusiness(client);
if(isPlayerSpawned(client)) {
setPlayerInterior(client, getServerData().businesses[businessId].entranceInterior);
- setPlayerDimension(client, client, getServerData().businesses[businessId].entranceDimension);
- setPlayerPosition(client, client, getServerData().businesses[businessId].entrancePosition);
+ setPlayerDimension(client, getServerData().businesses[businessId].entranceDimension);
+ setPlayerPosition(client, getServerData().businesses[businessId].entrancePosition);
}
}
@@ -1486,6 +1515,10 @@ function getBusinessOwnerTypeText(ownerType) {
// ===========================================================================
+/**
+ * @param {number} businessId - The data index of the business
+ * @return {BusinessData} The business's data (class instance)
+ */
function getBusinessData(businessId) {
if(typeof getServerData().businesses[businessId] != null) {
return getServerData().businesses[businessId];
@@ -1561,6 +1594,8 @@ function reloadAllBusinessesCommand(command, params, client) {
getServerData().businesses = loadBusinessesFromDatabase();
createAllBusinessPickups();
createAllBusinessBlips();
+ setAllBusinessIndexes();
+ cacheAllBusinessItems();
messageAdminAction(`All businesses have been reloaded by an admin!`);
}
@@ -1612,10 +1647,8 @@ function buyFromBusinessCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
-
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
@@ -1627,15 +1660,15 @@ function buyFromBusinessCommand(command, params, client) {
if(getBusinessData(businessId).hasInterior) {
if(!getPlayerBusiness(client)) {
if(!doesPlayerHaveKeyBindsDisabled(client) && doesPlayerHaveKeyBindForCommand(client, "enter")) {
- messagePlayerTip(client, `You need to enter the business first! Press {ALTCOLOUR}${toUpperCase(getKeyNameFromId(getPlayerKeyBindForCommand(client, "enter")).key)} {MAINCOLOUR}to enter and exit a business`);
+ messagePlayerTip(client, getLocaleString(client, "NeedToEnterPropertyKeyPress", "business", `{ALTCOLOUR}${toUpperCase(getKeyNameFromId(getPlayerKeyBindForCommand(client, "enter")).key)}{MAINCOLOUR}`));
} else {
- messagePlayerNormal(client, `You need to enter the business first! Use /enter to enter and exit a business`);
+ messagePlayerNormal(client, getLocaleString(client, "NeedToEnterBusinessCommand", "business", "{ALTCOLOUR}/enter{MAINCOLOUR}"));
}
return false;
}
}
- let itemSlot = toInteger(splitParams[0]) || 1;
+ let itemSlot = toInteger(getParam(params, " ", 1)) || 1;
if(typeof getBusinessData(businessId).floorItemCache[itemSlot-1] == "undefined") {
messagePlayerError(client, `Item slot ${itemSlot} doesn't exist!`);
@@ -1649,9 +1682,9 @@ function buyFromBusinessCommand(command, params, client) {
let amount = 1;
if(areThereEnoughParams(params, 2, " ")) {
- amount = toInteger(splitParams[1]) || 1;
+ amount = toInteger(getParam(params, " ", 2)) || 1;
if(amount <= 0) {
- messagePlayerError(client, "The amount must be more than 0!");
+ messagePlayerError(client, getLocaleString(client, "AmountMustBeMoreThan", "0"));
return false;
}
}
@@ -1663,17 +1696,15 @@ function buyFromBusinessCommand(command, params, client) {
let firstSlot = getPlayerFirstEmptyHotBarSlot(client);
if(firstSlot == -1) {
- messagePlayerError(client, `You don't have any space to carry this (full inventory)!`);
+ messagePlayerError(client, messagePlayerError(client, getLocaleString(client, "InventoryFullCantCarry")));
return false;
}
let totalCost = getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).buyPrice*amount;
- let individualCost = getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).buyPrice;
let itemName = getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).itemTypeIndex).name;
- let priceEach = (amount > 1) ? `($${individualCost} each)` : ``;
if(getPlayerCurrentSubAccount(client).cash < totalCost) {
- messagePlayerError(client, `You don't have enough money! You need {ALTCOLOUR}${getBusinessData(businessId).floorItemCache[itemSlot-1].buyPrice*amount-getPlayerCurrentSubAccount(client).cash} {MAINCOLOUR}more!`);
+ messagePlayerError(client, getLocaleString(client, "NotEnoughCashNeedAmountMore", `{ALTCOLOUR}${getBusinessData(businessId).floorItemCache[itemSlot-1].buyPrice*amount-getPlayerCurrentSubAccount(client).cash}{MAINCOLOUR}`));
return false;
}
@@ -1688,9 +1719,9 @@ function buyFromBusinessCommand(command, params, client) {
}
let useType = getItemTypeData(getItemData(getBusinessData(businessId).floorItemCache[itemSlot-1]).itemTypeIndex).useType;
- if(useType == VRR_ITEM_USETYPE_WEAPON || VRR_ITEM_USETYPE_TAZER) {
+ if(useType == VRR_ITEM_USETYPE_WEAPON || VRR_ITEM_USETYPE_TAZER || useType == VRR_ITEM_USETYPE_AMMO_CLIP) {
if(isPlayerWeaponBanned(client) && !isPlayerExemptFromAntiCheat(client)) {
- messagePlayerError(client, `You are not allowed to buy weapons`);
+ messagePlayerError(client, getLocaleString(client, "WeaponBanned"));
return false;
}
}
@@ -1700,24 +1731,23 @@ function buyFromBusinessCommand(command, params, client) {
if(!doesPlayerHaveKeyBindsDisabled(client) && doesPlayerHaveKeyBindForCommand("inv")) {
let keyData = getPlayerKeyBindForCommand("inv");
- messagePlayerNewbieTip(client, `Press ${getKeyNameFromId(keyData.key)} to see your items.`);
+ messagePlayerNewbieTip(client, getLocaleString(client, "ViewInventoryKeyPressTip"), `{ALTCOLOUR}${getKeyNameFromId(keyData.key)}{MAINCOLOUR}`);
} else {
- messagePlayerNewbieTip(client, `Use /inv to see your items.`);
+ messagePlayerNewbieTip(client, getLocaleString(client, "ViewInventoryKeyPressTip"), `{ALTCOLOUR}/inv{MAINCOLOUR}`);
}
}
// ===========================================================================
function setBusinessItemSellPriceCommand(command, params, client) {
- let splitParams = params.split(" ");
- let businessId = getBusinessFromParams(splitParams[2]) || getPlayerBusiness(client);
+ let businessId = getBusinessFromParams(getParam(params, " ", 3)) || getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
- let itemSlot = toInteger(splitParams[0]) || 0;
+ let itemSlot = toInteger(getParam(params, " ", 1)) || 0;
if(typeof getBusinessData(businessId).floorItemCache[itemSlot-1] == "undefined") {
messagePlayerError(client, `Item slot ${itemSlot-1} doesn't exist!`);
@@ -1730,7 +1760,7 @@ function setBusinessItemSellPriceCommand(command, params, client) {
}
let oldPrice = getBusinessData(businessId).floorItemCache[itemSlot-1].buyPrice;
- let newPrice = toInteger(splitParams[1]) || oldPrice;
+ let newPrice = toInteger(getParam(params, " ", 2)) || oldPrice;
if(newPrice < 0) {
messagePlayerError(client, "The price can't be negative!");
return false;
@@ -1744,15 +1774,14 @@ function setBusinessItemSellPriceCommand(command, params, client) {
// ===========================================================================
function storeItemInBusinessStorageCommand(command, params, client) {
- let splitParams = params.split(" ");
- let businessId = getBusinessFromParams(splitParams[2]) || getPlayerBusiness(client);
+ let businessId = getBusinessFromParams(getParam(params, " ", 3)) || getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
- let itemSlot = toInteger(splitParams[0]) || 0;
+ let itemSlot = toInteger(getParam(params, " ", 1)) || 0;
if(typeof getBusinessData(businessId).floorItemCache[itemSlot-1] == "undefined") {
messagePlayerError(client, `Item slot ${itemSlot} doesn't exist!`);
@@ -1780,15 +1809,14 @@ function storeItemInBusinessStorageCommand(command, params, client) {
// ===========================================================================
function stockItemOnBusinessFloorCommand(command, params, client) {
- let splitParams = params.split(" ");
let businessId = getPlayerBusiness(client);
if(!getBusinessData(businessId)) {
- messagePlayerError(client, "Business not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidBusiness"));
return false;
}
- let itemSlot = toInteger(splitParams[0]) || 0;
+ let itemSlot = toInteger(getParam(params, " ", 1)) || 0;
if(typeof getBusinessData(businessId).storageItemCache[itemSlot-1] == "undefined") {
messagePlayerError(client, `Item slot ${itemSlot} doesn't exist!`);
@@ -1850,8 +1878,8 @@ function cacheAllBusinessItems() {
// ===========================================================================
function cacheBusinessItems(businessId) {
- getBusinessData(businessId).floorItemCache = [];
- getBusinessData(businessId).storageItemCache = [];
+ getBusinessData(businessId).floorItemCache.splice(0, getBusinessData(businessId).floorItemCache.length);
+ getBusinessData(businessId).storageItemCache.splice(0, getBusinessData(businessId).storageItemCache.length);
logToConsole(LOG_VERBOSE, `[VRR.Business] Caching business items for business ${businessId} (${getBusinessData(businessId).name}) ...`);
for(let i in getServerData().items) {
@@ -2123,3 +2151,35 @@ function deleteBusinessPickups(business) {
// ===========================================================================
+function getBusinessFromParams(params) {
+ if(isNaN(params)) {
+ for(let i in getServerData().businesses) {
+ if(toLowerCase(getServerData().businesses[i].name).indexOf(toLowerCase(params)) != -1) {
+ return i;
+ }
+ }
+ } else {
+ if(typeof getServerData().businesses[params] != "undefined") {
+ return toInteger(params);
+ }
+ }
+ return false;
+}
+
+// ===========================================================================
+
+function deleteAllBusinessBlips() {
+ for(let i in getServerData().businesses) {
+ deleteBusinessBlips(i);
+ }
+}
+
+// ===========================================================================
+
+function deleteAllBusinessPickups() {
+ for(let i in getServerData().businesses) {
+ deleteBusinessPickups(i);
+ }
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/chat.js b/scripts/server/chat.js
index bc0b1c1e..fbb63857 100644
--- a/scripts/server/chat.js
+++ b/scripts/server/chat.js
@@ -13,6 +13,43 @@ function initChatScript() {
return true;
}
+function processPlayerChat(client, messageText) {
+ if(!getPlayerData(client)) {
+ messagePlayerError(client, "You need to login before you can chat!");
+ return false;
+ }
+
+ if(!isPlayerLoggedIn(client)) {
+ messagePlayerError(client, "You need to login before you can chat!");
+ return false;
+ }
+
+ if(!isPlayerSpawned(client)) {
+ messagePlayerError(client, "You need to spawn before you can chat!");
+ return false;
+ }
+
+ if(isPlayerMuted(client)) {
+ messagePlayerError(client, "You are muted and can't chat!");
+ return false;
+ }
+
+ messageText = messageText.substring(0, 128);
+
+ /*
+ let clients = getClients();
+ for(let i in clients) {
+ let translatedText;
+ translatedText = await translateMessage(messageText, getPlayerData(client).locale, getPlayerData(clients[i]).locale);
+
+ let original = (getPlayerData(client).locale == getPlayerData(clients[i]).locale) ? `` : ` {ALTCOLOUR}(${messageText})`;
+ messagePlayerNormal(clients[i], `💬 ${getCharacterFullName(client)}: [#FFFFFF]${translatedText}${original}`, clients[i], getColourByName("mediumGrey"));
+ }
+ */
+ messagePlayerNormal(null, `💬 ${getCharacterFullName(client)}: ${messageText}`);
+ messageDiscordChatChannel(`💬 ${getCharacterFullName(client)}: ${messageText}`);
+}
+
// ===========================================================================
function meActionCommand(command, params, client) {
@@ -152,8 +189,10 @@ function clanChatCommand(command, params, client) {
function talkToNearbyPlayers(client, messageText) {
let clients = getClients();
for(let i in clients) {
- if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().talkDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
- messagePlayerTalk(clients[i], client, messageText);
+ if(isPlayerSpawned(clients[i])) {
+ if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().talkDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
+ messagePlayerTalk(clients[i], client, messageText);
+ }
}
}
}
@@ -163,8 +202,10 @@ function talkToNearbyPlayers(client, messageText) {
function phoneOutgoingToNearbyPlayers(client, messageText) {
let clients = getClients();
for(let i in clients) {
- if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().talkDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
- messagePlayerNormal(`[#CCCCCC]${getCharacterFullName(client)} {ALTCOLOUR}(to phone): {MAINCOLOUR}${messageText}`);
+ if(isPlayerSpawned(clients[i])) {
+ if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().talkDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
+ messagePlayerNormal(`[#CCCCCC]${getCharacterFullName(client)} {ALTCOLOUR}(to phone): {MAINCOLOUR}${messageText}`);
+ }
}
}
}
@@ -174,8 +215,10 @@ function phoneOutgoingToNearbyPlayers(client, messageText) {
function phoneIncomingToNearbyPlayers(client, messageText) {
let clients = getClients();
for(let i in clients) {
- if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().phoneSpeakerDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
- messagePlayerNormal(`[#CCCCCC]${getCharacterFullName(client)} {ALTCOLOUR}(from phone): {MAINCOLOUR}${messageText}`);
+ if(isPlayerSpawned(clients[i])) {
+ if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().phoneSpeakerDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
+ messagePlayerNormal(`[#CCCCCC]${getCharacterFullName(client)} {ALTCOLOUR}(from phone): {MAINCOLOUR}${messageText}`);
+ }
}
}
}
@@ -185,8 +228,10 @@ function phoneIncomingToNearbyPlayers(client, messageText) {
function whisperToNearbyPlayers(client, messageText) {
let clients = getClients();
for(let i in clients) {
- if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().whisperDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
- messagePlayerWhisper(clients[i], client, messageText);
+ if(isPlayerSpawned(clients[i])) {
+ if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().whisperDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
+ messagePlayerWhisper(clients[i], client, messageText);
+ }
}
}
}
@@ -196,19 +241,23 @@ function whisperToNearbyPlayers(client, messageText) {
function shoutToNearbyPlayers(client, messageText) {
let clients = getClients();
for(let i in clients) {
- if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().shoutDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
- messagePlayerShout(clients[i], client, messageText);
+ if(isPlayerSpawned(clients[i])) {
+ if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().shoutDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
+ messagePlayerShout(clients[i], client, messageText);
+ }
}
}
}
// ===========================================================================
-function megaphoneToNearbyPlayers(client, messageText) {
+function megaPhoneToNearbyPlayers(client, messageText) {
let clients = getClients();
for(let i in clients) {
- if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().megaphoneDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
- messagePlayerShout(clients[i], client, messageText);
+ if(isPlayerSpawned(clients[i])) {
+ if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().megaphoneDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
+ messagePlayerMegaPhone(clients[i], client, messageText);
+ }
}
}
}
@@ -218,8 +267,10 @@ function megaphoneToNearbyPlayers(client, messageText) {
function doActionToNearbyPlayers(client, messageText) {
let clients = getClients();
for(let i in clients) {
- if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().doActionDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
- messagePlayerDoAction(clients[i], client, messageText);
+ if(isPlayerSpawned(clients[i])) {
+ if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().doActionDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
+ messagePlayerDoAction(clients[i], client, messageText);
+ }
}
}
}
@@ -229,8 +280,10 @@ function doActionToNearbyPlayers(client, messageText) {
function meActionToNearbyPlayers(client, messageText) {
let clients = getClients();
for(let i in clients) {
- if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().meActionDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
- messagePlayerMeAction(clients[i], client, messageText);
+ if(isPlayerSpawned(clients[i])) {
+ if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || (getDistance(getPlayerPosition(client), getPlayerPosition(clients[i])) <= getGlobalConfig().meActionDistance && getPlayerDimension(client) == getPlayerDimension(clients[i]))) {
+ messagePlayerMeAction(clients[i], client, messageText);
+ }
}
}
}
@@ -240,8 +293,10 @@ function meActionToNearbyPlayers(client, messageText) {
function clanChat(client, messageText) {
let clients = getClients();
for(let i in clients) {
- if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || arePlayersInSameClan(client, clients[i])) {
- messagePlayerClanChat(clients[i], client, messageText);
+ if(isPlayerSpawned(clients[i])) {
+ if(hasBitFlag(getPlayerData(clients[i]).accountData.flags.moderation, getModerationFlagValue("CanHearEverything")) || arePlayersInSameClan(client, clients[i])) {
+ messagePlayerClanChat(clients[i], client, messageText);
+ }
}
}
}
diff --git a/scripts/server/clan.js b/scripts/server/clan.js
index 0fe5a808..0155dd4d 100644
--- a/scripts/server/clan.js
+++ b/scripts/server/clan.js
@@ -163,7 +163,7 @@ function listClanRanksCommand(command, params, client) {
}
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
@@ -207,7 +207,7 @@ function deleteClanCommand(command, params, client) {
let clanId = getClanFromParams(params);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
@@ -228,17 +228,16 @@ function setClanOwnerCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
- let clanId = getClanFromParams(splitParams[0]);
- let targetClient = getPlayerFromParams(splitParams[1]);
+ let clanId = getClanFromParams(getParam(params, " ", 1));
+ let targetClient = getPlayerFromParams(getParam(params, " ", 2));
if(!targetClient) {
- messagePlayerError(client, "Player not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
@@ -265,7 +264,7 @@ function setClanTagCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
@@ -290,7 +289,7 @@ function setClanNameCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
@@ -315,13 +314,12 @@ function createClanRankCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let rankId = toInteger(splitParams[0]);
- let rankName = splitParams[1];
+ let rankId = toInteger(getParam(params, " ", 1));
+ let rankName = getParam(params, " ", 2);
let rankIndex = createClanRank(clanId, rankId, rankName);
@@ -345,7 +343,7 @@ function deleteClanRankCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
@@ -353,7 +351,7 @@ function deleteClanRankCommand(command, params, client) {
let tempRankName = getClanRankData(clanId, rankId);
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
@@ -375,11 +373,10 @@ function setClanMemberTagCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
- let targetClient = getPlayerFromParams(splitParams[0]);
+ let targetClient = getPlayerFromParams(getParam(params, " ", 1));
if(!targetClient) {
- messagePlayerError(client, "Player not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -402,10 +399,10 @@ function setClanMemberTagCommand(command, params, client) {
}
}
- getPlayerCurrentSubAccount(targetClient).ClanTag = splitParams[1];
+ getPlayerCurrentSubAccount(targetClient).ClanTag = getParam(params, " ", 2);
- messagePlayerSuccess(client, `You set {ALTCOLOUR}${getCharacterFullName(targetClient)}'s {MAINCOLOUR}clan tag to {ALTCOLOUR}${splitParams[1]}`);
- messagePlayerAlert(client, `{ALTCOLOUR}${getCharacterFullName(targetClient)} {MAINCOLOUR}set your clan tag to {ALTCOLOUR}${splitParams[1]}`);
+ messagePlayerSuccess(client, `You set {ALTCOLOUR}${getCharacterFullName(targetClient)}'s {MAINCOLOUR}clan tag to {ALTCOLOUR}${getParam(params, " ", 2)}`);
+ messagePlayerAlert(client, `{ALTCOLOUR}${getCharacterFullName(targetClient)} {MAINCOLOUR}set your clan tag to {ALTCOLOUR}${getParam(params, " ", 2)}`);
}
// ===========================================================================
@@ -425,7 +422,7 @@ function setClanRankTagCommand(command, params, client) {
let newTag = splitParams[splitParams.length-1];
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
@@ -452,11 +449,10 @@ function setClanRankLevelCommand(command, params, client) {
return false;
}
- let splitParams = params.split(" ");
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
@@ -464,7 +460,7 @@ function setClanRankLevelCommand(command, params, client) {
let newLevel = splitParams[splitParams.length-1];
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
@@ -504,15 +500,14 @@ function addClanMemberFlagCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let targetClient = getPlayerFromParams(splitParams[0]);
+ let targetClient = getPlayerFromParams(getParam(params, " ", 1));
if(!targetClient) {
- messagePlayerError(client, "Player not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -535,9 +530,9 @@ function addClanMemberFlagCommand(command, params, client) {
}
}
- let flagValue = getClanFlagValue(splitParams[1]);
+ let flagValue = getClanFlagValue(getParam(params, " ", 2));
getPlayerCurrentSubAccount(client).clanFlags = getPlayerCurrentSubAccount(client).clanFlags | flagValue;
- messagePlayerSuccess(client, `You added the {ALTCOLOUR}${splitParams[1]} {MAINCOLOUR}clan flag to {ALTCOLOUR}${getCharacterFullName(client)}`);
+ messagePlayerSuccess(client, `You added the {ALTCOLOUR}${getParam(params, " ", 2)} {MAINCOLOUR}clan flag to {ALTCOLOUR}${getCharacterFullName(client)}`);
}
// ===========================================================================
@@ -556,15 +551,14 @@ function removeClanMemberFlagCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let targetClient = getPlayerFromParams(splitParams[0]);
+ let targetClient = getPlayerFromParams(getParam(params, " ", 1));
if(!targetClient) {
- messagePlayerError(client, "Player not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -587,9 +581,9 @@ function removeClanMemberFlagCommand(command, params, client) {
}
}
- let flagValue = getClanFlagValue(splitParams[1]);
+ let flagValue = getClanFlagValue(getParam(params, " ", 2));
getPlayerCurrentSubAccount(client).clanFlags = getPlayerCurrentSubAccount(client).clanFlags & ~flagValue;
- messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${splitParams[1]} {MAINCOLOUR}clan flag from {ALTCOLOUR}${getCharacterFullName(client)}`);
+ messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${getParam(params, " ", 2)} {MAINCOLOUR}clan flag from {ALTCOLOUR}${getCharacterFullName(client)}`);
}
// ===========================================================================
@@ -608,27 +602,26 @@ function addClanRankFlagCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let rankId = getClanRankFromParams(clanId, splitParams[0]);
+ let rankId = getClanRankFromParams(clanId, getParam(params, " ", 1));
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
- if(!getClanFlagValue(splitParams[1])) {
+ if(!getClanFlagValue(getParam(params, " ", 2))) {
messagePlayerError(client, "Clan flag not found!");
return false;
}
- let flagValue = getClanFlagValue(splitParams[1]);
+ let flagValue = getClanFlagValue(getParam(params, " ", 2));
addBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
- messagePlayerSuccess(client, `You added the {ALTCOLOUR}${splitParams[1]} {MAINCOLOUR}clan flag to rank {ALTCOLOUR}${getClanRankData(clanId, rankId).name}`);
+ messagePlayerSuccess(client, `You added the {ALTCOLOUR}${getParam(params, " ", 2)} {MAINCOLOUR}clan flag to rank {ALTCOLOUR}${getClanRankData(clanId, rankId).name}`);
}
// ===========================================================================
@@ -647,27 +640,26 @@ function removeClanRankFlagCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let rankId = getClanRankFromParams(clanId, splitParams[0]);
+ let rankId = getClanRankFromParams(clanId, getParam(params, " ", 1));
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
- if(!getClanFlagValue(splitParams[1])) {
+ if(!getClanFlagValue(getParam(params, " ", 2))) {
messagePlayerError(client, "Clan flag not found!");
return false;
}
- let flagValue = getClanFlagValue(splitParams[1]);
+ let flagValue = getClanFlagValue(getParam(params, " ", 2));
removeBitFlag(getClanRankData(clanId, rankId).flags, flagValue);
- messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${splitParams[1]} {MAINCOLOUR}clan flag from rank {ALTCOLOUR}${getClanRankData(clanId, rankId).name}`);
+ messagePlayerSuccess(client, `You removed the {ALTCOLOUR}${getParam(params, " ", 2)} {MAINCOLOUR}clan flag from rank {ALTCOLOUR}${getClanRankData(clanId, rankId).name}`);
}
// ===========================================================================
@@ -686,15 +678,14 @@ function showClanRankFlagsCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let rankId = getClanRankFromParams(clanId, splitParams[0]);
+ let rankId = getClanRankFromParams(clanId, getParam(params, " ", 1));
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
@@ -734,15 +725,14 @@ function setClanMemberTitleCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let targetClient = getPlayerFromParams(splitParams[0]);
+ let targetClient = getPlayerFromParams(getParam(params, " ", 1));
if(!targetClient) {
- messagePlayerError(client, "Player not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
@@ -761,7 +751,7 @@ function setClanMemberTitleCommand(command, params, client) {
}
let oldMemberTitle = getPlayerCurrentSubAccount(client).clanTitle;
- getPlayerCurrentSubAccount(client).clanTitle = splitParams[1];
+ getPlayerCurrentSubAccount(client).clanTitle = getParam(params, " ", 2);
messagePlayerSuccess(client, `You changed the name of {ALTCOLOUR}${getCharacterFullName(client)} {MAINCOLOUR}from {ALTCOLOUR}${oldMemberTitle} {MAINCOLOUR}to {ALTCOLOUR}${params}`);
}
@@ -781,20 +771,19 @@ function setClanRankTitleCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let rankId = getClanRankFromParams(clanId, splitParams[0]);
+ let rankId = getClanRankFromParams(clanId, getParam(params, " ", 1));
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
let oldRankName = getClanRankData(clanId, rankId).name;
- getClanRankData(clanId, rankId).name = splitParams[1];
+ getClanRankData(clanId, rankId).name = getParam(params, " ", 2);
messagePlayerSuccess(client, `You changed the name of rank ${rankId} from {ALTCOLOUR}${oldRankName} {MAINCOLOUR}to {ALTCOLOUR}${params}`);
}
@@ -814,21 +803,20 @@ function setClanMemberRankCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let targetClient = getPlayerFromParams(splitParams[0]);
- let rankId = getClanRankFromParams(clanId, splitParams[1]);
+ let targetClient = getPlayerFromParams(getParam(params, " ", 1));
+ let rankId = getClanRankFromParams(clanId, getParam(params, " ", 2));
if(!targetClient) {
- messagePlayerError(client, "Player not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidPlayer"));
return false;
}
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
@@ -899,6 +887,10 @@ function deleteClan(clanId) {
// ===========================================================================
+/**
+ * @param {number} clanId - The data index of the clan
+ * @return {ClanData} The clan's data (class instance)
+ */
function getClanData(clanId) {
if(typeof getServerData().clans[clanId] != null) {
return getServerData().clans[clanId];
@@ -956,6 +948,10 @@ function saveClanToDatabase(clanId) {
return false;
}
+ if(!tempClanData.needsSaved) {
+ return false;
+ }
+
let dbConnection = connectToDatabase();
if(dbConnection) {
if(tempClanData.needsSaved) {
@@ -998,40 +994,41 @@ function saveClanToDatabase(clanId) {
function saveClanRankToDatabase(clanId, rankId) {
let tempClanRankData = getClanRankData(clanId, rankId);
+ if(!tempClanRankData.needsSaved) {
+ return false;
+ }
+
let dbConnection = connectToDatabase();
if(dbConnection) {
- if(tempClanRankData.needsSaved) {
- let safeName = escapeDatabaseString(dbConnection, tempClanRankData.name);
- let safeTag = escapeDatabaseString(dbConnection, tempClanRankData.customTag);
- //let safeTitle = escapeDatabaseString(dbConnection, tempClanRankData.name);
+ let safeName = escapeDatabaseString(dbConnection, tempClanRankData.name);
+ let safeTag = escapeDatabaseString(dbConnection, tempClanRankData.customTag);
+ //let safeTitle = escapeDatabaseString(dbConnection, tempClanRankData.name);
- let data = [
- ["clan_rank_name", safeName],
- ["clan_rank_clan", tempClanRankData.clan],
- ["clan_rank_custom_tag", safeTag],
- //["clan_rank_title", safeTitle],
- ["clan_rank_flags", tempClanRankData.flags],
- ["clan_rank_level", tempClanRankData.level],
- ["clan_rank_enabled", boolToInt(tempClanRankData.enabled)],
- ];
+ let data = [
+ ["clan_rank_name", safeName],
+ ["clan_rank_clan", tempClanRankData.clan],
+ ["clan_rank_custom_tag", safeTag],
+ //["clan_rank_title", safeTitle],
+ ["clan_rank_flags", tempClanRankData.flags],
+ ["clan_rank_level", tempClanRankData.level],
+ ["clan_rank_enabled", boolToInt(tempClanRankData.enabled)],
+ ];
- let dbQuery = null;
- if(tempClanRankData.databaseId == 0) {
- let queryString = createDatabaseInsertQuery("clan_rank", data);
- dbQuery = queryDatabase(dbConnection, queryString);
- getClanRankData(clanId, rankId).databaseId = getDatabaseInsertId(dbConnection);
- getClanRankData(clanId, rankId).needsSaved = false;
- } else {
- let queryString = createDatabaseUpdateQuery("clan_rank", data, `clan_rank_id=${tempClanRankData.databaseId} LIMIT 1`);
- dbQuery = queryDatabase(dbConnection, queryString);
- getClanRankData(clanId, rankId).needsSaved = false;
- }
-
- freeDatabaseQuery(dbQuery);
- disconnectFromDatabase(dbConnection);
- return true;
- }
+ let dbQuery = null;
+ if(tempClanRankData.databaseId == 0) {
+ let queryString = createDatabaseInsertQuery("clan_rank", data);
+ dbQuery = queryDatabase(dbConnection, queryString);
+ getClanRankData(clanId, rankId).databaseId = getDatabaseInsertId(dbConnection);
+ getClanRankData(clanId, rankId).needsSaved = false;
+ } else {
+ let queryString = createDatabaseUpdateQuery("clan_rank", data, `clan_rank_id=${tempClanRankData.databaseId} LIMIT 1`);
+ dbQuery = queryDatabase(dbConnection, queryString);
+ getClanRankData(clanId, rankId).needsSaved = false;
+ }
+ freeDatabaseQuery(dbQuery);
+ disconnectFromDatabase(dbConnection);
+ return true;
}
return false;
@@ -1189,15 +1186,14 @@ function showClanFlagListCommand(command, params, client) {
let clanId = getPlayerClan(client);
if(!getClanData(clanId)) {
- messagePlayerError(client, "Clan not found!");
+ messagePlayerError(client, getLocaleString(client, "InvalidClan"));
return false;
}
- let splitParams = params.split(" ");
- let rankId = getClanRankFromParams(clanId, splitParams[0]);
+let rankId = getClanRankFromParams(clanId, getParam(params, " ", 1));
if(!getClanRankData(clanId, rankId)) {
- messagePlayerError(client, "Clan rank not found!");
+ messagePlayerError(client, getLocaleString(client, "ClanRankInvalid"));
return false;
}
@@ -1215,4 +1211,42 @@ function showClanFlagListCommand(command, params, client) {
messagePlayerInfo(client, chunkedList[i].join(", "));
}
}
-*/
\ No newline at end of file
+*/
+
+function getClanFromParams(params) {
+ if(isNaN(params)) {
+ for(let i in getServerData().clans) {
+ if(toLowerCase(getServerData().clans[i].name).indexOf(toLowerCase(params)) != -1) {
+ return i;
+ }
+ }
+ } else {
+ if(typeof getServerData().clans[params] != "undefined") {
+ return toInteger(params);
+ }
+ }
+
+ return false;
+}
+
+// ===========================================================================
+
+function getClanRankFromParams(clanId, params) {
+ if(isNaN(params)) {
+ for(let i in getClanData(clanId).ranks) {
+ if((toLowerCase(getClanData(clanId).ranks[i].name).indexOf(toLowerCase(params)) != -1)) {
+ return i;
+ }
+ }
+ } else {
+ for(let i in getClanData(clanId).ranks) {
+ if(getClanData(clanId).ranks[i].level == toInteger(params)) {
+ return i;
+ }
+ }
+ }
+
+ return false;
+}
+
+// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/class.js b/scripts/server/class.js
index 62ce4b2c..6219c2d1 100644
--- a/scripts/server/class.js
+++ b/scripts/server/class.js
@@ -22,8 +22,6 @@ function initClassScript() {
class ServerData {
constructor(dbAssoc = false) {
this.databaseId = 0;
- this.name = "";
- this.password = "";
this.needsSaved = false;
this.newCharacter = {
@@ -59,6 +57,8 @@ class ServerData {
this.guiTextColourSecondary = [0, 0, 0];
this.showLogo = true;
this.inflationMultiplier = 1;
+ this.testerOnly = false;
+ this.settings = 0;
this.antiCheat = {
enabled: false,
@@ -104,52 +104,47 @@ class ServerData {
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.characterSelectCameraPosition = toVector3(dbAssoc["svr_charselect_cam_pos_x"], dbAssoc["svr_charselect_cam_pos_y"], dbAssoc["svr_charselect_cam_pos_z"]);
- //this.characterSelectCameraLookAt = toVector3(dbAssoc["svr_charselect_cam_lookat_x"], dbAssoc["svr_charselect_cam_lookat_y"], dbAssoc["svr_charselect_cam_lookat_z"]);
-
- //this.characterSelectPedPosition = toVector3(dbAssoc["svr_charselect_ped_pos_x"], dbAssoc["svr_charselect_ped_pos_y"], dbAssoc["svr_charselect_ped_pos_z"]);
- //this.characterSelectPedHeading = toFloat(dbAssoc["svr_charselect_ped_rot_z"]);
- //this.characterSelectInterior = toInteger(dbAssoc["svr_charselect_int"]);
- //this.characterSelectDimension = toInteger(dbAssoc["svr_charselect_int"]);
-
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(dbAssoc["svr_start_snow_falling"]);
- this.groundSnow = intToBool(dbAssoc["svr_start_snow_ground"]);
- this.useGUI = intToBool(dbAssoc["svr_gui"]);
+ this.fallingSnow = hasBitFlag(this.settings, getServerSettingsFlagValue("FallingSnow"));
+ this.groundSnow = hasBitFlag(this.settings, getServerSettingsFlagValue("GroundSnow"));
+ this.useGUI = hasBitFlag(this.settings, getServerSettingsFlagValue("GUI"));
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.showLogo = intToBool(dbAssoc["svr_logo"]);
+ this.showLogo = hasBitFlag(this.settings, getServerSettingsFlagValue("Logo"));
this.inflationMultiplier = toFloat(dbAssoc["svr_inflation_multiplier"]);
+ this.testerOnly = hasBitFlag(this.settings, getServerSettingsFlagValue("Testing"));
this.antiCheat = {
- enabled: intToBool(dbAssoc["svr_ac_enabled"]),
- checkGameScripts: intToBool(dbAssoc["svr_ac_check_scripts"]),
- gameScriptBlackListEnabled: intToBool(dbAssoc["svr_ac_script_bl"]),
- gameScriptWhiteListEnabled: intToBool(dbAssoc["svr_ac_script_wl"]),
+ enabled: hasBitFlag(this.settings, getServerSettingsFlagValue("Anticheat")),
+ checkGameScripts: hasBitFlag(this.settings, getServerSettingsFlagValue("CheckGameScripts")),
+ gameScriptBlackListEnabled: hasBitFlag(this.settings, getServerSettingsFlagValue("GameScriptBlackList")),
+ gameScriptWhiteListEnabled: hasBitFlag(this.settings, getServerSettingsFlagValue("GameScriptWhiteList")),
gameScriptWhiteList: [],
gameScriptBlackList: [],
};
this.discordBotToken = intToBool(dbAssoc["svr_discord_bot_token"]);
- this.discordEnabled = intToBool(dbAssoc["svr_discord_bot_enabled"]);
+ this.discordEnabled = hasBitFlag(this.settings, getServerSettingsFlagValue("DiscordBot"));
- this.createJobPickups = intToBool(dbAssoc["svr_job_pickups"]);
- this.createBusinessPickups = intToBool(dbAssoc["svr_biz_pickups"]);
- this.createHousePickups = intToBool(dbAssoc["svr_house_pickups"]);
- this.createJobBlips = intToBool(dbAssoc["svr_job_blips"]);
- this.createBusinessBlips = intToBool(dbAssoc["svr_biz_blips"]);
- this.createHouseBlips = intToBool(dbAssoc["svr_house_blips"]);
+ this.createJobPickups = hasBitFlag(this.settings, getServerSettingsFlagValue("JobPickups"));
+ this.createBusinessPickups = hasBitFlag(this.settings, getServerSettingsFlagValue("BusinessPickups"));
+ this.createHousePickups = hasBitFlag(this.settings, getServerSettingsFlagValue("HousePickups"));
+ this.createJobBlips = hasBitFlag(this.settings, getServerSettingsFlagValue("JobBlips"));
+ this.createBusinessBlips = hasBitFlag(this.settings, getServerSettingsFlagValue("BusinessBlips"));
+ this.createHouseBlips = hasBitFlag(this.settings, getServerSettingsFlagValue("HouseBlips"));
this.introMusicURL = dbAssoc["svr_intro_music"];
- this.useRealTime = intToBool(dbAssoc["svr_time_realtime_enabled"]);
+ this.useRealTime = hasBitFlag(this.settings, getServerSettingsFlagValue("RealTime"));
this.realTimeZone = dbAssoc["svr_time_realtime_timezone"];
this.discordConfig = {
@@ -178,10 +173,10 @@ class ClientData {
this.connectTime = 0;
this.clientVersion = "0.0.0";
this.loginAttemptsRemaining = 3;
+ this.afk = false;
- this.jobRoute = false;
- this.jobRouteStop = false;
- this.jobRouteIsland = false;
+ this.jobRoute = -1;
+ this.jobRouteLocation = -1;
this.jobRouteVehicle = false;
this.spawned = false;
@@ -247,10 +242,27 @@ class ClientData {
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;
}
};
@@ -276,7 +288,6 @@ class AccountData {
this.notes = [];
this.messages = [];
- this.keyBinds = [];
this.contacts = [];
this.subAccounts = [];
@@ -286,6 +297,7 @@ class AccountData {
this.chatScrollLines = 1;
this.streamingRadioVolume = 20;
+ this.locale = 0;
if(dbAssoc) {
this.databaseId = dbAssoc["acct_id"];
@@ -306,7 +318,6 @@ class AccountData {
this.notes = [];
this.messages = [];
- this.keyBinds = [];
this.contacts = [];
this.subAccounts = [];
@@ -314,6 +325,7 @@ class AccountData {
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"]);
}
}
};
@@ -420,7 +432,6 @@ class SubAccountData {
this.clanTitle = 0;
this.isWorking = false;
this.jobUniform = this.skin;
- this.lastJobVehicle = null;
this.job = 0;
this.jobRank = 0;
this.weapons = [];
@@ -893,10 +904,6 @@ class VehicleData {
this.colour2IsRGBA = 0;
this.colour3IsRGBA = 0;
this.colour4IsRGBA = 0;
- this.colour1RGBA = toColour(255, 255, 255, 255);
- this.colour2RGBA = toColour(255, 255, 255, 255);
- this.colour3RGBA = toColour(255, 255, 255, 255);
- this.colour4RGBA = toColour(255, 255, 255, 255);
this.colour1 = (vehicle) ? vehicle.colour1 : 1;
this.colour2 = (vehicle) ? vehicle.colour2 : 1;
this.colour3 = (vehicle) ? vehicle.colour3 : 1;
@@ -944,7 +951,7 @@ class VehicleData {
this.interior = 0;
this.dimension = 0;
- this.respawnTime = 0;
+ this.lastActiveTime = false;
if(dbAssoc) {
// General Info
@@ -968,10 +975,6 @@ class VehicleData {
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.colour1RGBA = toColour(toInteger(dbAssoc["veh_col1_r"]), toInteger(dbAssoc["veh_col1_g"]), toInteger(dbAssoc["veh_col1_b"]), toInteger(dbAssoc["veh_col1_a"]));
- this.colour2RGBA = toColour(toInteger(dbAssoc["veh_col2_r"]), toInteger(dbAssoc["veh_col2_g"]), toInteger(dbAssoc["veh_col2_b"]), toInteger(dbAssoc["veh_col2_a"]));
- this.colour3RGBA = toColour(toInteger(dbAssoc["veh_col3_r"]), toInteger(dbAssoc["veh_col3_g"]), toInteger(dbAssoc["veh_col3_b"]), toInteger(dbAssoc["veh_col3_a"]));
- this.colour4RGBA = toColour(toInteger(dbAssoc["veh_col4_r"]), toInteger(dbAssoc["veh_col4_g"]), toInteger(dbAssoc["veh_col4_b"]), toInteger(dbAssoc["veh_col4_a"]));
this.colour1 = toInteger(dbAssoc["veh_col1"]);
this.colour2 = toInteger(dbAssoc["veh_col2"]);
this.colour3 = toInteger(dbAssoc["veh_col3"]);
@@ -1085,6 +1088,7 @@ class JobData {
this.locations = [];
this.whiteList = [];
this.blackList = [];
+ this.routes = [];
if(dbAssoc) {
this.databaseId = dbAssoc["job_id"];
@@ -1104,6 +1108,7 @@ class JobData {
this.locations = [];
this.whiteList = [];
this.blackList = [];
+ this.routes = [];
}
}
};
@@ -1229,7 +1234,7 @@ class JobUniformData {
class JobLocationData {
constructor(dbAssoc = false) {
this.databaseId = 0;
- this.job = 0;
+ this.jobId = 0;
this.position = toVector3(0.0, 0.0, 0.0);
this.blip = false;
this.pickup = false;
@@ -1239,10 +1244,11 @@ class JobLocationData {
this.index = -1;
this.jobIndex = -1;
this.needsSaved = false;
+ this.routeCache = [];
if(dbAssoc) {
this.databaseId = dbAssoc["job_loc_id"];
- this.job = dbAssoc["job_loc_job"];
+ 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;
@@ -1445,6 +1451,20 @@ class ItemTypeData {
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"]);
@@ -1475,6 +1495,13 @@ class ItemTypeData {
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"]);
}
}
};
@@ -1578,6 +1605,7 @@ class NPCTriggerData {
this.npcId = 0;
this.index = 0;
this.npc = 0;
+ this.npcIndex = -1;
this.triggerType = 0;
this.conditions = [];
this.responses = [];
@@ -1595,6 +1623,7 @@ class NPCTriggerConditionData {
this.databaseId = 0;
this.triggerId = 0;
this.index = 0;
+ this.triggerIndex = 0;
this.conditionType = 0;
this.conditionValue = false;
this.matchType = false;
@@ -1614,6 +1643,7 @@ class NPCTriggerResponseData {
this.databaseId = 0;
this.triggerId = 0;
this.index = 0;
+ this.triggerIndex = 0;
this.responseType = 0;
this.responseValue = false;
@@ -1672,26 +1702,35 @@ class JobRouteData {
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 = toColour(255, 255, 255, 255);
- this.vehicleColour2 = toColour(255, 255, 255, 255);
+ 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.colour1 = toColour(toInteger(dbAssoc["job_route_col1_r"]), toInteger(dbAssoc["job_route_col1_g"]), toInteger(dbAssoc["job_route_col1_b"]), 255);
- this.colour2 = toColour(toInteger(dbAssoc["job_route_col2_r"]), toInteger(dbAssoc["job_route_col2_g"]), toInteger(dbAssoc["job_route_col2_b"]), 255);
+ 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"]);
}
}
@@ -1704,12 +1743,12 @@ class JobRouteLocationData {
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;
- this.previousStop = 0;
if(dbAssoc) {
this.databaseId = toInteger(dbAssoc["job_route_loc_id"]);
@@ -1719,7 +1758,6 @@ class JobRouteLocationData {
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"]);
- this.previousStop = toInteger(dbAssoc["job_route_loc_prev"]);
}
}
};
\ No newline at end of file
diff --git a/scripts/server/client.js b/scripts/server/client.js
index bfe7d182..1e72c866 100644
--- a/scripts/server/client.js
+++ b/scripts/server/client.js
@@ -19,65 +19,68 @@ function addAllNetworkHandlers() {
logToConsole(LOG_DEBUG, "[VRR.Client]: Adding network handlers ...");
// KeyBind
- addNetworkHandler("vrr.useKeyBind", playerUsedKeyBind);
+ addNetworkEventHandler("vrr.useKeyBind", playerUsedKeyBind);
// GUI
- addNetworkHandler("vrr.promptAnswerNo", playerPromptAnswerNo);
- addNetworkHandler("vrr.promptAnswerYes", playerPromptAnswerYes);
+ addNetworkEventHandler("vrr.promptAnswerNo", playerPromptAnswerNo);
+ addNetworkEventHandler("vrr.promptAnswerYes", playerPromptAnswerYes);
+ addNetworkEventHandler("vrr.toggleGUI", playerToggledGUI);
+ addNetworkEventHandler("vrr.2fa", checkPlayerTwoFactorAuthentication);
// AFK
- addNetworkHandler("vrr.afk", playerChangeAFKState);
+ addNetworkEventHandler("vrr.afk", playerChangeAFKState);
// Event
- addNetworkHandler("vrr.pickup", onPlayerNearPickup);
- addNetworkHandler("vrr.enteredSphere", onPlayerEnteredSphere);
- addNetworkHandler("vrr.exitedSphere", onPlayerExitedSphere);
- addNetworkHandler("vrr.playerDeath", onPlayerDeath);
- addNetworkHandler("vrr.onPlayerEnterVehicle", onPlayerEnteredVehicle);
- addNetworkHandler("vrr.onPlayerExitVehicle", onPlayerExitedVehicle);
+ addNetworkEventHandler("vrr.pickup", onPlayerNearPickup);
+ addNetworkEventHandler("vrr.enteredSphere", onPlayerEnteredSphere);
+ addNetworkEventHandler("vrr.exitedSphere", onPlayerExitedSphere);
+ addNetworkEventHandler("vrr.playerDeath", onPlayerDeath);
+ addNetworkEventHandler("vrr.onPlayerEnterVehicle", onPlayerEnteredVehicle);
+ addNetworkEventHandler("vrr.onPlayerExitVehicle", onPlayerExitedVehicle);
// Job
- addNetworkHandler("vrr.arrivedAtJobRouteStop", playerArrivedAtJobRouteStop);
+ addNetworkEventHandler("vrr.arrivedAtJobRouteLocation", playerArrivedAtJobRouteLocation);
// Client
- addNetworkHandler("vrr.clientReady", playerClientReady);
- addNetworkHandler("vrr.guiReady", playerGUIReady);
- addNetworkHandler("vrr.clientStarted", playerClientStarted);
- addNetworkHandler("vrr.clientStopped", playerClientStopped);
+ addNetworkEventHandler("vrr.clientReady", playerClientReady);
+ addNetworkEventHandler("vrr.guiReady", playerGUIReady);
+ addNetworkEventHandler("vrr.clientStarted", playerClientStarted);
+ addNetworkEventHandler("vrr.clientStopped", playerClientStopped);
// Account
- addNetworkHandler("vrr.checkLogin", checkLogin);
- addNetworkHandler("vrr.checkRegistration", checkRegistration);
+ addNetworkEventHandler("vrr.checkLogin", checkLogin);
+ addNetworkEventHandler("vrr.checkRegistration", checkRegistration);
+ addNetworkEventHandler("vrr.checkResetPassword", checkAccountResetPasswordRequest);
+ addNetworkEventHandler("vrr.checkChangePassword", checkAccountChangePassword);
// Developer
- addNetworkHandler("vrr.runCodeSuccess", clientRunCodeSuccess);
- addNetworkHandler("vrr.runCodeFail", clientRunCodeFail);
+ addNetworkEventHandler("vrr.runCodeSuccess", clientRunCodeSuccess);
+ addNetworkEventHandler("vrr.runCodeFail", clientRunCodeFail);
// SubAccount
- addNetworkHandler("vrr.checkNewCharacter", checkNewCharacter);
- addNetworkHandler("vrr.nextCharacter", checkNextCharacter);
- addNetworkHandler("vrr.previousCharacter", checkPreviousCharacter);
- addNetworkHandler("vrr.selectCharacter", selectCharacter);
+ addNetworkEventHandler("vrr.checkNewCharacter", checkNewCharacter);
+ addNetworkEventHandler("vrr.nextCharacter", checkNextCharacter);
+ addNetworkEventHandler("vrr.previousCharacter", checkPreviousCharacter);
+ addNetworkEventHandler("vrr.selectCharacter", selectCharacter);
// Item
- addNetworkHandler("vrr.itemActionDelayComplete", playerItemActionDelayComplete);
+ addNetworkEventHandler("vrr.itemActionDelayComplete", playerItemActionDelayComplete);
+ addNetworkEventHandler("vrr.weaponDamage", playerDamagedByPlayer);
- addNetworkHandler("vrr.weaponDamage", playerDamagedByPlayer);
-
- addNetworkHandler("vrr.player.position", updatePositionInPlayerData);
- addNetworkHandler("vrr.player.heading", updateHeadingInPlayerData);
- addNetworkHandler("vrr.player.lookat", setPlayerHeadLookPosition);
-
- addNetworkHandler("vrr.skinSelected", playerFinishedSkinSelection);
-
- addNetworkHandler("vrr.clientInfo", updateConnectionLogOnClientInfoReceive);
+ // Misc
+ addNetworkEventHandler("vrr.player.position", updatePositionInPlayerData);
+ addNetworkEventHandler("vrr.player.heading", updateHeadingInPlayerData);
+ addNetworkEventHandler("vrr.player.lookat", setPlayerHeadLookPosition);
+ addNetworkEventHandler("vrr.skinSelected", playerFinishedSkinSelection);
+ addNetworkEventHandler("vrr.clientInfo", updateConnectionLogOnClientInfoReceive);
+ addNetworkEventHandler("vrr.vehBuyState", receiveVehiclePurchaseStateUpdateFromClient);
}
// ===========================================================================
function updatePlayerNameTag(client) {
//logToConsole(LOG_DEBUG, `[VRR.Client] Sending ${getPlayerDisplayForConsole(client)}'s updated nametag to all players`);
- triggerNetworkEvent("vrr.nametag", null, getPlayerName(client), getPlayerNameForNameTag(client), getPlayerColour(client), false, client.ping);
+ sendNetworkEventToPlayer("vrr.nametag", null, getPlayerName(client), getPlayerNameForNameTag(client), getPlayerColour(client), getPlayerData(client).afk, getPlayerPing(client));
}
// ===========================================================================
@@ -94,7 +97,7 @@ function updateAllPlayerNameTags() {
function updatePlayerPing(client) {
//logToConsole(LOG_DEBUG, `[VRR.Client] Sending ${getPlayerDisplayForConsole(client)}'s ping to all players`);
- triggerNetworkEvent("vrr.ping", null, getPlayerName(client), client.ping);
+ sendNetworkEventToPlayer("vrr.ping", null, getPlayerName(client), client.ping);
}
// ===========================================================================
@@ -135,7 +138,7 @@ function playerClientStopped(client) {
function showGameMessage(client, text, colour, duration) {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing game message to ${getPlayerDisplayForConsole(client)} (${text}) for ${duration} milliseconds`);
- triggerNetworkEvent("vrr.smallGameMessage", client, text, colour, duration);
+ sendNetworkEventToPlayer("vrr.smallGameMessage", client, text, colour, duration);
}
// ===========================================================================
@@ -146,7 +149,7 @@ function enableCityAmbienceForPlayer(client, clearElements = false) {
//}
//logToConsole(LOG_DEBUG, `[VRR.Client] Setting ${getPlayerDisplayForConsole(client)}'s city ambience to ${toUpperCase(getOnOffFromBool(false))}`);
- //triggerNetworkEvent("vrr.ambience", client, true);
+ //sendNetworkEventToPlayer("vrr.ambience", client, true);
}
// ===========================================================================
@@ -157,14 +160,14 @@ function disableCityAmbienceForPlayer(client, clearElements = false) {
//}
//logToConsole(LOG_DEBUG, `[VRR.Client] Setting ${getPlayerDisplayForConsole(client)}'s city ambience to ${toUpperCase(getOnOffFromBool(false))}`);
- //triggerNetworkEvent("vrr.ambience", client, false, clearElements);
+ //sendNetworkEventToPlayer("vrr.ambience", client, false, clearElements);
}
// ===========================================================================
function clearPlayerOwnedPeds(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Clearing peds owned by ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.clearPeds", client);
+ sendNetworkEventToPlayer("vrr.clearPeds", client);
}
// ===========================================================================
@@ -172,41 +175,41 @@ function clearPlayerOwnedPeds(client) {
function updatePlayerSpawnedState(client, state) {
logToConsole(LOG_DEBUG, `[VRR.Client] Setting ${getPlayerDisplayForConsole(client)}'s spawned state ${toUpperCase(getOnOffFromBool(state))}`);
getPlayerData(client).spawned = true;
- triggerNetworkEvent("vrr.spawned", client, state);
+ sendNetworkEventToPlayer("vrr.spawned", client, state);
}
// ===========================================================================
function setPlayerControlState(client, state) {
logToConsole(LOG_DEBUG, `[VRR.Client] Setting ${getPlayerDisplayForConsole(client)}'s control state ${toUpperCase(getOnOffFromBool(state))}`);
- triggerNetworkEvent("vrr.control", client, state, !state);
+ sendNetworkEventToPlayer("vrr.control", client, state, !state);
}
// ===========================================================================
function updatePlayerShowLogoState(client, state) {
logToConsole(LOG_DEBUG, `[VRR.Client] Setting ${getPlayerDisplayForConsole(client)}'s logo state ${toUpperCase(getOnOffFromBool(state))}`);
- triggerNetworkEvent("vrr.logo", client, state);
+ sendNetworkEventToPlayer("vrr.logo", client, state);
}
// ===========================================================================
function restorePlayerCamera(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Restoring ${getPlayerDisplayForConsole(client)}'s camera`);
- triggerNetworkEvent("vrr.restoreCamera", client);
+ sendNetworkEventToPlayer("vrr.restoreCamera", client);
}
// ===========================================================================
function setPlayer2DRendering(client, hudState = false, labelState = false, smallGameMessageState = false, scoreboardState = false, hotBarState = false, itemActionDelayState = false) {
- triggerNetworkEvent("vrr.set2DRendering", client, hudState, labelState, smallGameMessageState, scoreboardState, hotBarState, itemActionDelayState);
+ sendNetworkEventToPlayer("vrr.set2DRendering", client, hudState, labelState, smallGameMessageState, scoreboardState, hotBarState, itemActionDelayState);
}
// ===========================================================================
function syncPlayerProperties(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending signal to sync ${getPlayerDisplayForConsole(client)}'s player ped properties`);
- triggerNetworkEvent("vrr.player.sync", null, client.player);
+ sendNetworkEventToPlayer("vrr.player.sync", null, client.player);
}
// ===========================================================================
@@ -214,7 +217,7 @@ function syncPlayerProperties(client) {
function updatePlayerSnowState(client) {
if(isSnowSupported(getServerGame())) {
logToConsole(LOG_DEBUG, `[VRR.Client] Setting ${getPlayerDisplayForConsole(client)}'s snow state (Falling: ${toUpperCase(getOnOffFromBool(getServerConfig().fallingSnow))}, Ground: ${toUpperCase(getOnOffFromBool(getServerConfig().groundSnow))})`);
- triggerNetworkEvent("vrr.snow", client, getServerConfig().fallingSnow, getServerConfig().groundSnow);
+ sendNetworkEventToPlayer("vrr.snow", client, getServerConfig().fallingSnow, getServerConfig().groundSnow);
}
}
@@ -224,7 +227,7 @@ function sendExcludedModelsForGroundSnowToPlayer(client) {
if(getGameConfig().excludedGroundSnowModels[getServerGame()].length > 0) {
for(let i in getGameConfig().excludedGroundSnowModels[getServerGame()]) {
logToConsole(LOG_DEBUG, `[VRR.Misc] Sending excluded model ${i} for ground snow to ${getPlayerName(client)}`);
- triggerNetworkEvent("vrr.excludeGroundSnow", client, getGameConfig().excludedGroundSnowModels[getServerGame()][i]);
+ sendNetworkEventToPlayer("vrr.excludeGroundSnow", client, getGameConfig().excludedGroundSnowModels[getServerGame()][i]);
}
}
}
@@ -235,7 +238,7 @@ function sendRemovedWorldObjectsToPlayer(client) {
if(getGameConfig().removedWorldObjects[getServerGame()].length > 0) {
for(let i in getGameConfig().removedWorldObjects[getServerGame()]) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending removed world object ${i} (${getGameConfig().removedWorldObjects[getServerGame()][i][0]}) to ${getPlayerName(client)}`);
- triggerNetworkEvent("vrr.removeWorldObject", client, getGameConfig().removedWorldObjects[getServerGame()][i][0], getGameConfig().removedWorldObjects[getServerGame()][i][1], getGameConfig().removedWorldObjects[getServerGame()][i][2]);
+ sendNetworkEventToPlayer("vrr.removeWorldObject", client, getGameConfig().removedWorldObjects[getServerGame()][i][0], getGameConfig().removedWorldObjects[getServerGame()][i][1], getGameConfig().removedWorldObjects[getServerGame()][i][2]);
}
}
return true;
@@ -261,273 +264,287 @@ function updatePlayerHotBar(client) {
}
tempHotBarItems.push([i, itemExists, itemImage, itemValue]);
}
- triggerNetworkEvent("vrr.hotbar", client, getPlayerData(client).activeHotBarSlot, tempHotBarItems);
+ sendNetworkEventToPlayer("vrr.hotbar", client, getPlayerData(client).activeHotBarSlot, tempHotBarItems);
}
// ===========================================================================
function setPlayerWeaponDamageEnabled(client, state) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending weapon damage state for ${getPlayerDisplayForConsole(client)} to all players`);
- triggerNetworkEvent("vrr.weaponDamageEnabled", null, getPlayerName(client), state);
+ sendNetworkEventToPlayer("vrr.weaponDamageEnabled", null, getPlayerName(client), state);
}
// ===========================================================================
function setPlayerWeaponDamageEvent(client, eventType) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending weapon damage event (${eventType}) for ${getPlayerDisplayForConsole(client)} to all players`);
- triggerNetworkEvent("vrr.weaponDamageEvent", null, getPlayerName(client), eventType);
+ sendNetworkEventToPlayer("vrr.weaponDamageEvent", null, getPlayerName(client), eventType);
getPlayerData(client).weaponDamageEvent = eventType;
}
// ===========================================================================
-function sendJobRouteStopToPlayer(client, position, colour) {
+function sendJobRouteLocationToPlayer(client, position, colour) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending job route stop data to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.showJobRouteStop", client, position, colour);
+ sendNetworkEventToPlayer("vrr.showJobRouteLocation", client, position, colour);
+}
+
+// ===========================================================================
+
+function showPlayerChangePasswordGUI(client) {
+ logToConsole(LOG_DEBUG, `[VRR.Client] Sending change password GUI signal to ${getPlayerDisplayForConsole(client)}`);
+ sendNetworkEventToPlayer("vrr.changePassword", client);
}
// ===========================================================================
function showPlayerLoginSuccessGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending login success GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.loginSuccess", client);
+ sendNetworkEventToPlayer("vrr.loginSuccess", client);
}
// ===========================================================================
function showPlayerLoginFailedGUI(client, errorMessage) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending login failed GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.loginFailed", client, errorMessage);
+ sendNetworkEventToPlayer("vrr.loginFailed", client, errorMessage);
}
// ===========================================================================
function showPlayerRegistrationSuccessGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending registration success GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.registrationSuccess", client);
+ sendNetworkEventToPlayer("vrr.registrationSuccess", client);
}
// ===========================================================================
function showPlayerRegistrationFailedGUI(client, errorMessage) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending registration failed GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.registrationFailed", client, errorMessage);
+ sendNetworkEventToPlayer("vrr.registrationFailed", client, errorMessage);
}
// ===========================================================================
function sendPlayerGUIColours(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending GUI colours to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.guiColour", client, getServerConfig().guiColourPrimary[0], getServerConfig().guiColourPrimary[1], getServerConfig().guiColourPrimary[2], getServerConfig().guiColourSecondary[0], getServerConfig().guiColourSecondary[1], getServerConfig().guiColourSecondary[2], getServerConfig().guiTextColourPrimary[0], getServerConfig().guiTextColourPrimary[1], getServerConfig().guiTextColourPrimary[2]);
+ sendNetworkEventToPlayer("vrr.guiColour", client, getServerConfig().guiColourPrimary[0], getServerConfig().guiColourPrimary[1], getServerConfig().guiColourPrimary[2], getServerConfig().guiColourSecondary[0], getServerConfig().guiColourSecondary[1], getServerConfig().guiColourSecondary[2], getServerConfig().guiTextColourPrimary[0], getServerConfig().guiTextColourPrimary[1], getServerConfig().guiTextColourPrimary[2]);
}
// ===========================================================================
function sendPlayerGUIInit(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending GUI init signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.guiInit", client);
+ sendNetworkEventToPlayer("vrr.guiInit", client);
}
// ===========================================================================
function showPlayerLoginGUI(client, errorMessage = "") {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show login GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.showLogin", client);
+ sendNetworkEventToPlayer("vrr.showLogin", client);
}
// ===========================================================================
function showPlayerRegistrationGUI(client, errorMessage = "") {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show registration GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.showRegistration", client);
+ sendNetworkEventToPlayer("vrr.showRegistration", client);
}
// ===========================================================================
function showPlayerNewCharacterGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show new character GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.showNewCharacter", client);
+ sendNetworkEventToPlayer("vrr.showNewCharacter", client);
+}
+
+// ===========================================================================
+
+function showPlayerChangePasswordGUI(client, errorMessage = "") {
+ logToConsole(LOG_DEBUG, `[VRR.Client] Sending show change password GUI signal to ${getPlayerDisplayForConsole(client)}`);
+ sendNetworkEventToPlayer("vrr.showChangePassword", client);
+}
+
+// ===========================================================================
+
+function showPlayerResetPasswordCodeInputGUI(client) {
+ logToConsole(LOG_DEBUG, `[VRR.Client] Sending show reset password GUI signal to ${getPlayerDisplayForConsole(client)}`);
+ sendNetworkEventToPlayer("vrr.showResetPasswordCodeInput", client);
}
// ===========================================================================
function showPlayerCharacterSelectGUI(client, firstName, lastName, cash, clan, lastPlayed, skin) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending character select GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.showCharacterSelect", client, firstName, lastName, cash, clan, lastPlayed, skin);
+ sendNetworkEventToPlayer("vrr.showCharacterSelect", client, firstName, lastName, cash, clan, lastPlayed, skin);
}
// ===========================================================================
function updatePlayerCharacterSelectGUI(client, firstName, lastName, cash, clan, lastPlayed, skin) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending update character select GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.switchCharacterSelect", client, firstName, lastName, cash, clan, lastPlayed, skin);
+ sendNetworkEventToPlayer("vrr.switchCharacterSelect", client, firstName, lastName, cash, clan, lastPlayed, skin);
}
// ===========================================================================
function showPlayerCharacterSelectSuccessGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending character select success GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.characterSelectSuccess", client);
+ sendNetworkEventToPlayer("vrr.characterSelectSuccess", client);
}
// ===========================================================================
function showPlayerCharacterSelectFailedGUI(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending character select failed GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.characterSelectFailed", client);
+ sendNetworkEventToPlayer("vrr.characterSelectFailed", client);
}
// ===========================================================================
-function showPlayerPromptGUI(client, promptMessage, promptTitle) {
+function showPlayerPromptGUI(client, promptMessage, promptTitle, yesButtonText, noButtonText) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show prompt GUI signal to ${getPlayerDisplayForConsole(client)} (Title: ${promptTitle}, Message: ${promptMessage})`);
- triggerNetworkEvent("vrr.showPrompt", client, promptMessage, promptTitle);
+ sendNetworkEventToPlayer("vrr.showPrompt", client, promptMessage, promptTitle, yesButtonText, noButtonText);
}
// ===========================================================================
-function showPlayerInfoGUI(client, infoMessage, infoTitle) {
+function showPlayerInfoGUI(client, infoMessage, infoTitle, buttonText = "OK") {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show info GUI signal to ${getPlayerDisplayForConsole(client)} (Title: ${infoTitle}, Message: ${infoMessage})`);
- triggerNetworkEvent("vrr.showInfo", client, infoMessage, infoTitle);
+ sendNetworkEventToPlayer("vrr.showInfo", client, infoMessage, infoTitle, buttonText);
}
// ===========================================================================
-function showPlayerErrorGUI(client, errorMessage, errorTitle) {
+function showPlayerErrorGUI(client, errorMessage, errorTitle, buttonText = "OK") {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending show error GUI signal to ${getPlayerDisplayForConsole(client)} (Title: ${errorTitle}, Message: ${errorMessage})`);
- triggerNetworkEvent("vrr.showInfo", client, errorMessage, errorTitle);
+ sendNetworkEventToPlayer("vrr.showInfo", client, errorMessage, errorTitle, buttonText);
}
// ===========================================================================
function sendRunCodeToClient(client, code, returnTo) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending runcode to ${getPlayerDisplayForConsole(client)} (returnTo: ${getPlayerDisplayForConsole(getClientFromIndex(returnTo))}, Code: ${code})`);
- triggerNetworkEvent("vrr.runCode", client, code, returnTo);
+ sendNetworkEventToPlayer("vrr.runCode", client, code, returnTo);
}
// ===========================================================================
function sendPlayerWorkingState(client, state) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending working state (${toUpperCase(getYesNoFromBool(state))}) to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.working", client, state);
+ sendNetworkEventToPlayer("vrr.working", client, state);
}
// ===========================================================================
function sendPlayerJobType(client, jobType) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending job type (${jobType}) to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.jobType", client, jobType);
+ sendNetworkEventToPlayer("vrr.jobType", client, jobType);
}
// ===========================================================================
function sendPlayerStopJobRoute(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending signal to abort job route to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.stopJobRoute", client);
+ sendNetworkEventToPlayer("vrr.hideJobRouteLocation", client);
}
// ===========================================================================
function sendPlayerMouseCameraToggle(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending signal to toggle mouse camera ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.mouseCamera", client);
+ sendNetworkEventToPlayer("vrr.mouseCamera", client);
}
// ===========================================================================
function setPlayerMouseCameraState(client, state) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending signal to toggle mouse camera ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.mouseCameraForce", client, state);
+ sendNetworkEventToPlayer("vrr.mouseCameraForce", client, state);
}
// ===========================================================================
function sendPlayerMouseCursorToggle(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending signal to toggle mouse cursor ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.mouseCursor", client);
+ sendNetworkEventToPlayer("vrr.mouseCursor", client);
}
// ===========================================================================
function sendAddAccountKeyBindToClient(client, key, keyState) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending added keybind to ${getPlayerDisplayForConsole(client)} (Key: ${toUpperCase(getKeyNameFromId(key))}, State: ${(keyState) ? "down" : "up"})`);
- triggerNetworkEvent("vrr.addKeyBind", client, toInteger(key), (keyState) ? KEYSTATE_DOWN : KEYSTATE_UP);
+ sendNetworkEventToPlayer("vrr.addKeyBind", client, toInteger(key), (keyState) ? KEYSTATE_DOWN : KEYSTATE_UP);
}
// ===========================================================================
function sendClearKeyBindsToClient(client, key, keyState) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending added keybind to ${getPlayerDisplayForConsole(client)} (Key: ${toUpperCase(getKeyNameFromId(key))}, State: ${(keyState) ? "down" : "up"})`);
- triggerNetworkEvent("vrr.clearKeyBinds", client);
+ sendNetworkEventToPlayer("vrr.clearKeyBinds", client);
}
// ===========================================================================
function sendRemoveAccountKeyBindToClient(client, key) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending deleted keybind to ${getPlayerDisplayForConsole(client)} (Key: ${toUpperCase(getKeyNameFromId(key))})`);
- triggerNetworkEvent("vrr.delKeyBind", client, toInteger(key));
+ sendNetworkEventToPlayer("vrr.delKeyBind", client, toInteger(key));
}
// ===========================================================================
function sendPlayerSetPosition(client, position) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending set position signal to ${getPlayerDisplayForConsole(client)} (Position: ${position.x}, ${position.y}, ${position.z})`);
- triggerNetworkEvent("vrr.position", client, position);
+ sendNetworkEventToPlayer("vrr.position", client, position);
}
// ===========================================================================
function sendPlayerSetHeading(client, heading) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending set heading signal to ${getPlayerDisplayForConsole(client)} (Heading: ${heading})`);
- triggerNetworkEvent("vrr.heading", client, heading);
+ sendNetworkEventToPlayer("vrr.heading", client, heading);
}
// ===========================================================================
function sendPlayerSetInterior(client, interior) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending set interior signal to ${getPlayerDisplayForConsole(client)} (Interior: ${interior})`);
- triggerNetworkEvent("vrr.interior", client, interior);
+ sendNetworkEventToPlayer("vrr.interior", client, interior);
}
// ===========================================================================
function sendPlayerFrozenState(client, state) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending set frozen signal to ${getPlayerDisplayForConsole(client)} (State: ${toUpperCase(getYesNoFromBool(state))})`);
- triggerNetworkEvent("vrr.frozen", client, state);
-}
-
-// ===========================================================================
-
-function givePlayerWeapon(client, weaponId, ammo, active) {
- logToConsole(LOG_DEBUG, `[VRR.Client] Sending signal to ${getPlayerDisplayForConsole(client)} to give weapon (Weapon: ${weaponId}, Ammo: ${ammo})`);
- triggerNetworkEvent("vrr.giveWeapon", client, weaponId, ammo, active);
+ sendNetworkEventToPlayer("vrr.frozen", client, state);
}
// ===========================================================================
function clearPlayerWeapons(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending signal to ${getPlayerDisplayForConsole(client)} to clear weapons`);
- triggerNetworkEvent("vrr.clearWeapons", client);
+ sendNetworkEventToPlayer("vrr.clearWeapons", client);
}
// ===========================================================================
function showPlayerNewCharacterFailedGUI(client, errorMessage) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending new character failed GUI signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.newCharacterFailed", client, errorMessage);
+ sendNetworkEventToPlayer("vrr.newCharacterFailed", client, errorMessage);
}
// ===========================================================================
function sendPlayerRemoveFromVehicle(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Sending remove from vehicle signal to ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.removeFromVehicle", client);
+ sendNetworkEventToPlayer("vrr.removeFromVehicle", client);
}
// ===========================================================================
function sendChatBoxMessageToPlayer(client, message, colour) {
- triggerNetworkEvent("vrr.m", client, message, colour)
+ sendNetworkEventToPlayer("vrr.m", client, message, colour)
//messageClient(message, client, colour);
}
@@ -538,7 +555,7 @@ function showPlayerItemTakeDelay(client, itemId) {
let delay = getItemTypeData(getItemData(itemId).itemTypeIndex).pickupDelay;
if(delay > 0) {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item TAKE delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
- triggerNetworkEvent("vrr.showItemActionDelay", client, delay);
+ sendNetworkEventToPlayer("vrr.showItemActionDelay", client, delay);
} else {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item TAKE delay to ${getPlayerDisplayForConsole(client)} (instant)`);
playerItemActionDelayComplete(client);
@@ -553,7 +570,7 @@ function showPlayerItemUseDelay(client, itemSlot) {
let delay = getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).useDelay;
if(delay > 0) {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item USE delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
- triggerNetworkEvent("vrr.showItemActionDelay", client, delay);
+ sendNetworkEventToPlayer("vrr.showItemActionDelay", client, delay);
} else {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item USE delay to ${getPlayerDisplayForConsole(client)} (instant)`);
playerItemActionDelayComplete(client);
@@ -568,7 +585,7 @@ function showPlayerItemDropDelay(client, itemSlot) {
let delay = getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).dropDelay;
if(delay > 0) {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item DROP delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
- triggerNetworkEvent("vrr.showItemActionDelay", client, delay);
+ sendNetworkEventToPlayer("vrr.showItemActionDelay", client, delay);
} else {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item DROP delay to ${getPlayerDisplayForConsole(client)} (instant)`);
playerItemActionDelayComplete(client);
@@ -583,7 +600,7 @@ function showPlayerItemPickupDelay(client, itemId) {
let delay = getItemTypeData(getItemData(itemId).itemTypeIndex).pickupDelay;
if(delay > 0) {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item PICKUP delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
- triggerNetworkEvent("vrr.showItemActionDelay", client, delay);
+ sendNetworkEventToPlayer("vrr.showItemActionDelay", client, delay);
} else {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item PICKUP delay to ${getPlayerDisplayForConsole(client)} (instant)`);
playerItemActionDelayComplete(client);
@@ -598,7 +615,7 @@ function showPlayerItemPutDelay(client, itemSlot) {
let delay = getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).putDelay;
if(delay > 0) {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item PUT delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
- triggerNetworkEvent("vrr.showItemActionDelay", client, delay);
+ sendNetworkEventToPlayer("vrr.showItemActionDelay", client, delay);
} else {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item PUT delay to ${getPlayerDisplayForConsole(client)} (instant)`);
playerItemActionDelayComplete(client);
@@ -614,7 +631,7 @@ function showPlayerItemSwitchDelay(client, itemSlot) {
let delay = getItemTypeData(getItemData(getPlayerData(client).hotBarItems[itemSlot]).itemTypeIndex).switchDelay;
if(delay > 0) {
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item switch delay to ${getPlayerDisplayForConsole(client)} (${delay} milliseconds)`);
- triggerNetworkEvent("vrr.showItemActionDelay", client, delay);
+ sendNetworkEventToPlayer("vrr.showItemActionDelay", client, delay);
} else{
logToConsole(LOG_DEBUG, `[VRR.Client] Showing item switch delay to ${getPlayerDisplayForConsole(client)} (instant)`);
playerItemActionDelayComplete(client);
@@ -633,14 +650,14 @@ function showPlayerItemSwitchDelay(client, itemSlot) {
function sendPlayerDrunkEffect(client, amount, duration) {
logToConsole(LOG_DEBUG, `[VRR.Client] Setting drunk effect for ${getPlayerDisplayForConsole(client)} to ${amount} for ${duration} milliseconds`);
- triggerNetworkEvent("vrr.drunkEffect", client, amount, duration);
+ sendNetworkEventToPlayer("vrr.drunkEffect", client, amount, duration);
}
// ===========================================================================
function sendPlayerClearPedState(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Clearing ped state for ${getPlayerDisplayForConsole(client)}`);
- triggerNetworkEvent("vrr.clearPedState", client);
+ sendNetworkEventToPlayer("vrr.clearPedState", client);
}
// ===========================================================================
@@ -677,9 +694,20 @@ function playerDamagedByPlayer(client, damagerEntityName, weaponId, pedPiece, he
}
break;
+ case VRR_WEAPON_DAMAGE_EVENT_EXTINGUISH:
+ break;
+
+ case VRR_WEAPON_DAMAGE_EVENT_MACE:
+ break;
+
+ case VRR_WEAPON_DAMAGE_EVENT_NORMAL:
+ logToConsole(LOG_DEBUG, `[VRR.Client] ${getPlayerDisplayForConsole(client)}'s damager ${getPlayerDisplayForConsole(damagerEntity)} caused ${healthLoss} damage (damage reduction makes it ${(healthLoss*getPlayerData(client).incomingDamageMultiplier)})`);
+ setPlayerHealth(client, getPlayerHealth(client)-(healthLoss*getPlayerData(client).incomingDamageMultiplier));
+ break;
+
default:
- getPlayerData(client).health = getPlayerData(client).health-(healthLoss*getPlayerData(client).incomingDamageMultiplier);
- setPlayerHealth(client, getPlayerData(client).health);
+ logToConsole(LOG_DEBUG, `[VRR.Client] ${getPlayerDisplayForConsole(client)}'s damager ${getPlayerDisplayForConsole(damagerEntity)} caused ${healthLoss} damage (damage reduction makes it ${(healthLoss*getPlayerData(client).incomingDamageMultiplier)})`);
+ setPlayerHealth(client, getPlayerHealth(client)-(healthLoss*getPlayerData(client).incomingDamageMultiplier));
break;
}
}
@@ -687,13 +715,13 @@ function playerDamagedByPlayer(client, damagerEntityName, weaponId, pedPiece, he
// ===========================================================================
function setPlayerCameraLookAt(client, cameraPosition, lookAtPosition) {
- triggerNetworkEvent("vrr.cameraLookAt", client, cameraPosition, lookAtPosition);
+ sendNetworkEventToPlayer("vrr.cameraLookAt", client, cameraPosition, lookAtPosition);
}
// ===========================================================================
function sendTimeMinuteDurationToPlayer(client, minuteDuration) {
- triggerNetworkEvent("vrr.minuteDuration", client, minuteDuration);
+ sendNetworkEventToPlayer("vrr.minuteDuration", client, minuteDuration);
}
// ===========================================================================
@@ -724,13 +752,13 @@ function forcePlayerIntoSkinSelect(client) {
setPlayerDimension(client, client.index+500);
}
- triggerNetworkEvent("vrr.skinSelect", client, true);
+ sendNetworkEventToPlayer("vrr.skinSelect", client, true);
}
// ===========================================================================
function updatePlayerCash(client) {
- triggerNetworkEvent("vrr.money", client, getPlayerCurrentSubAccount(client).cash);
+ sendNetworkEventToPlayer("vrr.money", client, getPlayerCurrentSubAccount(client).cash);
}
// ===========================================================================
@@ -748,7 +776,7 @@ function sendAllPoliceStationBlips(client) {
getColourByName("policeBlue"),
]);
}
- triggerNetworkEvent("vrr.blips", client, tempBlips);
+ sendNetworkEventToPlayer("vrr.blips", client, tempBlips);
}
}
@@ -767,7 +795,7 @@ function sendAllFireStationBlips(client) {
getColourByName("firefighterRed"),
]);
}
- triggerNetworkEvent("vrr.blips", client, tempBlips);
+ sendNetworkEventToPlayer("vrr.blips", client, tempBlips);
}
}
@@ -786,7 +814,7 @@ function sendAllHospitalBlips(client) {
getColourByName("medicPink"),
]);
}
- triggerNetworkEvent("vrr.blips", client, tempBlips);
+ sendNetworkEventToPlayer("vrr.blips", client, tempBlips);
}
}
@@ -805,7 +833,7 @@ function sendAllAmmunationBlips(client) {
0
]);
}
- triggerNetworkEvent("vrr.blips", client, tempBlips);
+ sendNetworkEventToPlayer("vrr.blips", client, tempBlips);
}
}
@@ -824,7 +852,7 @@ function sendAllPayAndSprayBlips(client) {
0
]);
}
- triggerNetworkEvent("vrr.blips", client, tempBlips);
+ sendNetworkEventToPlayer("vrr.blips", client, tempBlips);
}
}
@@ -843,27 +871,27 @@ function sendAllFuelStationBlips(client) {
getColourByName("burntOrange"),
]);
}
- triggerNetworkEvent("vrr.blips", client, tempBlips);
+ sendNetworkEventToPlayer("vrr.blips", client, tempBlips);
}
}
// ===========================================================================
function sendPlayerSetHealth(client, health) {
- triggerNetworkEvent("vrr.health", client, health);
+ sendNetworkEventToPlayer("vrr.health", client, health);
}
// ===========================================================================
function sendPlayerSetArmour(client, armour) {
- triggerNetworkEvent("vrr.armour", client, armour);
+ sendNetworkEventToPlayer("vrr.armour", client, armour);
}
// ===========================================================================
function playerFinishedSkinSelection(client, allowedSkinIndex) {
- triggerNetworkEvent("vrr.skinSelect", client, false);
+ sendNetworkEventToPlayer("vrr.skinSelect", client, false);
if(allowedSkinIndex == -1) {
messagePlayerAlert(client, "You canceled the skin change.");
restorePlayerCamera(client);
@@ -902,6 +930,7 @@ function playerFinishedSkinSelection(client, allowedSkinIndex) {
}
restorePlayerCamera(client);
+ setPlayerControlState(client, true);
deleteItem(getPlayerData(client).itemActionItem);
switchPlayerActiveHotBarSlot(client, -1);
@@ -914,28 +943,28 @@ function playerFinishedSkinSelection(client, allowedSkinIndex) {
// ===========================================================================
function sendPlayerChatScrollLines(client, amount) {
- triggerNetworkEvent("vrr.chatScrollLines", client, amount);
+ sendNetworkEventToPlayer("vrr.chatScrollLines", client, amount);
}
// ===========================================================================
function playRadioStreamForPlayer(client, streamURL, loop = true, volume = 0, element = false) {
logToConsole(LOG_DEBUG, `[VRR.Client] Forcing ${getPlayerDisplayForConsole(client)} to stream ${streamURL}`);
- triggerNetworkEvent("vrr.radioStream", client, streamURL, loop, volume, element);
+ sendNetworkEventToPlayer("vrr.radioStream", client, streamURL, loop, volume, element);
}
// ===========================================================================
function playAudioFileForPlayer(client, audioName, loop = true, volume = 0, element = false) {
logToConsole(LOG_DEBUG, `[VRR.Client] Forcing ${getPlayerDisplayForConsole(client)} to play audio ${audioName}`);
- triggerNetworkEvent("vrr.audioFileStream", client, audioName, loop, volume);
+ sendNetworkEventToPlayer("vrr.audioFileStream", client, audioName, loop, volume);
}
// ===========================================================================
function stopRadioStreamForPlayer(client) {
logToConsole(LOG_DEBUG, `[VRR.Client] Forcing ${getPlayerDisplayForConsole(client)} to stop their radio stream`);
- triggerNetworkEvent("vrr.stopRadioStream", client);
+ sendNetworkEventToPlayer("vrr.stopRadioStream", client);
}
// ===========================================================================
@@ -943,20 +972,20 @@ function stopRadioStreamForPlayer(client) {
function setPlayerStreamingRadioVolume(client, volumeLevel, elementId = false) {
getPlayerData(client).accountData.streamingRadioVolume = volumeLevel;
getPlayerData(client).streamingRadioElement = elementId;
- triggerNetworkEvent("vrr.radioVolume", client, volumeLevel, elementId);
+ sendNetworkEventToPlayer("vrr.radioVolume", client, volumeLevel, elementId);
}
// ===========================================================================
function setVehicleLightsState(vehicle, state) {
setEntityData(vehicle, "vrr.lights", getVehicleData(vehicle).lights);
- triggerNetworkEvent("vrr.veh.lights", null, vehicle.id, state);
+ sendNetworkEventToPlayer("vrr.veh.lights", null, vehicle.id, state);
}
// ===========================================================================
function sendPlayerEnterPropertyKey(client, key) {
- triggerNetworkEvent("vrr.enterPropertyKey", client, key);
+ sendNetworkEventToPlayer("vrr.enterPropertyKey", client, key);
}
// ===========================================================================
@@ -991,13 +1020,13 @@ function makePedPlayAnimation(ped, animationSlot, positionOffset) {
break;
}
//}
- triggerNetworkEvent("vrr.pedAnim", null, ped.id, animationData[1], animationData[2], animationData[3], animationData[4], animationData[5], positionOffset, freezePlayer);
+ sendNetworkEventToPlayer("vrr.pedAnim", null, ped.id, animationData[1], animationData[2], animationData[3], animationData[4], animationData[5], positionOffset, freezePlayer);
}
// ===========================================================================
function makePedStopAnimation(ped) {
- triggerNetworkEvent("vrr.pedStopAnim", null, ped.id);
+ sendNetworkEventToPlayer("vrr.pedStopAnim", null, ped.id);
}
// ===========================================================================
@@ -1005,13 +1034,13 @@ function makePedStopAnimation(ped) {
function forcePedAnimation(ped, animationSlot) {
let animationData = getAnimationData(animationSlot);
- triggerNetworkEvent("vrr.forcePedAnim", null, ped.id, animationData[1], animationData[2], animationData[3], animationData[4]);
+ sendNetworkEventToPlayer("vrr.forcePedAnim", null, ped.id, animationData[1], animationData[2], animationData[3], animationData[4]);
}
// ===========================================================================
function hideAllPlayerGUI(client) {
- triggerNetworkEvent("vrr.hideAllGUI", client);
+ sendNetworkEventToPlayer("vrr.hideAllGUI", client);
}
// ===========================================================================
@@ -1025,37 +1054,37 @@ function setPlayerHeadLookPosition(client, position) {
// ===========================================================================
function sendPlayerGameScriptState(client, scriptName, state) {
- triggerNetworkEvent("vrr.gameScript", client, scriptName, state);
+ sendNetworkEventToPlayer("vrr.gameScript", client, scriptName, state);
}
// ===========================================================================
function requestClientInfo(client) {
- triggerNetworkEvent("vrr.clientInfo", client);
+ sendNetworkEventToPlayer("vrr.clientInfo", client);
}
// ===========================================================================
function updateInteriorLightsForPlayer(client, state) {
- triggerNetworkEvent("vrr.interiorLights", client, state);
+ sendNetworkEventToPlayer("vrr.interiorLights", client, state);
}
// ===========================================================================
function forcePlayerToSyncElementProperties(client, element) {
- triggerNetworkEvent("vrr.syncElement", client, element.id);
+ sendNetworkEventToPlayer("vrr.syncElement", client, element.id);
}
// ===========================================================================
function sendPlayerPedPartsAndProps(client) {
- triggerNetworkEvent("vrr.ped")
+ sendNetworkEventToPlayer("vrr.ped")
}
// ===========================================================================
-function setPlayerVanillaRadioStation(client, radioStationId) {
- triggerNetworkEvent("vrr.vanillaRadio", client, radioStationId);
+function forcePlayerWantedLevel(client, wantedLevel) {
+ sendNetworkEventToPlayer("vrr.wantedLevel", client, wantedLevel);
return true;
}
@@ -1079,8 +1108,30 @@ function updateAllInteriorVehiclesForPlayer(client, interior, dimension) {
// ===========================================================================
-function setPlayerBuyingVehicleState(state, vehicle, position) {
-
+function setPlayerBuyingVehicleState(client, state, vehicleId, position) {
+ if(getGlobalConfig().useServerSideVehiclePurchaseCheck == false) {
+ sendNetworkEventToPlayer("vrr.vehBuyState", client, state, vehicleId, position);
+ }
}
-// ===========================================================================
\ No newline at end of file
+// ==========================================================================
+
+function receiveVehiclePurchaseStateUpdateFromClient(client, state) {
+ if(getGlobalConfig().useServerSideVehiclePurchaseCheck == false) {
+ checkVehicleBuying(client);
+ }
+}
+
+// ===========================================================================
+
+function sendPlayerLogLevel(client, tempLogLevel = logLevel) {
+ sendNetworkEventToPlayer("vrr.logLevel", client, tempLogLevel);
+}
+
+// ==========================================================================
+
+function setPlayerInfiniteRun(client, state) {
+ sendNetworkEventToPlayer("vrr.infiniteRun", client, state);
+}
+
+// ==========================================================================
\ No newline at end of file
diff --git a/scripts/server/colour.js b/scripts/server/colour.js
deleted file mode 100644
index 630b66c9..00000000
--- a/scripts/server/colour.js
+++ /dev/null
@@ -1,367 +0,0 @@
-// ===========================================================================
-// Vortrex's Roleplay Resource
-// https://github.com/VortrexFTW/gtac_roleplay
-// ===========================================================================
-// FILE: colour.js
-// DESC: Provides colours, functions and usage
-// TYPE: Server (JavaScript)
-// ===========================================================================
-
-let serverColours = {
- hex: {
- byType: {
- talkMessage: "C8C8C8",
- shoutMessage: "FFFFC8",
- whisperMessage: "828282",
- doActionMessage: "B19CD9",
- meActionMessage: "B19CD9",
- errorMessage: "ED4337",
- syntaxMessage: "C8C8C8",
- normalMessage: "FFFFFF",
- alertMessage: "FFFF00",
- successMessage: "00B400",
- clanChatMessage: "00BE00",
- businessBlue: "0099FF",
- houseGreen: "11CC11",
- clanOrange: "FF9900",
- vehiclePurple: "960096",
- jobYellow: "FFFF00",
- },
- byName: {
- white: "FFFFFF",
- black: "000000",
- red: "FF0000",
- yellow: "FFFF00",
- royalBlue: "0000FF",
- teal: "00FFFF",
- orange: "FF8000",
- softRed: "ED4337",
- softGreen: "32CD32",
- lightPurple: "960096",
- lightGrey: "C8C8C8",
- mediumGrey: "969696",
- darkGrey: "404040",
- policeBlue: "3250C8",
- medicPink: "DB7093",
- firefighterRed: "CD3C3C",
- busDriverGreen: "32A032",
- taxiDriverYellow: "F0E664",
- deliveryPurple: "B19CD9",
- civilianWhite: "C8C8C8",
- burntYellow: "D2D200",
- burntOrange: "D27800",
- bankGreen: "00B400",
- softYellow: "EAC67E",
- businessBlue: "0099FF",
- houseGreen: "11CC11",
- clanOrange: "FF9900",
- vehiclePurple: "960096",
- jobYellow: "FFFF00",
- },
- },
-
- byType: {
- talkMessage: toColour(200, 200, 200),
- shoutMessage: toColour(255, 255, 200),
- whisperMessage: toColour(130, 130, 130),
- doActionMessage: toColour(177, 156, 217, 255),
- meActionMessage: toColour(177, 156, 217, 255),
- errorMessage: toColour(237, 67, 55, 255),
- syntaxMessage: toColour(200, 200, 200, 255),
- normalMessage: toColour(255, 255, 255, 255),
- alertMessage: toColour(255, 255, 0, 255),
- successMessage: toColour(0, 180, 0, 255),
- clanChatMessage: toColour(0, 190, 0, 255),
- },
- byName: {
- white: toColour(255, 255, 255, 255),
- black: toColour(0, 0, 0, 255),
- red: toColour(255, 0, 0, 255),
- yellow: toColour(255, 255, 0, 255),
- royalBlue: toColour(0, 0, 255, 255),
- teal: toColour(0, 255, 255, 255),
- orange: toColour(255, 128, 0, 255),
- softRed: toColour(205, 60, 60, 255),
- softGreen: toColour(50, 205, 50, 255),
- lightPurple: toColour(150, 0, 150, 255),
- lightGrey: toColour(200, 200, 200, 255),
- mediumGrey: toColour(150, 150, 150, 255),
- darkGrey: toColour(64, 64, 64, 255),
- policeBlue: toColour(50, 80, 200, 255),
- medicPink: toColour(219, 112, 147, 255),
- firefighterRed: toColour(205, 60, 60, 255),
- busDriverGreen: toColour(50, 160, 50, 255),
- taxiDriverYellow: toColour(240, 230, 100, 255),
- deliveryPurple: toColour(177, 156, 217, 255),
- civilianWhite: toColour(200, 200, 200, 255),
- burntYellow: toColour(210, 210, 0, 255),
- burntOrange: toColour(210, 120, 0, 255),
- bankGreen: toColour(0, 150, 0, 255),
- softYellow: toColour(234, 198, 126, 255),
- businessBlue: toColour(0, 153, 255, 255),
- houseGreen: toColour(17, 204, 17, 255),
- clanOrange: toColour(255, 153, 0, 255),
- },
-};
-
-// ===========================================================================
-
-function getServerColours() {
- return serverColours;
-}
-
-// ===========================================================================
-
-function getColourByType(typeName) {
- return getServerColours().byType[typeName];
-}
-
-// ===========================================================================
-
-function getColourByName(colourName) {
- return getServerColours().byName[colourName];
-}
-
-// ===========================================================================
-
-function getHexColourByName(colourName) {
- //let rgbaColour = getServerColours().byName[colourName];
- //let rgbaArray = rgbaArrayFromToColour(rgbaColour);
- //return rgbToHex(rgbaArray[0], rgbaArray[1], rgbaArray[2]);
-
- return `#${getServerColours().hex.byName[colourName]}`;
-}
-
-// ===========================================================================
-
-function getHexColourByType(colourName) {
- //let rgbaColour = getServerColours().byType[colourName];
- //let rgbaArray = rgbaArrayFromToColour(rgbaColour);
- //return rgbToHex(rgbaArray[0], rgbaArray[1], rgbaArray[2]);
-
- return `#${getServerColours().hex.byType[colourName]}`;
-}
-
-// ===========================================================================
-
-function getPlayerColour(client) {
- if(getPlayerData(client) != false) {
- if(!isPlayerLoggedIn(client)) {
- return getColourByName("darkGrey");
- } else {
- if(isPlayerWorking(client)) {
- return getJobData(getJobIndexFromDatabaseId(getPlayerCurrentSubAccount(client).job)).colour;
- }
- }
- }
-
- return getColourByName("civilianWhite");
-}
-
-// ===========================================================================
-
-/**
- * Gets the red/green colour depending on bool (red = false, green = true) for inline use in chatbox messages
- *
- * @param {Boolean} boolValue The boolean value
- * @return {String} Red or green inline HEX colour string
- *
- */
-function getBoolRedGreenInlineColour(boolValue) {
- return (!boolValue) ? "[#CD3C3C]" : "[#32CD32]";
-}
-
-// ===========================================================================
-
-/**
- * Gets an array of RGB colour values from a HEX colour string
- *
- * @param {String} hexColour Hex colour string
- * @return {Array} 3-slot array where each slot is an RGB colour value
- *
- */
-function hexToRgb(h) {
- return [
- '0x'+h[1]+h[2]|0,
- '0x'+h[3]+h[4]|0,
- '0x'+h[5]+h[6]|0
- ];
-}
-
-// ===========================================================================
-
-/**
- * Gets a HEX colour string from RGB values, without brackets (example: #FFFFFF)
- *
- * @param {Number} red Red RGB value
- * @param {Number} green Green RGB value
- * @param {Number} blue Blue RGB value
- * @return {String} HEX colour string
- *
- */
-function rgbToHex(r, g, b) {
- return "#"+((1<<24)+(r<<16)+(g<<8)+ b).toString(16).slice(1);
-}
-
-// ===========================================================================
-
-/**
- * Gets the current colour for a player (affected by job and status)
- *
- * @param {Client} client Player client
- * @return {Number} Colour integer
- *
- */
-function getClientChatColour(client) {
- let tempJob = getPlayerCurrentSubAccount(client).job;
- if(tempJob != -1) {
- if(getPlayerData(client).isWorking) {
- return getJobData(tempJob).jobColour;
- }
- }
- return getColourByName("white");
-}
-
-// ===========================================================================
-
-/**
- * Gets a toColour-created colour integer with random RGB values (alpha is always 255)
- *
- * @return {Number} Colour integer
- *
- */
-function getRandomRGB() {
- return toColour.apply(null, [
- getRandom(0, 255),
- getRandom(0, 255),
- getRandom(0, 255),
- 255
- ]);
-}
-
-// ===========================================================================
-
-/**
- * Gets a hex formatting colour by name for use inline in chatbox messages (example: [#FFFFFF]).
- *
- * @param {String} colourName - Colour name
- * @return {String} HEX-formatted colour string with brackets
- *
- */
-function getInlineChatColourByName(colourName) {
- return `{${colourName}}`;
-}
-
-// ===========================================================================
-
-/**
- * Gets a hex formatting colour by type for use inline in chatbox messages (example: [#FFFFFF]).
- *
- * @param {String} colourName - Colour type
- * @return {String} HEX-formatted colour string with brackets
- *
- */
-function getInlineChatColourByType(colourName) {
- return `{${colourName}}`;
-}
-
-// ===========================================================================
-
-/**
- * Gets an array of RGBA colour values from a toColour integer.
- *
- * @param {Number} colour - Colour integer created by toColour
- * @return {Array} 4-slot array where each slot is an RGBA colour value
- *
- */
-function rgbaArrayFromToColour(colour) {
- //return [
- // (colour >> 24) & 0xFF, // red
- // (colour >> 16) & 0xFF,
- // (colour >> 8) & 0xFF,
- // colour & 0xFF // alpha
- //];
- return [
- (colour >> 16) & 0xFF, // red
- (colour >> 8) & 0xFF,
- colour & 0xFF,
- (colour >> 24) & 0xFF// alpha
- ];
-}
-
-// ===========================================================================
-
-function hexFromToColour(colour) {
- let rgba = rgbaArrayFromToColour(colour);
- return rgbToHex(rgba[0], rgba[1], rgba[2]);
-}
-
-// ===========================================================================
-
-function replaceColoursInMessage(messageText) {
- if(messageText == null) {
- return "";
- }
-
- let tempFind = `{RESETCOLOUR}`;
- let tempRegex = new RegExp(tempFind, 'g');
- messageText = messageText.replace(tempRegex, "[/#]");
-
- tempFind = `{ALTCOLOUR}`;
- tempRegex = new RegExp(tempFind, 'g');
- messageText = messageText.replace(tempRegex, "[#C8C8C8]");
-
- tempFind = `{MAINCOLOUR}`;
- tempRegex = new RegExp(tempFind, 'g');
- messageText = messageText.replace(tempRegex, "[#FFFFFF]");
-
- for(let i in getServerColours().hex.byName) {
- let find = `{${i}}`;
- let re = new RegExp(find, 'g');
- messageText = messageText.replace(re, `[#${getServerColours().hex.byName[i]}]`);
- }
-
- for(let i in getServerColours().hex.byType) {
- let find = `{${i}}`;
- let re = new RegExp(find, 'g');
- messageText = messageText.replace(re, `[#${getServerColours().hex.byType[i]}]`);
- }
-
- return messageText;
-}
-
-// ===========================================================================
-
-function removeColoursInMessage(messageText) {
- if(messageText == null) {
- return "";
- }
-
- let tempFind = `{RESETCOLOUR}`;
- let tempRegex = new RegExp(tempFind, 'g');
- messageText = messageText.replace(tempRegex, "");
-
- tempFind = `{ALTCOLOUR}`;
- tempRegex = new RegExp(tempFind, 'g');
- messageText = messageText.replace(tempRegex, "");
-
- tempFind = `{MAINCOLOUR}`;
- tempRegex = new RegExp(tempFind, 'g');
- messageText = messageText.replace(tempRegex, "");
-
- for(let i in getServerColours().hex.byName) {
- let find = `{${i}}`;
- let re = new RegExp(find, 'g');
- messageText = messageText.replace(re, "");
- }
-
- for(let i in getServerColours().hex.byType) {
- let find = `{${i}}`;
- let re = new RegExp(find, 'g');
- messageText = messageText.replace(re, "");
- }
-
- return messageText;
-}
-
-// ===========================================================================
\ No newline at end of file
diff --git a/scripts/server/command.js b/scripts/server/command.js
index ef575bcd..a7d1aaa6 100644
--- a/scripts/server/command.js
+++ b/scripts/server/command.js
@@ -68,12 +68,12 @@ function loadCommands() {
commandData("stopanim", stopPlayerAnimationCommand, "", getStaffFlagValue("None"), true, true, "Stops your current animation"),
],
antiCheat: [
- commandData("addacscriptwl", addAntiCheatWhiteListedScriptCommand, "